diff --git a/controllers/templatesync/template_sync.go b/controllers/templatesync/template_sync.go index 3b3ecfae..d326a4c5 100644 --- a/controllers/templatesync/template_sync.go +++ b/controllers/templatesync/template_sync.go @@ -280,7 +280,11 @@ func (r *PolicyReconciler) Reconcile(ctx context.Context, request reconcile.Requ // Gather raw object definition from the policy template object, gvk, err := unstructured.UnstructuredJSONScheme.Decode(policyT.ObjectDefinition.Raw, nil, nil) if err != nil { - resultError = err + // If it's missing the Kind, don't requeue since that requires an update to the Policy + if !runtime.IsMissingKind(err) { + resultError = err + } + errMsg := fmt.Sprintf("Failed to decode policy template with err: %s", err) _ = r.emitTemplateError(ctx, instance, tIndex, fmt.Sprintf("template-%v", tIndex), false, errMsg) diff --git a/test/e2e/case10_error_test.go b/test/e2e/case10_error_test.go index ca79086a..aea9ae62 100644 --- a/test/e2e/case10_error_test.go +++ b/test/e2e/case10_error_test.go @@ -315,7 +315,7 @@ var _ = Describe("Test error handling", func() { By("Creating the ConfigurationPolicy on the managed cluster directly") _, err := kubectlManaged( "apply", - "--filename=../resources/case10_template_sync_error_test/working-policy-configpol.yaml", + "--filename="+yamlBasePath+"working-policy-configpol.yaml", "--namespace="+clusterNamespace, ) Expect(err).ShouldNot(HaveOccurred()) @@ -353,6 +353,27 @@ var _ = Describe("Test error handling", func() { 1, ).Should(BeTrue()) }) + It("should only generate one event for a missing kind", func() { + policyName := "case10-missing-kind" + hubApplyPolicy(policyName, + yamlBasePath+"missing-kind.yaml") + + By("Checking for the error event and ensuring it only occurs once") + Eventually( + checkForEvent( + policyName, "Object 'Kind' is missing in", + ), + defaultTimeoutSeconds, + 1, + ).Should(BeTrue()) + Consistently( + getMatchingEvents( + policyName, "Object 'Kind' is missing in", + ), + defaultTimeoutSeconds, + 1, + ).Should(HaveLen(2)) + }) }) // Checks for an event on the managed cluster @@ -381,3 +402,31 @@ func checkForEvent(policyName, msgSubStr string) func() bool { return false } } + +// Checks for an event on the managed cluster +func getMatchingEvents(policyName, msgSubStr string) func() []string { + return func() []string { + eventInterface := clientManagedDynamic.Resource(gvrEvent).Namespace(clusterNamespace) + + eventList, err := eventInterface.List(context.TODO(), metav1.ListOptions{ + FieldSelector: "involvedObject.name=" + policyName, + }) + if err != nil { + return []string{} + } + + matchingEvents := []string{} + for _, event := range eventList.Items { + msg, found, err := unstructured.NestedString(event.Object, "message") + if !found || err != nil { + continue + } + + if strings.Contains(msg, msgSubStr) { + matchingEvents = append(matchingEvents, msg) + } + } + + return matchingEvents + } +} diff --git a/test/resources/case10_template_sync_error_test/missing-kind.yaml b/test/resources/case10_template_sync_error_test/missing-kind.yaml new file mode 100644 index 00000000..057e5e13 --- /dev/null +++ b/test/resources/case10_template_sync_error_test/missing-kind.yaml @@ -0,0 +1,17 @@ +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: case10-missing-kind + labels: + policy.open-cluster-management.io/cluster-name: managed + policy.open-cluster-management.io/cluster-namespace: managed + policy.open-cluster-management.io/root-policy: case10-missing-kind +spec: + remediationAction: inform + disabled: false + policy-templates: + - objectDefinition: + spec: + object-templates: + - metadata: + labels: {}