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

feat: Add support for server-side-apply in generate rules (#7705)

* feat: Add support for server-side-apply in generate rules

Signed-off-by: Mike Bryant <mike@mikebryant.me.uk>

* chore: run make codegen-all

Signed-off-by: Mike Bryant <mike.bryant@mettle.co.uk>

* chore: Remove unnecessary file I got from copy/paste

Signed-off-by: Mike Bryant <mike.bryant@mettle.co.uk>

---------

Signed-off-by: Mike Bryant <mike@mikebryant.me.uk>
Signed-off-by: Mike Bryant <mike.bryant@mettle.co.uk>
Co-authored-by: Chip Zoller <chipzoller@gmail.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: Jim Bugwadia <jim@nirmata.com>
Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Mike Bryant 2023-08-02 18:59:37 +01:00 committed by GitHub
parent 329c11a058
commit fd67707c00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 357 additions and 10 deletions

View file

@ -117,6 +117,12 @@ type Spec struct {
// Defaults to "false" if not specified.
// +optional
GenerateExisting bool `json:"generateExisting,omitempty" yaml:"generateExisting,omitempty"`
// UseServerSideApply controls whether to use server-side apply for generate rules
// If is set to "true" create & update for generate rules will use apply instead of create/update.
// Defaults to "false" if not specified.
// +optional
UseServerSideApply bool `json:"useServerSideApply,omitempty" yaml:"useServerSideApply,omitempty"`
}
func (s *Spec) SetRules(rules []Rule) {

View file

@ -78,6 +78,12 @@ type Spec struct {
// Defaults to "false" if not specified.
// +optional
GenerateExisting bool `json:"generateExisting,omitempty" yaml:"generateExisting,omitempty"`
// UseServerSideApply controls whether to use server-side apply for generate rules
// If is set to "true" create & update for generate rules will use apply instead of create/update.
// Defaults to "false" if not specified.
// +optional
UseServerSideApply bool `json:"useServerSideApply,omitempty" yaml:"useServerSideApply,omitempty"`
}
func (s *Spec) SetRules(rules []Rule) {

View file

@ -7764,6 +7764,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -15606,6 +15612,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -23759,6 +23771,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -31603,6 +31621,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy

View file

@ -3947,6 +3947,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -11789,6 +11795,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy

View file

@ -3948,6 +3948,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -11792,6 +11798,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy

View file

@ -7967,6 +7967,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -15809,6 +15815,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -23962,6 +23974,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy
@ -31806,6 +31824,12 @@ spec:
as well as patched resources. Optional. The default value is set
to "true", it must be set to "false" to disable the validation checks.
type: boolean
useServerSideApply:
description: UseServerSideApply controls whether to use server-side
apply for generate rules If is set to "true" create & update for
generate rules will use apply instead of create/update. Defaults
to "false" if not specified.
type: boolean
validationFailureAction:
default: Audit
description: ValidationFailureAction defines if a validation policy

View file

@ -275,6 +275,20 @@ If is set to &ldquo;true&rdquo; generate rule will be triggered and applied to e
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
<tr>
<td>
<code>useServerSideApply</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>UseServerSideApply controls whether to use server-side apply for generate rules
If is set to &ldquo;true&rdquo; create &amp; update for generate rules will use apply instead of create/update.
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -526,6 +540,20 @@ If is set to &ldquo;true&rdquo; generate rule will be triggered and applied to e
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
<tr>
<td>
<code>useServerSideApply</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>UseServerSideApply controls whether to use server-side apply for generate rules
If is set to &ldquo;true&rdquo; create &amp; update for generate rules will use apply instead of create/update.
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -3679,6 +3707,20 @@ If is set to &ldquo;true&rdquo; generate rule will be triggered and applied to e
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
<tr>
<td>
<code>useServerSideApply</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>UseServerSideApply controls whether to use server-side apply for generate rules
If is set to &ldquo;true&rdquo; create &amp; update for generate rules will use apply instead of create/update.
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
</tbody>
</table>
<hr />
@ -6070,6 +6112,20 @@ If is set to &ldquo;true&rdquo; generate rule will be triggered and applied to e
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
<tr>
<td>
<code>useServerSideApply</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>UseServerSideApply controls whether to use server-side apply for generate rules
If is set to &ldquo;true&rdquo; create &amp; update for generate rules will use apply instead of create/update.
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -6320,6 +6376,20 @@ If is set to &ldquo;true&rdquo; generate rule will be triggered and applied to e
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
<tr>
<td>
<code>useServerSideApply</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>UseServerSideApply controls whether to use server-side apply for generate rules
If is set to &ldquo;true&rdquo; create &amp; update for generate rules will use apply instead of create/update.
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -7242,6 +7312,20 @@ If is set to &ldquo;true&rdquo; generate rule will be triggered and applied to e
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
<tr>
<td>
<code>useServerSideApply</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>UseServerSideApply controls whether to use server-side apply for generate rules
If is set to &ldquo;true&rdquo; create &amp; update for generate rules will use apply instead of create/update.
Defaults to &ldquo;false&rdquo; if not specified.</p>
</td>
</tr>
</tbody>
</table>
<hr />

View file

@ -11,6 +11,7 @@ import (
datautils "github.com/kyverno/kyverno/pkg/utils/data"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func manageClone(log logr.Logger, target, sourceSpec kyvernov1.ResourceSpec, policy kyvernov1.PolicyInterface, ur kyvernov1beta1.UpdateRequest, rule kyvernov1.Rule, client dclient.Interface) generateResponse {
@ -50,6 +51,13 @@ func manageClone(log logr.Logger, target, sourceSpec kyvernov1.ResourceSpec, pol
if sourceObjCopy.GetNamespace() != target.GetNamespace() && sourceObjCopy.GetOwnerReferences() != nil {
sourceObjCopy.SetOwnerReferences(nil)
}
// Clean up parameters that shouldn't be copied
sourceObjCopy.SetUID("")
sourceObjCopy.SetSelfLink("")
var emptyTime metav1.Time
sourceObjCopy.SetCreationTimestamp(emptyTime)
sourceObjCopy.SetManagedFields(nil)
sourceObjCopy.SetResourceVersion("")
targetObj, err := client.GetResource(context.TODO(), target.GetAPIVersion(), target.GetKind(), target.GetNamespace(), target.GetName())
if err != nil {
@ -64,13 +72,15 @@ func manageClone(log logr.Logger, target, sourceSpec kyvernov1.ResourceSpec, pol
}
if targetObj != nil {
sourceObjCopy.SetUID(targetObj.GetUID())
sourceObjCopy.SetSelfLink(targetObj.GetSelfLink())
sourceObjCopy.SetCreationTimestamp(targetObj.GetCreationTimestamp())
sourceObjCopy.SetManagedFields(targetObj.GetManagedFields())
sourceObjCopy.SetResourceVersion(targetObj.GetResourceVersion())
if datautils.DeepEqual(sourceObjCopy, targetObj) {
return newSkipGenerateResponse(nil, target, nil)
if !policy.GetSpec().UseServerSideApply {
sourceObjCopy.SetUID(targetObj.GetUID())
sourceObjCopy.SetSelfLink(targetObj.GetSelfLink())
sourceObjCopy.SetCreationTimestamp(targetObj.GetCreationTimestamp())
sourceObjCopy.SetManagedFields(targetObj.GetManagedFields())
sourceObjCopy.SetResourceVersion(targetObj.GetResourceVersion())
if datautils.DeepEqual(sourceObjCopy, targetObj) {
return newSkipGenerateResponse(nil, target, nil)
}
}
return newUpdateGenerateResponse(sourceObjCopy.UnstructuredContent(), target, nil)
}

View file

@ -403,7 +403,11 @@ func applyRule(log logr.Logger, client dclient.Interface, rule kyvernov1.Rule, t
common.ManageLabels(newResource, trigger, policy, rule.Name)
if response.GetAction() == Create {
newResource.SetResourceVersion("")
_, err = client.CreateResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), newResource, false)
if policy.GetSpec().UseServerSideApply {
_, err = client.ApplyResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), targetMeta.GetName(), newResource, false, "generate")
} else {
_, err = client.CreateResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), newResource, false)
}
if err != nil {
if !apierrors.IsAlreadyExists(err) {
return newGenResources, err
@ -415,7 +419,11 @@ func applyRule(log logr.Logger, client dclient.Interface, rule kyvernov1.Rule, t
generatedObj, err := client.GetResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), targetMeta.GetName())
if err != nil {
logger.V(2).Info("target resource not found, creating new target")
_, err = client.CreateResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), newResource, false)
if policy.GetSpec().UseServerSideApply {
_, err = client.ApplyResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), targetMeta.GetName(), newResource, false, "generate")
} else {
_, err = client.CreateResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), newResource, false)
}
if err != nil {
return newGenResources, err
}
@ -433,7 +441,11 @@ func applyRule(log logr.Logger, client dclient.Interface, rule kyvernov1.Rule, t
newResource.SetNamespace("default")
}
_, err = client.UpdateResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), newResource, false)
if policy.GetSpec().UseServerSideApply {
_, err = client.ApplyResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), targetMeta.GetName(), newResource, false, "generate")
} else {
_, err = client.UpdateResource(context.TODO(), targetMeta.GetAPIVersion(), targetMeta.GetKind(), targetMeta.GetNamespace(), newResource, false)
}
if err != nil {
logger.Error(err, "failed to update resource")
return newGenResources, err

View file

@ -37,6 +37,7 @@ type SpecApplyConfiguration struct {
MutateExistingOnPolicyUpdate *bool `json:"mutateExistingOnPolicyUpdate,omitempty"`
GenerateExistingOnPolicyUpdate *bool `json:"generateExistingOnPolicyUpdate,omitempty"`
GenerateExisting *bool `json:"generateExisting,omitempty"`
UseServerSideApply *bool `json:"useServerSideApply,omitempty"`
}
// SpecApplyConfiguration constructs an declarative configuration of the Spec type for use with
@ -150,3 +151,11 @@ func (b *SpecApplyConfiguration) WithGenerateExisting(value bool) *SpecApplyConf
b.GenerateExisting = &value
return b
}
// WithUseServerSideApply sets the UseServerSideApply field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UseServerSideApply field is set to the value of the last call.
func (b *SpecApplyConfiguration) WithUseServerSideApply(value bool) *SpecApplyConfiguration {
b.UseServerSideApply = &value
return b
}

