mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 15:37:19 +00:00
CLI: Global variables (#2401)
* CLI: Global variables Signed-off-by: Kumar Mallikarjuna <kumarmallikarjuna1@gmail.com> * Removed redundant reference Signed-off-by: Kumar Mallikarjuna <kumarmallikarjuna1@gmail.com> * Changed error message Signed-off-by: Kumar Mallikarjuna <kumarmallikarjuna1@gmail.com>
This commit is contained in:
parent
17d0fc16b2
commit
6d6dc8f1bc
7 changed files with 80 additions and 11 deletions
|
@ -150,7 +150,7 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
|
||||||
return rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("pass the values either using set flag or values_file flag", err)
|
return rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("pass the values either using set flag or values_file flag", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
variables, valuesMap, namespaceSelectorMap, err := common.GetVariable(variablesString, valuesFile, fs, false, "")
|
variables, globalValMap, valuesMap, namespaceSelectorMap, err := common.GetVariable(variablesString, valuesFile, fs, false, "")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !sanitizederror.IsErrorSanitized(err) {
|
if !sanitizederror.IsErrorSanitized(err) {
|
||||||
|
@ -281,7 +281,7 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
|
||||||
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(policy)
|
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(policy)
|
||||||
|
|
||||||
for _, resource := range resources {
|
for _, resource := range resources {
|
||||||
thisPolicyResourceValues, err := common.CheckVariableForPolicy(valuesMap, policy.GetName(), resource.GetName(), resource.GetKind(), variables, kindOnwhichPolicyIsApplied, variable)
|
thisPolicyResourceValues, err := common.CheckVariableForPolicy(valuesMap, globalValMap, policy.GetName(), resource.GetName(), resource.GetKind(), variables, kindOnwhichPolicyIsApplied, variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.Name, resource.GetName()), err)
|
return rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.Name, resource.GetName()), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ type Rule struct {
|
||||||
|
|
||||||
type Values struct {
|
type Values struct {
|
||||||
Policies []Policy `json:"policies"`
|
Policies []Policy `json:"policies"`
|
||||||
|
GlobalValues map[string]string `json:"globalValues"`
|
||||||
NamespaceSelectors []NamespaceSelector `json:"namespaceSelector"`
|
NamespaceSelectors []NamespaceSelector `json:"namespaceSelector"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,11 +393,12 @@ func RemoveDuplicateAndObjectVariables(matches [][]string) string {
|
||||||
return variableStr
|
return variableStr
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetVariable(variablesString, valuesFile string, fs billy.Filesystem, isGit bool, policyResourcePath string) (map[string]string, map[string]map[string]Resource, map[string]map[string]string, error) {
|
func GetVariable(variablesString, valuesFile string, fs billy.Filesystem, isGit bool, policyResourcePath string) (map[string]string, map[string]string, map[string]map[string]Resource, map[string]map[string]string, error) {
|
||||||
valuesMapResource := make(map[string]map[string]Resource)
|
valuesMapResource := make(map[string]map[string]Resource)
|
||||||
valuesMapRule := make(map[string]map[string]Rule)
|
valuesMapRule := make(map[string]map[string]Rule)
|
||||||
namespaceSelectorMap := make(map[string]map[string]string)
|
namespaceSelectorMap := make(map[string]map[string]string)
|
||||||
variables := make(map[string]string)
|
variables := make(map[string]string)
|
||||||
|
globalValMap := make(map[string]string)
|
||||||
reqObjVars := ""
|
reqObjVars := ""
|
||||||
|
|
||||||
var yamlFile []byte
|
var yamlFile []byte
|
||||||
|
@ -431,19 +433,21 @@ func GetVariable(variablesString, valuesFile string, fs billy.Filesystem, isGit
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return variables, valuesMapResource, namespaceSelectorMap, sanitizederror.NewWithError("unable to read yaml", err)
|
return variables, globalValMap, valuesMapResource, namespaceSelectorMap, sanitizederror.NewWithError("unable to read yaml", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
valuesBytes, err := yaml.ToJSON(yamlFile)
|
valuesBytes, err := yaml.ToJSON(yamlFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return variables, valuesMapResource, namespaceSelectorMap, sanitizederror.NewWithError("failed to convert json", err)
|
return variables, globalValMap, valuesMapResource, namespaceSelectorMap, sanitizederror.NewWithError("failed to convert json", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
values := &Values{}
|
values := &Values{}
|
||||||
if err := json.Unmarshal(valuesBytes, values); err != nil {
|
if err := json.Unmarshal(valuesBytes, values); err != nil {
|
||||||
return variables, valuesMapResource, namespaceSelectorMap, sanitizederror.NewWithError("failed to decode yaml", err)
|
return variables, globalValMap, valuesMapResource, namespaceSelectorMap, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalValMap = values.GlobalValues
|
||||||
|
|
||||||
for _, p := range values.Policies {
|
for _, p := range values.Policies {
|
||||||
resourceMap := make(map[string]Resource)
|
resourceMap := make(map[string]Resource)
|
||||||
for _, r := range p.Resources {
|
for _, r := range p.Resources {
|
||||||
|
@ -497,7 +501,7 @@ func GetVariable(variablesString, valuesFile string, fs billy.Filesystem, isGit
|
||||||
Policies: storePolices,
|
Policies: storePolices,
|
||||||
})
|
})
|
||||||
|
|
||||||
return variables, valuesMapResource, namespaceSelectorMap, nil
|
return variables, globalValMap, valuesMapResource, namespaceSelectorMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MutatePolices - function to apply mutation on policies
|
// MutatePolices - function to apply mutation on policies
|
||||||
|
@ -947,16 +951,27 @@ func PrintMutatedPolicy(mutatedPolicies []*v1.ClusterPolicy) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckVariableForPolicy(valuesMap map[string]map[string]Resource, policyName string, resourceName string, resourceKind string, variables map[string]string, kindOnwhichPolicyIsApplied map[string]struct{}, variable string) (map[string]string, error) {
|
func CheckVariableForPolicy(valuesMap map[string]map[string]Resource, globalValMap map[string]string, policyName string, resourceName string, resourceKind string, variables map[string]string, kindOnwhichPolicyIsApplied map[string]struct{}, variable string) (map[string]string, error) {
|
||||||
// get values from file for this policy resource combination
|
// get values from file for this policy resource combination
|
||||||
thisPolicyResourceValues := make(map[string]string)
|
thisPolicyResourceValues := make(map[string]string)
|
||||||
if len(valuesMap[policyName]) != 0 && !reflect.DeepEqual(valuesMap[policyName][resourceName], Resource{}) {
|
if len(valuesMap[policyName]) != 0 && !reflect.DeepEqual(valuesMap[policyName][resourceName], Resource{}) {
|
||||||
thisPolicyResourceValues = valuesMap[policyName][resourceName].Values
|
thisPolicyResourceValues = valuesMap[policyName][resourceName].Values
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range variables {
|
for k, v := range variables {
|
||||||
thisPolicyResourceValues[k] = v
|
thisPolicyResourceValues[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if thisPolicyResourceValues == nil && len(globalValMap) > 0 {
|
||||||
|
thisPolicyResourceValues = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range globalValMap {
|
||||||
|
if _, ok := thisPolicyResourceValues[k]; !ok {
|
||||||
|
thisPolicyResourceValues[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// skipping the variable check for non matching kind
|
// skipping the variable check for non matching kind
|
||||||
if _, ok := kindOnwhichPolicyIsApplied[resourceKind]; ok {
|
if _, ok := kindOnwhichPolicyIsApplied[resourceKind]; ok {
|
||||||
if len(variable) > 0 && len(thisPolicyResourceValues) == 0 && len(store.GetContext().Policies) == 0 {
|
if len(variable) > 0 && len(thisPolicyResourceValues) == 0 && len(store.GetContext().Policies) == 0 {
|
||||||
|
|
|
@ -335,7 +335,7 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, valuesFile s
|
||||||
|
|
||||||
fmt.Printf("\nExecuting %s...", values.Name)
|
fmt.Printf("\nExecuting %s...", values.Name)
|
||||||
|
|
||||||
variables, valuesMap, namespaceSelectorMap, err := common.GetVariable(variablesString, values.Variables, fs, isGit, policyResourcePath)
|
variables, globalValMap, valuesMap, namespaceSelectorMap, err := common.GetVariable(variablesString, values.Variables, fs, isGit, policyResourcePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !sanitizederror.IsErrorSanitized(err) {
|
if !sanitizederror.IsErrorSanitized(err) {
|
||||||
return sanitizederror.NewWithError("failed to decode yaml", err)
|
return sanitizederror.NewWithError("failed to decode yaml", err)
|
||||||
|
@ -409,7 +409,7 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, valuesFile s
|
||||||
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(policy)
|
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(policy)
|
||||||
|
|
||||||
for _, resource := range resources {
|
for _, resource := range resources {
|
||||||
thisPolicyResourceValues, err := common.CheckVariableForPolicy(valuesMap, policy.GetName(), resource.GetName(), resource.GetKind(), variables, kindOnwhichPolicyIsApplied, variable)
|
thisPolicyResourceValues, err := common.CheckVariableForPolicy(valuesMap, globalValMap, policy.GetName(), resource.GetName(), resource.GetKind(), variables, kindOnwhichPolicyIsApplied, variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.Name, resource.GetName()), err)
|
return sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.Name, resource.GetName()), err)
|
||||||
}
|
}
|
||||||
|
|
20
test/cli/test/variables/cm-globalval-example.yaml
Normal file
20
test/cli/test/variables/cm-globalval-example.yaml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: cm-globalval-example
|
||||||
|
spec:
|
||||||
|
validationFailureAction: enforce
|
||||||
|
background: false
|
||||||
|
rules:
|
||||||
|
- name: validate-mode
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Pod
|
||||||
|
validate:
|
||||||
|
message: "The value {{ request.mode }} for val1 is not equal to 'dev'."
|
||||||
|
deny:
|
||||||
|
conditions:
|
||||||
|
- key: "{{ request.mode }}"
|
||||||
|
operator: NotEquals
|
||||||
|
value: dev
|
|
@ -63,3 +63,21 @@ spec:
|
||||||
containers:
|
containers:
|
||||||
- name: nginx
|
- name: nginx
|
||||||
image: nginx:1.12
|
image: nginx:1.12
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-global-prod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:latest
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-global-dev
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.12
|
||||||
|
|
|
@ -3,6 +3,7 @@ policies:
|
||||||
- cm-variable-example.yaml
|
- cm-variable-example.yaml
|
||||||
- cm-array-example.yaml
|
- cm-array-example.yaml
|
||||||
- cm-blk-scalar-example.yaml
|
- cm-blk-scalar-example.yaml
|
||||||
|
- cm-globalval-example.yaml
|
||||||
resources:
|
resources:
|
||||||
- resources.yaml
|
- resources.yaml
|
||||||
variables: variables.yaml
|
variables: variables.yaml
|
||||||
|
@ -31,3 +32,11 @@ results:
|
||||||
rule: validate-blk-role-annotation
|
rule: validate-blk-role-annotation
|
||||||
resource: test-blk-app
|
resource: test-blk-app
|
||||||
result: pass
|
result: pass
|
||||||
|
- policy: cm-globalval-example
|
||||||
|
rule: validate-mode
|
||||||
|
resource: test-global-dev
|
||||||
|
result: pass
|
||||||
|
- policy: cm-globalval-example
|
||||||
|
rule: validate-mode
|
||||||
|
resource: test-global-prod
|
||||||
|
result: fail
|
||||||
|
|
|
@ -15,7 +15,7 @@ policies:
|
||||||
rules:
|
rules:
|
||||||
- name: validate-role-annotation
|
- name: validate-role-annotation
|
||||||
values:
|
values:
|
||||||
roles-dictionary.data.allowed-roles: "[\"app\",\"test\"]"
|
roles-dictionary.data.allowed-roles: '["app","test"]'
|
||||||
resources:
|
resources:
|
||||||
- name: test-web
|
- name: test-web
|
||||||
values:
|
values:
|
||||||
|
@ -37,3 +37,10 @@ policies:
|
||||||
- name: test-blk-app
|
- name: test-blk-app
|
||||||
values:
|
values:
|
||||||
request.object.metadata.annotations.role: app
|
request.object.metadata.annotations.role: app
|
||||||
|
- name: cm-globalval-example
|
||||||
|
resources:
|
||||||
|
- name: test-global-prod
|
||||||
|
values:
|
||||||
|
request.mode: prod
|
||||||
|
globalValues:
|
||||||
|
request.mode: dev
|
||||||
|
|
Loading…
Add table
Reference in a new issue