diff --git a/README.md b/README.md index 82ffceb..4b8619b 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,43 @@ spec: ``` +As you probably noticed in the previous example, conditions are made using vitamin Golang template +(better known as Helm template), so **all the functions available in Helm are available here too.** +This way you start creating wonderful policies from first minute. + +**Sometimes you need to store information** during conditions' evaluation that will be useful in later messages shown to the team. +This will help your mates having meaningful messages that save time during debug. + +Because of that, there is a special function available in templates called `setVar`. It can be used as follows: + +```yaml +apiVersion: admitik.freepik.com/v1alpha1 +kind: ClusterAdmissionPolicy +spec: + + ... + + conditions: + - name: store-vars-for-later-usage + key: | + {{- $someDataForLater := dict "name" "example-name" "namespace" "example-namespace" -}} + + + {{/* Store your data under your desired key. You can use as many keys as needed */}} + {{- setVar "some_key" $someDataForLater -}} + + + {{- printf "force-condition-not-being-met" -}} + value: "condition-key-result" + + message: + template: | + {{- $myVars := .vars -}} + + {{- $someKeyInside := $myVars.some_key-}} + + {{- printf "let's show some stored data: %s/%s" $someKeyInside.name $someKeyInside.namespace -}} +``` ## How to develop diff --git a/charts/admitik/Chart.yaml b/charts/admitik/Chart.yaml index 235fa43..897988a 100644 --- a/charts/admitik/Chart.yaml +++ b/charts/admitik/Chart.yaml @@ -4,10 +4,10 @@ apiVersion: v2 name: admitik type: application description: >- - A Helm chart for admitik, an admission controller for Kubernetes + A Helm chart for Admitik, an admission controller for Kubernetes that allow resources entrance if conditions are met (realtime) -version: 0.1.0 # chart version -appVersion: "0.1.0" # admitik version +version: 0.2.0 # chart version +appVersion: "0.2.0" # admitik version kubeVersion: ">=1.22.0-0" # kubernetes version home: https://github.com/freepik-company/admitik sources: diff --git a/internal/template/functions.go b/internal/template/functions.go index 8a3bbf5..059408e 100644 --- a/internal/template/functions.go +++ b/internal/template/functions.go @@ -17,8 +17,26 @@ import ( // for people who are already comfortable with Helm. Not all the extra functionality was added to keep this simpler. // Ref: https://github.com/helm/helm/blob/main/pkg/engine/funcs.go -func EvaluateTemplate(templateString string, data map[string]interface{}) (result string, err error) { +func EvaluateTemplate(templateString string, data *map[string]interface{}) (result string, err error) { + + // setVar function is defined as clojure to intercept 'data' + // done this way as 'data' being passed as func param in later func map is not convenient + setVar := func(key string, value interface{}) string { + + // Init data['vars'] when needed + vars, ok := (*data)["vars"].(map[string]interface{}) + if !ok || vars == nil { + vars = make(map[string]interface{}) + (*data)["vars"] = vars + } + + // Store data inside + vars[key] = value + return "" + } + templateFunctionsMap := GetFunctionsMap() + templateFunctionsMap["setVar"] = setVar // Create a Template object from the given string parsedTemplate, err := template.New("main").Funcs(templateFunctionsMap).Parse(templateString) diff --git a/internal/xyz/server.go b/internal/xyz/server.go index 4d40e5e..0078b75 100644 --- a/internal/xyz/server.go +++ b/internal/xyz/server.go @@ -171,7 +171,7 @@ func (s *HttpServer) handleRequest(response http.ResponseWriter, request *http.R // Evaluate template conditions var conditionPassed []bool for _, condition := range caPolicyObj.Spec.Conditions { - parsedKey, err := template.EvaluateTemplate(condition.Key, specificTemplateInjectedObject) + parsedKey, err := template.EvaluateTemplate(condition.Key, &specificTemplateInjectedObject) if err != nil { logger.Info(fmt.Sprintf("failed evaluating condition '%s': %s", condition.Name, err.Error())) conditionPassed = append(conditionPassed, false) @@ -183,7 +183,7 @@ func (s *HttpServer) handleRequest(response http.ResponseWriter, request *http.R // When some condition is not met, evaluate message's template and emit a negative response if slices.Contains(conditionPassed, false) { - parsedMessage, err := template.EvaluateTemplate(caPolicyObj.Spec.Message.Template, specificTemplateInjectedObject) + parsedMessage, err := template.EvaluateTemplate(caPolicyObj.Spec.Message.Template, &specificTemplateInjectedObject) if err != nil { logger.Info(fmt.Sprintf("failed parsing message template: %s", err.Error())) return