mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 15:37:19 +00:00
fix: remove timestamp checks for the clone rule (#6439)
* remove timestamp checks Signed-off-by: ShutingZhao <shuting@nirmata.com> * add kuttl tests Signed-off-by: ShutingZhao <shuting@nirmata.com> --------- Signed-off-by: ShutingZhao <shuting@nirmata.com>
This commit is contained in:
parent
f4f729623d
commit
264eaec049
15 changed files with 163 additions and 55 deletions
|
@ -1124,7 +1124,7 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont
|
||||||
var newRuleResponse []engineapi.RuleResponse
|
var newRuleResponse []engineapi.RuleResponse
|
||||||
|
|
||||||
for _, rule := range generateResponse.PolicyResponse.Rules {
|
for _, rule := range generateResponse.PolicyResponse.Rules {
|
||||||
genResource, _, err := c.ApplyGeneratePolicy(log.Log, &policyContext, gr, []string{rule.Name})
|
genResource, err := c.ApplyGeneratePolicy(log.Log, &policyContext, gr, []string{rule.Name})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rule.Status = engineapi.RuleStatusError
|
rule.Status = engineapi.RuleStatusError
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -21,25 +21,25 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe
|
||||||
cfg config.Configuration,
|
cfg config.Configuration,
|
||||||
namespaceLabels map[string]string,
|
namespaceLabels map[string]string,
|
||||||
logger logr.Logger,
|
logger logr.Logger,
|
||||||
) (*engine.PolicyContext, bool, error) {
|
) (*engine.PolicyContext, error) {
|
||||||
ctx := context.NewContext()
|
ctx := context.NewContext()
|
||||||
var new, old unstructured.Unstructured
|
var new, old unstructured.Unstructured
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest != nil {
|
if ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest != nil {
|
||||||
if err := ctx.AddRequest(ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest); err != nil {
|
if err := ctx.AddRequest(ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest); err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to load request in context: %w", err)
|
return nil, fmt.Errorf("failed to load request in context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
new, old, err = admissionutils.ExtractResources(nil, ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest)
|
new, old, err = admissionutils.ExtractResources(nil, ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to load request in context: %w", err)
|
return nil, fmt.Errorf("failed to load request in context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(new, unstructured.Unstructured{}) {
|
if !reflect.DeepEqual(new, unstructured.Unstructured{}) {
|
||||||
if !check(&new, trigger) {
|
if !check(&new, trigger) {
|
||||||
err := fmt.Errorf("resources don't match")
|
err := fmt.Errorf("resources don't match")
|
||||||
return nil, false, fmt.Errorf("resource %v: %w", ur.Spec.GetResource().String(), err)
|
return nil, fmt.Errorf("resource %v: %w", ur.Spec.GetResource().String(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,27 +49,27 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe
|
||||||
}
|
}
|
||||||
|
|
||||||
if trigger == nil {
|
if trigger == nil {
|
||||||
return nil, false, fmt.Errorf("trigger resource does not exist")
|
return nil, fmt.Errorf("trigger resource does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.AddResource(trigger.Object)
|
err = ctx.AddResource(trigger.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to load resource in context: %w", err)
|
return nil, fmt.Errorf("failed to load resource in context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.AddOldResource(old.Object)
|
err = ctx.AddOldResource(old.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to load resource in context: %w", err)
|
return nil, fmt.Errorf("failed to load resource in context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.AddUserInfo(ur.Spec.Context.UserRequestInfo)
|
err = ctx.AddUserInfo(ur.Spec.Context.UserRequestInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to load SA in context: %w", err)
|
return nil, fmt.Errorf("failed to load SA in context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.AddServiceAccount(ur.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
err = ctx.AddServiceAccount(ur.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to load UserInfo in context: %w", err)
|
return nil, fmt.Errorf("failed to load UserInfo in context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.AddImageInfos(trigger, cfg); err != nil {
|
if err := ctx.AddImageInfos(trigger, cfg); err != nil {
|
||||||
|
@ -83,7 +83,7 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe
|
||||||
WithAdmissionInfo(ur.Spec.Context.UserRequestInfo).
|
WithAdmissionInfo(ur.Spec.Context.UserRequestInfo).
|
||||||
WithNamespaceLabels(namespaceLabels)
|
WithNamespaceLabels(namespaceLabels)
|
||||||
|
|
||||||
return policyContext, false, nil
|
return policyContext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func check(admissionRsc, existingRsc *unstructured.Unstructured) bool {
|
func check(admissionRsc, existingRsc *unstructured.Unstructured) bool {
|
||||||
|
|
|
@ -90,7 +90,6 @@ func (c *GenerateController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error {
|
||||||
var err error
|
var err error
|
||||||
var resource *unstructured.Unstructured
|
var resource *unstructured.Unstructured
|
||||||
var genResources []kyvernov1.ResourceSpec
|
var genResources []kyvernov1.ResourceSpec
|
||||||
var precreatedResource bool
|
|
||||||
logger.Info("start processing UR", "ur", ur.Name, "resourceVersion", ur.GetResourceVersion())
|
logger.Info("start processing UR", "ur", ur.Name, "resourceVersion", ur.GetResourceVersion())
|
||||||
|
|
||||||
// 1 - Check if the trigger exists
|
// 1 - Check if the trigger exists
|
||||||
|
@ -127,7 +126,7 @@ func (c *GenerateController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error {
|
||||||
|
|
||||||
// 2 - Apply the generate policy on the resource
|
// 2 - Apply the generate policy on the resource
|
||||||
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(resource.GetKind(), resource.GetNamespace(), c.nsLister, logger)
|
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(resource.GetKind(), resource.GetNamespace(), c.nsLister, logger)
|
||||||
genResources, precreatedResource, err = c.applyGenerate(*resource, *ur, namespaceLabels)
|
genResources, err = c.applyGenerate(*resource, *ur, namespaceLabels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Need not update the status when policy doesn't apply on resource, because all the update requests are removed by the cleanup controller
|
// Need not update the status when policy doesn't apply on resource, because all the update requests are removed by the cleanup controller
|
||||||
if strings.Contains(err.Error(), doesNotApply) {
|
if strings.Contains(err.Error(), doesNotApply) {
|
||||||
|
@ -141,36 +140,36 @@ func (c *GenerateController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 - Update Status
|
// 4 - Update Status
|
||||||
return updateStatus(c.statusControl, *ur, err, genResources, precreatedResource)
|
return updateStatus(c.statusControl, *ur, err, genResources)
|
||||||
}
|
}
|
||||||
|
|
||||||
const doesNotApply = "policy does not apply to resource"
|
const doesNotApply = "policy does not apply to resource"
|
||||||
|
|
||||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur kyvernov1beta1.UpdateRequest, namespaceLabels map[string]string) ([]kyvernov1.ResourceSpec, bool, error) {
|
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur kyvernov1beta1.UpdateRequest, namespaceLabels map[string]string) ([]kyvernov1.ResourceSpec, error) {
|
||||||
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String())
|
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String())
|
||||||
logger.V(3).Info("applying generate policy rule")
|
logger.V(3).Info("applying generate policy rule")
|
||||||
|
|
||||||
policy, err := c.getPolicySpec(ur)
|
policy, err := c.getPolicySpec(ur)
|
||||||
if err != nil && !apierrors.IsNotFound(err) {
|
if err != nil && !apierrors.IsNotFound(err) {
|
||||||
logger.Error(err, "error in fetching policy")
|
logger.Error(err, "error in fetching policy")
|
||||||
return nil, false, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ur.Spec.DeleteDownstream || apierrors.IsNotFound(err) {
|
if ur.Spec.DeleteDownstream || apierrors.IsNotFound(err) {
|
||||||
err = c.deleteDownstream(policy, &ur)
|
err = c.deleteDownstream(policy, &ur)
|
||||||
return nil, false, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
policyContext, precreatedResource, err := common.NewBackgroundContext(c.client, &ur, policy, &resource, c.configuration, namespaceLabels, logger)
|
policyContext, err := common.NewBackgroundContext(c.client, &ur, policy, &resource, c.configuration, namespaceLabels, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, precreatedResource, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the policy still applies to the resource
|
// check if the policy still applies to the resource
|
||||||
engineResponse := c.engine.GenerateResponse(context.Background(), policyContext, ur)
|
engineResponse := c.engine.GenerateResponse(context.Background(), policyContext, ur)
|
||||||
if len(engineResponse.PolicyResponse.Rules) == 0 {
|
if len(engineResponse.PolicyResponse.Rules) == 0 {
|
||||||
logger.V(4).Info(doesNotApply)
|
logger.V(4).Info(doesNotApply)
|
||||||
return nil, false, errors.New(doesNotApply)
|
return nil, errors.New(doesNotApply)
|
||||||
}
|
}
|
||||||
|
|
||||||
var applicableRules []string
|
var applicableRules []string
|
||||||
|
@ -226,15 +225,11 @@ func (c *GenerateController) getPolicySpec(ur kyvernov1beta1.UpdateRequest) (kyv
|
||||||
return npolicyObj, nil
|
return npolicyObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateStatus(statusControl common.StatusControlInterface, ur kyvernov1beta1.UpdateRequest, err error, genResources []kyvernov1.ResourceSpec, precreatedResource bool) error {
|
func updateStatus(statusControl common.StatusControlInterface, ur kyvernov1beta1.UpdateRequest, err error, genResources []kyvernov1.ResourceSpec) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, err := statusControl.Failed(ur.GetName(), err.Error(), genResources); err != nil {
|
if _, err := statusControl.Failed(ur.GetName(), err.Error(), genResources); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if precreatedResource {
|
|
||||||
if _, err := statusControl.Skip(ur.GetName(), genResources); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if _, err := statusControl.Success(ur.GetName(), genResources); err != nil {
|
if _, err := statusControl.Success(ur.GetName(), genResources); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -243,7 +238,7 @@ func updateStatus(statusControl common.StatusControlInterface, ur kyvernov1beta1
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, ur kyvernov1beta1.UpdateRequest, applicableRules []string) (genResources []kyvernov1.ResourceSpec, processExisting bool, err error) {
|
func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, ur kyvernov1beta1.UpdateRequest, applicableRules []string) (genResources []kyvernov1.ResourceSpec, err error) {
|
||||||
// Get the response as the actions to be performed on the resource
|
// Get the response as the actions to be performed on the resource
|
||||||
// - - substitute values
|
// - - substitute values
|
||||||
policy := policyContext.Policy()
|
policy := policyContext.Policy()
|
||||||
|
@ -265,17 +260,7 @@ func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext
|
||||||
}
|
}
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
processExisting = false
|
|
||||||
var genResource []kyvernov1.ResourceSpec
|
var genResource []kyvernov1.ResourceSpec
|
||||||
|
|
||||||
if len(rule.MatchResources.Kinds) > 0 {
|
|
||||||
if len(rule.MatchResources.Annotations) == 0 && rule.MatchResources.Selector == nil {
|
|
||||||
rcreationTime := resource.GetCreationTimestamp()
|
|
||||||
pcreationTime := policy.GetCreationTimestamp()
|
|
||||||
processExisting = rcreationTime.Before(&pcreationTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if applyRules == kyvernov1.ApplyOne && applyCount > 0 {
|
if applyRules == kyvernov1.ApplyOne && applyCount > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -283,33 +268,26 @@ func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext
|
||||||
// add configmap json data to context
|
// add configmap json data to context
|
||||||
if err := c.engine.ContextLoader(policyContext.Policy(), rule)(context.TODO(), rule.Context, policyContext.JSONContext()); err != nil {
|
if err := c.engine.ContextLoader(policyContext.Policy(), rule)(context.TODO(), rule.Context, policyContext.JSONContext()); err != nil {
|
||||||
log.Error(err, "cannot add configmaps to context")
|
log.Error(err, "cannot add configmaps to context")
|
||||||
return nil, processExisting, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if rule, err = variables.SubstituteAllInRule(log, policyContext.JSONContext(), rule); err != nil {
|
if rule, err = variables.SubstituteAllInRule(log, policyContext.JSONContext(), rule); err != nil {
|
||||||
log.Error(err, "variable substitution failed for rule %s", rule.Name)
|
log.Error(err, "variable substitution failed for rule %s", rule.Name)
|
||||||
return nil, processExisting, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() || !processExisting {
|
genResource, err = applyRule(log, c.client, rule, resource, jsonContext, policy, ur)
|
||||||
genResource, err = applyRule(log, c.client, rule, resource, jsonContext, policy, ur)
|
if err != nil {
|
||||||
if err != nil {
|
log.Error(err, "failed to apply generate rule", "policy", policy.GetName(),
|
||||||
log.Error(err, "failed to apply generate rule", "policy", policy.GetName(),
|
"rule", rule.Name, "resource", resource.GetName(), "suggestion", "users need to grant Kyverno's service account additional privileges")
|
||||||
"rule", rule.Name, "resource", resource.GetName(), "suggestion", "users need to grant Kyverno's service account additional privileges")
|
return nil, err
|
||||||
return nil, processExisting, err
|
|
||||||
}
|
|
||||||
ruleNameToProcessingTime[rule.Name] = time.Since(startTime)
|
|
||||||
genResources = append(genResources, genResource...)
|
|
||||||
}
|
}
|
||||||
|
ruleNameToProcessingTime[rule.Name] = time.Since(startTime)
|
||||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
|
genResources = append(genResources, genResource...)
|
||||||
processExisting = false
|
|
||||||
}
|
|
||||||
|
|
||||||
applyCount++
|
applyCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
return genResources, processExisting, nil
|
return genResources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiversion string, err error) {
|
func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiversion string, err error) {
|
||||||
|
|
|
@ -92,7 +92,7 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
|
||||||
}
|
}
|
||||||
|
|
||||||
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(trigger.GetKind(), trigger.GetNamespace(), c.nsLister, logger)
|
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(trigger.GetKind(), trigger.GetNamespace(), c.nsLister, logger)
|
||||||
policyContext, _, err := common.NewBackgroundContext(c.client, ur, policy, trigger, c.configuration, namespaceLabels, logger)
|
policyContext, err := common.NewBackgroundContext(c.client, ur, policy, trigger, c.configuration, namespaceLabels, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithName(rule.Name).Error(err, "failed to build policy context")
|
logger.WithName(rule.Name).Error(err, "failed to build policy context")
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
|
|
|
@ -407,7 +407,7 @@ func (pc *PolicyController) requeuePolicies() {
|
||||||
|
|
||||||
func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyvernov1.Rule, policy kyvernov1.PolicyInterface) (skip bool, err error) {
|
func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyvernov1.Rule, policy kyvernov1.PolicyInterface) (skip bool, err error) {
|
||||||
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(triggerResource.GetKind(), triggerResource.GetNamespace(), pc.nsLister, pc.log)
|
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(triggerResource.GetKind(), triggerResource.GetNamespace(), pc.nsLister, pc.log)
|
||||||
policyContext, _, err := backgroundcommon.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, namespaceLabels, pc.log)
|
policyContext, err := backgroundcommon.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, namespaceLabels, pc.log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("failed to build policy context for rule %s: %w", rule.Name, err)
|
return false, fmt.Errorf("failed to build policy context for rule %s: %w", rule.Name, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: kyverno.io/v2beta1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: cpol-clone-sync-create-source-after-policy
|
||||||
|
status:
|
||||||
|
conditions:
|
||||||
|
- reason: Succeeded
|
||||||
|
status: "True"
|
||||||
|
type: Ready
|
|
@ -0,0 +1,30 @@
|
||||||
|
apiVersion: kyverno.io/v2beta1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: cpol-clone-sync-create-source-after-policy
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- name: clone-secret
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
name: regcred
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
clone:
|
||||||
|
namespace: default
|
||||||
|
name: regcred
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
foo: YmFy
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: regcred
|
||||||
|
namespace: default
|
||||||
|
type: Opaque
|
|
@ -0,0 +1,5 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: regcred
|
||||||
|
namespace: cpol-clone-sync-create-source-after-policy-ns
|
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cpol-clone-sync-create-source-after-policy-ns
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This is a corner case test to ensure a clone rule is applied when the source is created after the ClusterPolicy.
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
If the downstream resource is created, the test passes. If it is not created, the test fails.
|
||||||
|
|
||||||
|
## Reference Issue(s)
|
||||||
|
|
||||||
|
https://github.com/kyverno/kyverno/issues/5411
|
|
@ -0,0 +1,10 @@
|
||||||
|
apiVersion: kyverno.io/v2beta1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: pol-clone-sync-create-source-after-policy
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
status:
|
||||||
|
conditions:
|
||||||
|
- reason: Succeeded
|
||||||
|
status: "True"
|
||||||
|
type: Ready
|
|
@ -0,0 +1,36 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
---
|
||||||
|
apiVersion: kyverno.io/v2beta1
|
||||||
|
kind: Policy
|
||||||
|
metadata:
|
||||||
|
name: pol-clone-sync-create-source-after-policy
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- name: clone-secret
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- ConfigMap
|
||||||
|
generate:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
name: mynewsecret
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
synchronize: true
|
||||||
|
clone:
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
name: regcred
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
foo: YmFy
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: regcred
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
type: Opaque
|
|
@ -0,0 +1,5 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: mynewsecret
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: mycm
|
||||||
|
namespace: pol-clone-sync-create-source-after-policy-ns
|
||||||
|
data:
|
||||||
|
food: cheese
|
||||||
|
day: monday
|
||||||
|
color: red
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This is a corner case test to ensure a clone rule is applied when the source is created after the ClusterPolicy.
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
If the downstream resource is created, the test passes. If it is not created, the test fails.
|
||||||
|
|
||||||
|
## Reference Issue(s)
|
||||||
|
|
||||||
|
https://github.com/kyverno/kyverno/issues/5411
|
Loading…
Add table
Reference in a new issue