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 8, 2023
1 parent 3f97c64 commit 0252bc7
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 28 deletions.
28 changes: 28 additions & 0 deletions controllers/configurationpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
gocmp "github.com/google/go-cmp/cmp"
"github.com/prometheus/client_golang/prometheus"
templates "github.com/stolostron/go-template-utils/v3/pkg/templates"
yaml "gopkg.in/yaml.v3"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
extensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
Expand Down Expand Up @@ -1011,6 +1012,33 @@ 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 {
// marshal raw template into YAML if that has not already been done by the template resolution fn
var yamlObj interface{}

err = yaml.Unmarshal(rawData, &yamlObj)
if err != nil {
addTemplateErrorViolation("Error unmarshaling YAML for raw template", err.Error())

return
}

resolvedJSON, err := json.Marshal(yamlObj)
if err != nil {
addTemplateErrorViolation("Error parsing raw template", err.Error())

return
}
err = json.Unmarshal(resolvedJSON, &objTemps)
if err != nil {
addTemplateErrorViolation("Error unmarshalling raw template", 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"
case29RangePolicyName string = "case29-configpolicy"
case29NoTemplatePolicyName string = "case29-configpolicy-notemplate"
case29RangePolicyYaml string = "../resources/case29_multiline_templatization/case29_policy.yaml"
case29NoTemplatePolicyYaml string = "../resources/case29_multiline_templatization/case29_policy_notemplate.yaml"
case29ConfigMapsYaml string = "../resources/case29_multiline_templatization/case29_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"
case29Unterminated string = "policy-pod-create-unterminated"
case29UnterminatedYaml string = "../resources/case29_multiline_templatization/case29_unterminated.yaml"
case29WrongArgs string = "policy-pod-create-wrong-args"
case29WrongArgsYaml string = "../resources/case29_multiline_templatization/case29_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", case29ConfigMapsYaml, "-n", "default")
for _, cfgMapName := range []string{"29config1", "29config2"} {
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", case29RangePolicyYaml, "-n", testNamespace)
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28RangePolicyName, testNamespace, true, defaultTimeoutSeconds)
case29RangePolicyName, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())

By("Verifying that the " + case28RangePolicyName + " policy is compliant")
By("Verifying that the " + case29RangePolicyName + " policy is compliant")
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(
clientManagedDynamic,
gvrConfigPolicy,
case28RangePolicyName,
case29RangePolicyName,
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{"29config1", "29config2"} {
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", case29NoTemplatePolicyYaml, "-n", testNamespace)
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case29NoTemplatePolicyName, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())

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

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

AfterAll(func() {
deleteConfigPolicies([]string{case28RangePolicyName})
utils.Kubectl("delete", "-f", case28ConfigMapsYaml)
deleteConfigPolicies([]string{case29RangePolicyName, case29NoTemplatePolicyName})
utils.Kubectl("delete", "-f", case29ConfigMapsYaml)
})
})
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", case29UnterminatedYaml, "-n", testNamespace)
plc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28Unterminated, testNamespace, true, defaultTimeoutSeconds)
case29Unterminated, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28Unterminated, testNamespace, true, defaultTimeoutSeconds)
case29Unterminated, testNamespace, true, defaultTimeoutSeconds)

return utils.GetComplianceState(managedPlc)
}, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant"))
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28Unterminated, testNamespace, true, defaultTimeoutSeconds)
case29Unterminated, 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", case29WrongArgsYaml, "-n", testNamespace)
plc = utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28WrongArgs, testNamespace, true, defaultTimeoutSeconds)
case29WrongArgs, testNamespace, true, defaultTimeoutSeconds)
Expect(plc).NotTo(BeNil())
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28WrongArgs, testNamespace, true, defaultTimeoutSeconds)
case29WrongArgs, testNamespace, true, defaultTimeoutSeconds)

return utils.GetComplianceState(managedPlc)
}, defaultTimeoutSeconds, 1).Should(Equal("NonCompliant"))
Eventually(func() interface{} {
managedPlc := utils.GetWithTimeout(clientManagedDynamic, gvrConfigPolicy,
case28WrongArgs, testNamespace, true, defaultTimeoutSeconds)
case29WrongArgs, 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{case29Unterminated, case29WrongArgs})
})
})
})
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: 28config1
name: 29config1
data:
name: testvalue1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: 28config2
name: 29config2
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: case29-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: case29-configpolicy-notemplate
spec:
remediationAction: inform
severity: low
object-templates-raw: |
- complianceType: musthave
objectDefinition:
apiVersion: v1
kind: ConfigMap
metadata:
name: 29config1
namespace: default
data:
extraData: exists!

0 comments on commit 0252bc7

Please sign in to comment.