diff --git a/internal/ordering_test.go b/internal/ordering_test.go index d8a6d9d..4c473ae 100644 --- a/internal/ordering_test.go +++ b/internal/ordering_test.go @@ -252,12 +252,12 @@ policies: remediationAction: inform name: bird extraDependencies: - - name: tiger2 - kind: ConfigurationPolicy - compliance: "Compliant" - - name: lion2 - kind: ConfigurationPolicy - compliance: "Compliant" + - name: tiger2 + kind: ConfigurationPolicy + compliance: "Compliant" + - name: lion2 + kind: ConfigurationPolicy + compliance: "Compliant" `, wantFile: "testdata/ordering/manifest-level-name.yaml", wantErr: "", @@ -283,7 +283,7 @@ policies: wantFile: "testdata/ordering/manifest-level-name-raw-consolidate-false.yaml", wantErr: "", }, - "complicated raw policies with consolidateManifests true": { + "consolidateManifests true and objTemplate with raw": { tmpDir: tmpDir, generator: ` apiVersion: policy.open-cluster-management.io/v1 @@ -297,16 +297,58 @@ policyDefaults: policies: - name: one manifests: + - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} + name: bird - path: {{printf "%v/%v" .Dir "configmap.yaml"}} name: tiger - - path: {{printf "%v/%v" .Dir "configmap.yaml"}} - name: rabbit +`, + wantFile: "testdata/ordering/manifest-level-name-raw-consolidate-true.yaml", + wantErr: "", + }, + "consolidateManifests true and objTemplate with empty name": { + tmpDir: tmpDir, + generator: ` +apiVersion: policy.open-cluster-management.io/v1 +kind: PolicyGenerator +metadata: + name: test +policyDefaults: + orderPolicies: true + namespace: my-policies + consolidateManifests: true +policies: +- name: one + manifests: - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} - name: bird - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} + name: bird + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} +`, + wantFile: "testdata/ordering/manifest-level-name-raw-consolidate-true-empty-name.yaml", + wantErr: "", + }, + "consolidateManifests true and objTemplate with name": { + tmpDir: tmpDir, + generator: ` +apiVersion: policy.open-cluster-management.io/v1 +kind: PolicyGenerator +metadata: + name: test +policyDefaults: + orderPolicies: true + namespace: my-policies + consolidateManifests: true +policies: +- name: one + manifests: - path: {{printf "%v/%v" .Dir "object-templates-raw.yaml"}} + name: bird + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + - path: {{printf "%v/%v" .Dir "configmap.yaml"}} + name: tiger `, - wantFile: "testdata/ordering/manifest-level-name-raw-consolidate-true.yaml", + wantFile: "testdata/ordering/manifest-level-name-raw-consolidate-true-with-name.yaml", wantErr: "", }, } diff --git a/internal/testdata/ordering/manifest-level-name-raw-consolidate-true-empty-name.yaml b/internal/testdata/ordering/manifest-level-name-raw-consolidate-true-empty-name.yaml new file mode 100644 index 0000000..d8e7c37 --- /dev/null +++ b/internal/testdata/ordering/manifest-level-name-raw-consolidate-true-empty-name.yaml @@ -0,0 +1,158 @@ +--- +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: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: one + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + - 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 + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: bird + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: bird2 + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: one3 + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=cabbage + kind: ConfigMap + metadata: + name: config-2 + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=cabbage + kind: ConfigMap + metadata: + name: config-2 + 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: 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 diff --git a/internal/testdata/ordering/manifest-level-name-raw-consolidate-true-with-name.yaml b/internal/testdata/ordering/manifest-level-name-raw-consolidate-true-with-name.yaml new file mode 100644 index 0000000..41ebe62 --- /dev/null +++ b/internal/testdata/ordering/manifest-level-name-raw-consolidate-true-with-name.yaml @@ -0,0 +1,122 @@ +--- +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: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: bird + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: bird2 + spec: + object-templates-raw: |- + - complianceType: musthave + objectDefinition: + apiVersion: v1 + kind: ConfigMap + metadata: + name: example + namespace: default + data: + extraData: data + remediationAction: inform + severity: low + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: tiger + spec: + object-templates: + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=cabbage + kind: ConfigMap + metadata: + name: config-2 + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=potato + kind: ConfigMap + metadata: + name: my-configmap + - complianceType: musthave + objectDefinition: + apiVersion: v1 + data: + game.properties: enemies=cabbage + kind: ConfigMap + metadata: + name: config-2 + 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: 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 diff --git a/internal/testdata/ordering/manifest-level-name-raw-consolidate-true.yaml b/internal/testdata/ordering/manifest-level-name-raw-consolidate-true.yaml index e4cd3f8..8868476 100644 --- a/internal/testdata/ordering/manifest-level-name-raw-consolidate-true.yaml +++ b/internal/testdata/ordering/manifest-level-name-raw-consolidate-true.yaml @@ -48,78 +48,6 @@ spec: extraData: data remediationAction: inform severity: low - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: one - spec: - object-templates-raw: |- - - complianceType: musthave - objectDefinition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: example - namespace: default - data: - extraData: data - remediationAction: inform - severity: low - - 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 - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: one3 - spec: - object-templates-raw: |- - - complianceType: musthave - objectDefinition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: example - namespace: default - data: - extraData: data - remediationAction: inform - severity: low - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: one4 - spec: - object-templates-raw: |- - - complianceType: musthave - objectDefinition: - apiVersion: v1 - kind: ConfigMap - metadata: - name: example - namespace: default - data: - extraData: data - remediationAction: inform - severity: low - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 kind: ConfigurationPolicy @@ -143,22 +71,6 @@ spec: kind: ConfigMap metadata: name: config-2 - - complianceType: musthave - objectDefinition: - apiVersion: v1 - data: - game.properties: enemies=potato - kind: ConfigMap - metadata: - name: my-configmap - - complianceType: musthave - objectDefinition: - apiVersion: v1 - data: - game.properties: enemies=cabbage - kind: ConfigMap - metadata: - name: config-2 remediationAction: inform severity: low remediationAction: inform diff --git a/internal/utils.go b/internal/utils.go index 7615523..e5abe36 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -169,7 +169,9 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ objectTemplates := make([]map[string]interface{}, 0, objectTemplatesLength) policyTemplates := make([]map[string]interface{}, 0, policyTemplatesLength) - policyNameCounter := 0 + var consolidatedPolicyName string + + policyNameCounter := map[string]int{} for i, manifestGroup := range manifestGroups { complianceType := policyConf.Manifests[i].ComplianceType @@ -179,7 +181,10 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ ignorePending := policyConf.Manifests[i].IgnorePending extraDeps := policyConf.Manifests[i].ExtraDependencies - manifestNameCounter := 0 + policyName := policyConf.Manifests[i].Name + if policyName == "" { + policyName = policyConf.Name + } for _, manifest := range manifestGroup { err := setGatekeeperEnforcementAction(manifest, @@ -204,11 +209,12 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ _, found, _ := unstructured.NestedString(manifest, "object-templates-raw") if found { + policyNameCounter[policyName]++ policyTemplate = buildPolicyTemplate( policyConf, manifest["object-templates-raw"], &policyConf.Manifests[i].ConfigurationPolicyOptions, - getConfigurationPolicyName(policyConf, i, &policyNameCounter, &manifestNameCounter), + getConfigurationPolicyName(policyName, policyNameCounter[policyName]), ) } else { policyTemplate = map[string]interface{}{"objectDefinition": manifest} @@ -256,17 +262,20 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ } if policyConf.ConsolidateManifests { + if consolidatedPolicyName == "" { + consolidatedPolicyName = policyConf.Manifests[i].Name + } // put all objTemplate with manifest into single consolidated objectTemplates objectTemplates = append(objectTemplates, objTemplate) } else { + policyNameCounter[policyName]++ // casting each objTemplate with manifest to objectTemplates type // build policyTemplate for each objectTemplates policyTemplate := buildPolicyTemplate( policyConf, []map[string]interface{}{objTemplate}, &policyConf.Manifests[i].ConfigurationPolicyOptions, - getConfigurationPolicyName(policyConf, i, - &policyNameCounter, &manifestNameCounter), + getConfigurationPolicyName(policyName, policyNameCounter[policyName]), ) setTemplateOptions(policyTemplate, ignorePending, extraDeps) @@ -285,13 +294,18 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ // just build one policyTemplate by using the above non-empty consolidated objectTemplates // ConsolidateManifests = true or there is non-policy-type manifest if policyConf.ConsolidateManifests && len(objectTemplates) > 0 { + if consolidatedPolicyName == "" { + consolidatedPolicyName = policyConf.Name + } + + policyNameCounter[consolidatedPolicyName]++ // If ConsolidateManifests is true and multiple manifest[].names are provided, the configuration policy // name will be the first name of manifest[].names policyTemplate := buildPolicyTemplate( policyConf, objectTemplates, &policyConf.ConfigurationPolicyOptions, - getConfigurationPolicyName(policyConf, 0, &policyNameCounter, nil), + getConfigurationPolicyName(consolidatedPolicyName, policyNameCounter[consolidatedPolicyName]), ) setTemplateOptions(policyTemplate, policyConf.IgnorePending, policyConf.ExtraDependencies) policyTemplates = append(policyTemplates, policyTemplate) @@ -327,38 +341,12 @@ func getPolicyTemplates(policyConf *types.PolicyConfig) ([]map[string]interface{ return policyTemplates, nil } -// getConfigurationPolicyName returns the `ConfigurationPolicy` name based on the provided PolicyConfig. -// When a name is assigned, it increments the associated counter, using it as a suffix if it's greater -// than one to create unique names. If both `manifest[].name` and `policies.name` are provided, -// `manifest[].name` takes priority as the configuration name. -func getConfigurationPolicyName(policyConf *types.PolicyConfig, manifestGroupIndex int, - policyNameCounter *int, manifestNameCounter *int, -) string { - // Do not append a number to configName when it is used for the first time. - configName := policyConf.Manifests[manifestGroupIndex].Name - - // For the case where ConsolidateManifests is true and the manifest's name is provided, - if manifestNameCounter == nil && configName != "" { - return configName - } - - if manifestNameCounter != nil && configName != "" { - *manifestNameCounter++ - if *manifestNameCounter > 1 { - return fmt.Sprintf("%s%d", configName, *manifestNameCounter) - } - - return configName - } - - configName = policyConf.Name - - *policyNameCounter++ - if *policyNameCounter > 1 { - return fmt.Sprintf("%s%d", configName, *policyNameCounter) +func getConfigurationPolicyName(name string, count int) string { + if count > 1 { + return fmt.Sprintf("%s%d", name, count) } - return configName + return name } // setGatekeeperEnforcementAction function override gatekeeper.constraint.enforcementAction