View file

@ -38,6 +38,7 @@ type SpecApplyConfiguration struct {
MutateExistingOnPolicyUpdate *bool `json:"mutateExistingOnPolicyUpdate,omitempty"`
GenerateExistingOnPolicyUpdate *bool `json:"generateExistingOnPolicyUpdate,omitempty"`
GenerateExisting *bool `json:"generateExisting,omitempty"`
UseServerSideApply *bool `json:"useServerSideApply,omitempty"`
}
// SpecApplyConfiguration constructs an declarative configuration of the Spec type for use with
@ -151,3 +152,11 @@ func (b *SpecApplyConfiguration) WithGenerateExisting(value bool) *SpecApplyConf
b.GenerateExisting = &value
return b
}
// WithUseServerSideApply sets the UseServerSideApply field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UseServerSideApply field is set to the value of the last call.
func (b *SpecApplyConfiguration) WithUseServerSideApply(value bool) *SpecApplyConfiguration {
b.UseServerSideApply = &value
return b
}

View file

@ -48,6 +48,10 @@ type Interface interface {
UpdateResource(ctx context.Context, apiVersion string, kind string, namespace string, obj interface{}, dryRun bool, subresources ...string) (*unstructured.Unstructured, error)
// UpdateStatusResource updates the resource "status" subresource
UpdateStatusResource(ctx context.Context, apiVersion string, kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error)
// ApplyResource applies object for the specified resource/namespace using server-side apply
ApplyResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, obj interface{}, dryRun bool, fieldManager string, subresources ...string) (*unstructured.Unstructured, error)
// ApplyStatusResource applies the resource "status" subresource using server-side apply
ApplyStatusResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, obj interface{}, dryRun bool, fieldManager string) (*unstructured.Unstructured, error)
}
// Client enables interaction with k8 resource
@ -226,6 +230,36 @@ func (c *client) UpdateStatusResource(ctx context.Context, apiVersion string, ki
return nil, fmt.Errorf("unable to update resource ")
}
// ApplyResource updates object for the specified resource/namespace
func (c *client) ApplyResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, obj interface{}, dryRun bool, fieldManager string, subresources ...string) (*unstructured.Unstructured, error) {
// We have a different field manager for different situations, so a generated object that then goes through admission control
// won't have the changes wiped out by any use of server-side apply in the mutation path
options := metav1.ApplyOptions{FieldManager: "kyverno-" + fieldManager, Force: true}
if dryRun {
options.DryRun = []string{metav1.DryRunAll}
}
// convert typed to unstructured obj
if unstructuredObj, err := kubeutils.ObjToUnstructured(obj); err == nil && unstructuredObj != nil {
return c.getResourceInterface(apiVersion, kind, namespace).Apply(ctx, name, unstructuredObj, options, subresources...)
}
return nil, fmt.Errorf("unable to apply resource ")
}
// ApplyStatusResource updates the resource "status" subresource
func (c *client) ApplyStatusResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, obj interface{}, dryRun bool, fieldManager string) (*unstructured.Unstructured, error) {
// We have a different field manager for different situations, so a generated object that then goes through admission control
// won't have the changes wiped out by any use of server-side apply in the mutation path
options := metav1.ApplyOptions{FieldManager: "kyverno-" + fieldManager, Force: true}
if dryRun {
options.DryRun = []string{metav1.DryRunAll}
}
// convert typed to unstructured obj
if unstructuredObj, err := kubeutils.ObjToUnstructured(obj); err == nil && unstructuredObj != nil {
return c.getResourceInterface(apiVersion, kind, namespace).ApplyStatus(ctx, name, unstructuredObj, options)
}
return nil, fmt.Errorf("unable to apply resource ")
}
// Discovery return the discovery client implementation
func (c *client) Discovery() IDiscovery {
return c.disco

View file

@ -0,0 +1,5 @@
# A pre-test sleep is needed here due to https://github.com/kudobuilder/kuttl/pull/422
apiVersion: kuttl.dev/v1beta1
kind: TestStep
commands:
- command: sleep 3

View file

@ -0,0 +1,6 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- policy.yaml
assert:
- policy-ready.yaml

View file

@ -0,0 +1,6 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- ns.yaml
assert:
- cloned.yaml

View file

@ -0,0 +1,6 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- editeddownstream.yaml
assert:
- finalsecret.yaml

View file

@ -0,0 +1,11 @@
## Description
This test ensures that modification of the downstream (cloned/generated) resource used by a ClusterPolicy `generate` rule with sync enabled using a clone declaration and server-side apply causes those changes to be merged from the state of the upstream/source.
## Expected Behavior
After the downstream resource is modified, the changes should be merged with the clone after synchronization occurs. If the downstream resource is synced with the state of the source resource, and also respects the modifications to other fields, the test passes. If the downstream resource doesn't retain the cloned fields and the directly modified fields, the test fails.
## Reference Issue(s)
N/A

View file

@ -0,0 +1,8 @@
apiVersion: v1
data:
foo: YmFy
kind: Secret
metadata:
name: regcred
namespace: myfoons
type: Opaque

View file

@ -0,0 +1,9 @@
apiVersion: v1
data:
foo: bm90YmFjaGhlcmU=
foo2: bm90YmFjaGhlcmU=
kind: Secret
metadata:
name: regcred
namespace: myfoons
type: Opaque

View file

@ -0,0 +1,9 @@
apiVersion: v1
data:
foo: YmFy
foo2: bm90YmFjaGhlcmU=
kind: Secret
metadata:
name: regcred
namespace: myfoons
type: Opaque

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: myfoons

View file

@ -0,0 +1,9 @@
apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
name: cpol-clone-sync-modify-downstream-apply
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,32 @@
apiVersion: v1
data:
foo: YmFy
kind: Secret
metadata:
name: regcred
namespace: default
type: Opaque
---
apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
name: cpol-clone-sync-modify-downstream-apply
spec:
rules:
- name: cpol-clone-sync-modify-downstream-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
useServerSideApply: true
---