1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-04-08 18:15:48 +00:00

Handle errors properly for mutate and generate on existing resources (#3863)

Signed-off-by: ShutingZhao <shuting@nirmata.com>

Co-authored-by: Prateek Pandey <prateek.pandey@nirmata.com>
This commit is contained in:
shuting 2022-05-11 00:36:50 +08:00 committed by GitHub
parent 22e85209c4
commit 5532203091
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 45 deletions

View file

@ -13,6 +13,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context"
utils "github.com/kyverno/kyverno/pkg/utils"
"github.com/pkg/errors"
admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
@ -24,28 +25,28 @@ func NewBackgroundContext(dclient dclient.Interface, ur *urkyverno.UpdateRequest
ctx := context.NewContext()
requestString := ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest
var request admissionv1.AdmissionRequest
var new, old unstructured.Unstructured
err := json.Unmarshal([]byte(requestString), &request)
if err != nil {
logger.Error(err, "error parsing the request string")
}
if requestString != "" {
err := json.Unmarshal([]byte(requestString), &request)
if err != nil {
return nil, false, errors.Wrap(err, "error parsing the request string")
}
if err := ctx.AddRequest(&request); err != nil {
logger.Error(err, "failed to load request in context")
return nil, false, err
}
if err := ctx.AddRequest(&request); err != nil {
return nil, false, errors.Wrap(err, "failed to load request in context")
}
new, old, err := utils.ExtractResources(nil, &request)
if err != nil {
logger.Error(err, "failed to load request in context")
return nil, false, err
}
new, old, err = utils.ExtractResources(nil, &request)
if err != nil {
return nil, false, errors.Wrap(err, "failed to load request in context")
}
if !reflect.DeepEqual(new, unstructured.Unstructured{}) {
if !check(&new, trigger) {
err := fmt.Errorf("resources don't match")
logger.Error(err, "", "resource", ur.Spec.Resource)
return nil, false, err
if !reflect.DeepEqual(new, unstructured.Unstructured{}) {
if !check(&new, trigger) {
err := fmt.Errorf("resources don't match")
return nil, false, errors.Wrapf(err, "resource %v", ur.Spec.Resource)
}
}
}
@ -53,28 +54,28 @@ func NewBackgroundContext(dclient dclient.Interface, ur *urkyverno.UpdateRequest
trigger = &old
}
err = ctx.AddResource(trigger.Object)
if trigger == nil {
return nil, false, errors.New("trigger resource does not exist")
}
err := ctx.AddResource(trigger.Object)
if err != nil {
logger.Error(err, "failed to load resource in context")
return nil, false, err
return nil, false, errors.Wrap(err, "failed to load resource in context")
}
err = ctx.AddOldResource(old.Object)
if err != nil {
logger.Error(err, "failed to load resource in context")
return nil, false, err
return nil, false, errors.Wrap(err, "failed to load resource in context")
}
err = ctx.AddUserInfo(ur.Spec.Context.UserRequestInfo)
if err != nil {
logger.Error(err, "failed to load SA in context")
return nil, false, err
return nil, false, errors.Wrapf(err, "failed to load SA in context")
}
err = ctx.AddServiceAccount(ur.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
if err != nil {
logger.Error(err, "failed to load UserInfo in context")
return nil, false, err
return nil, false, errors.Wrapf(err, "failed to load UserInfo in context")
}
if err := ctx.AddImageInfos(trigger); err != nil {

View file

@ -12,6 +12,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/response"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@ -48,17 +49,19 @@ func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInte
continue
}
logger.Info("creating new UR")
logger.Info("creating new UR for mutate")
ur := newUR(policy, trigger, ruleType)
err := pc.handleUpdateRequest(ur, trigger, rule, policy)
skip, err := pc.handleUpdateRequest(ur, trigger, rule, policy)
if err != nil {
pc.log.Error(err, "failed to create new UR policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
pc.log.Error(err, "failed to create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
continue
} else {
pc.log.V(4).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
}
if skip {
continue
}
pc.log.V(4).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
}
}
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
@ -72,18 +75,22 @@ func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInte
continue
}
logger.Info("creating new UR")
logger.Info("creating new UR for generate")
ur := newUR(policy, trigger, ruleType)
err := pc.handleUpdateRequest(ur, trigger, rule, policy)
skip, err := pc.handleUpdateRequest(ur, trigger, rule, policy)
if err != nil {
pc.log.Error(err, "failed to create new UR policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
pc.log.Error(err, "failed to create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
errors = append(errors, err)
continue
} else {
pc.log.V(4).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
}
if skip {
continue
}
pc.log.V(4).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
}
err := engineutils.CombineErrors(errors)
return err
@ -92,31 +99,35 @@ func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInte
return nil
}
func (pc *PolicyController) handleUpdateRequest(ur *urkyverno.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyverno.Rule, policy kyverno.PolicyInterface) error {
func (pc *PolicyController) handleUpdateRequest(ur *urkyverno.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyverno.Rule, policy kyverno.PolicyInterface) (skip bool, err error) {
policyContext, _, err := common.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, nil, pc.log)
if err != nil {
pc.log.WithName(rule.Name).Error(err, "failed to build policy context for existing")
return false, errors.Wrapf(err, "failed to build policy context for rule %s", rule.Name)
}
engineResponse := engine.ApplyBackgroundChecks(policyContext)
if len(engineResponse.PolicyResponse.Rules) == 0 {
return true, nil
}
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
if ruleResponse.Status != response.RuleStatusPass {
pc.log.Error(err, "can not create new UR for genExisting rule on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule.Status", ruleResponse.Status)
pc.log.Error(err, "can not create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule.Status", ruleResponse.Status)
continue
}
new, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), ur, metav1.CreateOptions{})
if err != nil {
return err
return false, err
}
new.Status.State = urkyverno.Pending
if _, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
pc.log.Error(err, "failed to set UpdateRequest state to Pending")
return err
return false, err
}
}
return err
return false, err
}
func (pc *PolicyController) listMutateURs(policyKey string, trigger *unstructured.Unstructured) []*urkyverno.UpdateRequest {