From bbbc248a2ddeee2b908fe8dbfa02eeeb12c9ccb8 Mon Sep 17 00:00:00 2001 From: Jeffrey Luo Date: Thu, 11 Apr 2024 14:24:29 -0400 Subject: [PATCH] Add support for object-templates-raw Adds support for manifest files with only object-templates-raw field, which gets put into a ConfigurationPolicy. Signed-off-by: Jeffrey Luo --- docs/policygenerator-reference.yaml | 5 +- .../object-templates-raw.yaml | 13 ++ examples/policyGenerator.yaml | 5 + internal/ordering_test.go | 51 +++++ internal/plugin_config_test.go | 23 +++ internal/plugin_test.go | 84 +++++++- ...efault-extradeps-object-templates-raw.yaml | 184 ++++++++++++++++++ .../ignore-pending-object-templates-raw.yaml | 164 ++++++++++++++++ internal/utils.go | 41 +++- internal/utils_test.go | 72 +++++++ 10 files changed, 632 insertions(+), 10 deletions(-) create mode 100644 examples/input-object-templates-raw/object-templates-raw.yaml create mode 100644 internal/testdata/ordering/default-extradeps-object-templates-raw.yaml create mode 100644 internal/testdata/ordering/ignore-pending-object-templates-raw.yaml diff --git a/docs/policygenerator-reference.yaml b/docs/policygenerator-reference.yaml index 259ff25..62d9eeb 100644 --- a/docs/policygenerator-reference.yaml +++ b/docs/policygenerator-reference.yaml @@ -216,7 +216,10 @@ policies: # 1) Non-root policy type manifests such as IamPolicy, CertificatePolicy, and ConfigurationPolicy that have a # "Policy" suffix. These are not modified except for patches and are directly added as a Policy's # policy-templates entry. - # 2) For everything else, ConfigurationPolicy objects are generated to wrap these manifests. The resulting + # 2) Manifests containing only an `object-templates-raw` key. The corresponding value will be used directly in + # a generated ConfigurationPolicy without modification, which will then be added as a Policy's + # policy-templates entry. + # 3) For everything else, ConfigurationPolicy objects are generated to wrap these manifests. The resulting # ConfigurationPolicy is added as a Policy's policy-templates entry. - path: "" # Optional. (See policyDefaults.complianceType for description.) diff --git a/examples/input-object-templates-raw/object-templates-raw.yaml b/examples/input-object-templates-raw/object-templates-raw.yaml new file mode 100644 index 0000000..6e93b71 --- /dev/null +++ b/examples/input-object-templates-raw/object-templates-raw.yaml @@ -0,0 +1,13 @@ + object-templates-raw: | + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: game-config-aliens + namespace: default + data: + game.properties: | + enemies=aliens + ui.properties: | + color.good=purple diff --git a/examples/policyGenerator.yaml b/examples/policyGenerator.yaml index fe57134..bc24393 100644 --- a/examples/policyGenerator.yaml +++ b/examples/policyGenerator.yaml @@ -53,6 +53,11 @@ policies: - path: input-kyverno/ policySets: - policyset-kyverno +- name: policy-object-templates-raw + disabled: true + manifests: + - path: input-object-templates-raw/ + remediationAction: enforce - name: policy-require-ns-labels manifests: - path: input-gatekeeper/ diff --git a/internal/ordering_test.go b/internal/ordering_test.go index d95cfb1..c282f81 100644 --- a/internal/ordering_test.go +++ b/internal/ordering_test.go @@ -271,6 +271,7 @@ func TestIgnorePending(t *testing.T) { t.Parallel() tmpDir := t.TempDir() createConfigMap(t, tmpDir, "configmap.yaml") + createObjectTemplatesRawManifest(t, tmpDir, "object-templates-raw.yaml") tests := map[string]genOutTest{ "policyDefaults.ignorePending is propagated to all manifests": { @@ -368,6 +369,30 @@ policies: wantFile: "testdata/ordering/ignore-pending-manifest-override.yaml", wantErr: "", }, + "policyDefaults.ignorePending is propagated with object-templates-raw": { + tmpDir: tmpDir, + generator: ` +apiVersion: policy.open-cluster-management.io/v1 +kind: PolicyGenerator +metadata: + name: test +policyDefaults: + consolidateManifests: false + ignorePending: true + namespace: my-policies +policies: +- name: one + manifests: + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} +- name: two + manifests: + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} +`, + wantFile: "testdata/ordering/ignore-pending-object-templates-raw.yaml", + wantErr: "", + }, } for name := range tests { @@ -544,6 +569,7 @@ func TestExtraDependencies(t *testing.T) { tmpDir := t.TempDir() createConfigMap(t, tmpDir, "configmap.yaml") createConfigPolicyManifest(t, tmpDir, "configpolicy.yaml") + createObjectTemplatesRawManifest(t, tmpDir, "object-templates-raw.yaml") tests := map[string]genOutTest{ "policyDefaults.extraDependencies are propagated to all manifests": { @@ -746,6 +772,31 @@ policies: wantFile: "testdata/ordering/extradeps-overrides.yaml", wantErr: "", }, + "policyDefaults.extraDependencies are propagated with object-templates-raw": { + tmpDir: tmpDir, + generator: ` +apiVersion: policy.open-cluster-management.io/v1 +kind: PolicyGenerator +metadata: + name: test +policyDefaults: + consolidateManifests: false + namespace: my-policies + extraDependencies: + - name: extrafoo +policies: +- name: one + manifests: + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} +- name: two + manifests: + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} +`, + wantFile: "testdata/ordering/default-extradeps-object-templates-raw.yaml", + wantErr: "", + }, } for name := range tests { diff --git a/internal/plugin_config_test.go b/internal/plugin_config_test.go index 510ce0b..18b7b67 100644 --- a/internal/plugin_config_test.go +++ b/internal/plugin_config_test.go @@ -83,6 +83,29 @@ spec: } } +func createObjectTemplatesRawManifest(t *testing.T, tmpDir, filename string) { + t.Helper() + + manifestsPath := path.Join(tmpDir, filename) + yamlContent := ` +object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data +` + + err := os.WriteFile(manifestsPath, []byte(yamlContent), 0o666) + if err != nil { + t.Fatalf("Failed to write %s", manifestsPath) + } +} + func TestConfig(t *testing.T) { t.Parallel() tmpDir := t.TempDir() diff --git a/internal/plugin_test.go b/internal/plugin_test.go index 6534382..19e98cf 100644 --- a/internal/plugin_test.go +++ b/internal/plugin_test.go @@ -1556,6 +1556,73 @@ spec: assertEqual(t, output, expected) } +func TestCreatePolicyFromObjectTemplatesRawManifest(t *testing.T) { + t.Parallel() + tmpDir := t.TempDir() + createObjectTemplatesRawManifest(t, tmpDir, "objectTemplatesRawPluginTest.yaml") + + p := Plugin{} + p.PolicyDefaults.Namespace = "my-policies" + policyConf := types.PolicyConfig{ + PolicyOptions: types.PolicyOptions{ + Categories: []string{"AC Access Control"}, + Controls: []string{"AC-3 Access Enforcement"}, + Standards: []string{"NIST SP 800-53"}, + }, + Name: "policy-app-config", + Manifests: []types.Manifest{ + {Path: path.Join(tmpDir, "objectTemplatesRawPluginTest.yaml")}, + }, + } + p.Policies = append(p.Policies, policyConf) + p.applyDefaults(map[string]interface{}{}) + + err := p.createPolicy(&p.Policies[0]) + if err != nil { + t.Fatal(err.Error()) + } + + output := p.outputBuffer.String() + + expected := ` +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + annotations: + policy.open-cluster-management.io/categories: AC Access Control + policy.open-cluster-management.io/controls: AC-3 Access Enforcement + policy.open-cluster-management.io/description: "" + policy.open-cluster-management.io/standards: NIST SP 800-53 + name: policy-app-config + namespace: my-policies +spec: + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: policy-app-config + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + remediationAction: inform +` + expected = strings.TrimPrefix(expected, "\n") + assertEqual(t, output, expected) +} + func TestCreatePolicyWithGkConstraintTemplate(t *testing.T) { t.Parallel() tmpDir := t.TempDir() @@ -3420,6 +3487,7 @@ func TestGenerateEvaluationInterval(t *testing.T) { t.Parallel() tmpDir := t.TempDir() createConfigMap(t, tmpDir, "configmap.yaml") + createObjectTemplatesRawManifest(t, tmpDir, "object-templates-raw.yaml") p := Plugin{} var err error @@ -3481,7 +3549,14 @@ func TestGenerateEvaluationInterval(t *testing.T) { {Path: path.Join(tmpDir, "configmap.yaml")}, }, } - p.Policies = append(p.Policies, policyConf, policyConf2, policyConf3) + // Test that the policy defaults get inherited with object-templates-raw. + policyConf4 := types.PolicyConfig{ + Name: "policy-app-config4", + Manifests: []types.Manifest{ + {Path: path.Join(tmpDir, "object-templates-raw.yaml")}, + }, + } + p.Policies = append(p.Policies, policyConf, policyConf2, policyConf3, policyConf4) p.applyDefaults( map[string]interface{}{ "policies": []interface{}{ @@ -3523,7 +3598,7 @@ func TestGenerateEvaluationInterval(t *testing.T) { t.Fatal(err.Error()) } - assertEqual(t, len(generatedManifests), 9) + assertEqual(t, len(generatedManifests), 12) for _, manifest := range generatedManifests { kind, _ := manifest["kind"].(string) @@ -3559,6 +3634,11 @@ func TestGenerateEvaluationInterval(t *testing.T) { assertEqual(t, len(policyTemplates), 1) evaluationInterval := getYAMLEvaluationInterval(t, policyTemplates[0], true) assertEqual(t, len(evaluationInterval), 0) + } else if name == "policy-app-config4" { + assertEqual(t, len(policyTemplates), 1) + evaluationInterval := getYAMLEvaluationInterval(t, policyTemplates[0], false) + assertEqual(t, evaluationInterval["compliant"], "never") + assertEqual(t, evaluationInterval["noncompliant"], "15s") } } } diff --git a/internal/testdata/ordering/default-extradeps-object-templates-raw.yaml b/internal/testdata/ordering/default-extradeps-object-templates-raw.yaml new file mode 100644 index 0000000..53af9cd --- /dev/null +++ b/internal/testdata/ordering/default-extradeps-object-templates-raw.yaml @@ -0,0 +1,184 @@ +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + annotations: + policy.open-cluster-management.io/categories: CM Configuration Management + policy.open-cluster-management.io/controls: CM-2 Baseline Configuration + policy.open-cluster-management.io/description: "" + policy.open-cluster-management.io/standards: NIST SP 800-53 + name: one + namespace: my-policies +spec: + disabled: false + policy-templates: + - extraDependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: extrafoo + namespace: my-policies + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: one + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + remediationAction: inform + severity: low + - extraDependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: extrafoo + namespace: my-policies + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: one2 + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + remediationAction: inform +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + annotations: + policy.open-cluster-management.io/categories: CM Configuration Management + policy.open-cluster-management.io/controls: CM-2 Baseline Configuration + policy.open-cluster-management.io/description: "" + policy.open-cluster-management.io/standards: NIST SP 800-53 + name: two + namespace: my-policies +spec: + disabled: false + policy-templates: + - extraDependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: extrafoo + namespace: my-policies + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: two + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + remediationAction: inform + severity: low + - extraDependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: extrafoo + namespace: my-policies + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: two2 + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + remediationAction: inform +--- +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: placement-one + namespace: my-policies +spec: + predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: [] + tolerations: + - key: cluster.open-cluster-management.io/unavailable + operator: Exists + - key: cluster.open-cluster-management.io/unreachable + operator: Exists +--- +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: placement-two + namespace: my-policies +spec: + predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: [] + tolerations: + - key: cluster.open-cluster-management.io/unavailable + operator: Exists + - key: cluster.open-cluster-management.io/unreachable + operator: Exists +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: binding-one + namespace: my-policies +placementRef: + apiGroup: cluster.open-cluster-management.io + kind: Placement + name: placement-one +subjects: + - apiGroup: policy.open-cluster-management.io + kind: Policy + name: one +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: binding-two + namespace: my-policies +placementRef: + apiGroup: cluster.open-cluster-management.io + kind: Placement + name: placement-two +subjects: + - apiGroup: policy.open-cluster-management.io + kind: Policy + name: two diff --git a/internal/testdata/ordering/ignore-pending-object-templates-raw.yaml b/internal/testdata/ordering/ignore-pending-object-templates-raw.yaml new file mode 100644 index 0000000..db0434e --- /dev/null +++ b/internal/testdata/ordering/ignore-pending-object-templates-raw.yaml @@ -0,0 +1,164 @@ +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + annotations: + policy.open-cluster-management.io/categories: CM Configuration Management + policy.open-cluster-management.io/controls: CM-2 Baseline Configuration + policy.open-cluster-management.io/description: "" + policy.open-cluster-management.io/standards: NIST SP 800-53 + name: one + namespace: my-policies +spec: + disabled: false + policy-templates: + - ignorePending: true + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: one + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + remediationAction: inform + severity: low + - ignorePending: true + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: one2 + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + remediationAction: inform +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + annotations: + policy.open-cluster-management.io/categories: CM Configuration Management + policy.open-cluster-management.io/controls: CM-2 Baseline Configuration + policy.open-cluster-management.io/description: "" + policy.open-cluster-management.io/standards: NIST SP 800-53 + name: two + namespace: my-policies +spec: + disabled: false + policy-templates: + - ignorePending: true + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: two + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + remediationAction: inform + severity: low + - ignorePending: true + objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: two2 + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + remediationAction: inform +--- +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: placement-one + namespace: my-policies +spec: + predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: [] + tolerations: + - key: cluster.open-cluster-management.io/unavailable + operator: Exists + - key: cluster.open-cluster-management.io/unreachable + operator: Exists +--- +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement +metadata: + name: placement-two + namespace: my-policies +spec: + predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: [] + tolerations: + - key: cluster.open-cluster-management.io/unavailable + operator: Exists + - key: cluster.open-cluster-management.io/unreachable + operator: Exists +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: binding-one + namespace: my-policies +placementRef: + apiGroup: cluster.open-cluster-management.io + kind: Placement + name: placement-one +subjects: + - apiGroup: policy.open-cluster-management.io + kind: Policy + name: one +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: binding-two + namespace: my-policies +placementRef: + apiGroup: cluster.open-cluster-management.io + kind: Placement + name: placement-two +subjects: + - apiGroup: policy.open-cluster-management.io + kind: Policy + name: two diff --git a/internal/utils.go b/internal/utils.go index 3e6f50c..6b16f03 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -187,7 +187,19 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ } if isPolicyTypeManifest { - policyTemplate := map[string]interface{}{"objectDefinition": manifest} + var policyTemplate map[string]interface{} + + _, found, _ := unstructured.NestedString(manifest, "object-templates-raw") + if found { + policyTemplate = buildPolicyTemplate( + policyConf, + len(policyTemplates)+1, + manifest["object-templates-raw"], + &policyConf.Manifests[i].ConfigurationPolicyOptions, + ) + } else { + policyTemplate = map[string]interface{}{"objectDefinition": manifest} + } // Only set dependency options if it's an OCM policy if isOcmPolicy { @@ -309,6 +321,13 @@ func setTemplateOptions(tmpl map[string]interface{}, ignorePending bool, extraDe // - the manifest is a root policy manifest // - the manifest is invalid because it is missing a name func isPolicyTypeManifest(manifest map[string]interface{}, informGatekeeperPolicies bool) (bool, bool, error) { + // check for object-templates-raw separate from policies since they have separate requirements + _, found, _ := unstructured.NestedString(manifest, "object-templates-raw") + if found { + // return true for isPolicyType, since object-templates-raw is in a ConfigurationPolicy + return true, true, nil + } + apiVersion, found, err := unstructured.NestedString(manifest, "apiVersion") if !found || err != nil { return false, false, errors.New("invalid or not found apiVersion") @@ -398,7 +417,7 @@ func processKustomizeDir(path string) ([]map[string]interface{}, error) { func buildPolicyTemplate( policyConf *types.PolicyConfig, policyNum int, - objectTemplates []map[string]interface{}, + objectTemplates interface{}, configPolicyOptionsOverrides *types.ConfigurationPolicyOptions, ) map[string]interface{} { var name string @@ -408,6 +427,18 @@ func buildPolicyTemplate( name = policyConf.Name } + policySpec := map[string]interface{}{ + "remediationAction": policyConf.RemediationAction, + "severity": policyConf.Severity, + } + + switch objectTemplates.(type) { + case string: + policySpec["object-templates-raw"] = objectTemplates + case []map[string]interface{}: + policySpec["object-templates"] = objectTemplates + } + policyTemplate := map[string]interface{}{ "objectDefinition": map[string]interface{}{ "apiVersion": policyAPIVersion, @@ -415,11 +446,7 @@ func buildPolicyTemplate( "metadata": map[string]interface{}{ "name": name, }, - "spec": map[string]interface{}{ - "object-templates": objectTemplates, - "remediationAction": policyConf.RemediationAction, - "severity": policyConf.Severity, - }, + "spec": policySpec, }, } diff --git a/internal/utils_test.go b/internal/utils_test.go index a06111d..3ae2006 100644 --- a/internal/utils_test.go +++ b/internal/utils_test.go @@ -1262,6 +1262,78 @@ func TestGetPolicyTemplateInvalidManifest(t *testing.T) { assertEqual(t, err.Error(), expected) } +func TestGetPolicyTemplateObjectTemplatesRaw(t *testing.T) { + t.Parallel() + tmpDir := t.TempDir() + manifestPath := path.Join(tmpDir, "object-templates-raw.yaml") + manifestYAMLMultiple := ` +object-templates-raw: | + content1 +--- +object-templates-raw: | + content2 +` + manifestYAMLContent1 := `content1 +` + manifestYAMLContent2 := `content2 +` + + err := os.WriteFile(manifestPath, []byte(manifestYAMLMultiple), 0o666) + if err != nil { + t.Fatalf("Failed to write %s", manifestPath) + } + + policyConf := types.PolicyConfig{ + PolicyOptions: types.PolicyOptions{ + ConsolidateManifests: true, + }, + ConfigurationPolicyOptions: types.ConfigurationPolicyOptions{ + ComplianceType: "musthave", + RemediationAction: "enforce", + Severity: "low", + }, + Manifests: []types.Manifest{{Path: manifestPath}}, + Name: "configpolicy-object-templates-raw-config", + } + + policyTemplates, err := getPolicyTemplates(&policyConf) + if err != nil { + t.Fatalf("Failed to get the policy templates: %v", err) + } + + assertEqual(t, len(policyTemplates), 2) + + policyTemplate1 := policyTemplates[0] + objdef := policyTemplate1["objectDefinition"].(map[string]interface{}) + + spec, ok := objdef["spec"].(map[string]interface{}) + if !ok { + t.Fatal("The spec field is an invalid format") + } + + objectTemplatesRaw, ok := spec["object-templates-raw"].(string) + if !ok { + t.Fatal("The object-templates-raw field is an invalid format") + } + + assertEqual(t, objectTemplatesRaw, manifestYAMLContent1) + + policyTemplate2 := policyTemplates[1] + objdef = policyTemplate2["objectDefinition"].(map[string]interface{}) + + spec, ok = objdef["spec"].(map[string]interface{}) + if !ok { + t.Fatal("The spec field is an invalid format") + } + + objectTemplatesRaw, ok = spec["object-templates-raw"].(string) + if !ok { + t.Fatal("The object-templates-raw field is an invalid format") + } + + assertEqual(t, objectTemplatesRaw, manifestYAMLContent2) +} + func TestUnmarshalManifestFile(t *testing.T) { t.Parallel() tmpDir := t.TempDir()