Skip to content

Commit

Permalink
Process object-templates-raw properly with no templatization
Browse files Browse the repository at this point in the history
If object-templates-raw was set without including a template, it was not properly being converted into a normal object-templates array and thus was not generating a status properly. This change marshals the object-templates-raw string into an object for further processing.

Signed-off-by: Will Kutler <wkutler@redhat.com>
  • Loading branch information
willkutler committed Feb 9, 2023
1 parent 3f97c64 commit 81a17a9
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 28 deletions.
14 changes: 14 additions & 0 deletions controllers/configurationpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
yaml "sigs.k8s.io/yaml"

policyv1 "open-cluster-management.io/config-policy-controller/api/v1"
common "open-cluster-management.io/config-policy-controller/pkg/common"
Expand Down Expand Up @@ -1011,6 +1012,19 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi

// Otherwise, set the resolved data for use in further processing
plc.Spec.ObjectTemplates[i].ObjectDefinition.Raw = resolvedTemplate.ResolvedJSON
} else if isRawObjTemplate {
// Unmarshal raw template YAML into object if that has not already been done by the template
// resolution function
err = yaml.Unmarshal(rawData, &objTemps)
if err != nil {
addTemplateErrorViolation("Error parsing the YAML in the object-templates-raw field", err.Error())

return
}

plc.Spec.ObjectTemplates = objTemps

break
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,44 @@ import (
)

const (
case28RangePolicyName string = "case28-configpolicy"
case28RangePolicyYaml string = "../resources/case28_multiline_templatization/case28_policy.yaml"
case28ConfigMapsYaml string = "../resources/case28_multiline_templatization/case28_configmaps.yaml"
case30RangePolicyName string = "case30-configpolicy"
case30NoTemplatePolicyName string = "case30-configpolicy-notemplate"
case30RangePolicyYaml string = "../resources/case30_multiline_templatization/case30_policy.yaml"
case30NoTemplatePolicyYaml string = "../resources/case30_multiline_templatization/case30_policy_notemplate.yaml"
case30ConfigMapsYaml string = "../resources/case30_multiline_templatization/case30_configmaps.yaml"
)

const (
case28Unterminated string = "policy-pod-create-unterminated"
case28UnterminatedYaml string = "../resources/case28_multiline_templatization/case28_unterminated.yaml"
case28WrongArgs string = "policy-pod-create-wrong-args"
case28WrongArgsYaml string = "../resources/case28_multiline_templatization/case28_wrong_args.yaml"
case30Unterminated string = "policy-pod-create-unterminated"
case30UnterminatedYaml string = "../resources/case30_multiline_templatization/case30_unterminated.yaml"
case30WrongArgs string = "policy-pod-create-wrong-args"
case30WrongArgsYaml string = "../resources/case30_multiline_templatization/case30_wrong_args.yaml"
)

var _ = Describe("Test multiline templatization", Ordered, func() {
Describe("Verify multiline template with range keyword", Ordered, func() {
It("configmap should be created properly on the managed cluster", func() {
By("Creating config maps on managed")
utils.Kubectl("apply", "-f", case28ConfigMapsYaml, "-n", "default")
for _, cfgMapName := range []string{"28config1", "28config2"} {
utils.Kubectl("apply", "-f", case30ConfigMapsYaml, "-n", "default")
for _, cfgMapName := range []string{"30config1", "30config2"} {
cfgmap := utils.GetWithTimeout(clientManagedDynamic, gvrConfigMap,
cfgMapName, "default", true, defaultTimeoutSeconds)
Expect(cfgmap).NotTo(BeNil())
}
})
It("both configmaps should be updated properly on the managed cluster", func() {
By("Creating policy with range template on managed")
utils.Kubectl("apply", "-f", case28RangePolicyYaml, "-n", testNamespace)
utils.Kubectl("apply", "-f", case30RangePolicyYaml, "-n", testNamespace)
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28RangePolicyName, testNamespace, true, defaultTimeoutSeconds)
case30RangePolicyName, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())

By("Verifying that the " + case28RangePolicyName + " policy is compliant")
By("Verifying that the " + case30RangePolicyName + " policy is compliant")
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(
clientManagedDynamic,
gvrConfigPolicy,
case28RangePolicyName,
case30RangePolicyName,
testNamespace,
true,
defaultTimeoutSeconds,
Expand All @@ -60,7 +62,7 @@ var _ = Describe("Test multiline templatization", Ordered, func() {
}, defaultTimeoutSeconds, 1).Should(Equal("Compliant"))

By("Verifying that both configmaps have the updated data")
for _, cfgMapName := range []string{"28config1", "28config2"} {
for _, cfgMapName := range []string{"30config1", "30config2"} {
Eventually(
func() interface{} {
configMap, err := clientManaged.CoreV1().ConfigMaps("default").Get(
Expand All @@ -78,48 +80,70 @@ var _ = Describe("Test multiline templatization", Ordered, func() {
}
})

It("processes policies with no template correctly", func() {
By("Creating policy with no template in object-templates-raw")
utils.Kubectl("apply", "-f", case30NoTemplatePolicyYaml, "-n", testNamespace)
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case30NoTemplatePolicyName, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())

By("Verifying that the " + case30NoTemplatePolicyName + " policy is compliant")
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(
clientManagedDynamic,
gvrConfigPolicy,
case30NoTemplatePolicyName,
testNamespace,
true,
defaultTimeoutSeconds,
)

return utils.GetComplianceState(managedPlc)
}, defaultTimeoutSeconds, 1).Should(Equal("Compliant"))
})

AfterAll(func() {
deleteConfigPolicies([]string{case28RangePolicyName})
utils.Kubectl("delete", "-f", case28ConfigMapsYaml)
deleteConfigPolicies([]string{case30RangePolicyName, case30NoTemplatePolicyName})
utils.Kubectl("delete", "-f", case30ConfigMapsYaml)
})
})
Describe("Test invalid multiline templates", func() {
It("should generate noncompliant for invalid template strings", func() {
By("Creating policies on managed")
// create policy with unterminated template
utils.Kubectl("apply", "-f", case28UnterminatedYaml, "-n", testNamespace)
utils.Kubectl("apply", "-f", case30UnterminatedYaml, "-n", testNamespace)
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28Unterminated, testNamespace, true, defaultTimeoutSeconds)
case30Unterminated, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28Unterminated, testNamespace, true, defaultTimeoutSeconds)
case30Unterminated, testNamespace, true, defaultTimeoutSeconds)

return utils.GetComplianceState(managedPlc)
}, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant"))
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28Unterminated, testNamespace, true, defaultTimeoutSeconds)
case30Unterminated, testNamespace, true, defaultTimeoutSeconds)

return strings.Contains(
utils.GetStatusMessage(managedPlc).(string),
"unterminated character constant",
)
}, 10, 1).Should(BeTrue())
// create policy with incomplete args in template
utils.Kubectl("apply", "-f", case28WrongArgsYaml, "-n", testNamespace)
utils.Kubectl("apply", "-f", case30WrongArgsYaml, "-n", testNamespace)
plc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28WrongArgs, testNamespace, true, defaultTimeoutSeconds)
case30WrongArgs, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28WrongArgs, testNamespace, true, defaultTimeoutSeconds)
case30WrongArgs, testNamespace, true, defaultTimeoutSeconds)

return utils.GetComplianceState(managedPlc)
}, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant"))
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28WrongArgs, testNamespace, true, defaultTimeoutSeconds)
case30WrongArgs, testNamespace, true, defaultTimeoutSeconds)

return strings.Contains(
utils.GetStatusMessage(managedPlc).(string),
Expand All @@ -128,7 +152,7 @@ var _ = Describe("Test multiline templatization", Ordered, func() {
}, 10, 1).Should(BeTrue())
})
AfterAll(func() {
deleteConfigPolicies([]string{case28Unterminated, case28WrongArgs})
deleteConfigPolicies([]string{case30Unterminated, case30WrongArgs})
})
})
})
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: 28config1
name: 30config1
data:
name: testvalue1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: 28config2
name: 30config2
data:
name: testvalue2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: case28-configpolicy
name: case30-configpolicy
spec:
remediationAction: enforce
severity: low
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: case30-configpolicy-notemplate
spec:
remediationAction: enforce
severity: low
object-templates-raw: |
- complianceType: musthave
objectDefinition:
apiVersion: v1
kind: ConfigMap
metadata:
name: 30config1
namespace: default
data:
extraData: exists!

0 comments on commit 81a17a9

Please sign in to comment.