Skip to content

Commit

Permalink
Adapt shoot validations to also work with NamespacedCloudProfiles and…
Browse files Browse the repository at this point in the history
… CloudProfiles from reference
  • Loading branch information
LucaBernstein committed Jul 12, 2024
1 parent dcbbaf0 commit 508e976
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 15 deletions.
17 changes: 12 additions & 5 deletions pkg/admission/validator/shoot.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/gardener/gardener/pkg/apis/core"
gardencorehelper "github.com/gardener/gardener/pkg/apis/core/helper"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/utils/gardener"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/validation/field"
Expand Down Expand Up @@ -126,7 +127,6 @@ func (s *shoot) validateShootUpdate(ctx context.Context, oldShoot, shoot *core.S
var (
fldPath = field.NewPath("spec", "provider")
infraConfigFldPath = fldPath.Child("infrastructureConfig")
cloudProfile = &gardencorev1beta1.CloudProfile{}
)

// InfrastructureConfig update
Expand All @@ -139,9 +139,13 @@ func (s *shoot) validateShootUpdate(ctx context.Context, oldShoot, shoot *core.S
return err
}

if err := s.client.Get(ctx, client.ObjectKey{Name: shoot.Spec.CloudProfileName}, cloudProfile); err != nil {
cloudProfile, err := gardener.GetCloudProfile(ctx, s.client, gardener.BuildCloudProfileReference(shoot.Spec.CloudProfileName, shoot.Spec.CloudProfile), shoot.Namespace)
if err != nil {
return err
}
if cloudProfile == nil {
return fmt.Errorf("cloudprofile could not be found")
}

if oldShoot.Spec.Provider.InfrastructureConfig == nil {
return field.InternalError(infraConfigFldPath, errors.New("InfrastructureConfig is not available on old shoot"))
Expand Down Expand Up @@ -180,8 +184,7 @@ func (s *shoot) validateShootUpdate(ctx context.Context, oldShoot, shoot *core.S

func (s *shoot) validateShootCreation(ctx context.Context, shoot *core.Shoot) error {
var (
fldPath = field.NewPath("spec", "provider")
cloudProfile = &gardencorev1beta1.CloudProfile{}
fldPath = field.NewPath("spec", "provider")
)
if shoot.Spec.Provider.InfrastructureConfig == nil {
return field.Required(fldPath.Child("infrastructureConfig"), "InfrastructureConfig must be set for AWS shoots")
Expand All @@ -192,9 +195,13 @@ func (s *shoot) validateShootCreation(ctx context.Context, shoot *core.Shoot) er
return err
}

if err := s.client.Get(ctx, client.ObjectKey{Name: shoot.Spec.CloudProfileName}, cloudProfile); err != nil {
cloudProfile, err := gardener.GetCloudProfile(ctx, s.client, gardener.BuildCloudProfileReference(shoot.Spec.CloudProfileName, shoot.Spec.CloudProfile), shoot.Namespace)
if err != nil {
return err
}
if cloudProfile == nil {
return fmt.Errorf("cloudprofile could not be found")
}

awsCloudProfile, err := decodeCloudProfileConfig(s.decoder, cloudProfile.Spec.ProviderConfig)
if err != nil {
Expand Down
61 changes: 51 additions & 10 deletions pkg/admission/validator/shoot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ var _ = Describe("Shoot validator", func() {
var (
shootValidator extensionswebhook.Validator

ctrl *gomock.Controller
mgr *mockmanager.MockManager
c *mockclient.MockClient
cloudProfile *gardencorev1beta1.CloudProfile
shoot *core.Shoot

ctx = context.TODO()
cloudProfileKey = client.ObjectKey{Name: "aws"}
gp2type = string(apisaws.VolumeTypeGP2)
ctrl *gomock.Controller
mgr *mockmanager.MockManager
c *mockclient.MockClient
cloudProfile *gardencorev1beta1.CloudProfile
namespacedCloudProfile *gardencorev1beta1.NamespacedCloudProfile
shoot *core.Shoot

ctx = context.TODO()
cloudProfileKey = client.ObjectKey{Name: "aws"}
namespacedCloudProfileKey = client.ObjectKey{Name: "aws-nscpfl", Namespace: namespace}
gp2type = string(apisaws.VolumeTypeGP2)

regionName = "us-west"
imageName = "Foo"
Expand Down Expand Up @@ -114,13 +116,28 @@ var _ = Describe("Shoot validator", func() {
},
}

namespacedCloudProfile = &gardencorev1beta1.NamespacedCloudProfile{
ObjectMeta: metav1.ObjectMeta{
Name: "aws-nscpfl",
},
Spec: gardencorev1beta1.NamespacedCloudProfileSpec{
Parent: gardencorev1beta1.CloudProfileReference{
Kind: "CloudProfile",
Name: "aws",
},
},
Status: gardencorev1beta1.NamespacedCloudProfileStatus{
CloudProfileSpec: cloudProfile.Spec, // TODO(LucaBernstein): Okay to mock like this?
},
}

shoot = &core.Shoot{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: namespace,
},
Spec: core.ShootSpec{
CloudProfileName: cloudProfile.Name,
CloudProfileName: &cloudProfile.Name,
Provider: core.Provider{
InfrastructureConfig: &runtime.RawExtension{
Raw: encode(&apisawsv1alpha1.InfrastructureConfig{
Expand Down Expand Up @@ -364,6 +381,30 @@ var _ = Describe("Shoot validator", func() {
err := shootValidator.Validate(ctx, shoot, nil)
Expect(err).NotTo(HaveOccurred())
})

It("should also work for CloudProfile reference instead of cloudProfileName in Shoot", func() {
shoot.Spec.CloudProfileName = nil
shoot.Spec.CloudProfile = &core.CloudProfileReference{
Kind: "CloudProfile",
Name: "aws",
}
c.EXPECT().Get(ctx, cloudProfileKey, &gardencorev1beta1.CloudProfile{}).SetArg(2, *cloudProfile)

err := shootValidator.Validate(ctx, shoot, nil)
Expect(err).NotTo(HaveOccurred())
})

It("should also work for NamespacedCloudProfile referenced from Shoot", func() {
shoot.Spec.CloudProfileName = nil
shoot.Spec.CloudProfile = &core.CloudProfileReference{
Kind: "NamespacedCloudProfile",
Name: "aws-nscpfl",
}
c.EXPECT().Get(ctx, namespacedCloudProfileKey, &gardencorev1beta1.NamespacedCloudProfile{}).SetArg(2, *namespacedCloudProfile)

err := shootValidator.Validate(ctx, shoot, nil)
Expect(err).NotTo(HaveOccurred())
})
})

Context("Workerless Shoot", func() {
Expand Down

0 comments on commit 508e976

Please sign in to comment.