Skip to content

Commit

Permalink
Cleanup CloudProfile docker migration and Add Validation MachineImage…
Browse files Browse the repository at this point in the history
…Version CRI (#6480)

* Add validation that cri should contain docker and can't be nil

* Add defaulting for cri

* Drop migration code from controller

* make generate

* Adapt changes in local provider

* Address PR Review

* Address PR Review
  • Loading branch information
acumino committed Aug 16, 2022
1 parent af2b9ac commit d144b5d
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 84 deletions.
4 changes: 4 additions & 0 deletions example/provider-local/garden/base/cloudprofile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ spec:
- version: 1.0.0
cri:
- name: containerd
# provider-local image doesn't contain a full docker runtime but includes nerdctl imitating the docker CLI for fulfilling gardener's bootstrap needs:
# see https://github.com/gardener/machine-controller-manager-provider-local/blob/f2c93198c794afc4e8e742a26026584ecce9aadf/node/Dockerfile#L9-L20
# this can be removed as soon as https://github.com/gardener/gardener/issues/4673 is resolved
- name: docker
providerConfig:
apiVersion: local.provider.extensions.gardener.cloud/v1alpha1
kind: CloudProfileConfig
Expand Down
15 changes: 15 additions & 0 deletions pkg/apis/core/v1alpha1/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ func defaultSubject(obj *rbacv1.Subject) {
}
}

// SetDefaults_MachineImageVersion sets default values for MachineImageVersion objects.
func SetDefaults_MachineImageVersion(obj *MachineImageVersion) {
if len(obj.CRI) == 0 {
obj.CRI = []CRI{
{
Name: CRINameDocker,
},
}
}

if len(obj.Architectures) == 0 {
obj.Architectures = []string{v1beta1constants.ArchitectureAMD64}
}
}

// SetDefaults_MachineType sets default values for MachineType objects.
func SetDefaults_MachineType(obj *MachineType) {
if obj.Usable == nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/apis/core/v1alpha1/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,4 +742,20 @@ var _ = Describe("Defaults", func() {
Expect(obj.RecommenderInterval).To(PointTo(Equal(metav1.Duration{Duration: time.Minute})))
})
})

Describe("#SetDefaults_MachineImageVersion", func() {
var obj *MachineImageVersion

BeforeEach(func() {
obj = &MachineImageVersion{}
})

It("should correctly default the MachineImageVersion", func() {
SetDefaults_MachineImageVersion(obj)

Expect(len(obj.CRI)).To(Equal(1))
Expect(obj.CRI[0].Name).To(Equal(CRINameDocker))
Expect(obj.Architectures).To(Equal([]string{"amd64"}))
})
})
})
7 changes: 7 additions & 0 deletions pkg/apis/core/v1alpha1/zz_generated.defaults.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pkg/apis/core/v1beta1/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,14 @@ func SetDefaults_ControllerRegistrationDeployment(obj *ControllerRegistrationDep

// SetDefaults_MachineImageVersion sets default values for MachineImageVersion objects.
func SetDefaults_MachineImageVersion(obj *MachineImageVersion) {
if len(obj.CRI) == 0 {
obj.CRI = []CRI{
{
Name: CRINameDocker,
},
}
}

if len(obj.Architectures) == 0 {
obj.Architectures = []string{v1beta1constants.ArchitectureAMD64}
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/core/v1beta1/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,8 @@ var _ = Describe("Defaults", func() {
It("should correctly set the default MachineImageVersion", func() {
SetDefaults_MachineImageVersion(obj)

Expect(len(obj.CRI)).To(Equal(1))
Expect(obj.CRI[0].Name).To(Equal(CRINameDocker))
Expect(obj.Architectures).To(Equal([]string{"amd64"}))
})
})
Expand Down
14 changes: 14 additions & 0 deletions pkg/apis/core/validation/cloudprofile.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ func validateMachineImages(machineImages []core.MachineImage, fldPath *field.Pat
func validateContainerRuntimesInterfaces(cris []core.CRI, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
duplicateCRI := sets.String{}
hasDocker := false

if len(cris) == 0 {
allErrs = append(allErrs, field.Required(fldPath, "must provide at least one supported container runtime"))
return allErrs
}

for i, cri := range cris {
criPath := fldPath.Index(i)
Expand All @@ -344,12 +350,20 @@ func validateContainerRuntimesInterfaces(cris []core.CRI, fldPath *field.Path) f
}
duplicateCRI.Insert(string(cri.Name))

if cri.Name == core.CRINameDocker {
hasDocker = true
}

if !availableWorkerCRINames.Has(string(cri.Name)) {
allErrs = append(allErrs, field.NotSupported(criPath, cri, availableWorkerCRINames.List()))
}
allErrs = append(allErrs, validateContainerRuntimes(cri.ContainerRuntimes, criPath.Child("containerRuntimes"))...)
}

if !hasDocker {
allErrs = append(allErrs, field.Invalid(fldPath, cris, "must provide docker as supported container runtime"))
}

return allErrs
}

Expand Down
58 changes: 58 additions & 0 deletions pkg/apis/core/validation/cloudprofile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirableVersion: core.ExpirableVersion{
Version: "1.2.3",
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand Down Expand Up @@ -411,6 +412,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "3.4.6",
Classification: &supportedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand All @@ -422,6 +424,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "3.4.5",
Classification: &previewClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand Down Expand Up @@ -461,6 +464,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "0.1.2",
Classification: &supportedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand All @@ -472,6 +476,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "a.b.c",
Classification: &supportedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand Down Expand Up @@ -500,12 +505,14 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirationDate: expirationDate,
Classification: &previewClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
{
ExpirableVersion: core.ExpirableVersion{
Version: "0.1.1",
Classification: &supportedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand All @@ -518,6 +525,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirationDate: expirationDate,
Classification: &supportedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand All @@ -538,6 +546,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "0.1.2",
Classification: &classification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand All @@ -560,18 +569,21 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirableVersion: core.ExpirableVersion{
Version: "0.1.2",
},
CRI: []core.CRI{{Name: "docker"}},
Architectures: []string{"amd64", "arm64"},
},
{
ExpirableVersion: core.ExpirableVersion{
Version: "0.1.3",
},
CRI: []core.CRI{{Name: "docker"}},
Architectures: []string{"amd64"},
},
{
ExpirableVersion: core.ExpirableVersion{
Version: "0.1.4",
},
CRI: []core.CRI{{Name: "docker"}},
Architectures: []string{"arm64"},
},
},
Expand All @@ -591,6 +603,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirableVersion: core.ExpirableVersion{
Version: "0.1.2",
},
CRI: []core.CRI{{Name: "docker"}},
Architectures: []string{"foo"},
},
},
Expand All @@ -605,6 +618,32 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
})
})

