diff --git a/examples/customresourceinterpreter/webhook-configuration.yaml b/examples/customresourceinterpreter/webhook-configuration.yaml index 9883d6541..97a989cb5 100644 --- a/examples/customresourceinterpreter/webhook-configuration.yaml +++ b/examples/customresourceinterpreter/webhook-configuration.yaml @@ -6,7 +6,7 @@ metadata: webhooks: - name: workloads.example.com rules: - - operations: [ "InterpretReplica","ReviseReplica","Retain","AggregateStatus", "InterpretHealth", "InterpretStatus" ] + - operations: [ "InterpretReplica","ReviseReplica","Retain","AggregateStatus", "InterpretHealth", "InterpretStatus", "InterpretDependency" ] apiGroups: [ "workload.example.io" ] apiVersions: [ "v1alpha1" ] kinds: [ "Workload" ] diff --git a/examples/customresourceinterpreter/webhook/app/workloadwebhook.go b/examples/customresourceinterpreter/webhook/app/workloadwebhook.go index cc6958e75..635fdb17d 100644 --- a/examples/customresourceinterpreter/webhook/app/workloadwebhook.go +++ b/examples/customresourceinterpreter/webhook/app/workloadwebhook.go @@ -47,6 +47,8 @@ func (e *workloadInterpreter) Handle(ctx context.Context, req interpreter.Reques return e.responseWithExploreInterpretHealth(workload) case configv1alpha1.InterpreterOperationInterpretStatus: return e.responseWithExploreInterpretStatus(workload) + case configv1alpha1.InterpreterOperationInterpretDependency: + return e.responseWithExploreDependency(workload) default: return interpreter.Errored(http.StatusBadRequest, fmt.Errorf("wrong request operation type: %s", req.Operation)) } @@ -63,6 +65,13 @@ func (e *workloadInterpreter) responseWithExploreReplica(workload *workloadv1alp return res } +func (e *workloadInterpreter) responseWithExploreDependency(workload *workloadv1alpha1.Workload) interpreter.Response { + res := interpreter.Succeeded("") + res.Dependencies = []configv1alpha1.DependentObjectReference{{APIVersion: "v1", Kind: "ConfigMap", + Namespace: workload.Namespace, Name: workload.Spec.Template.Spec.Containers[0].EnvFrom[0].ConfigMapRef.Name}} + return res +} + func (e *workloadInterpreter) responseWithExploreReviseReplica(workload *workloadv1alpha1.Workload, req interpreter.Request) interpreter.Response { wantedWorkload := workload.DeepCopy() wantedWorkload.Spec.Replicas = req.DesiredReplicas diff --git a/pkg/webhook/configuration/validating.go b/pkg/webhook/configuration/validating.go index 997ed3e06..dd1f1ffa5 100644 --- a/pkg/webhook/configuration/validating.go +++ b/pkg/webhook/configuration/validating.go @@ -65,6 +65,7 @@ func (v *ValidatingAdmission) InjectDecoder(d *admission.Decoder) error { var supportedInterpreterOperation = sets.NewString( string(configv1alpha1.InterpreterOperationAll), string(configv1alpha1.InterpreterOperationInterpretReplica), + string(configv1alpha1.InterpreterOperationInterpretDependency), string(configv1alpha1.InterpreterOperationReviseReplica), string(configv1alpha1.InterpreterOperationRetain), string(configv1alpha1.InterpreterOperationAggregateStatus), diff --git a/test/e2e/resourceinterpreter_test.go b/test/e2e/resourceinterpreter_test.go index 18a2e5405..0e7dc1083 100644 --- a/test/e2e/resourceinterpreter_test.go +++ b/test/e2e/resourceinterpreter_test.go @@ -10,6 +10,7 @@ import ( "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" @@ -271,6 +272,50 @@ var _ = ginkgo.Describe("Resource interpreter webhook testing", func() { }) }) }) + + ginkgo.Context("InterpreterOperation InterpretDependency testing", func() { + var configMapNamespace, configMapName string + + ginkgo.BeforeEach(func() { + configMapNamespace = testNamespace + configMapName = configMapNamePrefix + rand.String(RandomStrLength) + + workload.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{{ + ConfigMapRef: &corev1.ConfigMapEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: configMapName}, + }}} + // configmaps should be propagated automatically. + policy.Spec.PropagateDeps = true + + cm := testhelper.NewConfigMap(configMapNamespace, configMapName, map[string]string{"RUN_ENV": "test"}) + + framework.CreateConfigMap(kubeClient, cm) + ginkgo.DeferCleanup(func() { + framework.RemoveConfigMap(kubeClient, configMapNamespace, configMapName) + }) + }) + + ginkgo.It("InterpretDependency testing", func() { + ginkgo.By("check if workload's dependency is interpreted", func() { + clusterNames := framework.ClusterNames() + gomega.Eventually(func(g gomega.Gomega) (int, error) { + var configmapNum int + for _, clusterName := range clusterNames { + clusterClient := framework.GetClusterClient(clusterName) + gomega.Expect(clusterClient).ShouldNot(gomega.BeNil()) + if _, err := clusterClient.CoreV1().ConfigMaps(configMapNamespace).Get(context.TODO(), configMapName, metav1.GetOptions{}); err != nil { + if apierrors.IsNotFound(err) { + continue + } + g.Expect(err).NotTo(gomega.HaveOccurred()) + } + configmapNum++ + } + return configmapNum, nil + }, pollTimeout, pollInterval).Should(gomega.Equal(len(clusterNames))) + }) + }) + }) }) var _ = framework.SerialDescribe("Resource interpreter customization testing", func() { diff --git a/test/helper/resource.go b/test/helper/resource.go index e8a4ceeb8..1235c55aa 100644 --- a/test/helper/resource.go +++ b/test/helper/resource.go @@ -506,7 +506,7 @@ func NewClusterWithResource(name string, allocatable, allocating, allocated core } // NewWorkload will build a workload object. -func NewWorkload(namespace string, name string) *workloadv1alpha1.Workload { +func NewWorkload(namespace, name string) *workloadv1alpha1.Workload { podLabels := map[string]string{"app": "nginx"} return &workloadv1alpha1.Workload{