From e732dfd16dddc226aed498fc84aa5a33d84796ca Mon Sep 17 00:00:00 2001 From: Peter Matseykanets Date: Thu, 1 Aug 2024 15:38:22 -0400 Subject: [PATCH] [v0.5] Set FailurePolicy to Ignore for settings validator (#446) * Set FailurePolicy to Ignore for settings validator * Add unit and integration tests Ref: https://github.com/rancher/rancher/issues/45841 --- .../v3/setting/validator.go | 6 +- .../v3/setting/validator_test.go | 11 +++ tests/integration/failPolicy_test.go | 68 ++++++++++++++----- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/pkg/resources/management.cattle.io/v3/setting/validator.go b/pkg/resources/management.cattle.io/v3/setting/validator.go index 6b336fd..c110bb0 100644 --- a/pkg/resources/management.cattle.io/v3/setting/validator.go +++ b/pkg/resources/management.cattle.io/v3/setting/validator.go @@ -57,9 +57,9 @@ func (v *Validator) Operations() []admissionregistrationv1.OperationType { // ValidatingWebhook returns the ValidatingWebhook. func (v *Validator) ValidatingWebhook(clientConfig admissionregistrationv1.WebhookClientConfig) []admissionregistrationv1.ValidatingWebhook { - return []admissionregistrationv1.ValidatingWebhook{ - *admission.NewDefaultValidatingWebhook(v, clientConfig, admissionregistrationv1.ClusterScope, v.Operations()), - } + valWebhook := admission.NewDefaultValidatingWebhook(v, clientConfig, admissionregistrationv1.ClusterScope, v.Operations()) + valWebhook.FailurePolicy = admission.Ptr(admissionregistrationv1.Ignore) + return []admissionregistrationv1.ValidatingWebhook{*valWebhook} } // Admitters returns the admitter objects. diff --git a/pkg/resources/management.cattle.io/v3/setting/validator_test.go b/pkg/resources/management.cattle.io/v3/setting/validator_test.go index efed341..01f7ea8 100644 --- a/pkg/resources/management.cattle.io/v3/setting/validator_test.go +++ b/pkg/resources/management.cattle.io/v3/setting/validator_test.go @@ -20,6 +20,7 @@ import ( "github.com/rancher/webhook/pkg/admission" "github.com/rancher/webhook/pkg/resources/management.cattle.io/v3/setting" + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" ) type SettingSuite struct { @@ -164,6 +165,16 @@ func (s *SettingSuite) validate(op v1.Operation) { } } +func (s *SettingSuite) TestValidatingWebhookFailurePolicy() { + t := s.T() + validator := setting.NewValidator(nil) + + webhook := validator.ValidatingWebhook(admissionregistrationv1.WebhookClientConfig{}) + require.Len(t, webhook, 1) + ignorePolicy := admissionregistrationv1.Ignore + require.Equal(t, &ignorePolicy, webhook[0].FailurePolicy) +} + func (s *SettingSuite) setup() admission.Admitter { validator := setting.NewValidator(nil) s.Len(validator.Admitters(), 1, "expected 1 admitter") diff --git a/tests/integration/failPolicy_test.go b/tests/integration/failPolicy_test.go index eadc6b9..7de47d3 100644 --- a/tests/integration/failPolicy_test.go +++ b/tests/integration/failPolicy_test.go @@ -8,6 +8,7 @@ import ( "github.com/rancher/lasso/pkg/client" v3 "github.com/rancher/rancher/pkg/apis/cluster.cattle.io/v3" + mgmtv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" provisioningv1 "github.com/rancher/rancher/pkg/apis/provisioning.cattle.io/v1" "github.com/rancher/wrangler/v3/pkg/gvk" "github.com/rancher/wrangler/v3/pkg/kubeconfig" @@ -43,21 +44,11 @@ func (m *FailurePolicySuite) SetupSuite() { schemes.Register(provisioningv1.AddToScheme) schemes.Register(corev1.AddToScheme) } +func (m *FailurePolicySuite) SetupTest() { + m.checkWebhookIsDown() +} -func (m *FailurePolicySuite) TestNamespaceFail() { - const testNamespace = "test-namespace" - validCreateObj := &corev1.Namespace{ - ObjectMeta: v1.ObjectMeta{ - Name: testNamespace, - }, - } - - objGVK, err := gvk.Get(validCreateObj) - m.Require().NoError(err, "failed to get GVK") - - client, err := m.clientFactory.ForKind(objGVK) - m.Require().NoError(err, "Failed to create client") - +func (m *FailurePolicySuite) checkWebhookIsDown() { podGVK := schema.GroupVersionKind{ Group: "", Version: "v1", @@ -72,14 +63,29 @@ func (m *FailurePolicySuite) TestNamespaceFail() { pods := corev1.PodList{} podClient.List(context.Background(), "cattle-system", &pods, listOpts) m.Require().Equal(0, len(pods.Items), "Test can not run while rancher-webhook pods are still running") +} + +func (m *FailurePolicySuite) TestNamespaceFail() { + const name = "test-namespace" + validCreateObj := &corev1.Namespace{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + }, + } + + objGVK, err := gvk.Get(validCreateObj) + m.Require().NoError(err, "failed to get GVK") + + client, err := m.clientFactory.ForKind(objGVK) + m.Require().NoError(err, "Failed to create client") ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) defer cancel() err = client.Create(ctx, "", validCreateObj, nil, v1.CreateOptions{}) m.Require().True(errors.IsInternalError(err), "Webhook should fail with service unavailable when the webhook is down instead we received :%v", err) - // attempt to clean up namespace if the create went through - defer client.Delete(ctx, "", testNamespace, v1.DeleteOptions{}) + // Attempt to clean up the namespace if the create went through. + defer client.Delete(ctx, "", name, v1.DeleteOptions{}) validCreateObj.Name = "default" err = client.Update(ctx, "", validCreateObj, nil, v1.UpdateOptions{}) @@ -92,3 +98,33 @@ func (m *FailurePolicySuite) TestNamespaceFail() { err = client.Update(ctx, "", validCreateObj, nil, v1.UpdateOptions{}) m.Require().True(errors.IsInternalError(err), "Webhook should fail to update kube-system namespace with service unavailable when the webhook is down instead we received :%v", err) } + +func (m *FailurePolicySuite) TestSettingSucceed() { + const name = "new-setting" + createObj := &mgmtv3.Setting{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + }, + } + objGVK, err := gvk.Get(createObj) + m.Require().NoError(err, "failed to get GVK") + + client, err := m.clientFactory.ForKind(objGVK) + m.Require().NoError(err, "Failed to create client") + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) + defer cancel() + err = client.Create(ctx, "", createObj, nil, v1.CreateOptions{}) + m.Require().NoError(err) + + // Attempt to clean up the setting if the create went through. + defer client.Delete(ctx, "", name, v1.DeleteOptions{}) + + updateObj := &mgmtv3.Setting{} + err = client.Get(ctx, "", name, updateObj, v1.GetOptions{}) + m.Require().NoError(err) + updateObj.Value = "new-value" + + err = client.Update(ctx, "", updateObj, updateObj, v1.UpdateOptions{}) + m.Require().NoError(err) +}