mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
file removed in clean up
This commit is contained in:
parent
bde04ed097
commit
742f8083ad
1 changed files with 0 additions and 401 deletions
|
@ -1,401 +0,0 @@
|
||||||
package annotations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
pinfo "github.com/nirmata/kyverno/pkg/info"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
)
|
|
||||||
|
|
||||||
//Policy information for annotations
|
|
||||||
type Policy struct {
|
|
||||||
Status string `json:"status"`
|
|
||||||
// Key Type/Name
|
|
||||||
MutationRules map[string]Rule `json:"mutationrules,omitempty"`
|
|
||||||
ValidationRules map[string]Rule `json:"validationrules,omitempty"`
|
|
||||||
GenerationRules map[string]Rule `json:"generationrules,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//Rule information for annotations
|
|
||||||
type Rule struct {
|
|
||||||
Status string `json:"status"`
|
|
||||||
Changes string `json:"changes,omitempty"` // TODO for mutation changes
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Policy) getOverAllStatus() string {
|
|
||||||
// mutation
|
|
||||||
for _, v := range p.MutationRules {
|
|
||||||
if v.Status == "Failure" {
|
|
||||||
return "Failure"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// validation
|
|
||||||
for _, v := range p.ValidationRules {
|
|
||||||
if v.Status == "Failure" {
|
|
||||||
return "Failure"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// generation
|
|
||||||
for _, v := range p.GenerationRules {
|
|
||||||
if v.Status == "Failure" {
|
|
||||||
return "Failure"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "Success"
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRules(rules []*pinfo.RuleInfo, ruleType pinfo.RuleType) map[string]Rule {
|
|
||||||
if len(rules) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
annrules := make(map[string]Rule, 0)
|
|
||||||
// var annrules map[string]Rule
|
|
||||||
for _, r := range rules {
|
|
||||||
if r.RuleType != ruleType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
rule := Rule{Status: getStatus(r.IsSuccessful())}
|
|
||||||
if !r.IsSuccessful() {
|
|
||||||
rule.Message = r.GetErrorString()
|
|
||||||
} else {
|
|
||||||
if ruleType == pinfo.Mutation {
|
|
||||||
// If ruleType is Mutation
|
|
||||||
// then for succesful mutation we store the json patch being applied in the annotation information
|
|
||||||
rule.Changes = r.Changes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
annrules[r.Name] = rule
|
|
||||||
}
|
|
||||||
return annrules
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Policy) updatePolicy(obj *Policy, ruleType pinfo.RuleType) bool {
|
|
||||||
updates := false
|
|
||||||
// Check Mutation rules
|
|
||||||
switch ruleType {
|
|
||||||
case pinfo.All:
|
|
||||||
if p.compareMutationRules(obj.MutationRules) {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
if p.compareValidationRules(obj.ValidationRules) {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
if p.compareGenerationRules(obj.GenerationRules) {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
case pinfo.Mutation:
|
|
||||||
if p.compareMutationRules(obj.MutationRules) {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
case pinfo.Validation:
|
|
||||||
if p.compareValidationRules(obj.ValidationRules) {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
case pinfo.Generation:
|
|
||||||
if p.compareGenerationRules(obj.GenerationRules) {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
if p.Status != obj.Status {
|
|
||||||
updates = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check if any rules failed
|
|
||||||
p.Status = p.getOverAllStatus()
|
|
||||||
// If there are any updates then the annotation can be updated, can skip
|
|
||||||
return updates
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Policy) compareMutationRules(rules map[string]Rule) bool {
|
|
||||||
// check if the rules have changed
|
|
||||||
if !reflect.DeepEqual(p.MutationRules, rules) {
|
|
||||||
p.MutationRules = rules
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Policy) compareValidationRules(rules map[string]Rule) bool {
|
|
||||||
// check if the rules have changed
|
|
||||||
if !reflect.DeepEqual(p.ValidationRules, rules) {
|
|
||||||
p.ValidationRules = rules
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Policy) compareGenerationRules(rules map[string]Rule) bool {
|
|
||||||
// check if the rules have changed
|
|
||||||
if !reflect.DeepEqual(p.GenerationRules, rules) {
|
|
||||||
p.GenerationRules = rules
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func newAnnotationForPolicy(pi *pinfo.PolicyInfo) *Policy {
|
|
||||||
return &Policy{Status: getStatus(pi.IsSuccessful()),
|
|
||||||
MutationRules: getRules(pi.Rules, pinfo.Mutation),
|
|
||||||
ValidationRules: getRules(pi.Rules, pinfo.Validation),
|
|
||||||
GenerationRules: getRules(pi.Rules, pinfo.Generation),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//AddPolicy will add policy annotation if not present or update if present
|
|
||||||
// modifies obj
|
|
||||||
// returns true, if there is any update -> caller need to update the obj
|
|
||||||
// returns false, if there is no change -> caller can skip the update
|
|
||||||
func AddPolicy(obj *unstructured.Unstructured, pi *pinfo.PolicyInfo, ruleType pinfo.RuleType) bool {
|
|
||||||
PolicyObj := newAnnotationForPolicy(pi)
|
|
||||||
// get annotation
|
|
||||||
ann := obj.GetAnnotations()
|
|
||||||
// check if policy already has annotation
|
|
||||||
cPolicy, ok := ann[BuildKey(pi.Name)]
|
|
||||||
if !ok {
|
|
||||||
PolicyByte, err := json.Marshal(PolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// insert policy information
|
|
||||||
ann[BuildKey(pi.Name)] = string(PolicyByte)
|
|
||||||
// set annotation back to unstr
|
|
||||||
obj.SetAnnotations(ann)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
cPolicyObj := Policy{}
|
|
||||||
err := json.Unmarshal([]byte(cPolicy), &cPolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// update policy information inside the annotation
|
|
||||||
// 1> policy status
|
|
||||||
// 2> Mutation, Validation, Generation
|
|
||||||
if cPolicyObj.updatePolicy(PolicyObj, ruleType) {
|
|
||||||
|
|
||||||
cPolicyByte, err := json.Marshal(cPolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// update policy information
|
|
||||||
ann[BuildKey(pi.Name)] = string(cPolicyByte)
|
|
||||||
// set annotation back to unstr
|
|
||||||
obj.SetAnnotations(ann)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//RemovePolicy to remove annotations
|
|
||||||
// return true -> if there was an entry and we deleted it
|
|
||||||
// return false -> if there is no entry, caller need not update
|
|
||||||
func RemovePolicy(obj *unstructured.Unstructured, policy string) bool {
|
|
||||||
// get annotations
|
|
||||||
ann := obj.GetAnnotations()
|
|
||||||
if ann == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if _, ok := ann[BuildKey(policy)]; !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
delete(ann, BuildKey(policy))
|
|
||||||
// set annotation back to unstr
|
|
||||||
obj.SetAnnotations(ann)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//ParseAnnotationsFromObject extracts annotations from the JSON obj
|
|
||||||
func ParseAnnotationsFromObject(bytes []byte) map[string]string {
|
|
||||||
var objectJSON map[string]interface{}
|
|
||||||
json.Unmarshal(bytes, &objectJSON)
|
|
||||||
meta, ok := objectJSON["metadata"].(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
glog.Error("unable to parse")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ann, ok, err := unstructured.NestedStringMap(meta, "annotations")
|
|
||||||
if err != nil || !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return ann
|
|
||||||
}
|
|
||||||
|
|
||||||
func PatchAnnotations(ann map[string]string, pi *pinfo.PolicyInfo, ruleType pinfo.RuleType) ([]byte, error) {
|
|
||||||
if ruleType != pinfo.All && !pi.ContainsRuleType(ruleType) {
|
|
||||||
// the rule was not proceesed in the current policy application
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
// transform the PolicyInfo to anotation struct
|
|
||||||
policyObj := newAnnotationForPolicy(pi)
|
|
||||||
if ann == nil {
|
|
||||||
ann = make(map[string]string, 0)
|
|
||||||
policyByte, err := json.Marshal(policyObj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// create a json patch to add annotation object
|
|
||||||
ann[BuildKeyString(pi.Name)] = string(policyByte)
|
|
||||||
// patch adds the annotation map with the policy information
|
|
||||||
jsonPatch, err := createAddJSONPatchMap(ann)
|
|
||||||
return jsonPatch, err
|
|
||||||
}
|
|
||||||
// if the annotations map already exists then we need to update it by adding a patch to the field inside the annotation
|
|
||||||
cPolicy, ok := ann[BuildKey(pi.Name)]
|
|
||||||
if !ok {
|
|
||||||
// annotations does not contain the policy
|
|
||||||
policyByte, err := json.Marshal(policyObj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
jsonPatch, err := createAddJSONPatch(BuildKey(pi.Name), string(policyByte))
|
|
||||||
return jsonPatch, err
|
|
||||||
}
|
|
||||||
// an annotaion exists for the policy, we need to update the information if anything has changed
|
|
||||||
cPolicyObj := Policy{}
|
|
||||||
err := json.Unmarshal([]byte(cPolicy), &cPolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
// error while unmarshallign the content
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// update policy information inside the annotation
|
|
||||||
// 1> policy status
|
|
||||||
// 2> rule (name, status,changes,type)
|
|
||||||
update := cPolicyObj.updatePolicy(policyObj, ruleType)
|
|
||||||
if !update {
|
|
||||||
// there is not update, so we dont
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
policyByte, err := json.Marshal(cPolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
jsonPatch, err := createAddJSONPatch(BuildKey(pi.Name), string(policyByte))
|
|
||||||
return jsonPatch, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//AddPolicyJSONPatch generate JSON Patch to add policy informatino JSON patch
|
|
||||||
func AddPolicyJSONPatch(ann map[string]string, pi *pinfo.PolicyInfo, ruleType pinfo.RuleType) (map[string]string, []byte, error) {
|
|
||||||
if !pi.ContainsRuleType(ruleType) {
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
PolicyObj := newAnnotationForPolicy(pi)
|
|
||||||
if ann == nil {
|
|
||||||
ann = make(map[string]string, 0)
|
|
||||||
PolicyByte, err := json.Marshal(PolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
// create a json patch to add annotation object
|
|
||||||
ann[BuildKey(pi.Name)] = string(PolicyByte)
|
|
||||||
// create add JSON patch
|
|
||||||
jsonPatch, err := createAddJSONPatch(BuildKey(pi.Name), string(PolicyByte))
|
|
||||||
return ann, jsonPatch, err
|
|
||||||
}
|
|
||||||
// if the annotations map is present then we
|
|
||||||
cPolicy, ok := ann[BuildKey(pi.Name)]
|
|
||||||
if !ok {
|
|
||||||
PolicyByte, err := json.Marshal(PolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
// insert policy information
|
|
||||||
ann[BuildKey(pi.Name)] = string(PolicyByte)
|
|
||||||
// create add JSON patch
|
|
||||||
jsonPatch, err := createAddJSONPatch(BuildKey(pi.Name), string(PolicyByte))
|
|
||||||
|
|
||||||
return ann, jsonPatch, err
|
|
||||||
}
|
|
||||||
cPolicyObj := Policy{}
|
|
||||||
err := json.Unmarshal([]byte(cPolicy), &cPolicyObj)
|
|
||||||
// update policy information inside the annotation
|
|
||||||
// 1> policy status
|
|
||||||
// 2> rule (name, status,changes,type)
|
|
||||||
update := cPolicyObj.updatePolicy(PolicyObj, ruleType)
|
|
||||||
if !update {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cPolicyByte, err := json.Marshal(cPolicyObj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
// update policy information
|
|
||||||
ann[BuildKey(pi.Name)] = string(cPolicyByte)
|
|
||||||
// create update JSON patch
|
|
||||||
jsonPatch, err := createReplaceJSONPatch(BuildKey(pi.Name), string(cPolicyByte))
|
|
||||||
return ann, jsonPatch, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//RemovePolicyJSONPatch remove JSON patch
|
|
||||||
func RemovePolicyJSONPatch(ann map[string]string, policy string) (map[string]string, []byte, error) {
|
|
||||||
if ann == nil {
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
jsonPatch, err := createRemoveJSONPatchKey(policy)
|
|
||||||
return ann, jsonPatch, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type patchMapValue struct {
|
|
||||||
Op string `json:"op"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Value map[string]string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type patchStringValue struct {
|
|
||||||
Op string `json:"op"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func createRemoveJSONPatchMap() ([]byte, error) {
|
|
||||||
payload := []patchMapValue{{
|
|
||||||
Op: "remove",
|
|
||||||
Path: "/metadata/annotations",
|
|
||||||
}}
|
|
||||||
return json.Marshal(payload)
|
|
||||||
|
|
||||||
}
|
|
||||||
func createAddJSONPatchMap(ann map[string]string) ([]byte, error) {
|
|
||||||
|
|
||||||
payload := []patchMapValue{{
|
|
||||||
Op: "add",
|
|
||||||
Path: "/metadata/annotations",
|
|
||||||
Value: ann,
|
|
||||||
}}
|
|
||||||
return json.Marshal(payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createAddJSONPatch(key, value string) ([]byte, error) {
|
|
||||||
|
|
||||||
payload := []patchStringValue{{
|
|
||||||
Op: "add",
|
|
||||||
Path: "/metadata/annotations/" + key,
|
|
||||||
Value: value,
|
|
||||||
}}
|
|
||||||
return json.Marshal(payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createReplaceJSONPatch(key, value string) ([]byte, error) {
|
|
||||||
// if ann == nil {
|
|
||||||
// ann = make(map[string]string, 0)
|
|
||||||
// }
|
|
||||||
payload := []patchStringValue{{
|
|
||||||
Op: "replace",
|
|
||||||
Path: "/metadata/annotations/" + key,
|
|
||||||
Value: value,
|
|
||||||
}}
|
|
||||||
return json.Marshal(payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createRemoveJSONPatchKey(key string) ([]byte, error) {
|
|
||||||
payload := []patchStringValue{{
|
|
||||||
Op: "remove",
|
|
||||||
Path: "/metadata/annotations/" + key,
|
|
||||||
}}
|
|
||||||
return json.Marshal(payload)
|
|
||||||
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue