1
0
Fork 0
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:
Shivkumar Dudhani 2019-08-19 17:06:05 -07:00 committed by GitHub
parent bde04ed097
commit 742f8083ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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)
}