1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/webhooks/annotations.go
2019-08-26 13:34:42 -07:00

176 lines
4.6 KiB
Go

package webhooks
import (
"encoding/json"
"github.com/nirmata/kyverno/pkg/engine"
jsonpatch "github.com/evanphx/json-patch"
"github.com/golang/glog"
)
const (
policyAnnotation = "policies.kyverno.io"
// lastAppliedPatches = policyAnnotation + "last-applied-patches"
)
type policyPatch struct {
PolicyName string `json:"policyname"`
// RulePatches []string `json:"patches"`
RulePatches interface{} `json:"patches"`
}
type rulePatch struct {
RuleName string `json:"rulename"`
Op string `json:"op"`
Path string `json:"path"`
}
type response struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value"`
}
func generateAnnotationPatches(annotations map[string]string, policyResponse engine.PolicyResponse) []byte {
if annotations == nil {
annotations = map[string]string{}
}
var patchResponse response
value := generateAnnotationsFromPolicyResponse(policyResponse)
if value == nil {
// no patches or error while processing patches
return nil
}
if _, ok := annotations[policyAnnotation]; ok {
// create update patch string
patchResponse = response{
Op: "replace",
Path: "/metadata/annotations/" + policyAnnotation,
Value: string(value),
}
} else {
patchResponse = response{
Op: "add",
Path: "/metadata/annotations",
Value: map[string]string{policyAnnotation: string(value)},
}
}
patchByte, _ := json.Marshal(patchResponse)
// check the patch
_, err := jsonpatch.DecodePatch([]byte("[" + string(patchByte) + "]"))
if err != nil {
glog.Errorf("Failed to make patch from annotation'%s', err: %v\n ", string(patchByte), err)
}
return patchByte
}
// func prepareAnnotationPatches(resource *unstructured.Unstructured, policyInfos []info.PolicyInfo) []byte {
// annots := resource.GetAnnotations()
// if annots == nil {
// annots = map[string]string{}
// }
// var patchResponse response
// value := annotationFromPolicies(policyInfos)
// if _, ok := annots[policyAnnotation]; ok {
// // create update patch string
// patchResponse = response{
// Op: "replace",
// Path: "/metadata/annotations/" + policyAnnotation,
// Value: string(value),
// }
// } else {
// patchResponse = response{
// Op: "add",
// Path: "/metadata/annotations",
// Value: map[string]string{policyAnnotation: string(value)},
// }
// }
// patchByte, _ := json.Marshal(patchResponse)
// // check the patch
// _, err := jsonpatch.DecodePatch([]byte("[" + string(patchByte) + "]"))
// if err != nil {
// glog.Errorf("Failed to make patch from annotation'%s', err: %v\n ", string(patchByte), err)
// }
// return patchByte
// }
// func annotationFromPolicies(policyInfos []info.PolicyInfo) []byte {
// var policyPatches []policyPatch
// for _, policyInfo := range policyInfos {
// var pp policyPatch
// pp.PolicyName = policyInfo.Name
// pp.RulePatches = annotationFromPolicy(policyInfo)
// policyPatches = append(policyPatches, pp)
// }
// result, _ := json.Marshal(policyPatches)
// return result
// }
func generateAnnotationsFromPolicyResponse(policyResponse engine.PolicyResponse) []byte {
var rulePatches []rulePatch
// generate annotation for each mutation JSON patch to be applied on the resource
for _, rule := range policyResponse.Rules {
var patchmap map[string]string
patch := engine.JoinPatches(rule.Patches)
if err := json.Unmarshal(patch, &patchmap); err != nil {
glog.Errorf("Failed to parse patch bytes, err: %v\n", err)
continue
}
rp := rulePatch{
RuleName: rule.Name,
Op: patchmap["op"],
Path: patchmap["path"]}
rulePatches = append(rulePatches, rp)
glog.V(4).Infof("Annotation value prepared: %v\n", rulePatches)
}
patch, err := json.Marshal(rulePatches)
if err != nil {
glog.Info("failed to marshall: %v", err)
return nil
}
return patch
}
// func annotationFromPolicy(policyInfo info.PolicyInfo) []rulePatch {
// if !policyInfo.IsSuccessful() {
// glog.V(2).Infof("Policy %s failed, skip preparing annotation\n", policyInfo.Name)
// return nil
// }
// var rulePatches []rulePatch
// for _, ruleInfo := range policyInfo.Rules {
// for _, patch := range ruleInfo.Patches {
// var patchmap map[string]string
// if err := json.Unmarshal(patch, &patchmap); err != nil {
// glog.Errorf("Failed to parse patch bytes, err: %v\n", err)
// continue
// }
// rp := rulePatch{
// RuleName: ruleInfo.Name,
// Op: patchmap["op"],
// Path: patchmap["path"]}
// rulePatches = append(rulePatches, rp)
// glog.V(4).Infof("Annotation value prepared: %v\n", rulePatches)
// }
// }
// return rulePatches
// }