It("should forbid if no cri is present", func() {
cloudProfile.Spec.MachineImages[0].Versions[0].CRI = nil

errorList := ValidateCloudProfile(cloudProfile)

Expect(errorList).To(ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeRequired),
"Field": Equal("spec.machineImages[0].versions[0].cri"),
}))))
})

It("should forbid if docker container runtime interface not present", func() {
cloudProfile.Spec.MachineImages[0].Versions[0].CRI = []core.CRI{
{
Name: core.CRINameContainerD,
},
}

errorList := ValidateCloudProfile(cloudProfile)

Expect(errorList).To(ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{
"Type": Equal(field.ErrorTypeInvalid),
"Field": Equal("spec.machineImages[0].versions[0].cri"),
}))))
})

It("should forbid non-supported container runtime interface names", func() {
cloudProfile.Spec.MachineImages = []core.MachineImage{
{
Expand All @@ -618,6 +657,9 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
{
Name: "invalid-cri-name",
},
{
Name: "docker",
},
},
},
},
Expand All @@ -633,6 +675,9 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
{
Name: core.CRINameContainerD,
},
{
Name: "docker",
},
},
},
},
Expand All @@ -655,6 +700,9 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
{
Name: core.CRINameContainerD,
},
{
Name: "docker",
},
}

errorList := ValidateCloudProfile(cloudProfile)
Expand All @@ -678,6 +726,9 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
},
},
},
{
Name: "docker",
},
}

errorList := ValidateCloudProfile(cloudProfile)
Expand Down Expand Up @@ -898,6 +949,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "1.2.3",
Classification: &supportedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand Down Expand Up @@ -948,20 +1000,23 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
Version: "2135.6.2",
Classification: &deprecatedClassification,
},
CRI: []core.CRI{{Name: "docker"}},
},
{
ExpirableVersion: core.ExpirableVersion{
Version: "2135.6.1",
Classification: &deprecatedClassification,
ExpirationDate: dateInThePast,
},
CRI: []core.CRI{{Name: "docker"}},
},
{
ExpirableVersion: core.ExpirableVersion{
Version: "2135.6.0",
Classification: &deprecatedClassification,
ExpirationDate: dateInThePast,
},
CRI: []core.CRI{{Name: "docker"}},
},
}
cloudProfileNew.Spec.MachineImages[0].Versions = versions[0:1]
Expand Down Expand Up @@ -1028,6 +1083,7 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirableVersion: core.ExpirableVersion{
Version: "1.2.3",
},
CRI: []core.CRI{{Name: "docker"}},
},
},
},
Expand Down Expand Up @@ -1073,12 +1129,14 @@ var _ = Describe("CloudProfile Validation Tests ", func() {
ExpirableVersion: core.ExpirableVersion{
Version: "1.17.2",
},
CRI: []core.CRI{{Name: "docker"}},
},
{
ExpirableVersion: core.ExpirableVersion{
Version: "1.17.1",
ExpirationDate: dateInThePast,
},
CRI: []core.CRI{{Name: "docker"}},
},
}
cloudProfile.Spec.MachineImages[0].Versions = versions
Expand Down
34 changes: 0 additions & 34 deletions pkg/controllermanager/controller/cloudprofile/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,39 +91,5 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
}
}

// TODO voelzmo - this migration step ensures that all MachineImageVersions in the Cloud Profile contain `docker` in their list of supported Container Runtimes
// This can be removed in a couple of versions. Note that while this is still in here, it is impossible to add an image without `docker` support!
migrationHappened := migrateMachineImageVersionCRISupport(cloudProfile)

if migrationHappened {
log.Info("Migrated Machine Image Versions to explicitly contain `docker` as supported CRI")
if err := r.Client.Update(ctx, cloudProfile); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to update Cloud Profile spec for machine image CRI migration: %w", err)
}
}

return reconcile.Result{}, nil
}

func migrateMachineImageVersionCRISupport(cloudProfile *gardencorev1beta1.CloudProfile) bool {
var migrationHappened bool
for i, image := range cloudProfile.Spec.MachineImages {
for j, version := range image.Versions {
if containsDockerCRIName(version.CRI) {
continue
}
cloudProfile.Spec.MachineImages[i].Versions[j].CRI = append(version.CRI, gardencorev1beta1.CRI{Name: gardencorev1beta1.CRINameDocker})
migrationHappened = true
}
}
return migrationHappened
}

func containsDockerCRIName(cris []gardencorev1beta1.CRI) bool {
for _, cri := range cris {
if cri.Name == gardencorev1beta1.CRINameDocker {
return true
}
}
return false
}
Loading

0 comments on commit d144b5d

Please sign in to comment.