mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
fix: stop mutation policies when autogen internals is enabled (#4004,#4009,#3996) (#4016)
* fix: stop mutation policies when autogen internals is enabled (#4004) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> (cherry picked from commitc9f8a68d8a
) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * fix: use background helper in ur generator (#4009) * fix: stop mutating cached resource in ur controller (#4003) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> (cherry picked from commitdac733755b
) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * fix: use background helper in ur generator Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> (cherry picked from commit3a3556919f
) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * refactor: move label helper utils from policy package to background package (#3996) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> (cherry picked from commit1712dfa947
) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
parent
eaa629714e
commit
56d32e93e7
13 changed files with 226 additions and 307 deletions
|
@ -457,17 +457,3 @@ type CloneFrom struct {
|
|||
// Name specifies name of the resource.
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
}
|
||||
|
||||
type ResourceSpec struct {
|
||||
// APIVersion specifies resource apiVersion.
|
||||
// +optional
|
||||
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
|
||||
// Kind specifies resource kind.
|
||||
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
|
||||
// Namespace specifies resource namespace.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
// Name specifies the resource name.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
}
|
||||
|
|
20
api/kyverno/v1/resource_spec_types.go
Normal file
20
api/kyverno/v1/resource_spec_types.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package v1
|
||||
|
||||
type ResourceSpec struct {
|
||||
// APIVersion specifies resource apiVersion.
|
||||
// +optional
|
||||
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
|
||||
// Kind specifies resource kind.
|
||||
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
|
||||
// Namespace specifies resource namespace.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
// Name specifies the resource name.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (s ResourceSpec) GetName() string { return s.Name }
|
||||
func (s ResourceSpec) GetNamespace() string { return s.Namespace }
|
||||
func (s ResourceSpec) GetKind() string { return s.Kind }
|
||||
func (s ResourceSpec) GetAPIVersion() string { return s.APIVersion }
|
|
@ -9,5 +9,9 @@ const (
|
|||
URMutatetriggerAPIVersionLabel = "mutate.updaterequest.kyverno.io/trigger-apiversion"
|
||||
|
||||
// URGeneratePolicyLabel adds the policy name to URs for generate policies
|
||||
URGeneratePolicyLabel = "generate.kyverno.io/policy-name"
|
||||
URGeneratePolicyLabel = "generate.kyverno.io/policy-name"
|
||||
URGenerateResourceNameLabel = "generate.kyverno.io/resource-name"
|
||||
URGenerateResourceNSLabel = "generate.kyverno.io/resource-namespace"
|
||||
URGenerateResourceKindLabel = "generate.kyverno.io/resource-kind"
|
||||
URGenerateRetryCountAnnotation = "generate.kyverno.io/retry-count"
|
||||
)
|
||||
|
|
|
@ -278,10 +278,7 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
urgen := webhookgenerate.NewGenerator(kyvernoClient,
|
||||
kyvernoInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
stopCh,
|
||||
log.Log.WithName("UpdateRequestGenerator"))
|
||||
urgen := webhookgenerate.NewGenerator(kyvernoClient, kyvernoInformer.Kyverno().V1beta1().UpdateRequests())
|
||||
|
||||
urc := background.NewController(
|
||||
kubeClient,
|
||||
|
|
|
@ -2,11 +2,21 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
pkglabels "k8s.io/apimachinery/pkg/labels"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
type Object interface {
|
||||
GetName() string
|
||||
GetNamespace() string
|
||||
GetKind() string
|
||||
GetAPIVersion() string
|
||||
}
|
||||
|
||||
func ManageLabels(unstr *unstructured.Unstructured, triggerResource unstructured.Unstructured) {
|
||||
// add managedBY label if not defined
|
||||
labels := unstr.GetLabels()
|
||||
|
@ -23,6 +33,35 @@ func ManageLabels(unstr *unstructured.Unstructured, triggerResource unstructured
|
|||
unstr.SetLabels(labels)
|
||||
}
|
||||
|
||||
func MutateLabelsSet(policyKey string, trigger Object) pkglabels.Set {
|
||||
set := pkglabels.Set{
|
||||
kyvernov1beta1.URMutatePolicyLabel: policyKey,
|
||||
}
|
||||
isNil := trigger == nil || (reflect.ValueOf(trigger).Kind() == reflect.Ptr && reflect.ValueOf(trigger).IsNil())
|
||||
if !isNil {
|
||||
set[kyvernov1beta1.URMutateTriggerNameLabel] = trigger.GetName()
|
||||
set[kyvernov1beta1.URMutateTriggerNSLabel] = trigger.GetNamespace()
|
||||
set[kyvernov1beta1.URMutatetriggerKindLabel] = trigger.GetKind()
|
||||
if trigger.GetAPIVersion() != "" {
|
||||
set[kyvernov1beta1.URMutatetriggerAPIVersionLabel] = trigger.GetAPIVersion()
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func GenerateLabelsSet(policyKey string, trigger Object) pkglabels.Set {
|
||||
set := pkglabels.Set{
|
||||
kyvernov1beta1.URGeneratePolicyLabel: policyKey,
|
||||
}
|
||||
isNil := trigger == nil || (reflect.ValueOf(trigger).Kind() == reflect.Ptr && reflect.ValueOf(trigger).IsNil())
|
||||
if !isNil {
|
||||
set[kyvernov1beta1.URGenerateResourceNameLabel] = trigger.GetName()
|
||||
set[kyvernov1beta1.URGenerateResourceNSLabel] = trigger.GetNamespace()
|
||||
set[kyvernov1beta1.URGenerateResourceKindLabel] = trigger.GetKind()
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func managedBy(labels map[string]string) {
|
||||
// ManagedBy label
|
||||
key := "app.kubernetes.io/managed-by"
|
||||
|
|
|
@ -4,12 +4,12 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
func (c *Controller) processUR(ur urkyverno.UpdateRequest) error {
|
||||
func (c *Controller) processUR(ur kyvernov1beta1.UpdateRequest) error {
|
||||
logger := c.log.WithValues("kind", ur.Kind, "namespace", ur.Namespace, "name", ur.Name)
|
||||
// 1- Corresponding policy has been deleted
|
||||
// then we don't delete the generated resources
|
||||
|
@ -19,7 +19,7 @@ func (c *Controller) processUR(ur urkyverno.UpdateRequest) error {
|
|||
deleteUR := false
|
||||
// check retry count in annotaion
|
||||
urAnnotations := ur.Annotations
|
||||
if val, ok := urAnnotations["generate.kyverno.io/retry-count"]; ok {
|
||||
if val, ok := urAnnotations[kyvernov1beta1.URGenerateRetryCountAnnotation]; ok {
|
||||
retryCount, err := strconv.ParseUint(val, 10, 32)
|
||||
if err != nil {
|
||||
logger.Error(err, "unable to convert retry-count")
|
||||
|
@ -44,7 +44,7 @@ func (c *Controller) processUR(ur urkyverno.UpdateRequest) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ownerResourceExists(log logr.Logger, client dclient.Interface, ur urkyverno.UpdateRequest) bool {
|
||||
func ownerResourceExists(log logr.Logger, client dclient.Interface, ur kyvernov1beta1.UpdateRequest) bool {
|
||||
_, err := client.GetResource("", ur.Spec.Resource.Kind, ur.Spec.Resource.Namespace, ur.Spec.Resource.Name)
|
||||
// trigger resources has been deleted
|
||||
if apierrors.IsNotFound(err) {
|
||||
|
@ -58,7 +58,7 @@ func ownerResourceExists(log logr.Logger, client dclient.Interface, ur urkyverno
|
|||
return true
|
||||
}
|
||||
|
||||
func deleteGeneratedResources(log logr.Logger, client dclient.Interface, ur urkyverno.UpdateRequest) error {
|
||||
func deleteGeneratedResources(log logr.Logger, client dclient.Interface, ur kyvernov1beta1.UpdateRequest) error {
|
||||
for _, genResource := range ur.Status.GeneratedResources {
|
||||
err := client.DeleteResource("", genResource.Kind, genResource.Namespace, genResource.Name, false)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/background/common"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
|
@ -96,7 +96,7 @@ func NewGenerateController(
|
|||
return &c, nil
|
||||
}
|
||||
|
||||
func (c *GenerateController) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
||||
func (c *GenerateController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error {
|
||||
logger := c.log.WithValues("name", ur.Name, "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name)
|
||||
var err error
|
||||
var resource *unstructured.Unstructured
|
||||
|
@ -114,10 +114,11 @@ func (c *GenerateController) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
|||
urAnnotations := ur.Annotations
|
||||
|
||||
if len(urAnnotations) == 0 {
|
||||
urAnnotations = make(map[string]string)
|
||||
urAnnotations["generate.kyverno.io/retry-count"] = "1"
|
||||
urAnnotations = map[string]string{
|
||||
urAnnotations[kyvernov1beta1.URGenerateRetryCountAnnotation]: "1",
|
||||
}
|
||||
} else {
|
||||
if val, ok := urAnnotations["generate.kyverno.io/retry-count"]; ok {
|
||||
if val, ok := urAnnotations[kyvernov1beta1.URGenerateRetryCountAnnotation]; ok {
|
||||
sleepCountInt64, err := strconv.ParseUint(val, 10, 32)
|
||||
if err != nil {
|
||||
logger.Error(err, "unable to convert retry-count")
|
||||
|
@ -136,12 +137,12 @@ func (c *GenerateController) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
|||
} else {
|
||||
time.Sleep(time.Second * time.Duration(sleepCountInt))
|
||||
incrementedCountString := strconv.Itoa(sleepCountInt)
|
||||
urAnnotations["generate.kyverno.io/retry-count"] = incrementedCountString
|
||||
urAnnotations[kyvernov1beta1.URGenerateRetryCountAnnotation] = incrementedCountString
|
||||
}
|
||||
|
||||
} else {
|
||||
time.Sleep(time.Second * 1)
|
||||
urAnnotations["generate.kyverno.io/retry-count"] = "1"
|
||||
urAnnotations[kyvernov1beta1.URGenerateRetryCountAnnotation] = "1"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +183,7 @@ func (c *GenerateController) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
|||
|
||||
const doesNotApply = "policy does not apply to resource"
|
||||
|
||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur urkyverno.UpdateRequest, namespaceLabels map[string]string) ([]kyverno.ResourceSpec, bool, error) {
|
||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur kyvernov1beta1.UpdateRequest, namespaceLabels map[string]string) ([]kyverno.ResourceSpec, bool, error) {
|
||||
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name)
|
||||
logger.V(3).Info("applying generate policy rule")
|
||||
|
||||
|
@ -219,10 +220,10 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
|
|||
if r.Status != response.RuleStatusPass {
|
||||
logger.V(4).Info("querying all update requests")
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: engineResponse.PolicyResponse.Policy.Name,
|
||||
"generate.kyverno.io/resource-name": engineResponse.PolicyResponse.Resource.Name,
|
||||
"generate.kyverno.io/resource-kind": engineResponse.PolicyResponse.Resource.Kind,
|
||||
"generate.kyverno.io/resource-namespace": engineResponse.PolicyResponse.Resource.Namespace,
|
||||
kyvernov1beta1.URGeneratePolicyLabel: engineResponse.PolicyResponse.Policy.Name,
|
||||
kyvernov1beta1.URGenerateResourceNameLabel: engineResponse.PolicyResponse.Resource.Name,
|
||||
kyvernov1beta1.URGenerateResourceKindLabel: engineResponse.PolicyResponse.Resource.Kind,
|
||||
kyvernov1beta1.URGenerateResourceNSLabel: engineResponse.PolicyResponse.Resource.Namespace,
|
||||
}))
|
||||
urList, err := c.urLister.List(selector)
|
||||
if err != nil {
|
||||
|
@ -271,7 +272,7 @@ func (c *GenerateController) cleanupClonedResource(targetSpec kyverno.ResourceSp
|
|||
}
|
||||
|
||||
// getPolicySpec gets the policy spec from the ClusterPolicy/Policy
|
||||
func (c *GenerateController) getPolicySpec(ur urkyverno.UpdateRequest) (kyverno.ClusterPolicy, error) {
|
||||
func (c *GenerateController) getPolicySpec(ur kyvernov1beta1.UpdateRequest) (kyverno.ClusterPolicy, error) {
|
||||
var policy kyverno.ClusterPolicy
|
||||
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(ur.Spec.Policy)
|
||||
|
@ -299,7 +300,7 @@ func (c *GenerateController) getPolicySpec(ur urkyverno.UpdateRequest) (kyverno.
|
|||
}
|
||||
}
|
||||
|
||||
func updateStatus(statusControl common.StatusControlInterface, ur urkyverno.UpdateRequest, err error, genResources []kyverno.ResourceSpec, precreatedResource bool) error {
|
||||
func updateStatus(statusControl common.StatusControlInterface, ur kyvernov1beta1.UpdateRequest, err error, genResources []kyverno.ResourceSpec, precreatedResource bool) error {
|
||||
if err != nil {
|
||||
if _, err := statusControl.Failed(ur.GetName(), err.Error(), genResources); err != nil {
|
||||
return err
|
||||
|
@ -316,7 +317,7 @@ func updateStatus(statusControl common.StatusControlInterface, ur urkyverno.Upda
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, ur urkyverno.UpdateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, processExisting bool, err error) {
|
||||
func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, ur kyvernov1beta1.UpdateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, processExisting bool, err error) {
|
||||
// Get the response as the actions to be performed on the resource
|
||||
// - - substitute values
|
||||
policy := policyContext.Policy
|
||||
|
@ -398,7 +399,7 @@ func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiv
|
|||
return
|
||||
}
|
||||
|
||||
func applyRule(log logr.Logger, client dclient.Interface, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy kyverno.PolicyInterface, ur urkyverno.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
func applyRule(log logr.Logger, client dclient.Interface, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy kyverno.PolicyInterface, ur kyvernov1beta1.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
var rdata map[string]interface{}
|
||||
var err error
|
||||
var mode ResourceMode
|
||||
|
@ -640,7 +641,7 @@ func getUnstrRule(rule *kyverno.Generation) (*unstructured.Unstructured, error)
|
|||
return utils.ConvertToUnstructured(ruleData)
|
||||
}
|
||||
|
||||
func deleteGeneratedResources(log logr.Logger, client dclient.Interface, ur urkyverno.UpdateRequest) error {
|
||||
func deleteGeneratedResources(log logr.Logger, client dclient.Interface, ur kyvernov1beta1.UpdateRequest) error {
|
||||
for _, genResource := range ur.Status.GeneratedResources {
|
||||
err := client.DeleteResource("", genResource.Kind, genResource.Namespace, genResource.Name, false)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
utilscommon "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/policyreport"
|
||||
"github.com/kyverno/kyverno/pkg/toggle"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
@ -152,7 +153,7 @@ func NewPolicyController(
|
|||
return &pc, nil
|
||||
}
|
||||
|
||||
func (pc *PolicyController) canBackgroundProcess(p kyverno.PolicyInterface) bool {
|
||||
func (pc *PolicyController) canBackgroundProcess(p kyvernov1.PolicyInterface) bool {
|
||||
logger := pc.log.WithValues("policy", p.GetName())
|
||||
if !p.BackgroundProcessingEnabled() {
|
||||
logger.V(4).Info("background processed is disabled")
|
||||
|
@ -169,7 +170,7 @@ func (pc *PolicyController) canBackgroundProcess(p kyverno.PolicyInterface) bool
|
|||
|
||||
func (pc *PolicyController) addPolicy(obj interface{}) {
|
||||
logger := pc.log
|
||||
p := obj.(*kyverno.ClusterPolicy)
|
||||
p := obj.(*kyvernov1.ClusterPolicy)
|
||||
|
||||
logger.Info("policy created", "uid", p.UID, "kind", "ClusterPolicy", "name", p.Name)
|
||||
|
||||
|
@ -178,11 +179,13 @@ func (pc *PolicyController) addPolicy(obj interface{}) {
|
|||
// register kyverno_policy_changes_total metric concurrently
|
||||
go pc.registerPolicyChangesMetricAddPolicy(logger, p)
|
||||
|
||||
if p.Spec.Background == nil || p.Spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
|
||||
pol, _ := utilscommon.MutatePolicy(p, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().ClusterPolicies().Update(context.TODO(), pol.(*kyverno.ClusterPolicy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to add policy ")
|
||||
if !toggle.AutogenInternals() {
|
||||
if p.Spec.Background == nil || p.Spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
|
||||
pol, _ := utilscommon.MutatePolicy(p, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().ClusterPolicies().Update(context.TODO(), pol.(*kyvernov1.ClusterPolicy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to add policy ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,19 +199,21 @@ func (pc *PolicyController) addPolicy(obj interface{}) {
|
|||
|
||||
func (pc *PolicyController) updatePolicy(old, cur interface{}) {
|
||||
logger := pc.log
|
||||
oldP := old.(*kyverno.ClusterPolicy)
|
||||
curP := cur.(*kyverno.ClusterPolicy)
|
||||
oldP := old.(*kyvernov1.ClusterPolicy)
|
||||
curP := cur.(*kyvernov1.ClusterPolicy)
|
||||
|
||||
// register kyverno_policy_rule_info_total metric concurrently
|
||||
go pc.registerPolicyRuleInfoMetricUpdatePolicy(logger, oldP, curP)
|
||||
// register kyverno_policy_changes_total metric concurrently
|
||||
go pc.registerPolicyChangesMetricUpdatePolicy(logger, oldP, curP)
|
||||
|
||||
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
|
||||
pol, _ := utilscommon.MutatePolicy(curP, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().ClusterPolicies().Update(context.TODO(), pol.(*kyverno.ClusterPolicy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update policy ")
|
||||
if !toggle.AutogenInternals() {
|
||||
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
|
||||
pol, _ := utilscommon.MutatePolicy(curP, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().ClusterPolicies().Update(context.TODO(), pol.(*kyvernov1.ClusterPolicy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update policy ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,14 +233,14 @@ func (pc *PolicyController) updatePolicy(old, cur interface{}) {
|
|||
|
||||
func (pc *PolicyController) deletePolicy(obj interface{}) {
|
||||
logger := pc.log
|
||||
p, ok := obj.(*kyverno.ClusterPolicy)
|
||||
p, ok := obj.(*kyvernov1.ClusterPolicy)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
logger.Info("couldn't get object from tombstone", "obj", obj)
|
||||
return
|
||||
}
|
||||
p, ok = tombstone.Obj.(*kyverno.ClusterPolicy)
|
||||
p, ok = tombstone.Obj.(*kyvernov1.ClusterPolicy)
|
||||
if !ok {
|
||||
logger.Info("tombstone container object that is not a policy", "obj", obj)
|
||||
return
|
||||
|
@ -264,7 +269,7 @@ func (pc *PolicyController) deletePolicy(obj interface{}) {
|
|||
|
||||
func (pc *PolicyController) addNsPolicy(obj interface{}) {
|
||||
logger := pc.log
|
||||
p := obj.(*kyverno.Policy)
|
||||
p := obj.(*kyvernov1.Policy)
|
||||
|
||||
// register kyverno_policy_rule_info_total metric concurrently
|
||||
go pc.registerPolicyRuleInfoMetricAddPolicy(logger, p)
|
||||
|
@ -273,14 +278,17 @@ func (pc *PolicyController) addNsPolicy(obj interface{}) {
|
|||
|
||||
logger.Info("policy created", "uid", p.UID, "kind", "Policy", "name", p.Name, "namespaces", p.Namespace)
|
||||
|
||||
spec := p.GetSpec()
|
||||
if spec.Background == nil || spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
|
||||
nsPol, _ := utilscommon.MutatePolicy(p, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().Policies(p.Namespace).Update(context.TODO(), nsPol.(*kyverno.Policy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to add namespace policy")
|
||||
if !toggle.AutogenInternals() {
|
||||
spec := p.GetSpec()
|
||||
if spec.Background == nil || spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
|
||||
nsPol, _ := utilscommon.MutatePolicy(p, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().Policies(p.Namespace).Update(context.TODO(), nsPol.(*kyvernov1.Policy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to add namespace policy")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !pc.canBackgroundProcess(p) {
|
||||
return
|
||||
}
|
||||
|
@ -290,19 +298,21 @@ func (pc *PolicyController) addNsPolicy(obj interface{}) {
|
|||
|
||||
func (pc *PolicyController) updateNsPolicy(old, cur interface{}) {
|
||||
logger := pc.log
|
||||
oldP := old.(*kyverno.Policy)
|
||||
curP := cur.(*kyverno.Policy)
|
||||
oldP := old.(*kyvernov1.Policy)
|
||||
curP := cur.(*kyvernov1.Policy)
|
||||
|
||||
// register kyverno_policy_rule_info_total metric concurrently
|
||||
go pc.registerPolicyRuleInfoMetricUpdatePolicy(logger, oldP, curP)
|
||||
// register kyverno_policy_changes_total metric concurrently
|
||||
go pc.registerPolicyChangesMetricUpdatePolicy(logger, oldP, curP)
|
||||
|
||||
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
|
||||
nsPol, _ := utilscommon.MutatePolicy(curP, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().Policies(curP.GetNamespace()).Update(context.TODO(), nsPol.(*kyverno.Policy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update namespace policy ")
|
||||
if !toggle.AutogenInternals() {
|
||||
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
|
||||
nsPol, _ := utilscommon.MutatePolicy(curP, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().Policies(curP.GetNamespace()).Update(context.TODO(), nsPol.(*kyvernov1.Policy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update namespace policy ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,14 +332,14 @@ func (pc *PolicyController) updateNsPolicy(old, cur interface{}) {
|
|||
|
||||
func (pc *PolicyController) deleteNsPolicy(obj interface{}) {
|
||||
logger := pc.log
|
||||
p, ok := obj.(*kyverno.Policy)
|
||||
p, ok := obj.(*kyvernov1.Policy)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
logger.Info("couldn't get object from tombstone", "obj", obj)
|
||||
return
|
||||
}
|
||||
p, ok = tombstone.Obj.(*kyverno.Policy)
|
||||
p, ok = tombstone.Obj.(*kyvernov1.Policy)
|
||||
if !ok {
|
||||
logger.Info("tombstone container object that is not a policy", "obj", obj)
|
||||
return
|
||||
|
@ -358,7 +368,7 @@ func (pc *PolicyController) deleteNsPolicy(obj interface{}) {
|
|||
pc.enqueuePolicy(pol)
|
||||
}
|
||||
|
||||
func (pc *PolicyController) enqueueRCRDeletedRule(old, cur kyverno.PolicyInterface) {
|
||||
func (pc *PolicyController) enqueueRCRDeletedRule(old, cur kyvernov1.PolicyInterface) {
|
||||
curRule := make(map[string]bool)
|
||||
for _, rule := range autogen.ComputeRules(cur) {
|
||||
curRule[rule.Name] = true
|
||||
|
@ -370,7 +380,7 @@ func (pc *PolicyController) enqueueRCRDeletedRule(old, cur kyverno.PolicyInterfa
|
|||
PolicyName: cur.GetName(),
|
||||
Results: []policyreport.EngineResponseResult{
|
||||
{
|
||||
Rules: []kyverno.ViolatedRule{
|
||||
Rules: []kyvernov1.ViolatedRule{
|
||||
{Name: rule.Name},
|
||||
},
|
||||
},
|
||||
|
@ -386,7 +396,7 @@ func (pc *PolicyController) enqueueRCRDeletedPolicy(policyName string) {
|
|||
})
|
||||
}
|
||||
|
||||
func (pc *PolicyController) enqueuePolicy(policy kyverno.PolicyInterface) {
|
||||
func (pc *PolicyController) enqueuePolicy(policy kyvernov1.PolicyInterface) {
|
||||
logger := pc.log
|
||||
key, err := cache.MetaNamespaceKeyFunc(policy)
|
||||
if err != nil {
|
||||
|
@ -493,7 +503,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (pc *PolicyController) getPolicy(key string) (policy kyverno.PolicyInterface, err error) {
|
||||
func (pc *PolicyController) getPolicy(key string) (policy kyvernov1.PolicyInterface, err error) {
|
||||
namespace, key, isNamespacedPolicy := ParseNamespacedPolicy(key)
|
||||
if !isNamespacedPolicy {
|
||||
return pc.pLister.Get(key)
|
||||
|
@ -507,7 +517,7 @@ func (pc *PolicyController) getPolicy(key string) (policy kyverno.PolicyInterfac
|
|||
return
|
||||
}
|
||||
|
||||
func generateTriggers(client client.Interface, rule kyverno.Rule, log logr.Logger) []*unstructured.Unstructured {
|
||||
func generateTriggers(client client.Interface, rule kyvernov1.Rule, log logr.Logger) []*unstructured.Unstructured {
|
||||
list := &unstructured.UnstructuredList{}
|
||||
|
||||
kinds := fetchUniqueKinds(rule)
|
||||
|
@ -559,7 +569,7 @@ func updateUR(kyvernoClient kyvernoclient.Interface, urLister kyvernov1beta1list
|
|||
}
|
||||
}
|
||||
|
||||
func missingAutoGenRules(policy kyverno.PolicyInterface, log logr.Logger) bool {
|
||||
func missingAutoGenRules(policy kyvernov1.PolicyInterface, log logr.Logger) bool {
|
||||
var podRuleName []string
|
||||
ruleCount := 1
|
||||
spec := policy.GetSpec()
|
||||
|
@ -571,7 +581,7 @@ func missingAutoGenRules(policy kyverno.PolicyInterface, log logr.Logger) bool {
|
|||
|
||||
if len(podRuleName) > 0 {
|
||||
annotations := policy.GetAnnotations()
|
||||
val, ok := annotations[kyverno.PodControllersAnnotation]
|
||||
val, ok := annotations[kyvernov1.PodControllersAnnotation]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
common "github.com/kyverno/kyverno/pkg/background/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
|
@ -35,10 +35,10 @@ func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInte
|
|||
updateUR(pc.kyvernoClient, pc.urLister.UpdateRequests(config.KyvernoNamespace), policyKey, append(mutateURs, generateURs...), pc.log.WithName("updateUR"))
|
||||
|
||||
for _, rule := range policy.GetSpec().Rules {
|
||||
var ruleType urkyverno.RequestType
|
||||
var ruleType kyvernov1beta1.RequestType
|
||||
|
||||
if rule.IsMutateExisting() {
|
||||
ruleType = urkyverno.Mutate
|
||||
ruleType = kyvernov1beta1.Mutate
|
||||
|
||||
triggers := generateTriggers(pc.client, rule, pc.log)
|
||||
for _, trigger := range triggers {
|
||||
|
@ -65,7 +65,7 @@ func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInte
|
|||
}
|
||||
}
|
||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
|
||||
ruleType = urkyverno.Generate
|
||||
ruleType = kyvernov1beta1.Generate
|
||||
triggers := generateTriggers(pc.client, rule, pc.log)
|
||||
for _, trigger := range triggers {
|
||||
gurs := pc.listGenerateURs(policyKey, trigger)
|
||||
|
@ -98,7 +98,7 @@ 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) (skip bool, err error) {
|
||||
func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.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 {
|
||||
return false, errors.Wrapf(err, "failed to build policy context for rule %s", rule.Name)
|
||||
|
@ -124,27 +124,23 @@ func (pc *PolicyController) handleUpdateRequest(ur *urkyverno.UpdateRequest, tri
|
|||
return false, err
|
||||
}
|
||||
|
||||
func (pc *PolicyController) listMutateURs(policyKey string, trigger *unstructured.Unstructured) []*urkyverno.UpdateRequest {
|
||||
selector := createMutateLabels(policyKey, trigger)
|
||||
mutateURs, err := pc.urLister.List(labels.SelectorFromSet(selector))
|
||||
func (pc *PolicyController) listMutateURs(policyKey string, trigger *unstructured.Unstructured) []*kyvernov1beta1.UpdateRequest {
|
||||
mutateURs, err := pc.urLister.List(labels.SelectorFromSet(common.MutateLabelsSet(policyKey, trigger)))
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list update request for mutate policy")
|
||||
}
|
||||
|
||||
return mutateURs
|
||||
}
|
||||
|
||||
func (pc *PolicyController) listGenerateURs(policyKey string, trigger *unstructured.Unstructured) []*urkyverno.UpdateRequest {
|
||||
selector := createGenerateLabels(policyKey, trigger)
|
||||
generateURs, err := pc.urLister.List(labels.SelectorFromSet(selector))
|
||||
func (pc *PolicyController) listGenerateURs(policyKey string, trigger *unstructured.Unstructured) []*kyvernov1beta1.UpdateRequest {
|
||||
generateURs, err := pc.urLister.List(labels.SelectorFromSet(common.GenerateLabelsSet(policyKey, trigger)))
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list update request for generate policy")
|
||||
}
|
||||
|
||||
return generateURs
|
||||
}
|
||||
|
||||
func newUR(policy kyverno.PolicyInterface, trigger *unstructured.Unstructured, ruleType urkyverno.RequestType) *urkyverno.UpdateRequest {
|
||||
func newUR(policy kyverno.PolicyInterface, trigger *unstructured.Unstructured, ruleType kyvernov1beta1.RequestType) *kyvernov1beta1.UpdateRequest {
|
||||
var policyNameNamespaceKey string
|
||||
|
||||
if policy.IsNamespaced() {
|
||||
|
@ -154,19 +150,19 @@ func newUR(policy kyverno.PolicyInterface, trigger *unstructured.Unstructured, r
|
|||
}
|
||||
|
||||
var label labels.Set
|
||||
if ruleType == urkyverno.Mutate {
|
||||
label = createMutateLabels(policyNameNamespaceKey, trigger)
|
||||
if ruleType == kyvernov1beta1.Mutate {
|
||||
label = common.MutateLabelsSet(policyNameNamespaceKey, trigger)
|
||||
} else {
|
||||
label = createGenerateLabels(policyNameNamespaceKey, trigger)
|
||||
label = common.GenerateLabelsSet(policyNameNamespaceKey, trigger)
|
||||
}
|
||||
|
||||
return &urkyverno.UpdateRequest{
|
||||
return &kyvernov1beta1.UpdateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "ur-",
|
||||
Namespace: config.KyvernoNamespace,
|
||||
Labels: label,
|
||||
},
|
||||
Spec: urkyverno.UpdateRequestSpec{
|
||||
Spec: kyvernov1beta1.UpdateRequestSpec{
|
||||
Type: ruleType,
|
||||
Policy: policyNameNamespaceKey,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
|
@ -178,44 +174,3 @@ func newUR(policy kyverno.PolicyInterface, trigger *unstructured.Unstructured, r
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createMutateLabels(policyKey string, trigger *unstructured.Unstructured) labels.Set {
|
||||
var selector labels.Set
|
||||
if trigger == nil {
|
||||
selector = labels.Set(map[string]string{
|
||||
urkyverno.URMutatePolicyLabel: policyKey,
|
||||
})
|
||||
} else {
|
||||
selector = labels.Set(map[string]string{
|
||||
urkyverno.URMutatePolicyLabel: policyKey,
|
||||
urkyverno.URMutateTriggerNameLabel: trigger.GetName(),
|
||||
urkyverno.URMutateTriggerNSLabel: trigger.GetNamespace(),
|
||||
urkyverno.URMutatetriggerKindLabel: trigger.GetKind(),
|
||||
})
|
||||
|
||||
if trigger.GetAPIVersion() != "" {
|
||||
selector[urkyverno.URMutatetriggerAPIVersionLabel] = trigger.GetAPIVersion()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return selector
|
||||
}
|
||||
|
||||
func createGenerateLabels(policyKey string, trigger *unstructured.Unstructured) labels.Set {
|
||||
var selector labels.Set
|
||||
if trigger == nil {
|
||||
selector = labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: policyKey,
|
||||
})
|
||||
} else {
|
||||
selector = labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: policyKey,
|
||||
"generate.kyverno.io/resource-name": trigger.GetName(),
|
||||
"generate.kyverno.io/resource-kind": trigger.GetKind(),
|
||||
"generate.kyverno.io/resource-namespace": trigger.GetNamespace(),
|
||||
})
|
||||
}
|
||||
|
||||
return selector
|
||||
}
|
||||
|
|
|
@ -374,7 +374,7 @@ func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse *response.E
|
|||
}
|
||||
}
|
||||
|
||||
func applyUpdateRequest(request *admissionv1.AdmissionRequest, ruleType kyvernov1beta1.RequestType, grGenerator updaterequest.Interface, userRequestInfo kyvernov1beta1.RequestInfo,
|
||||
func applyUpdateRequest(request *admissionv1.AdmissionRequest, ruleType kyvernov1beta1.RequestType, grGenerator updaterequest.Generator, userRequestInfo kyvernov1beta1.RequestInfo,
|
||||
action admissionv1.Operation, engineResponses ...*response.EngineResponse) (failedUpdateRequest []updateRequestResponse) {
|
||||
|
||||
requestBytes, err := json.Marshal(request)
|
||||
|
|
|
@ -77,7 +77,7 @@ type WebhookServer struct {
|
|||
prGenerator policyreport.GeneratorInterface
|
||||
|
||||
// update request generator
|
||||
urGenerator webhookgenerate.Interface
|
||||
urGenerator webhookgenerate.Generator
|
||||
|
||||
auditHandler AuditHandler
|
||||
|
||||
|
@ -111,7 +111,7 @@ func NewWebhookServer(
|
|||
webhookMonitor *webhookconfig.Monitor,
|
||||
configHandler config.Configuration,
|
||||
prGenerator policyreport.GeneratorInterface,
|
||||
urGenerator webhookgenerate.Interface,
|
||||
urGenerator webhookgenerate.Generator,
|
||||
auditHandler AuditHandler,
|
||||
cleanUp chan<- struct{},
|
||||
log logr.Logger,
|
||||
|
|
|
@ -5,197 +5,55 @@ import (
|
|||
"time"
|
||||
|
||||
backoff "github.com/cenkalti/backoff"
|
||||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/background/common"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
kyvernov1beta1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernov1beta1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/retry"
|
||||
)
|
||||
|
||||
// UpdateRequest provides interface to manage update requests
|
||||
type Interface interface {
|
||||
// Generator provides interface to manage update requests
|
||||
type Generator interface {
|
||||
Apply(gr kyvernov1beta1.UpdateRequestSpec, action admissionv1.Operation) error
|
||||
}
|
||||
|
||||
// info object stores message data to create update request
|
||||
type info struct {
|
||||
spec kyvernov1beta1.UpdateRequestSpec
|
||||
action admissionv1.Operation
|
||||
}
|
||||
|
||||
// Generator defines the implementation to mange update request resource
|
||||
type Generator struct {
|
||||
// generator defines the implementation to manage update request resource
|
||||
type generator struct {
|
||||
// clients
|
||||
client kyvernoclient.Interface
|
||||
stopCh <-chan struct{}
|
||||
log logr.Logger
|
||||
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister
|
||||
// listers
|
||||
urLister kyvernov1beta1listers.UpdateRequestNamespaceLister
|
||||
}
|
||||
|
||||
// NewGenerator returns a new instance of UpdateRequest resource generator
|
||||
func NewGenerator(client kyvernoclient.Interface, urInformer urkyvernoinformer.UpdateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
gen := &Generator{
|
||||
func NewGenerator(client kyvernoclient.Interface, urInformer kyvernov1beta1informers.UpdateRequestInformer) Generator {
|
||||
return &generator{
|
||||
client: client,
|
||||
stopCh: stopCh,
|
||||
log: log,
|
||||
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
|
||||
}
|
||||
return gen
|
||||
}
|
||||
|
||||
// Apply creates update request resource
|
||||
func (g *Generator) Apply(ur kyvernov1beta1.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
logger := g.log
|
||||
func (g *generator) Apply(ur kyvernov1beta1.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
logger.V(4).Info("reconcile Update Request", "request", ur)
|
||||
|
||||
message := info{
|
||||
action: action,
|
||||
spec: ur,
|
||||
}
|
||||
go g.processApply(message)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run starts the update request spec
|
||||
func (g *Generator) Run(workers int, stopCh <-chan struct{}) {
|
||||
logger := g.log
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
logger.V(4).Info("starting")
|
||||
defer func() {
|
||||
logger.V(4).Info("shutting down")
|
||||
}()
|
||||
|
||||
<-g.stopCh
|
||||
}
|
||||
|
||||
func (g *Generator) processApply(i info) {
|
||||
if err := g.generate(i); err != nil {
|
||||
logger.Error(err, "failed to update request CR")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) generate(i info) error {
|
||||
if err := retryApplyResource(g.client, i.spec, g.log, i.action, g.urLister); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func retryApplyResource(client kyvernoclient.Interface, urSpec kyvernov1beta1.UpdateRequestSpec,
|
||||
log logr.Logger, action admissionv1.Operation, urLister urkyvernolister.UpdateRequestNamespaceLister) error {
|
||||
|
||||
if action == admissionv1.Delete && urSpec.Type == kyvernov1beta1.Generate {
|
||||
if action == admissionv1.Delete && ur.Type == kyvernov1beta1.Generate {
|
||||
return nil
|
||||
}
|
||||
|
||||
var i int
|
||||
var err error
|
||||
|
||||
_, policyName, err := cache.SplitMetaNamespaceKey(urSpec.Policy)
|
||||
_, policyName, err := cache.SplitMetaNamespaceKey(ur.Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go g.applyResource(policyName, ur)
|
||||
return nil
|
||||
}
|
||||
|
||||
applyResource := func() error {
|
||||
ur := kyvernov1beta1.UpdateRequest{
|
||||
Spec: urSpec,
|
||||
Status: kyvernov1beta1.UpdateRequestStatus{
|
||||
State: kyvernov1beta1.Pending,
|
||||
},
|
||||
}
|
||||
|
||||
queryLabels := make(map[string]string)
|
||||
if ur.Spec.Type == kyvernov1beta1.Mutate {
|
||||
queryLabels := map[string]string{
|
||||
kyvernov1beta1.URMutatePolicyLabel: ur.Spec.Policy,
|
||||
"mutate.updaterequest.kyverno.io/trigger-name": ur.Spec.Resource.Name,
|
||||
"mutate.updaterequest.kyverno.io/trigger-namespace": ur.Spec.Resource.Namespace,
|
||||
"mutate.updaterequest.kyverno.io/trigger-kind": ur.Spec.Resource.Kind,
|
||||
}
|
||||
|
||||
if ur.Spec.Resource.APIVersion != "" {
|
||||
queryLabels["mutate.updaterequest.kyverno.io/trigger-apiversion"] = ur.Spec.Resource.APIVersion
|
||||
}
|
||||
} else if ur.Spec.Type == kyvernov1beta1.Generate {
|
||||
queryLabels = labels.Set(map[string]string{
|
||||
kyvernov1beta1.URGeneratePolicyLabel: policyName,
|
||||
"generate.kyverno.io/resource-name": urSpec.Resource.Name,
|
||||
"generate.kyverno.io/resource-kind": urSpec.Resource.Kind,
|
||||
"generate.kyverno.io/resource-namespace": urSpec.Resource.Namespace,
|
||||
})
|
||||
}
|
||||
|
||||
ur.SetNamespace(config.KyvernoNamespace)
|
||||
isExist := false
|
||||
log.V(4).Info("apply UpdateRequest", "ruleType", ur.Spec.Type)
|
||||
|
||||
urList, err := urLister.List(labels.SelectorFromSet(queryLabels))
|
||||
if err != nil {
|
||||
log.Error(err, "failed to get update request for the resource", "kind", urSpec.Resource.Kind, "name", urSpec.Resource.Name, "namespace", urSpec.Resource.Namespace)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range urList {
|
||||
log.V(4).Info("updating existing update request", "name", v.GetName())
|
||||
|
||||
v.Spec.Context = ur.Spec.Context
|
||||
v.Spec.Policy = ur.Spec.Policy
|
||||
v.Spec.Resource = ur.Spec.Resource
|
||||
v.Status.Message = ""
|
||||
|
||||
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.V(4).Info("failed to update UpdateRequest, retrying", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace(), "err", err.Error())
|
||||
i++
|
||||
return err
|
||||
} else {
|
||||
log.V(4).Info("successfully updated UpdateRequest", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace())
|
||||
}
|
||||
err = retry.RetryOnConflict(common.DefaultRetry, func() error {
|
||||
ur, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Get(context.TODO(), new.GetName(), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ur.Status.State = kyvernov1beta1.Pending
|
||||
_, err = client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), ur, metav1.UpdateOptions{})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
return err
|
||||
}
|
||||
isExist = true
|
||||
}
|
||||
|
||||
if !isExist {
|
||||
log.V(4).Info("creating new UpdateRequest", "type", ur.Spec.Type)
|
||||
|
||||
ur.SetGenerateName("ur-")
|
||||
ur.SetLabels(queryLabels)
|
||||
|
||||
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), &ur, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
log.V(4).Info("failed to create UpdateRequest, retrying", "retryCount", i, "name", ur.GetGenerateName(), "namespace", ur.GetNamespace(), "err", err.Error())
|
||||
i++
|
||||
return err
|
||||
} else {
|
||||
log.V(4).Info("successfully created UpdateRequest", "retryCount", i, "name", new.GetName(), "namespace", ur.GetNamespace())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *generator) applyResource(policyName string, urSpec kyvernov1beta1.UpdateRequestSpec) {
|
||||
exbackoff := &backoff.ExponentialBackOff{
|
||||
InitialInterval: 500 * time.Millisecond,
|
||||
RandomizationFactor: 0.5,
|
||||
|
@ -204,13 +62,57 @@ func retryApplyResource(client kyvernoclient.Interface, urSpec kyvernov1beta1.Up
|
|||
MaxElapsedTime: 3 * time.Second,
|
||||
Clock: backoff.SystemClock,
|
||||
}
|
||||
|
||||
exbackoff.Reset()
|
||||
err = backoff.Retry(applyResource, exbackoff)
|
||||
if err := backoff.Retry(func() error { return g.tryApplyResource(policyName, urSpec) }, exbackoff); err != nil {
|
||||
logger.Error(err, "failed to update request CR")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) tryApplyResource(policyName string, urSpec kyvernov1beta1.UpdateRequestSpec) error {
|
||||
l := logger.WithValues("ruleType", urSpec.Type, "kind", urSpec.Resource.Kind, "name", urSpec.Resource.Name, "namespace", urSpec.Resource.Namespace)
|
||||
var queryLabels labels.Set
|
||||
if urSpec.Type == kyvernov1beta1.Mutate {
|
||||
queryLabels = common.MutateLabelsSet(urSpec.Policy, urSpec.Resource)
|
||||
} else if urSpec.Type == kyvernov1beta1.Generate {
|
||||
queryLabels = common.GenerateLabelsSet(urSpec.Policy, urSpec.Resource)
|
||||
}
|
||||
urList, err := g.urLister.List(labels.SelectorFromSet(queryLabels))
|
||||
if err != nil {
|
||||
l.Error(err, "failed to get update request for the resource", "kind", urSpec.Resource.Kind, "name", urSpec.Resource.Name, "namespace", urSpec.Resource.Namespace)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range urList {
|
||||
l := l.WithValues("name", v.GetName())
|
||||
l.V(4).Info("updating existing update request")
|
||||
if _, err := common.Update(g.client, g.urLister, v.GetName(), func(ur *kyvernov1beta1.UpdateRequest) {
|
||||
v.Spec = urSpec
|
||||
}); err != nil {
|
||||
l.V(4).Error(err, "failed to update UpdateRequest")
|
||||
return err
|
||||
} else {
|
||||
l.V(4).Info("successfully updated UpdateRequest")
|
||||
}
|
||||
if _, err := common.UpdateStatus(g.client, g.urLister, v.GetName(), kyvernov1beta1.Pending, "", nil); err != nil {
|
||||
l.V(4).Error(err, "failed to update UpdateRequest status")
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(urList) == 0 {
|
||||
l.V(4).Info("creating new UpdateRequest")
|
||||
ur := kyvernov1beta1.UpdateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: config.KyvernoNamespace,
|
||||
GenerateName: "ur-",
|
||||
Labels: queryLabels,
|
||||
},
|
||||
Spec: urSpec,
|
||||
}
|
||||
if new, err := g.client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), &ur, metav1.CreateOptions{}); err != nil {
|
||||
l.V(4).Error(err, "failed to create UpdateRequest, retrying", "name", ur.GetGenerateName(), "namespace", ur.GetNamespace())
|
||||
return err
|
||||
} else {
|
||||
l.V(4).Info("successfully created UpdateRequest", "name", new.GetName(), "namespace", ur.GetNamespace())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
5
pkg/webhooks/updaterequest/log.go
Normal file
5
pkg/webhooks/updaterequest/log.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package updaterequest
|
||||
|
||||
import "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
var logger = log.Log.WithName("updaterequest-generator")
|
Loading…
Add table
Reference in a new issue