diff --git a/__debug_bin2514188118 b/__debug_bin2514188118 new file mode 100755 index 00000000..bface0c6 Binary files /dev/null and b/__debug_bin2514188118 differ diff --git a/controllers/configurationpolicy_controller.go b/controllers/configurationpolicy_controller.go index 23f626ee..2de015a7 100644 --- a/controllers/configurationpolicy_controller.go +++ b/controllers/configurationpolicy_controller.go @@ -1507,6 +1507,7 @@ func (r *ConfigurationPolicyReconciler) handleObjects( } var existingObj *unstructured.Unstructured + var allResourceNames []string if objDetails.name != "" { // named object, so checking just for the existence of the specific object // If the object couldn't be retrieved, this will be handled later on. @@ -1521,7 +1522,7 @@ func (r *ConfigurationPolicyReconciler) handleObjects( log.V(1).Info( "The object template does not specify a name. Will search for matching objects in the namespace.", ) - objNames = getNamesOfKind( + objNames, allResourceNames = getNamesOfKind( desiredObj, mapping.Resource, objDetails.isNamespaced, @@ -1556,6 +1557,8 @@ func (r *ConfigurationPolicyReconciler) handleObjects( objShouldExist := !strings.EqualFold(string(objectT.ComplianceType), string(policyv1.MustNotHave)) + shouldAddCondensedRelatedObj := false + if len(objNames) == 1 { name := objNames[0] singObj := singleObject{ @@ -1598,6 +1601,15 @@ func (r *ConfigurationPolicyReconciler) handleObjects( } else { resultEvent.compliant = false resultEvent.reason = reasonWantFoundDNE + // Length of objNames = 0, complianceType == musthave or mustonlyhave + // Find Noncompliant resources to add to the status.relatedObjects for debugging purpose + shouldAddCondensedRelatedObj = true + if objDetails.kind != "" && objDetails.name == "" { + // Change reason to Resource found but does not match + if len(allResourceNames) > 0 { + resultEvent.reason = reasonWantFoundNoMatch + } + } } } else { if exists { @@ -1606,21 +1618,36 @@ func (r *ConfigurationPolicyReconciler) handleObjects( } else { resultEvent.compliant = true resultEvent.reason = reasonWantNotFoundDNE + // Compliant, complianceType == mustnothave + // Find resources in the same namespace to add to the status.relatedObjects for debugging purpose + shouldAddCondensedRelatedObj = true } } result = objectTmplEvalResult{objectNames: objNames, events: []objectTmplEvalEvent{resultEvent}} - relatedObjects = addRelatedObjects( - resultEvent.compliant, - mapping.Resource, - objDetails.kind, - namespace, - objDetails.isNamespaced, - objNames, - resultEvent.reason, - nil, - ) + if shouldAddCondensedRelatedObj { + // relatedObjs name is * + relatedObjects = addCondensedRelatedObjs( + mapping.Resource, + resultEvent.compliant, + objDetails.kind, + namespace, + objDetails.isNamespaced, + resultEvent.reason, + ) + } else { + relatedObjects = addRelatedObjects( + resultEvent.compliant, + mapping.Resource, + objDetails.kind, + namespace, + objDetails.isNamespaced, + objNames, + resultEvent.reason, + nil, + ) + } } return relatedObjects, result @@ -1962,6 +1989,7 @@ func buildNameList( // getNamesOfKind returns an array with names of all of the resources found // matching the GVK specified. +// allResourceList includes names that are under the same namespace and kind. func getNamesOfKind( desiredObj unstructured.Unstructured, rsrc schema.GroupVersionResource, @@ -1970,30 +1998,31 @@ func getNamesOfKind( dclient dynamic.Interface, complianceType string, zeroValueEqualsNil bool, -) (kindNameList []string) { +) (kindNameList []string, allResourceList []string) { + var resList *unstructured.UnstructuredList + var err error + if namespaced { res := dclient.Resource(rsrc).Namespace(ns) - resList, err := res.List(context.TODO(), metav1.ListOptions{}) - if err != nil { - log.Error(err, "Could not list resources", "rsrc", rsrc, "namespaced", namespaced) - - return kindNameList - } + resList, err = res.List(context.TODO(), metav1.ListOptions{}) + } else { + res := dclient.Resource(rsrc) - return buildNameList(desiredObj, complianceType, resList, zeroValueEqualsNil) + resList, err = res.List(context.TODO(), metav1.ListOptions{}) } - res := dclient.Resource(rsrc) - - resList, err := res.List(context.TODO(), metav1.ListOptions{}) if err != nil { log.Error(err, "Could not list resources", "rsrc", rsrc, "namespaced", namespaced) - return kindNameList + return kindNameList, allResourceList + } + + for _, res := range resList.Items { + allResourceList = append(allResourceList, res.GetName()) } - return buildNameList(desiredObj, complianceType, resList, zeroValueEqualsNil) + return buildNameList(desiredObj, complianceType, resList, zeroValueEqualsNil), allResourceList } // enforceByCreatingOrDeleting can handle the situation where a musthave or mustonlyhave object is diff --git a/controllers/configurationpolicy_utils.go b/controllers/configurationpolicy_utils.go index 4522120a..0df60d2a 100644 --- a/controllers/configurationpolicy_utils.go +++ b/controllers/configurationpolicy_utils.go @@ -65,6 +65,45 @@ func addRelatedObjects( return relatedObjects } +// addCondensedRelatedObjs does not include all of relatedObjs. +// The Name field is "*". The list of objects will be presented on the console. +func addCondensedRelatedObjs( + rsrc schema.GroupVersionResource, + compliant bool, + kind string, + namespace string, + namespaced bool, + reason string, +) (relatedObjects []policyv1.RelatedObject) { + metadata := policyv1.ObjectMetadata{Name: "*"} + + if namespaced { + metadata.Namespace = namespace + } else { + metadata.Namespace = "" + } + + // Initialize the related object from the object handling + relatedObject := policyv1.RelatedObject{ + Reason: reason, + Object: policyv1.ObjectResource{ + APIVersion: rsrc.GroupVersion().String(), + Kind: kind, + Metadata: metadata, + }, + } + + if compliant { + relatedObject.Compliant = string(policyv1.Compliant) + } else { + relatedObject.Compliant = string(policyv1.NonCompliant) + } + + relatedObjects = append(relatedObjects, relatedObject) + + return relatedObjects +} + // unmarshalFromJSON unmarshals raw JSON data into an object func unmarshalFromJSON(rawData []byte) (unstructured.Unstructured, error) { var unstruct unstructured.Unstructured diff --git a/test/e2e/case14_selection_test.go b/test/e2e/case14_selection_test.go index 51be0bd9..9fa976b3 100644 --- a/test/e2e/case14_selection_test.go +++ b/test/e2e/case14_selection_test.go @@ -164,11 +164,14 @@ var _ = Describe("Test policy compliance with namespace selection", Ordered, fun // If an object name is specified in the policy, related objects match those in the template. // If an object name is not specified in the policy, related objects match those in the // cluster as this is not enforceable. - if policy.hasObjName { - Expect(checkRelated(plc)).Should(HaveLen(len(testNamespaces) + 1)) - } else { - Expect(checkRelated(plc)).Should(HaveLen(len(testNamespaces))) - } + // When hasObjName = false + // compliant: NonCompliant + // metadata: + // name: '*' + // namespace: range3 + // reason: Resource not found but should exist + // is attached for range3. + Expect(checkRelated(plc)).Should(HaveLen(len(testNamespaces) + 1)) } }) diff --git a/test/e2e/case37_no_name_test.go b/test/e2e/case37_no_name_test.go new file mode 100644 index 00000000..45d6fb72 --- /dev/null +++ b/test/e2e/case37_no_name_test.go @@ -0,0 +1,396 @@ +package e2e + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + "open-cluster-management.io/config-policy-controller/test/utils" +) + +var _ = Describe("Test a namespace-scope policy that is missing name", Ordered, func() { + const ( + case37GoodIngressPath string = "../resources/case37_no_name/case37_good_ingress.yaml" + case37BadIngressPath string = "../resources/case37_no_name/case37_bad_ingresses.yaml" + case37PolicyNSPath string = "../resources/case37_no_name/case37_no_name_policy.yaml" + case37PolicyNSName string = "case37-test-policy-1" + case37PolicyNotHavePath string = "../resources/case37_no_name/case37_no_name_policy_nothave.yaml" + case37PolicyMustnothaveName string = "case37-test-policy-mustnothave" + ) + Describe("Test a musthave", Ordered, func() { + BeforeAll(func() { + By("Creating a policy on managed") + utils.Kubectl("apply", "-f", case37PolicyNSPath, "-n", testNamespace) + plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyNSName, testNamespace, true, defaultTimeoutSeconds) + Expect(plc).ShouldNot(BeNil()) + }) + It("should have 1 NonCompliant relatedObject under the policy's status", func() { + By("Apply bad ingresses") + utils.Kubectl("apply", "-f", case37BadIngressPath) + + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyNSName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant")) + + var relatedObjects []interface{} + + By("relatedObjects should exist") + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyNSName, testNamespace, true, defaultTimeoutSeconds) + + var err error + + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(relatedObjects).ShouldNot(BeNil()) + + return relatedObjects + // Getting relatedObjects takes longer time + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + By("Check the kind of related object") + kind := relatedObjects[0].(map[string]interface{})["object"].(map[string]interface{})["kind"].(string) + Expect(kind).Should(Equal("Ingress")) + + By("Check the reason of related object") + relatedObjectsOne := relatedObjects[0].(map[string]interface{}) + Expect(relatedObjectsOne["reason"].(string)).Should(Equal("Resource found but does not match")) + + By("Check the name of related object is *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).Should(Equal("*")) + }) + It("should have 1 Compliant relatedObject under the policy's status", func() { + By("Apply good ingress") + utils.Kubectl("apply", "-f", case37GoodIngressPath) + + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyNSName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("Compliant")) + + var relatedObjects []interface{} + + By("relatedObjects should exist") + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyNSName, testNamespace, true, defaultTimeoutSeconds) + + var err error + + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(relatedObjects).ShouldNot(BeNil()) + + return relatedObjects + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + // NonCompliant relatedObjects Should be deleted and only the Compliant relatedObject remain + By("Check the kind of related object") + kind := relatedObjects[0].(map[string]interface{})["object"].(map[string]interface{})["kind"].(string) + Expect(kind).Should(Equal("Ingress")) + + By("Check the reason of related objects") + reason := relatedObjects[0].(map[string]interface{})["reason"].(string) + Expect(reason).Should(Equal("Resource found as expected")) + + By("Check the name of related object is not *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).ShouldNot(Equal("*")) + }) + AfterAll(func() { + utils.Kubectl("delete", "-f", case37PolicyNSPath, "-n", testNamespace, "--ignore-not-found") + utils.Kubectl("delete", "-f", case37GoodIngressPath, "--ignore-not-found") + utils.Kubectl("delete", "-f", case37BadIngressPath, "--ignore-not-found") + utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyNSName, testNamespace, false, defaultTimeoutSeconds) + }) + }) + Describe("Test a mustnothave", Ordered, func() { + BeforeAll(func() { + By("Creating a policy on managed") + utils.Kubectl("apply", "-f", case37PolicyNotHavePath, "-n", testNamespace) + plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + Expect(plc).ShouldNot(BeNil()) + }) + It("should have 1 Compliant relatedObject under the policy's status", func() { + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("Compliant")) + + By("relatedObjects should exist") + var relatedObjects []interface{} + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + var err error + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + g.Expect(err).ShouldNot(HaveOccurred()) + + return relatedObjects + // Getting relatedObjects takes longer time + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + By("Check the reasons of related object") + relatedObjectsOne := relatedObjects[0].(map[string]interface{}) + Expect(relatedObjectsOne["reason"].(string)).Should(Equal("Resource not found as expected")) + + By("Check the name of related object is *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).Should(Equal("*")) + }) + It("should have 1 Compliant relatedObject under the policy's status", func() { + By("Apply a ingress that is not related to policy") + utils.Kubectl("apply", "-f", case37BadIngressPath) + + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("Compliant")) + + var relatedObjects []interface{} + + By("relatedObjects should exist") + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + var err error + + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(relatedObjects).ShouldNot(BeNil()) + + return relatedObjects + // Getting relatedObjects takes longer time + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + By("Check the kind of related objects") + kind := relatedObjects[0].(map[string]interface{})["object"].(map[string]interface{})["kind"].(string) + Expect(kind).Should(Equal("Ingress")) + + By("Check the reasons of related objects") + relatedObjectsOne := relatedObjects[0].(map[string]interface{}) + Expect(relatedObjectsOne["reason"].(string)).Should(Equal("Resource not found as expected")) + + By("Check the name of related object is *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).Should(Equal("*")) + }) + It("should have 1 NonCompliant relatedObject under the policy's status", func() { + By("Apply a ingress") + utils.Kubectl("apply", "-f", case37GoodIngressPath) + + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant")) + + var relatedObjects []interface{} + + By("relatedObjects should exist") + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + var err error + + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(relatedObjects).ShouldNot(BeNil()) + + return relatedObjects + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + // NonCompliant relatedObjects Should be deleted and only the Compliant relatedObject remain + By("Check the kind of related objects") + kind := relatedObjects[0].(map[string]interface{})["object"].(map[string]interface{})["kind"].(string) + Expect(kind).Should(Equal("Ingress")) + + By("Check the reason of related object") + reason := relatedObjects[0].(map[string]interface{})["reason"].(string) + Expect(reason).Should(Equal("Resource found but should not exist")) + + By("Check the name of related object is not *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).ShouldNot(Equal("*")) + }) + AfterAll(func() { + utils.Kubectl("delete", "-f", case37PolicyNotHavePath, "-n", testNamespace, "--ignore-not-found") + utils.Kubectl("delete", "-f", case37GoodIngressPath, "--ignore-not-found") + utils.Kubectl("delete", "-f", case37BadIngressPath, "--ignore-not-found") + utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyMustnothaveName, testNamespace, false, defaultTimeoutSeconds) + }) + }) +}) + +var _ = Describe("Test a cluster-scope policy that is missing name ", Ordered, func() { + const ( + case37BadIngressClassPath string = "../resources/case37_no_name/case37_bad_ingressclass.yaml" + case37PolicyCSPath string = "../resources/case37_no_name/case37_no_name_clusterscope_policy.yaml" + case37PolicyCSName string = "case37-test-policy-clusterscope" + case37PolicyCSMustnothavePath string = "../resources/case37_no_name/" + + "case37_no_name_clusterscope_policy_nothave.yaml" + case37PolicyCSMustnothaveName string = "case37-test-policy-clusterscope-mustnothave" + ) + + Describe("Test a musthave", func() { + BeforeEach(func() { + By("Creating a policy on managed") + utils.Kubectl("apply", "-f", case37PolicyCSPath, "-n", testNamespace) + plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSName, testNamespace, true, defaultTimeoutSeconds) + Expect(plc).ShouldNot(BeNil()) + + By("Creating a IngressClass") + utils.Kubectl("apply", "-f", case37BadIngressClassPath) + }) + It("should have 1 NonCompliant relatedObject under the policy's status", func() { + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant")) + + var relatedObjects []interface{} + + By("relatedObjects should exist") + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSName, testNamespace, true, defaultTimeoutSeconds) + + var err error + + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(relatedObjects).ShouldNot(BeNil()) + + return relatedObjects + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + By("Check the kind of related object") + kind := relatedObjects[0].(map[string]interface{})["object"].(map[string]interface{})["kind"].(string) + Expect(kind).Should(Equal("IngressClass")) + + By("Check the reason of related object") + reason := relatedObjects[0].(map[string]interface{})["reason"].(string) + Expect(reason).Should(Equal("Resource found but does not match")) + + By("Check the name of relatedObject is *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).Should(Equal("*")) + }) + AfterEach(func() { + utils.Kubectl("delete", "-f", case37PolicyCSPath, "-n", testNamespace, "--ignore-not-found") + utils.Kubectl("delete", "-f", case37BadIngressClassPath, "--ignore-not-found") + utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSName, testNamespace, false, defaultTimeoutSeconds) + }) + }) + Describe("Test a mustnothave", func() { + BeforeEach(func() { + By("Creating a policy on managed") + utils.Kubectl("apply", "-f", case37PolicyCSMustnothavePath, "-n", testNamespace) + plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + Expect(plc).ShouldNot(BeNil()) + + By("Creating a IngressClass that is not related to the policy") + utils.Kubectl("apply", "-f", case37BadIngressClassPath) + }) + It("should have 1 Compliant relatedObject under the policy's status", func() { + var managedPlc *unstructured.Unstructured + + Eventually(func() interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + return utils.GetComplianceState(managedPlc) + }, defaultTimeoutSeconds, 1).Should(Equal("Compliant")) + + var relatedObjects []interface{} + + By("relatedObjects should exist") + Eventually(func(g Gomega) interface{} { + managedPlc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSMustnothaveName, testNamespace, true, defaultTimeoutSeconds) + + var err error + + relatedObjects, _, err = unstructured.NestedSlice(managedPlc.Object, "status", "relatedObjects") + + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(relatedObjects).ShouldNot(BeNil()) + + return relatedObjects + }, defaultTimeoutSeconds*2, 1).Should(HaveLen(1)) + + By("Check the kind of relatedObject") + kind := relatedObjects[0].(map[string]interface{})["object"].(map[string]interface{})["kind"].(string) + Expect(kind).Should(Equal("IngressClass")) + + By("Check the reason of relatedObject") + reason := relatedObjects[0].(map[string]interface{})["reason"].(string) + Expect(reason).Should(Equal("Resource not found as expected")) + + By("Check the name of relatedObject is *") + name, _, err := unstructured.NestedString(relatedObjects[0].(map[string]interface{}), + "object", "metadata", "name") + Expect(err).ShouldNot(HaveOccurred()) + Expect(name).Should(Equal("*")) + }) + AfterEach(func() { + utils.Kubectl("delete", "-f", case37PolicyCSMustnothavePath, "-n", testNamespace, "--ignore-not-found") + utils.Kubectl("delete", "-f", case37BadIngressClassPath, "--ignore-not-found") + utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy, + case37PolicyCSMustnothaveName, testNamespace, false, defaultTimeoutSeconds) + }) + }) +}) diff --git a/test/resources/case37_no_name/case37_bad_ingressclass.yaml b/test/resources/case37_no_name/case37_bad_ingressclass.yaml new file mode 100644 index 00000000..81f97316 --- /dev/null +++ b/test/resources/case37_no_name/case37_bad_ingressclass.yaml @@ -0,0 +1,6 @@ +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: case37-ingress-class +spec: + controller: alien.giant/web \ No newline at end of file diff --git a/test/resources/case37_no_name/case37_bad_ingresses.yaml b/test/resources/case37_no_name/case37_bad_ingresses.yaml new file mode 100644 index 00000000..4d23eb21 --- /dev/null +++ b/test/resources/case37_no_name/case37_bad_ingresses.yaml @@ -0,0 +1,33 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: case37-wrong-1-ingress +spec: + ingressClassName: wrong-name + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: case37-wrong-2-ingress +spec: + ingressClassName: wrong-name + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 801 \ No newline at end of file diff --git a/test/resources/case37_no_name/case37_good_ingress.yaml b/test/resources/case37_no_name/case37_good_ingress.yaml new file mode 100644 index 00000000..ce693ce4 --- /dev/null +++ b/test/resources/case37_no_name/case37_good_ingress.yaml @@ -0,0 +1,16 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: good-ingress +spec: + ingressClassName: test + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 \ No newline at end of file diff --git a/test/resources/case37_no_name/case37_no_name_clusterscope_policy.yaml b/test/resources/case37_no_name/case37_no_name_clusterscope_policy.yaml new file mode 100644 index 00000000..f08ed583 --- /dev/null +++ b/test/resources/case37_no_name/case37_no_name_clusterscope_policy.yaml @@ -0,0 +1,13 @@ +apiVersion: policy.open-cluster-management.io/v1 +kind: ConfigurationPolicy +metadata: + name: case37-test-policy-clusterscope +spec: + remediationAction: inform + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: networking.k8s.io/v1 + kind: IngressClass + spec: + controller: ingress.k8s.aws/alb diff --git a/test/resources/case37_no_name/case37_no_name_clusterscope_policy_nothave.yaml b/test/resources/case37_no_name/case37_no_name_clusterscope_policy_nothave.yaml new file mode 100644 index 00000000..715bea63 --- /dev/null +++ b/test/resources/case37_no_name/case37_no_name_clusterscope_policy_nothave.yaml @@ -0,0 +1,13 @@ +apiVersion: policy.open-cluster-management.io/v1 +kind: ConfigurationPolicy +metadata: + name: case37-test-policy-clusterscope-mustnothave +spec: + remediationAction: inform + object-templates: + - complianceType: mustnothave + objectDefinition: + apiVersion: networking.k8s.io/v1 + kind: IngressClass + spec: + controller: ingress.k8s.aws/alb \ No newline at end of file diff --git a/test/resources/case37_no_name/case37_no_name_policy.yaml b/test/resources/case37_no_name/case37_no_name_policy.yaml new file mode 100644 index 00000000..64be953f --- /dev/null +++ b/test/resources/case37_no_name/case37_no_name_policy.yaml @@ -0,0 +1,15 @@ +apiVersion: policy.open-cluster-management.io/v1 +kind: ConfigurationPolicy +metadata: + name: case37-test-policy-1 +spec: + remediationAction: inform + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + namespace: default + spec: + ingressClassName: test diff --git a/test/resources/case37_no_name/case37_no_name_policy_nothave.yaml b/test/resources/case37_no_name/case37_no_name_policy_nothave.yaml new file mode 100644 index 00000000..1071355e --- /dev/null +++ b/test/resources/case37_no_name/case37_no_name_policy_nothave.yaml @@ -0,0 +1,15 @@ +apiVersion: policy.open-cluster-management.io/v1 +kind: ConfigurationPolicy +metadata: + name: case37-test-policy-mustnothave +spec: + remediationAction: inform + object-templates: + - complianceType: mustnothave + objectDefinition: + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + namespace: default + spec: + ingressClassName: test \ No newline at end of file