mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 10:28:36 +00:00
Change of annotation purpose #262
This commit is contained in:
parent
998f612679
commit
4c34ff7a37
6 changed files with 129 additions and 11 deletions
|
@ -56,11 +56,8 @@ func Mutate(policy kyverno.Policy, resource unstructured.Unstructured) EngineRes
|
|||
|
||||
ruleInfo.Addf("Rule %s: Overlay succesfully applied.", rule.Name)
|
||||
|
||||
// merge the json patches
|
||||
patch := JoinPatches(rulePatches)
|
||||
|
||||
// strip slashes from string
|
||||
ruleInfo.Changes = string(patch)
|
||||
ruleInfo.Patches = rulePatches
|
||||
allPatches = append(allPatches, rulePatches...)
|
||||
|
||||
glog.V(4).Infof("overlay applied succesfully on resource %s/%s", resource.GetNamespace(), resource.GetName())
|
||||
|
@ -83,6 +80,8 @@ func Mutate(policy kyverno.Policy, resource unstructured.Unstructured) EngineRes
|
|||
} else {
|
||||
glog.V(4).Infof("patches applied succesfully on resource %s/%s", resource.GetNamespace(), resource.GetName())
|
||||
ruleInfo.Addf("Patches succesfully applied.")
|
||||
|
||||
ruleInfo.Patches = rulePatches
|
||||
allPatches = append(allPatches, rulePatches...)
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +95,11 @@ func Mutate(policy kyverno.Policy, resource unstructured.Unstructured) EngineRes
|
|||
}
|
||||
|
||||
patchedResource, err := ConvertToUnstructured(patchedDocument)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to convert patched resource to unstructuredtype, err%v\n:", err)
|
||||
return EngineResponse{PatchedResource: resource}
|
||||
}
|
||||
|
||||
return EngineResponse{
|
||||
Patches: allPatches,
|
||||
PatchedResource: *patchedResource,
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
func Validate(policy kyverno.Policy, resource unstructured.Unstructured) EngineResponse {
|
||||
resourceRaw, err := resource.MarshalJSON()
|
||||
if err != nil {
|
||||
glog.V(4).Infof("unable to marshal resource : %v\n", err)
|
||||
glog.V(4).Infof("Skip processing validating rule, unable to marshal resource : %v\n", err)
|
||||
return EngineResponse{PatchedResource: resource}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ type RuleInfo struct {
|
|||
Name string
|
||||
RuleType RuleType
|
||||
Msgs []string
|
||||
Changes string // this will store the mutation patch being applied by the rule
|
||||
Patches [][]byte // this will store the mutation patch being applied by the rule
|
||||
success bool
|
||||
}
|
||||
|
||||
|
|
113
pkg/webhooks/annotations.go
Normal file
113
pkg/webhooks/annotations.go
Normal file
|
@ -0,0 +1,113 @@
|
|||
package webhooks
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
"github.com/nirmata/kyverno/pkg/info"
|
||||
)
|
||||
|
||||
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 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 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
|
||||
}
|
|
@ -62,18 +62,20 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool
|
|||
}
|
||||
continue
|
||||
}
|
||||
// build annotations per policy being applied to show the mutation changes
|
||||
patches = append(patches, engineResponse.Patches...)
|
||||
glog.V(4).Infof("Mutation from policy %s has applied succesfully to %s %s/%s", policy.Name, request.Kind.Kind, resource.GetNamespace(), resource.GetName())
|
||||
|
||||
patches = append(patches, engineResponse.Patches...)
|
||||
policyInfos = append(policyInfos, policyInfo)
|
||||
glog.V(4).Infof("Mutation from policy %s has applied succesfully to %s %s/%s", policy.Name, request.Kind.Kind, resource.GetNamespace(), resource.GetName())
|
||||
}
|
||||
|
||||
// ADD ANNOTATIONS
|
||||
// TODO: merge the annotation patch with the patch response
|
||||
// ADD EVENTS
|
||||
if len(patches) > 0 {
|
||||
eventsInfo := newEventInfoFromPolicyInfo(policyInfos, (request.Operation == v1beta1.Update), info.Mutation)
|
||||
ws.eventGen.Add(eventsInfo...)
|
||||
|
||||
annotation := prepareAnnotationPatches(resource, policyInfos)
|
||||
patches = append(patches, annotation)
|
||||
}
|
||||
|
||||
ok, msg := isAdmSuccesful(policyInfos)
|
||||
|
|
|
@ -52,7 +52,6 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, res
|
|||
|
||||
engineResponse := engine.Validate(*policy, resource)
|
||||
if len(engineResponse.RuleInfos) == 0 {
|
||||
glog.Errorln("Failed to process validate rule, error parsing rawResource")
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue