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:
parent
22e85209c4
commit
5532203091
2 changed files with 57 additions and 45 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue