mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 07:26:55 +00:00
feat: allow generate pattern changes (#11202)
* chore: remove duplicate test steps Signed-off-by: ShutingZhao <shuting@nirmata.com> * feat: remove validation checks upon generate policy changes Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: return nil Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: chainsaw tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: restrict rule spec changes except for generate pattern Signed-off-by: ShutingZhao <shuting@nirmata.com> * chore: rename tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * chore: upadte e2e matrix Signed-off-by: ShutingZhao <shuting@nirmata.com> --------- Signed-off-by: ShutingZhao <shuting@nirmata.com>
This commit is contained in:
parent
e3d7f32146
commit
2d601a0830
78 changed files with 448 additions and 329 deletions
|
@ -9,12 +9,15 @@ import (
|
||||||
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
||||||
"github.com/kyverno/kyverno/pkg/autogen"
|
"github.com/kyverno/kyverno/pkg/autogen"
|
||||||
"github.com/kyverno/kyverno/pkg/background/common"
|
"github.com/kyverno/kyverno/pkg/background/common"
|
||||||
|
backgroundcommon "github.com/kyverno/kyverno/pkg/background/common"
|
||||||
generateutils "github.com/kyverno/kyverno/pkg/background/generate"
|
generateutils "github.com/kyverno/kyverno/pkg/background/generate"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||||
engineutils "github.com/kyverno/kyverno/pkg/utils/engine"
|
engineutils "github.com/kyverno/kyverno/pkg/utils/engine"
|
||||||
"go.uber.org/multierr"
|
"go.uber.org/multierr"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (pc *policyController) handleGenerate(policyKey string, policy kyvernov1.PolicyInterface) error {
|
func (pc *policyController) handleGenerate(policyKey string, policy kyvernov1.PolicyInterface) error {
|
||||||
|
@ -225,28 +228,99 @@ func (pc *policyController) buildUrForDataRuleChanges(policy kyvernov1.PolicyInt
|
||||||
return ur, nil
|
return ur, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pc *policyController) unlabelDownstream(selector updatedResource) {
|
||||||
|
for _, ruleSelector := range selector.ruleResources {
|
||||||
|
for _, kind := range ruleSelector.kinds {
|
||||||
|
updated, err := pc.client.ListResource(context.TODO(), "", kind, "", &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
backgroundcommon.GeneratePolicyLabel: selector.policy,
|
||||||
|
backgroundcommon.GeneratePolicyNamespaceLabel: selector.policyNamespace,
|
||||||
|
backgroundcommon.GenerateRuleLabel: ruleSelector.rule,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
utilruntime.HandleError(fmt.Errorf("failed to list old targets: %v", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, obj := range updated.Items {
|
||||||
|
labels := obj.GetLabels()
|
||||||
|
delete(labels, backgroundcommon.GeneratePolicyLabel)
|
||||||
|
delete(labels, backgroundcommon.GeneratePolicyNamespaceLabel)
|
||||||
|
delete(labels, backgroundcommon.GenerateRuleLabel)
|
||||||
|
obj.SetLabels(labels)
|
||||||
|
_, err = pc.client.UpdateResource(context.TODO(), obj.GetAPIVersion(), obj.GetKind(), obj.GetNamespace(), &obj, false)
|
||||||
|
if err != nil {
|
||||||
|
utilruntime.HandleError(fmt.Errorf("failed to un-label old targets %s/%s/%s/%s: %v", obj.GetAPIVersion(), obj.GetKind(), obj.GetNamespace(), obj.GetName(), err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type updatedResource struct {
|
||||||
|
policy string
|
||||||
|
policyNamespace string
|
||||||
|
ruleResources []ruleResource
|
||||||
|
}
|
||||||
|
|
||||||
|
type ruleResource struct {
|
||||||
|
rule string
|
||||||
|
kinds []string
|
||||||
|
}
|
||||||
|
|
||||||
// ruleDeletion returns true if any rule is deleted, along with deleted rules
|
// ruleDeletion returns true if any rule is deleted, along with deleted rules
|
||||||
func ruleDeletion(old, new kyvernov1.PolicyInterface) (_ kyvernov1.PolicyInterface, ruleDeleted bool) {
|
func ruleChange(old, new kyvernov1.PolicyInterface) (_ kyvernov1.PolicyInterface, ruleDeleted bool, _ updatedResource) {
|
||||||
if !new.GetDeletionTimestamp().IsZero() {
|
if !new.GetDeletionTimestamp().IsZero() {
|
||||||
return nil, false
|
return nil, false, updatedResource{}
|
||||||
}
|
}
|
||||||
|
|
||||||
newRules := new.GetSpec().Rules
|
newRules := new.GetSpec().Rules
|
||||||
oldRules := old.GetSpec().Rules
|
oldRules := old.GetSpec().Rules
|
||||||
newRulesMap := make(map[string]bool, len(newRules))
|
newRulesMap := make(map[string]kyvernov1.Rule, len(newRules))
|
||||||
var deletedRules []kyvernov1.Rule
|
var deletedRules []kyvernov1.Rule
|
||||||
|
updatedResources := updatedResource{
|
||||||
|
policy: new.GetName(),
|
||||||
|
policyNamespace: new.GetNamespace(),
|
||||||
|
}
|
||||||
|
|
||||||
for _, r := range newRules {
|
for _, r := range newRules {
|
||||||
newRulesMap[r.Name] = true
|
newRulesMap[r.Name] = r
|
||||||
}
|
}
|
||||||
for _, r := range oldRules {
|
for _, oldRule := range oldRules {
|
||||||
if exist := newRulesMap[r.Name]; !exist {
|
if newRule, exist := newRulesMap[oldRule.Name]; !exist {
|
||||||
deletedRules = append(deletedRules, r)
|
deletedRules = append(deletedRules, oldRule)
|
||||||
ruleDeleted = true
|
ruleDeleted = true
|
||||||
|
} else {
|
||||||
|
ruleRsrc := ruleResource{rule: oldRule.Name}
|
||||||
|
old, new := oldRule.Generation, newRule.Generation
|
||||||
|
if old.ResourceSpec != new.ResourceSpec || old.Clone != new.Clone {
|
||||||
|
ruleRsrc.kinds = append(ruleRsrc.kinds, old.ResourceSpec.GetKind())
|
||||||
|
}
|
||||||
|
if !datautils.DeepEqual(old.CloneList, new.CloneList) {
|
||||||
|
ruleRsrc.kinds = append(ruleRsrc.kinds, old.CloneList.Kinds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, oldForeach := range old.ForEachGeneration {
|
||||||
|
for _, newForeach := range new.ForEachGeneration {
|
||||||
|
if oldForeach.List == newForeach.List {
|
||||||
|
if oldForeach.ResourceSpec != newForeach.ResourceSpec || oldForeach.Clone != newForeach.Clone {
|
||||||
|
ruleRsrc.kinds = append(ruleRsrc.kinds, old.ResourceSpec.GetKind())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !datautils.DeepEqual(oldForeach.CloneList, newForeach.CloneList) {
|
||||||
|
ruleRsrc.kinds = append(ruleRsrc.kinds, old.CloneList.Kinds...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatedResources.ruleResources = append(updatedResources.ruleResources, ruleRsrc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildPolicyWithDeletedRules(old, deletedRules), ruleDeleted
|
return buildPolicyWithDeletedRules(old, deletedRules), ruleDeleted, updatedResources
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPolicyWithDeletedRules(policy kyvernov1.PolicyInterface, deletedRules []kyvernov1.Rule) kyvernov1.PolicyInterface {
|
func buildPolicyWithDeletedRules(policy kyvernov1.PolicyInterface, deletedRules []kyvernov1.Rule) kyvernov1.PolicyInterface {
|
||||||
|
|
|
@ -201,11 +201,13 @@ func (pc *policyController) updatePolicy(old, cur interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.V(2).Info("updating policy", "name", oldP.GetName())
|
logger.V(2).Info("updating policy", "name", oldP.GetName())
|
||||||
if deleted, ok := ruleDeletion(oldP, curP); ok {
|
if deleted, ok, selector := ruleChange(oldP, curP); ok {
|
||||||
err := pc.createURForDownstreamDeletion(deleted)
|
err := pc.createURForDownstreamDeletion(deleted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utilruntime.HandleError(fmt.Errorf("failed to create UR on rule deletion, clean up downstream resource may be failed: %v", err))
|
utilruntime.HandleError(fmt.Errorf("failed to create UR on rule deletion, clean up downstream resource may be failed: %v", err))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
pc.unlabelDownstream(selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
pc.enqueuePolicy(curP)
|
pc.enqueuePolicy(curP)
|
||||||
|
|
|
@ -11,61 +11,66 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
|
||||||
func immutableGenerateFields(new, old kyvernov1.PolicyInterface) error {
|
func immutableGenerateFields(new, old kyvernov1.PolicyInterface) (string, error) {
|
||||||
if new == nil || old == nil {
|
if new == nil || old == nil {
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !new.GetSpec().HasGenerate() {
|
oldRuleHashes, oldGenerationHashes, err := buildHashes(old.GetSpec().Rules)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
oldRuleHashes, err := buildHashes(old.GetSpec().Rules)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
newRuleHashes, err := buildHashes(new.GetSpec().Rules)
|
newRuleHashes, newGenerationHashes, err := buildHashes(new.GetSpec().Rules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(old.GetSpec().Rules) <= len(new.GetSpec().Rules) {
|
if !newGenerationHashes.IsSuperset(oldGenerationHashes) {
|
||||||
case true:
|
return "changes in the generate rule pattern could result in stale targets", nil
|
||||||
if newRuleHashes.IsSuperset(oldRuleHashes) {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return errors.New("change of immutable fields for a generate rule is disallowed")
|
|
||||||
}
|
|
||||||
case false:
|
|
||||||
if oldRuleHashes.IsSuperset(newRuleHashes) {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return errors.New("rule deletion - change of immutable fields for a generate rule is disallowed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
if !newRuleHashes.IsSuperset(oldRuleHashes) {
|
||||||
|
return "", errors.New("changes of the rule spec in a generate rule is disallowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetMutableFields(rule kyvernov1.Rule) *kyvernov1.Rule {
|
func resetMutableFields(rule kyvernov1.Rule) (*kyvernov1.Rule, *kyvernov1.Generation) {
|
||||||
new := new(kyvernov1.Rule)
|
new := new(kyvernov1.Rule)
|
||||||
rule.DeepCopyInto(new)
|
rule.DeepCopyInto(new)
|
||||||
new.Generation.Synchronize = true
|
generation := new.Generation
|
||||||
new.Generation.SetData(nil)
|
new.Generation = nil
|
||||||
new.Generation.ForEachGeneration = nil
|
generation.Synchronize = true
|
||||||
new.Generation.OrphanDownstreamOnPolicyDelete = true
|
generation.SetData(nil)
|
||||||
return new
|
generation.ForEachGeneration = nil
|
||||||
|
generation.OrphanDownstreamOnPolicyDelete = true
|
||||||
|
generation.GenerateExisting = nil
|
||||||
|
|
||||||
|
return new, generation
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildHashes(rules []kyvernov1.Rule) (sets.Set[string], error) {
|
func buildHashes(rules []kyvernov1.Rule) (ruleHashes sets.Set[string], generationHashes sets.Set[string], _ error) {
|
||||||
ruleHashes := sets.New[string]()
|
ruleHashes, generationHashes = sets.New[string](), sets.New[string]()
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
r := resetMutableFields(rule)
|
if !rule.HasGenerate() {
|
||||||
data, err := json.Marshal(r)
|
continue
|
||||||
|
}
|
||||||
|
r, generation := resetMutableFields(rule)
|
||||||
|
data, err := json.Marshal(generation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleHashes, fmt.Errorf("failed to create hash from the generate rule %v", err)
|
return ruleHashes, generationHashes, fmt.Errorf("failed to create hash from the generate rule %v", err)
|
||||||
}
|
}
|
||||||
hash := md5.Sum(data) //nolint:gosec
|
hash := md5.Sum(data) //nolint:gosec
|
||||||
|
generationHashes.Insert(hex.EncodeToString(hash[:]))
|
||||||
|
|
||||||
|
data, err = json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
return ruleHashes, generationHashes, fmt.Errorf("failed to create hash from the generate rule %v", err)
|
||||||
|
}
|
||||||
|
hash = md5.Sum(data) //nolint:gosec
|
||||||
ruleHashes.Insert(hex.EncodeToString(hash[:]))
|
ruleHashes.Insert(hex.EncodeToString(hash[:]))
|
||||||
}
|
}
|
||||||
return ruleHashes, nil
|
return ruleHashes, generationHashes, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,8 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := immutableGenerateFields(policy, oldPolicy); err != nil {
|
if warning, err := immutableGenerateFields(policy, oldPolicy); warning != "" || err != nil {
|
||||||
|
warnings = append(warnings, fmt.Sprintf("no synchronization will be performed to the old target resource upon policy updates: %s", warning))
|
||||||
return warnings, err
|
return warnings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2209,12 +2209,13 @@ func Test_Validate_RuleImageExtractorsJMESPath(t *testing.T) {
|
||||||
assert.Equal(t, expectedErr.Error(), actualErr.Error())
|
assert.Equal(t, expectedErr.Error(), actualErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_ImmutableGenerateFields(t *testing.T) {
|
func Test_GenerateFieldsUpdates(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
oldPolicy []byte
|
oldPolicy []byte
|
||||||
newPolicy []byte
|
newPolicy []byte
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
|
expectWarning bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "update-apiVersion",
|
name: "update-apiVersion",
|
||||||
|
@ -2292,7 +2293,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-kind",
|
name: "update-kind",
|
||||||
|
@ -2370,7 +2372,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-namespace",
|
name: "update-namespace",
|
||||||
|
@ -2448,7 +2451,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-name",
|
name: "update-name",
|
||||||
|
@ -2526,7 +2530,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-sync-flag",
|
name: "update-sync-flag",
|
||||||
|
@ -2604,7 +2609,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
|
expectWarning: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-clone-name",
|
name: "update-clone-name",
|
||||||
|
@ -2682,7 +2688,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-clone-namespace",
|
name: "update-clone-namespace",
|
||||||
|
@ -2760,7 +2767,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-clone-namespace-unset-new",
|
name: "update-clone-namespace-unset-new",
|
||||||
|
@ -2837,7 +2845,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-cloneList-kinds",
|
name: "update-cloneList-kinds",
|
||||||
|
@ -2916,7 +2925,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-cloneList-namespace",
|
name: "update-cloneList-namespace",
|
||||||
|
@ -2995,7 +3005,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-cloneList-selector",
|
name: "update-cloneList-selector",
|
||||||
|
@ -3085,7 +3096,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-clone-List-selector-unset",
|
name: "update-clone-List-selector-unset",
|
||||||
|
@ -3170,7 +3182,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: true,
|
expectedErr: false,
|
||||||
|
expectWarning: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update-cloneList-selector-nochange",
|
name: "update-cloneList-selector-nochange",
|
||||||
|
@ -3260,7 +3273,8 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
|
expectWarning: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3271,8 +3285,10 @@ func Test_ImmutableGenerateFields(t *testing.T) {
|
||||||
err = json.Unmarshal(test.newPolicy, &new)
|
err = json.Unmarshal(test.newPolicy, &new)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
err = immutableGenerateFields(new, old)
|
warning, err := immutableGenerateFields(new, old)
|
||||||
|
golangassert.Assert(t, (warning != "") == test.expectWarning, test.name, err)
|
||||||
golangassert.Assert(t, (err != nil) == test.expectedErr, test.name, err)
|
golangassert.Assert(t, (err != nil) == test.expectedErr, test.name, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,9 @@
|
||||||
"^generate$/^policy$/^standard$/^data$/^nosync$/^(pol-data-nosync-create-policy-invalid|pol-data-nosync-delete-downstream|pol-data-nosync-delete-policy|pol-data-nosync-delete-rule|pol-data-nosync-delete-rule-deprecated|pol-data-nosync-delete-trigger|pol-data-nosync-modify-downstream|pol-data-nosync-modify-rule|pol-data-nosync-update-trigger-no-match)\\[.*\\]$",
|
"^generate$/^policy$/^standard$/^data$/^nosync$/^(pol-data-nosync-create-policy-invalid|pol-data-nosync-delete-downstream|pol-data-nosync-delete-policy|pol-data-nosync-delete-rule|pol-data-nosync-delete-rule-deprecated|pol-data-nosync-delete-trigger|pol-data-nosync-modify-downstream|pol-data-nosync-modify-rule|pol-data-nosync-update-trigger-no-match)\\[.*\\]$",
|
||||||
"^generate$/^policy$/^standard$/^data$/^sync$/^(pol-data-sync-create-policy-invalid|pol-data-sync-create-policy-valid|pol-data-sync-delete-downstream|pol-data-sync-delete-policy|pol-data-sync-delete-rule|pol-data-sync-delete-rule-deprecated|pol-data-sync-delete-trigger|pol-data-sync-modify-downstream|pol-data-sync-modify-rule|pol-data-sync-modify-rule-deprecated|pol-data-sync-update-trigger-no-match)\\[.*\\]$",
|
"^generate$/^policy$/^standard$/^data$/^sync$/^(pol-data-sync-create-policy-invalid|pol-data-sync-create-policy-valid|pol-data-sync-delete-downstream|pol-data-sync-delete-policy|pol-data-sync-delete-rule|pol-data-sync-delete-rule-deprecated|pol-data-sync-delete-trigger|pol-data-sync-modify-downstream|pol-data-sync-modify-rule|pol-data-sync-modify-rule-deprecated|pol-data-sync-update-trigger-no-match)\\[.*\\]$",
|
||||||
"^generate$/^policy$/^standard$/^existing$/^(match-trigger-namespace|match-trigger-namespace-deprecated|non-match-trigger-namespace|non-match-trigger-namespace-deprecated)\\[.*\\]$",
|
"^generate$/^policy$/^standard$/^existing$/^(match-trigger-namespace|match-trigger-namespace-deprecated|non-match-trigger-namespace|non-match-trigger-namespace-deprecated)\\[.*\\]$",
|
||||||
"^generate$/^validation$/^clusterpolicy$/^(cloneList|immutable-clone|immutable-clonelist|immutable-downstream|immutable-rule-spec|orphan|prevent-loop|target-namespace-scope|use-generate-existing-on-policy-update)\\[.*\\]$",
|
"^generate$/^validation$/^clusterpolicy$/^(cloneList|immutable-rule-spec|orphan|prevent-loop|target-namespace-scope|use-generate-existing-on-policy-update|warn-clone-change|warn-clonelist-change|warn-downstream-change)\\[.*\\]$",
|
||||||
"^generate$/^validation$/^clusterpolicy$/^permissions$/^(no-permission|same-kind)\\[.*\\]$",
|
"^generate$/^validation$/^clusterpolicy$/^permissions$/^(no-permission|same-kind)\\[.*\\]$",
|
||||||
"^generate$/^validation$/^policy$/^(cloneList|immutable-clone|immutable-clonelist|immutable-downstream|immutable-rule-spec|permissions|prevent-loop|target-namespace-scope|use-generate-existing-on-policy-update)\\[.*\\]$"
|
"^generate$/^validation$/^policy$/^(cloneList|immutable-rule-spec|permissions|prevent-loop|target-namespace-scope|use-generate-existing-on-policy-update|warn-clone-change|warn-clonelist-change|warn-downstream-change)\\[.*\\]$"
|
||||||
],
|
],
|
||||||
"generate-validating-admission-policy": [
|
"generate-validating-admission-policy": [
|
||||||
"^generate-validating-admission-policy$/^clusterpolicy$/^standard$/^generate$/^(block-ephemeral-containers|block-exec-in-pods|cpol-all-match-resource|cpol-any-exclude-namespace-match-resource|cpol-any-exclude-resource|cpol-any-exclude-resource-match-with-namespace-selector|cpol-any-exclude-resource-match-with-object-selector|cpol-any-match-multiple-resources|cpol-any-match-resource|cpol-any-match-resources-by-names|cpol-match-all-exclude-one|cpol-match-kind-with-wildcard|cpol-match-resource-in-specific-namespace|cpol-with-an-exception|cpol-with-an-exception-excluding-namespaces|cpol-with-two-exceptions)\\[.*\\]$",
|
"^generate-validating-admission-policy$/^clusterpolicy$/^standard$/^generate$/^(block-ephemeral-containers|block-exec-in-pods|cpol-all-match-resource|cpol-any-exclude-namespace-match-resource|cpol-any-exclude-resource|cpol-any-exclude-resource-match-with-namespace-selector|cpol-any-exclude-resource-match-with-object-selector|cpol-any-match-multiple-resources|cpol-any-match-resource|cpol-any-match-resources-by-names|cpol-match-all-exclude-one|cpol-match-kind-with-wildcard|cpol-match-resource-in-specific-namespace|cpol-with-an-exception|cpol-with-an-exception-excluding-namespaces|cpol-with-two-exceptions)\\[.*\\]$",
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: sync-with-multi-clone-update
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- name: sync-secret
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
exclude:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
namespaces:
|
||||||
|
- kube-system
|
||||||
|
- default
|
||||||
|
- kube-public
|
||||||
|
- kyverno
|
||||||
|
generate:
|
||||||
|
generateExisting: false
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize : true
|
||||||
|
cloneList:
|
||||||
|
namespace: default
|
||||||
|
kinds:
|
||||||
|
- v1/Secret
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
allowedToBeCloned: "true"
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: bootstrap-config
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
allowedToBeCloned: "true"
|
||||||
|
data:
|
||||||
|
initial_lives: "100"
|
|
@ -4,7 +4,8 @@ This test verifies the synchronize behavior of generated resource, if the select
|
||||||
|
|
||||||
## Expected Behavior
|
## Expected Behavior
|
||||||
|
|
||||||
This test ensures that update of source resource(ConfigMap) match selected using `allowedToBeCloned: "true"` label get synchronized with target resource created by a ClusterPolicy `generate.cloneList` rule, otherwise the test fails.
|
1. update source resource (configmap) match selected using `allowedToBeCloned: "true"` label, the change should be synced to the target configmap.
|
||||||
|
2. remove configmap from the `cloneList.kinds` in the policy, update the source configmap, the change should not be synced to the previous cloned configmap
|
||||||
|
|
||||||
## Reference Issue(s)
|
## Reference Issue(s)
|
||||||
|
|
||||||
|
|
|
@ -7,28 +7,34 @@ spec:
|
||||||
- name: step-00
|
- name: step-00
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: permissions.yaml
|
file: 0-0-permissions.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: manifests.yaml
|
file: 0-1-manifests.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: cluster-policy.yaml
|
file: 0-2-cluster-policy.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: cluster-policy-ready.yaml
|
file: 0-3-cluster-policy-ready.yaml
|
||||||
- name: step-01
|
- name: step-01
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: ns.yaml
|
file: 1-0-ns.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: resource-assert.yaml
|
file: 1-1-resource-assert.yaml
|
||||||
- name: step-02
|
- name: step-02
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: ns.yaml
|
file: 2-0-update-source.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: resource-assert.yaml
|
file: 2-1-synchronized-target.yaml
|
||||||
- name: step-03
|
- name: step-03
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: update-source.yaml
|
file: 3-0-update-cluster-policy.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: synchronized-target.yaml
|
file: 0-3-cluster-policy-ready.yaml
|
||||||
|
- name: step-04
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: 4-0-update-source.yaml
|
||||||
|
- assert:
|
||||||
|
file: 2-1-synchronized-target.yaml
|
||||||
|
|
|
@ -30,6 +30,7 @@ spec:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
somekey: somevalue
|
somekey: somevalue
|
||||||
|
foo: bar
|
||||||
data:
|
data:
|
||||||
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
|
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
|
||||||
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"
|
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"
|
|
@ -0,0 +1,65 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: multiple-gens
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- name: k-kafka-address
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
exclude:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
namespaces:
|
||||||
|
- kube-system
|
||||||
|
- default
|
||||||
|
- kube-public
|
||||||
|
- kyverno
|
||||||
|
generate:
|
||||||
|
generateExisting: false
|
||||||
|
synchronize: true
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
name: zk-kafka-address-new
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
data:
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
somekey: somevalue
|
||||||
|
foo: bar
|
||||||
|
data:
|
||||||
|
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
|
||||||
|
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"
|
||||||
|
- name: super-secret
|
||||||
|
match:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
exclude:
|
||||||
|
any:
|
||||||
|
- resources:
|
||||||
|
namespaces:
|
||||||
|
- kube-system
|
||||||
|
- default
|
||||||
|
- kube-public
|
||||||
|
- kyverno
|
||||||
|
generate:
|
||||||
|
generateExisting: false
|
||||||
|
synchronize: true
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
name: supersecret
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
data:
|
||||||
|
kind: Secret
|
||||||
|
type: Opaque
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
somekey: somesecretvalue
|
||||||
|
data:
|
||||||
|
mysupersecretkey: bXlzdXBlcnNlY3JldHZhbHVl
|
|
@ -0,0 +1,6 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cpol-data-sync-delete-rule
|
||||||
|
labels:
|
||||||
|
foo: bar
|
|
@ -0,0 +1,10 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
KAFKA_ADDRESS: 192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092
|
||||||
|
ZK_ADDRESS: 192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
somekey: somevalue
|
||||||
|
name: zk-kafka-address-new
|
||||||
|
namespace: cpol-data-sync-delete-rule
|
|
@ -4,7 +4,9 @@ This test checks to ensure that deletion of a rule in a ClusterPolicy generate r
|
||||||
|
|
||||||
## Expected Behavior
|
## Expected Behavior
|
||||||
|
|
||||||
The downstream (generated) resource is expected to be deleted if the corresponding rule within a ClusterPolicy is deleted. If it is not deleted, the test fails. If it is deleted, the test passes.
|
1. create the namespace that triggers the policy, two rules should be applied and generate a configmap and a secret correspondingly.
|
||||||
|
2. update the configmap rule and trigger the policy again, a new configmap should be generated.
|
||||||
|
3. delete the newly updated configmap rule, the new configmap should be deleted while the old configmap preserves.
|
||||||
|
|
||||||
## Reference Issue(s)
|
## Reference Issue(s)
|
||||||
|
|
||||||
|
|
|
@ -7,34 +7,42 @@ spec:
|
||||||
- name: step-01
|
- name: step-01
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: permissions.yaml
|
file: 1-1-permissions.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: policy.yaml
|
file: 1-2-policy.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: policy-ready.yaml
|
file: 1-3-policy-ready.yaml
|
||||||
- name: step-02
|
- name: step-02
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: chainsaw-step-02-apply-1-1.yaml
|
file: 2-1-namespace.yaml
|
||||||
- name: step-03
|
- name: step-03
|
||||||
try:
|
try:
|
||||||
- assert:
|
- assert:
|
||||||
file: secret.yaml
|
file: 3-1-secret.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: configmap.yaml
|
file: 3-2-configmap.yaml
|
||||||
- name: step-04
|
- name: step-04
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
file: delete-rule.yaml
|
file: 4-1-rule-update.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: policy-ready.yaml
|
file: 1-3-policy-ready.yaml
|
||||||
- name: step-05
|
- name: step-05
|
||||||
try:
|
try:
|
||||||
- sleep:
|
- apply:
|
||||||
duration: 3s
|
file: 5-1-namespace-update.yaml
|
||||||
|
- assert:
|
||||||
|
file: 5-2-configmap-new.yaml
|
||||||
- name: step-06
|
- name: step-06
|
||||||
try:
|
try:
|
||||||
|
- apply:
|
||||||
|
file: 6-1-delete-rule.yaml
|
||||||
- assert:
|
- assert:
|
||||||
file: secret.yaml
|
file: 1-3-policy-ready.yaml
|
||||||
|
- name: step-07
|
||||||
|
try:
|
||||||
|
- assert:
|
||||||
|
file: 3-2-configmap.yaml
|
||||||
- error:
|
- error:
|
||||||
file: configmap.yaml
|
file: 5-2-configmap-new.yaml
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
|
||||||
kind: Test
|
|
||||||
metadata:
|
|
||||||
name: immutable-clone
|
|
||||||
spec:
|
|
||||||
steps:
|
|
||||||
- name: step-01
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
file: permissions.yaml
|
|
||||||
- apply:
|
|
||||||
file: policy.yaml
|
|
||||||
- assert:
|
|
||||||
file: policy-ready.yaml
|
|
||||||
- name: step-02
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-name.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-namespace.yaml
|
|
|
@ -1,29 +0,0 @@
|
||||||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
|
||||||
kind: Test
|
|
||||||
metadata:
|
|
||||||
name: immutable-clonelist
|
|
||||||
spec:
|
|
||||||
steps:
|
|
||||||
- name: step-01
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
file: cluster-policy.yaml
|
|
||||||
- assert:
|
|
||||||
file: cluster-policy-ready.yaml
|
|
||||||
- name: step-02
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-ns.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-kinds.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-selector.yaml
|
|
|
@ -1,34 +0,0 @@
|
||||||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
|
||||||
kind: Test
|
|
||||||
metadata:
|
|
||||||
name: immutable-downstream
|
|
||||||
spec:
|
|
||||||
steps:
|
|
||||||
- name: step-01
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
file: chainsaw-step-01-apply-1-1.yaml
|
|
||||||
- assert:
|
|
||||||
file: chainsaw-step-01-assert-1-1.yaml
|
|
||||||
- name: step-02
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-name.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-apiversion.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-namespace.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-kind.yaml
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
name: immutable-clone
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: step-01
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: permissions.yaml
|
||||||
|
- apply:
|
||||||
|
file: policy.yaml
|
||||||
|
- assert:
|
||||||
|
file: policy-ready.yaml
|
||||||
|
- name: step-02
|
||||||
|
try:
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-name.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-namespace.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
|
@ -0,0 +1,23 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
name: immutable-clonelist
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: step-01
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: cluster-policy.yaml
|
||||||
|
- assert:
|
||||||
|
file: cluster-policy-ready.yaml
|
||||||
|
- name: step-02
|
||||||
|
try:
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-ns.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-kinds.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-selector.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
|
@ -0,0 +1,26 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
name: immutable-downstream
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: step-01
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: chainsaw-step-01-apply-1-1.yaml
|
||||||
|
- assert:
|
||||||
|
file: chainsaw-step-01-assert-1-1.yaml
|
||||||
|
- name: step-02
|
||||||
|
try:
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-name.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-namespace.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-apiversion.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-kind.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
|
@ -1,22 +0,0 @@
|
||||||
apiVersion: kyverno.io/v2beta1
|
|
||||||
kind: Policy
|
|
||||||
metadata:
|
|
||||||
name: generate-update-clone
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- name: clone-secret
|
|
||||||
match:
|
|
||||||
any:
|
|
||||||
- resources:
|
|
||||||
kinds:
|
|
||||||
- ConfigMap
|
|
||||||
generate:
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
name: regcred
|
|
||||||
namespace: default
|
|
||||||
synchronize: true
|
|
||||||
clone:
|
|
||||||
namespace: ichangethis
|
|
||||||
name: regcred
|
|
|
@ -1,29 +0,0 @@
|
||||||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
|
||||||
kind: Test
|
|
||||||
metadata:
|
|
||||||
name: immutable-clonelist
|
|
||||||
spec:
|
|
||||||
steps:
|
|
||||||
- name: step-01
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
file: policy.yaml
|
|
||||||
- assert:
|
|
||||||
file: policy-ready.yaml
|
|
||||||
- name: step-02
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-ns.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-kinds.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-selector.yaml
|
|
|
@ -1,25 +0,0 @@
|
||||||
apiVersion: kyverno.io/v1
|
|
||||||
kind: Policy
|
|
||||||
metadata:
|
|
||||||
name: generate-update-clonelist
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
generateExisting: false
|
|
||||||
rules:
|
|
||||||
- name: sync-secret
|
|
||||||
match:
|
|
||||||
any:
|
|
||||||
- resources:
|
|
||||||
kinds:
|
|
||||||
- ConfigMap
|
|
||||||
generate:
|
|
||||||
namespace: default
|
|
||||||
synchronize : true
|
|
||||||
cloneList:
|
|
||||||
namespace: update-clonelist-ns
|
|
||||||
kinds:
|
|
||||||
- v1/Secret
|
|
||||||
- v1/ConfigMap
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
allowedToBeCloned: "true"
|
|
|
@ -1,34 +0,0 @@
|
||||||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
|
||||||
kind: Test
|
|
||||||
metadata:
|
|
||||||
name: immutable-downstream
|
|
||||||
spec:
|
|
||||||
steps:
|
|
||||||
- name: step-01
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
file: chainsaw-step-01-apply-1-1.yaml
|
|
||||||
- assert:
|
|
||||||
file: chainsaw-step-01-assert-1-1.yaml
|
|
||||||
- name: step-02
|
|
||||||
try:
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-name.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-apiversion.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-namespace.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-kind.yaml
|
|
|
@ -1,28 +0,0 @@
|
||||||
apiVersion: kyverno.io/v1
|
|
||||||
kind: Policy
|
|
||||||
metadata:
|
|
||||||
name: generate-update-downstream-rule
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
generateExisting: false
|
|
||||||
rules:
|
|
||||||
- name: k-kafka-address
|
|
||||||
match:
|
|
||||||
any:
|
|
||||||
- resources:
|
|
||||||
kinds:
|
|
||||||
- ConfigMap
|
|
||||||
generate:
|
|
||||||
synchronize: true
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
name: zk-kafka-address
|
|
||||||
namespace: ichangedthis
|
|
||||||
data:
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
somekey: somevalue
|
|
||||||
data:
|
|
||||||
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
|
|
||||||
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"
|
|
|
@ -12,13 +12,6 @@ spec:
|
||||||
file: policy-ready.yaml
|
file: policy-ready.yaml
|
||||||
- name: step-02
|
- name: step-02
|
||||||
try:
|
try:
|
||||||
- apply:
|
- script:
|
||||||
expect:
|
content: >
|
||||||
- check:
|
kubectl apply -f update-name.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
($error != null): true
|
|
||||||
file: update-namespace.yaml
|
|
||||||
- apply:
|
|
||||||
expect:
|
|
||||||
- check:
|
|
||||||
($error != null): true
|
|
||||||
file: update-name.yaml
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
name: immutable-clonelist
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: step-01
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: policy.yaml
|
||||||
|
- assert:
|
||||||
|
file: policy-ready.yaml
|
||||||
|
- name: step-02
|
||||||
|
try:
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-kinds.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- name: step-03
|
||||||
|
try:
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-selector.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
|
@ -11,7 +11,7 @@ spec:
|
||||||
any:
|
any:
|
||||||
- resources:
|
- resources:
|
||||||
kinds:
|
kinds:
|
||||||
-
|
- ConfigMap
|
||||||
generate:
|
generate:
|
||||||
namespace: default
|
namespace: default
|
||||||
synchronize : true
|
synchronize : true
|
|
@ -0,0 +1,23 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
name: immutable-downstream
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: step-01
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: chainsaw-step-01-apply-1-1.yaml
|
||||||
|
- assert:
|
||||||
|
file: chainsaw-step-01-assert-1-1.yaml
|
||||||
|
- name: step-02
|
||||||
|
try:
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-name.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-apiversion.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
||||||
|
- script:
|
||||||
|
content: >
|
||||||
|
kubectl apply -f update-kind.yaml 2>&1 | grep -q "Warning: no synchronization will be performed to the old target resource upon policy updates"
|
Loading…
Add table
Reference in a new issue