1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 10:28:36 +00:00

add process existing for mutation & validation + come cleanup

This commit is contained in:
shivkumar dudhani 2019-08-13 11:32:12 -07:00
parent 4bf3043a18
commit e7b538be79
16 changed files with 279 additions and 131 deletions

View file

@ -48,7 +48,7 @@ func (p *Policy) getOverAllStatus() string {
return "Success"
}
func getRules(rules []*pinfo.RuleInfo, ruleType pinfo.RuleType) map[string]Rule {
func getRules(rules []pinfo.RuleInfo, ruleType pinfo.RuleType) map[string]Rule {
if len(rules) == 0 {
return nil
}

View file

@ -1,107 +1,105 @@
package engine
import (
jsonpatch "github.com/evanphx/json-patch"
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ProcessExisting checks for mutation and validation violations of existing resources
func ProcessExisting(client *client.Client, policy *kyverno.Policy, filterK8Resources []utils.K8Resource) []info.PolicyInfo {
glog.Infof("Applying policy %s on existing resources", policy.Name)
// key uid
resourceMap := ListResourcesThatApplyToPolicy(client, policy, filterK8Resources)
policyInfos := []info.PolicyInfo{}
// for the filtered resource apply policy
for _, v := range resourceMap {
return nil
// glog.Infof("Applying policy %s on existing resources", policy.Name)
// // key uid
// resourceMap := ListResourcesThatApplyToPolicy(client, policy, filterK8Resources)
// policyInfos := []info.PolicyInfo{}
// // for the filtered resource apply policy
// for _, v := range resourceMap {
policyInfo, err := applyPolicy(client, policy, v)
if err != nil {
glog.Errorf("unable to apply policy %s on resource %s/%s", policy.Name, v.Resource.GetName(), v.Resource.GetNamespace())
glog.Error(err)
continue
}
policyInfos = append(policyInfos, policyInfo)
}
// policyInfo, err := applyPolicy(client, policy, v)
// if err != nil {
// glog.Errorf("unable to apply policy %s on resource %s/%s", policy.Name, v.Resource.GetName(), v.Resource.GetNamespace())
// glog.Error(err)
// continue
// }
// policyInfos = append(policyInfos, policyInfo)
// }
return policyInfos
// return policyInfos
}
func applyPolicy(client *client.Client, policy *kyverno.Policy, res resourceInfo) (info.PolicyInfo, error) {
var policyInfo info.PolicyInfo
glog.Infof("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
rawResource, err := res.Resource.MarshalJSON()
if err != nil {
return policyInfo, err
}
// Mutate
mruleInfos, err := mutation(policy, rawResource, res.Gvk)
policyInfo.AddRuleInfos(mruleInfos)
if err != nil {
return policyInfo, err
}
// Validation
//TODO check by value or pointer
vruleInfos, err := Validate(*policy, rawResource, *res.Gvk)
if err != nil {
return policyInfo, err
}
policyInfo.AddRuleInfos(vruleInfos)
policyInfo = info.NewPolicyInfo(policy.Name, res.Gvk.Kind, res.Resource.GetName(), res.Resource.GetNamespace(), policy.Spec.ValidationFailureAction)
// func applyPolicy(client *client.Client, policy *kyverno.Policy, res resourceInfo) (info.PolicyInfo, error) {
// var policyInfo info.PolicyInfo
// glog.Infof("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
// rawResource, err := res.Resource.MarshalJSON()
// if err != nil {
// return policyInfo, err
// }
// // Mutate
// mruleInfos, err := mutation(policy, rawResource, res.Gvk)
// policyInfo.AddRuleInfos(mruleInfos)
// if err != nil {
// return policyInfo, err
// }
// // Validation
// //TODO check by value or pointer
// vruleInfos, err := Validate(*policy, rawResource, *res.Gvk)
// if err != nil {
// return policyInfo, err
// }
// policyInfo.AddRuleInfos(vruleInfos)
// policyInfo = info.NewPolicyInfo(policy.Name, res.Gvk.Kind, res.Resource.GetName(), res.Resource.GetNamespace(), policy.Spec.ValidationFailureAction)
if res.Gvk.Kind == "Namespace" {
// if res.Gvk.Kind == "Namespace" {
// Generation
gruleInfos := Generate(client, policy, res.Resource)
policyInfo.AddRuleInfos(gruleInfos)
}
// // Generation
// gruleInfos := Generate(client, policy, res.Resource)
// policyInfo.AddRuleInfos(gruleInfos)
// }
return policyInfo, nil
}
// return policyInfo, nil
// }
func mutation(p *kyverno.Policy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
patches, ruleInfos := Mutate(*p, rawResource, *gvk)
if len(ruleInfos) == 0 {
// no rules were processed
return nil, nil
}
// if there are any errors return
for _, r := range ruleInfos {
if !r.IsSuccessful() {
return ruleInfos, nil
}
}
// if there are no patches // for overlay
if len(patches) == 0 {
return ruleInfos, nil
}
// option 2: (original Resource + patch) compare with (original resource)
mergePatches := JoinPatches(patches)
// merge the patches
patch, err := jsonpatch.DecodePatch(mergePatches)
if err != nil {
return nil, err
}
// apply the patches returned by mutate to the original resource
patchedResource, err := patch.Apply(rawResource)
if err != nil {
return nil, err
}
// compare (original Resource + patch) vs (original resource)
// to verify if they are equal
ruleInfo := info.NewRuleInfo("over-all mutation", info.Mutation)
if !jsonpatch.Equal(patchedResource, rawResource) {
//resource does not match so there was a mutation rule violated
// TODO : check the rule name "mutation rules"
ruleInfo.Fail()
ruleInfo.Add("resource does not satisfy mutation rules")
} else {
ruleInfo.Add("resource satisfys the mutation rule")
}
ruleInfos = append(ruleInfos, ruleInfo)
return ruleInfos, nil
}
// func mutation(p *kyverno.Policy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
// patches, ruleInfos := Mutate(*p, rawResource, *gvk)
// if len(ruleInfos) == 0 {
// // no rules were processed
// return nil, nil
// }
// // if there are any errors return
// for _, r := range ruleInfos {
// if !r.IsSuccessful() {
// return ruleInfos, nil
// }
// }
// // if there are no patches // for overlay
// if len(patches) == 0 {
// return ruleInfos, nil
// }
// // option 2: (original Resource + patch) compare with (original resource)
// mergePatches := JoinPatches(patches)
// // merge the patches
// patch, err := jsonpatch.DecodePatch(mergePatches)
// if err != nil {
// return nil, err
// }
// // apply the patches returned by mutate to the original resource
// patchedResource, err := patch.Apply(rawResource)
// if err != nil {
// return nil, err
// }
// // compare (original Resource + patch) vs (original resource)
// // to verify if they are equal
// ruleInfo := info.NewRuleInfo("over-all mutation", info.Mutation)
// if !jsonpatch.Equal(patchedResource, rawResource) {
// //resource does not match so there was a mutation rule violated
// // TODO : check the rule name "mutation rules"
// ruleInfo.Fail()
// ruleInfo.Add("resource does not satisfy mutation rules")
// } else {
// ruleInfo.Add("resource satisfys the mutation rule")
// }
// ruleInfos = append(ruleInfos, ruleInfo)
// return ruleInfos, nil
// }

View file

@ -14,8 +14,8 @@ import (
)
//Generate apply generation rules on a resource
func Generate(client *client.Client, policy *kyverno.Policy, ns unstructured.Unstructured) []*info.RuleInfo {
ris := []*info.RuleInfo{}
func Generate(client *client.Client, policy *kyverno.Policy, ns unstructured.Unstructured) []info.RuleInfo {
ris := []info.RuleInfo{}
for _, rule := range policy.Spec.Rules {
if rule.Generation == (kyverno.Generation{}) {
continue

View file

@ -6,20 +6,15 @@ import (
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
"github.com/nirmata/kyverno/pkg/info"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// Mutate performs mutation. Overlay first and then mutation patches
//TODO: check if gvk needs to be passed or can be set in resource
func Mutate(policy kyverno.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([][]byte, []*info.RuleInfo) {
func Mutate(policy kyverno.Policy, resource unstructured.Unstructured) ([][]byte, []info.RuleInfo) {
//TODO: convert rawResource to unstructured to avoid unmarhalling all the time for get some resource information
//TODO: pass unstructured instead of rawResource ?
resource, err := convertToUnstructured(rawResource)
if err != nil {
glog.Errorf("unable to convert raw resource to unstructured: %v", err)
}
var patches [][]byte
var ruleInfos []*info.RuleInfo
var ruleInfos []info.RuleInfo
for _, rule := range policy.Spec.Rules {
if reflect.DeepEqual(rule.Mutation, kyverno.Mutation{}) {
@ -29,7 +24,7 @@ func Mutate(policy kyverno.Policy, rawResource []byte, gvk metav1.GroupVersionKi
// check if the resource satisfies the filter conditions defined in the rule
//TODO: this needs to be extracted, to filter the resource so that we can avoid passing resources that
// dont statisfy a policy rule resource description
ok := MatchesResourceDescription(resource, rule, gvk)
ok := MatchesResourceDescription(resource, rule)
if !ok {
glog.V(4).Infof("resource %s/%s does not satisfy the resource description for the rule ", resource.GetNamespace(), resource.GetName())
continue
@ -39,7 +34,7 @@ func Mutate(policy kyverno.Policy, rawResource []byte, gvk metav1.GroupVersionKi
// Process Overlay
if rule.Mutation.Overlay != nil {
oPatches, err := processOverlay(resource, rule, rawResource)
oPatches, err := processOverlay(resource, rule)
if err == nil {
if len(oPatches) == 0 {
// if array elements dont match then we skip(nil patch, no error)
@ -66,7 +61,7 @@ func Mutate(policy kyverno.Policy, rawResource []byte, gvk metav1.GroupVersionKi
// Process Patches
if len(rule.Mutation.Patches) != 0 {
jsonPatches, errs := processPatches(rule, rawResource)
jsonPatches, errs := processPatches(resource, rule)
if len(errs) > 0 {
ruleInfo.Fail()
for _, err := range errs {

View file

@ -17,7 +17,7 @@ import (
// ProcessOverlay handles validating admission request
// Checks the target resources for rules defined in the policy
func processOverlay(resourceUnstr *unstructured.Unstructured, rule kyverno.Rule, rawResource []byte) ([][]byte, error) {
func processOverlay(resourceUnstr unstructured.Unstructured, rule kyverno.Rule) ([][]byte, error) {
//TODO check if there is better solution
resourceRaw, err := resourceUnstr.MarshalJSON()

View file

@ -3,9 +3,11 @@ package engine
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
jsonpatch "github.com/evanphx/json-patch"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
@ -13,7 +15,15 @@ import (
// ProcessPatches Returns array from separate patches that can be applied to the document
// Returns error ONLY in case when creation of resource should be denied.
func processPatches(rule kyverno.Rule, resource []byte) (allPatches [][]byte, errs []error) {
func processPatches(resourceUnstr unstructured.Unstructured, rule kyverno.Rule) (allPatches [][]byte, errs []error) {
//TODO check if there is better solution
resource, err := resourceUnstr.MarshalJSON()
if err != nil {
glog.V(4).Infof("unable to marshal resource : %v", err)
errs = append(errs, fmt.Errorf("unable to marshal resource : %v", err))
return nil, errs
}
if len(resource) == 0 {
errs = append(errs, errors.New("Source document for patching is empty"))
return nil, errs

View file

@ -150,11 +150,11 @@ func excludeNamespaces(namespaces []string, excludeNs string) []string {
}
//MatchesResourceDescription checks if the resource matches resource desription of the rule or not
func MatchesResourceDescription(resource *unstructured.Unstructured, rule kyverno.Rule, gvk metav1.GroupVersionKind) bool {
func MatchesResourceDescription(resource unstructured.Unstructured, rule kyverno.Rule) bool {
matches := rule.MatchResources.ResourceDescription
exclude := rule.ExcludeResources.ResourceDescription
if !findKind(matches.Kinds, gvk.Kind) {
if !findKind(matches.Kinds, resource.GetKind()) {
return false
}

View file

@ -12,30 +12,30 @@ import (
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
"github.com/nirmata/kyverno/pkg/info"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// Validate handles validating admission request
// Checks the target resources for rules defined in the policy
func Validate(policy kyverno.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
func Validate(policy kyverno.Policy, resource unstructured.Unstructured) ([]info.RuleInfo, error) {
//TODO: convert rawResource to unstructured to avoid unmarhalling all the time for get some resource information
//TODO: pass unstructured instead of rawResource ?
resourceUnstr, err := convertToUnstructured(rawResource)
if err != nil {
glog.Errorf("unable to convert raw resource to unstructured: %v", err)
}
resourceRaw, err := resourceUnstr.MarshalJSON()
// resourceUnstr, err := convertToUnstructured(rawResource)
// if err != nil {
// glog.Errorf("unable to convert raw resource to unstructured: %v", err)
// }
resourceRaw, err := resource.MarshalJSON()
if err != nil {
glog.V(4).Infof("unable to marshal resource : %v", err)
return nil, err
}
var resource interface{}
if err := json.Unmarshal(resourceRaw, &resource); err != nil {
var resourceInt interface{}
if err := json.Unmarshal(resourceRaw, &resourceInt); err != nil {
glog.V(4).Infof("unable to unmarshal resource : %v", err)
return nil, err
}
var ruleInfos []*info.RuleInfo
var ruleInfos []info.RuleInfo
for _, rule := range policy.Spec.Rules {
if reflect.DeepEqual(rule.Validation, kyverno.Validation{}) {
@ -45,21 +45,21 @@ func Validate(policy kyverno.Policy, rawResource []byte, gvk metav1.GroupVersion
// check if the resource satisfies the filter conditions defined in the rule
//TODO: this needs to be extracted, to filter the resource so that we can avoid passing resources that
// dont statisfy a policy rule resource description
ok := MatchesResourceDescription(resourceUnstr, rule, gvk)
ok := MatchesResourceDescription(resource, rule)
if !ok {
glog.V(4).Infof("resource %s/%s does not satisfy the resource description for the rule ", resourceUnstr.GetNamespace(), resourceUnstr.GetName())
glog.V(4).Infof("resource %s/%s does not satisfy the resource description for the rule ", resource.GetNamespace(), resource.GetName())
continue
}
ruleInfo := info.NewRuleInfo(rule.Name, info.Validation)
err := validateResourceWithPattern(resource, rule.Validation.Pattern)
err := validateResourceWithPattern(resourceInt, rule.Validation.Pattern)
if err != nil {
ruleInfo.Fail()
ruleInfo.Addf("Failed to apply pattern: %v.", err)
} else {
ruleInfo.Add("Pattern succesfully validated")
glog.V(4).Infof("pattern validated succesfully on resource %s/%s", resourceUnstr.GetNamespace(), resourceUnstr.GetName())
glog.V(4).Infof("pattern validated succesfully on resource %s/%s", resource.GetNamespace(), resource.GetName())
}
ruleInfos = append(ruleInfos, ruleInfo)
}

View file

@ -20,7 +20,7 @@ type PolicyInfo struct {
RNamespace string
//TODO: add check/enum for types
ValidationFailureAction string // BlockChanges, ReportViolation
Rules []*RuleInfo
Rules []RuleInfo
success bool
}
@ -135,8 +135,8 @@ func (ri *RuleInfo) GetErrorString() string {
}
//NewRuleInfo creates a new RuleInfo
func NewRuleInfo(ruleName string, ruleType RuleType) *RuleInfo {
return &RuleInfo{
func NewRuleInfo(ruleName string, ruleType RuleType) RuleInfo {
return RuleInfo{
Name: ruleName,
Msgs: []string{},
RuleType: ruleType,
@ -165,7 +165,7 @@ func (ri *RuleInfo) Addf(msg string, args ...interface{}) {
}
//RulesSuccesfuly check if the any rule has failed or not
func RulesSuccesfuly(rules []*RuleInfo) bool {
func RulesSuccesfuly(rules []RuleInfo) bool {
for _, r := range rules {
if !r.success {
return false
@ -175,7 +175,7 @@ func RulesSuccesfuly(rules []*RuleInfo) bool {
}
//AddRuleInfos sets the rule information
func (pi *PolicyInfo) AddRuleInfos(rules []*RuleInfo) {
func (pi *PolicyInfo) AddRuleInfos(rules []RuleInfo) {
if rules == nil {
return
}

93
pkg/policy/apply.go Normal file
View file

@ -0,0 +1,93 @@
package policy
import (
"time"
jsonpatch "github.com/evanphx/json-patch"
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
"github.com/nirmata/kyverno/pkg/engine"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// applyPolicy applies policy on a resource
//TODO: generation rules
func applyPolicy(policy kyverno.Policy, resource unstructured.Unstructured) (info.PolicyInfo, error) {
startTime := time.Now()
glog.V(4).Infof("Started apply policy %s on resource %s/%s/%s (%v)", policy.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), startTime)
defer func() {
glog.V(4).Infof("Finished applying %s on resource %s/%s/%s (%v)", policy.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), time.Since(startTime))
}()
// glog.V(4).Infof("apply policy %s with resource version %s on resource %s/%s/%s with resource version %s", policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion())
var policyInfo info.PolicyInfo
//MUTATION
mruleInfos, err := mutation(policy, resource)
policyInfo.AddRuleInfos(mruleInfos)
if err != nil {
return policyInfo, err
}
//VALIDATION
vruleInfos, err := engine.Validate(policy, resource)
policyInfo.AddRuleInfos(vruleInfos)
if err != nil {
return policyInfo, err
}
//TODO: GENERATION
return policyInfo, nil
}
func mutation(policy kyverno.Policy, resource unstructured.Unstructured) ([]info.RuleInfo, error) {
patches, ruleInfos := engine.Mutate(policy, resource)
if len(ruleInfos) == 0 {
//no rules processed
return nil, nil
}
for _, r := range ruleInfos {
if !r.IsSuccessful() {
// no failures while processing rule
return ruleInfos, nil
}
}
if len(patches) == 0 {
// no patches for the resources
// either there were failures or the overlay already was satisfied
return ruleInfos, nil
}
// (original resource + patch) == (original resource)
mergePatches := utils.JoinPatches(patches)
patch, err := jsonpatch.DecodePatch(mergePatches)
if err != nil {
return nil, err
}
rawResource, err := resource.MarshalJSON()
if err != nil {
glog.V(4).Infof("unable to marshal resource : %v", err)
return nil, err
}
// apply the patches returned by mutate to the original resource
patchedResource, err := patch.Apply(rawResource)
if err != nil {
return nil, err
}
//TODO: this will be removed after the support for patching for each rule
ruleInfo := info.NewRuleInfo("over-all mutation", info.Mutation)
if !jsonpatch.Equal(patchedResource, rawResource) {
//resource does not match so there was a mutation rule violated
// TODO : check the rule name "mutation rules"
ruleInfo.Fail()
ruleInfo.Add("resource does not satisfy mutation rules")
} else {
ruleInfo.Add("resource satisfys the mutation rule")
}
ruleInfos = append(ruleInfos, ruleInfo)
return ruleInfos, nil
}

View file

@ -397,7 +397,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
return err
}
// process policies on existing resources
pc.processExistingResources(p)
pc.processExistingResources(*p)
return pc.syncStatusOnly(p, pvList)
}

View file

@ -8,12 +8,13 @@ import (
"github.com/minio/minio/pkg/wildcard"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func (pc *PolicyController) processExistingResources(policy *kyverno.Policy) {
func (pc *PolicyController) processExistingResources(policy kyverno.Policy) {
// Parse through all the resources
// drops the cache after configured rebuild time
pc.rm.Drop()
@ -23,17 +24,27 @@ func (pc *PolicyController) processExistingResources(policy *kyverno.Policy) {
for _, resource := range resourceMap {
// pre-processing, check if the policy and resource version has been processed before
if !pc.rm.ProcessResource(policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion()) {
glog.V(4).Infof("policy %s with resource versio %s already processed on resource %s/%s/%s with resource version %s", policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion())
glog.V(4).Infof("policy %s with resource version %s already processed on resource %s/%s/%s with resource version %s", policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion())
continue
}
// apply the policy on each
glog.V(4).Infof("apply policy %s with resource version %s on resource %s/%s/%s with resource version %s", policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion())
applyPolicyOnResource(policy, resource)
// post-processing, register the resource as processed
pc.rm.RegisterResource(policy.GetName(), policy.GetResourceVersion(), resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion())
}
}
func listResources(client *client.Client, policy *kyverno.Policy, filterK8Resources []utils.K8Resource) map[string]unstructured.Unstructured {
func applyPolicyOnResource(policy kyverno.Policy, resource unstructured.Unstructured) *info.PolicyInfo {
policyInfo, err := applyPolicy(policy, resource)
if err != nil {
glog.V(4).Infof("failed to process policy %s on resource %s/%s/%s: %v", policy.GetName(), resource.GetKind(), resource.GetNamespace(), resource.GetName(), err)
return nil
}
return &policyInfo
}
func listResources(client *client.Client, policy kyverno.Policy, filterK8Resources []utils.K8Resource) map[string]unstructured.Unstructured {
// key uid
resourceMap := map[string]unstructured.Unstructured{}

View file

@ -187,3 +187,21 @@ func subsetSlice(a, b []interface{}) bool {
}
return true
}
// JoinPatches joins array of serialized JSON patches to the single JSONPatch array
func JoinPatches(patches [][]byte) []byte {
var result []byte
if len(patches) == 0 {
return result
}
result = append(result, []byte("[\n")...)
for index, patch := range patches {
result = append(result, patch...)
if index != len(patches)-1 {
result = append(result, []byte(",\n")...)
}
}
result = append(result, []byte("\n]")...)
return result
}

View file

@ -4,8 +4,11 @@ import (
"regexp"
"strings"
"github.com/golang/glog"
"github.com/minio/minio/pkg/wildcard"
"k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func Contains(list []string, element string) bool {
@ -74,3 +77,14 @@ func ParseKinds(list string) []K8Resource {
}
return resources
}
//ConvertToUnstructured coverts a raw resource into unstructured struct
func ConvertToUnstructured(data []byte) (*unstructured.Unstructured, error) {
resource := &unstructured.Unstructured{}
err := resource.UnmarshalJSON(data)
if err != nil {
glog.V(4).Infof("failed to unmarshall resource: %v", err)
return nil, err
}
return resource, nil
}

View file

@ -51,8 +51,17 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation)
glog.V(4).Infof("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
// resource, err := utils.ConvertToUnstructured(request.Object.Raw)
// if err != nil {
// glog.Errorf("unable to process policy %s resource %v: %v", policy.GetName(), request.Resource, err)
// continue
// }
//TODO: check if the GVK information is present in the request of we set it explicity here ?
glog.V(4).Infof("GVK is %v", resource.GroupVersionKind())
// resource.SetGroupVersionKind(schema.GroupVersionKind{Group: request.Kind.Group, Version: request.Kind.Version, Kind: request.Kind.Kind})
//TODO: passing policy value as we dont wont to modify the policy
policyPatches, ruleInfos := engine.Mutate(*policy, request.Object.Raw, request.Kind)
policyPatches, ruleInfos := engine.Mutate(*policy, *resource)
policyInfo.AddRuleInfos(ruleInfos)
policyInfos = append(policyInfos, policyInfo)
if !policyInfo.IsSuccessful() {

View file

@ -52,7 +52,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1
glog.V(4).Infof("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
ruleInfos, err := engine.Validate(*policy, request.Object.Raw, request.Kind)
ruleInfos, err := engine.Validate(*policy, *resource)
if err != nil {
// This is not policy error
// but if unable to parse request raw resource