Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiline templatization #95

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false"
.PHONY: manifests
manifests: controller-gen
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=config-policy-controller paths="./..." output:crd:artifacts:config=deploy/crds output:rbac:artifacts:config=deploy/rbac
mv deploy/crds/policy.open-cluster-management.io_configurationpolicies.yaml deploy/crds/kustomize/policy.open-cluster-management.io_configurationpolicies.yaml
# Add a newline so that the format matches what kubebuilder generates
@printf "\n---\n" > deploy/crds/policy.open-cluster-management.io_configurationpolicies.yaml
$(KUSTOMIZE) build deploy/crds/kustomize >> deploy/crds/policy.open-cluster-management.io_configurationpolicies.yaml

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
Expand Down
15 changes: 13 additions & 2 deletions api/v1/configurationpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,19 @@ type ConfigurationPolicySpec struct {
// 'matchLabels' and/or 'matchExpressions' are, 'include' will behave as if ['*'] were given. If
// 'matchExpressions' and 'matchLabels' are both not provided, 'include' must be provided to
// retrieve namespaces.
NamespaceSelector Target `json:"namespaceSelector,omitempty"`
ObjectTemplates []*ObjectTemplate `json:"object-templates,omitempty"`
NamespaceSelector Target `json:"namespaceSelector,omitempty"`
// 'object-templates' and 'object-templates-raw' are arrays of objects for the configuration
// policy to check, create, modify, or delete on the cluster. 'object-templates' is an array
// of objects, while 'object-templates-raw' is a string containing an array of objects in
// YAML format. Only one of the two object-templates variables can be set in a given
// configurationPolicy.
ObjectTemplates []*ObjectTemplate `json:"object-templates,omitempty"`
// 'object-templates' and 'object-templates-raw' are arrays of objects for the configuration
// policy to check, create, modify, or delete on the cluster. 'object-templates' is an array
// of objects, while 'object-templates-raw' is a string containing an array of objects in
// YAML format. Only one of the two object-templates variables can be set in a given
// configurationPolicy.
ObjectTemplatesRaw string `json:"object-templates-raw,omitempty"`
willkutler marked this conversation as resolved.
Show resolved Hide resolved
mprahl marked this conversation as resolved.
Show resolved Hide resolved
EvaluationInterval EvaluationInterval `json:"evaluationInterval,omitempty"`
// +kubebuilder:default:=None
PruneObjectBehavior PruneObjectBehavior `json:"pruneObjectBehavior,omitempty"`
Expand Down
59 changes: 45 additions & 14 deletions controllers/configurationpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,22 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
}
}

// set up raw data for template processing
var rawDataList [][]byte
var isRawObjTemplate bool

if plc.Spec.ObjectTemplatesRaw != "" {
rawDataList = [][]byte{[]byte(plc.Spec.ObjectTemplatesRaw)}
isRawObjTemplate = true
} else {
for _, objectT := range plc.Spec.ObjectTemplates {
rawDataList = append(rawDataList, objectT.ObjectDefinition.Raw)
}
isRawObjTemplate = false
}

tmplResolverCfg.InputIsYAML = isRawObjTemplate

tmplResolver, err := templates.NewResolver(&r.TargetK8sClient, r.TargetK8sConfig, tmplResolverCfg)
if err != nil {
// If the encryption key is invalid, clear the cache.
Expand All @@ -791,10 +807,13 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
if !disableTemplates {
startTime := time.Now().UTC()

for _, objectT := range plc.Spec.ObjectTemplates {
var objTemps []*policyv1.ObjectTemplate

// process object templates for go template usage
for i, rawData := range rawDataList {
// first check to make sure there are no hub-templates with delimiter - {{hub
// if one exists, it means the template resolution on the hub did not succeed.
if templates.HasTemplate(objectT.ObjectDefinition.Raw, "{{hub", false) {
if templates.HasTemplate(rawData, "{{hub", false) {
// check to see there is an annotation set to the hub error msg,
// if not ,set a generic msg
hubTemplatesErrMsg, ok := annotations["policy.open-cluster-management.io/hub-templates-error"]
Expand All @@ -814,10 +833,10 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
return
}

if templates.HasTemplate(objectT.ObjectDefinition.Raw, "", true) {
if templates.HasTemplate(rawData, "", true) {
log.V(1).Info("Processing policy templates")

resolvedTemplate, tplErr := tmplResolver.ResolveTemplate(objectT.ObjectDefinition.Raw, nil)
resolvedTemplate, tplErr := tmplResolver.ResolveTemplate(rawData, nil)

if errors.Is(tplErr, templates.ErrMissingAPIResource) ||
errors.Is(tplErr, templates.ErrMissingAPIResourceInvalidTemplate) {
Expand All @@ -829,7 +848,7 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
discoveryErr := r.refreshDiscoveryInfo()
if discoveryErr == nil {
tmplResolver.SetKubeAPIResourceList(r.apiResourceList)
resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(objectT.ObjectDefinition.Raw, nil)
resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(rawData, nil)
} else {
log.V(2).Info(
"Failed to refresh the API discovery information after a template encountered an unknown " +
Expand Down Expand Up @@ -871,7 +890,7 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
return
}

resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(objectT.ObjectDefinition.Raw, nil)
resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(rawData, nil)
}

if tplErr != nil {
Expand All @@ -880,8 +899,22 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
return
}

// Set the resolved data for use in further processing
objectT.ObjectDefinition.Raw = resolvedTemplate.ResolvedJSON
// If raw data, only one passthrough is needed, since all the object templates are in it
if isRawObjTemplate {
err := json.Unmarshal(resolvedTemplate.ResolvedJSON, &objTemps)
if err != nil {
addTemplateErrorViolation("Error unmarshalling raw template", err.Error())

return
}

plc.Spec.ObjectTemplates = objTemps

break
}

// Otherwise, set the resolved data for use in further processing
plc.Spec.ObjectTemplates[i].ObjectDefinition.Raw = resolvedTemplate.ResolvedJSON
}
}

Expand Down Expand Up @@ -2503,13 +2536,11 @@ func (r *ConfigurationPolicyReconciler) addForUpdate(policy *policyv1.Configurat
if policy.Spec == nil {
compliant = false
} else {
for index := range policy.Spec.ObjectTemplates {
if index < len(policy.Status.CompliancyDetails) {
if policy.Status.CompliancyDetails[index].ComplianceState == policyv1.NonCompliant {
compliant = false
for index := range policy.Status.CompliancyDetails {
if policy.Status.CompliancyDetails[index].ComplianceState == policyv1.NonCompliant {
compliant = false

break
}
break
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions deploy/crds/kustomize/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
resources:
- policy.open-cluster-management.io_configurationpolicies.yaml

# Add validation more complicated than Kubebuilder markers can provide
patches:
- path: obj-template-validation.json
target:
group: apiextensions.k8s.io
version: v1
kind: CustomResourceDefinition
name: configurationpolicies.policy.open-cluster-management.io
11 changes: 11 additions & 0 deletions deploy/crds/kustomize/obj-template-validation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"op":"add",
"path":"/spec/versions/0/schema/openAPIV3Schema/properties/spec/oneOf",
"value": [{
"required": ["object-templates"]
},{
"required": ["object-templates-raw"]
}]
}
]
Loading