diff --git a/changelogs/unreleased/6704-27149chen b/changelogs/unreleased/6704-27149chen new file mode 100644 index 0000000000..62a9084cb9 --- /dev/null +++ b/changelogs/unreleased/6704-27149chen @@ -0,0 +1,3 @@ +This pr made some improvements in Resource Modifiers: +1. add label selector +2. change the field name from groupKind to groupResource diff --git a/design/Implemented/json-substitution-action-design.md b/design/Implemented/json-substitution-action-design.md index 3d5b0eb28b..595fcd3a7e 100644 --- a/design/Implemented/json-substitution-action-design.md +++ b/design/Implemented/json-substitution-action-design.md @@ -26,7 +26,7 @@ Currently velero supports substituting certain values in the K8s resources durin ## Goals -- Allow the user to specify a GroupKind, Name(optional), JSON patch for modification. +- Allow the user to specify a GroupResource, Name(optional), JSON patch for modification. - Allow the user to specify multiple JSON patch. ## Non Goals @@ -74,7 +74,7 @@ velero restore create --from-backup backup-1 --resource-modifier-configmap resou ### Resource Modifier ConfigMap Structure - User first needs to provide details on which resources the JSON Substitutions need to be applied. - - For this the user will provide 4 inputs - Namespaces(for NS Scoped resources), GroupKind (kind.group format similar to includeResources field in velero) and Name Regex(optional). + - For this the user will provide 4 inputs - Namespaces(for NS Scoped resources), GroupResource (resource.group format similar to includeResources field in velero) and Name Regex(optional). - If the user does not provide the Name, the JSON Substitutions will be applied to all the resources of the given Group and Kind under the given namespaces. - Further the use will specify the JSON Patch using the structure of kubectl's "JSON Patch" based inputs. @@ -83,7 +83,7 @@ velero restore create --from-backup backup-1 --resource-modifier-configmap resou version: v1 resourceModifierRules: - conditions: - groupKind: persistentvolumeclaims + groupResource: persistentvolumeclaims resourceNameRegex: "mysql.*" namespaces: - bar @@ -119,7 +119,7 @@ kubectl create cm --from-file -n velero version: v1 resourceModifierRules: - conditions: - groupKind: persistentvolumeclaims.storage.k8s.io + groupResource: persistentvolumeclaims.storage.k8s.io resourceNameRegex: ".*" namespaces: - bar diff --git a/internal/resourcemodifiers/resource_modifiers.go b/internal/resourcemodifiers/resource_modifiers.go index a4d24012fb..ef81945223 100644 --- a/internal/resourcemodifiers/resource_modifiers.go +++ b/internal/resourcemodifiers/resource_modifiers.go @@ -2,7 +2,6 @@ package resourcemodifiers import ( "fmt" - "io" "regexp" "strconv" "strings" @@ -10,9 +9,11 @@ import ( jsonpatch "github.com/evanphx/json-patch" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "gopkg.in/yaml.v3" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/yaml" "github.com/vmware-tanzu/velero/pkg/util/collections" ) @@ -23,26 +24,27 @@ const ( ) type JSONPatch struct { - Operation string `yaml:"operation"` - From string `yaml:"from,omitempty"` - Path string `yaml:"path"` - Value string `yaml:"value,omitempty"` + Operation string `json:"operation"` + From string `json:"from,omitempty"` + Path string `json:"path"` + Value string `json:"value,omitempty"` } type Conditions struct { - Namespaces []string `yaml:"namespaces,omitempty"` - GroupKind string `yaml:"groupKind"` - ResourceNameRegex string `yaml:"resourceNameRegex"` + Namespaces []string `json:"namespaces,omitempty"` + GroupResource string `json:"groupResource"` + ResourceNameRegex string `json:"resourceNameRegex,omitempty"` + LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"` } type ResourceModifierRule struct { - Conditions Conditions `yaml:"conditions"` - Patches []JSONPatch `yaml:"patches"` + Conditions Conditions `json:"conditions"` + Patches []JSONPatch `json:"patches"` } type ResourceModifiers struct { - Version string `yaml:"version"` - ResourceModifierRules []ResourceModifierRule `yaml:"resourceModifierRules"` + Version string `json:"version"` + ResourceModifierRules []ResourceModifierRule `json:"resourceModifierRules"` } func GetResourceModifiersFromConfig(cm *v1.ConfigMap) (*ResourceModifiers, error) { @@ -58,7 +60,7 @@ func GetResourceModifiersFromConfig(cm *v1.ConfigMap) (*ResourceModifiers, error yamlData = v } - resModifiers, err := unmarshalResourceModifiers(&yamlData) + resModifiers, err := unmarshalResourceModifiers([]byte(yamlData)) if err != nil { return nil, errors.WithStack(err) } @@ -83,9 +85,11 @@ func (r *ResourceModifierRule) Apply(obj *unstructured.Unstructured, groupResour if !namespaceInclusion.ShouldInclude(obj.GetNamespace()) { return nil } - if !strings.EqualFold(groupResource, r.Conditions.GroupKind) { + + if r.Conditions.GroupResource != groupResource { return nil } + if r.Conditions.ResourceNameRegex != "" { match, err := regexp.MatchString(r.Conditions.ResourceNameRegex, obj.GetName()) if err != nil { @@ -95,6 +99,17 @@ func (r *ResourceModifierRule) Apply(obj *unstructured.Unstructured, groupResour return nil } } + + if r.Conditions.LabelSelector != nil { + selector, err := metav1.LabelSelectorAsSelector(r.Conditions.LabelSelector) + if err != nil { + return errors.Errorf("error in creating label selector %s", err.Error()) + } + if !selector.Matches(labels.Set(obj.GetLabels())) { + return nil + } + } + patches, err := r.PatchArrayToByteArray() if err != nil { return err @@ -107,7 +122,7 @@ func (r *ResourceModifierRule) Apply(obj *unstructured.Unstructured, groupResour return nil } -// convert all JsonPatch to string array with the format of jsonpatch.Patch and then convert it to byte array +// PatchArrayToByteArray converts all JsonPatch to string array with the format of jsonpatch.Patch and then convert it to byte array func (r *ResourceModifierRule) PatchArrayToByteArray() ([]byte, error) { var patches []string for _, patch := range r.Patches { @@ -148,22 +163,15 @@ func ApplyPatch(patch []byte, obj *unstructured.Unstructured, log logrus.FieldLo return nil } -func unmarshalResourceModifiers(yamlData *string) (*ResourceModifiers, error) { +func unmarshalResourceModifiers(yamlData []byte) (*ResourceModifiers, error) { resModifiers := &ResourceModifiers{} - err := decodeStruct(strings.NewReader(*yamlData), resModifiers) + err := yaml.UnmarshalStrict(yamlData, resModifiers) if err != nil { return nil, fmt.Errorf("failed to decode yaml data into resource modifiers %v", err) } return resModifiers, nil } -// decodeStruct restrict validate the keys in decoded mappings to exist as fields in the struct being decoded into -func decodeStruct(r io.Reader, s interface{}) error { - dec := yaml.NewDecoder(r) - dec.KnownFields(true) - return dec.Decode(s) -} - func addQuotes(value string) bool { if value == "" { return true diff --git a/internal/resourcemodifiers/resource_modifiers_test.go b/internal/resourcemodifiers/resource_modifiers_test.go index 911425f381..c2150bbc87 100644 --- a/internal/resourcemodifiers/resource_modifiers_test.go +++ b/internal/resourcemodifiers/resource_modifiers_test.go @@ -18,7 +18,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) { Namespace: "test-namespace", }, Data: map[string]string{ - "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupKind: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: replace\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", + "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: replace\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", }, } @@ -27,7 +27,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "persistentvolumeclaims", + GroupResource: "persistentvolumeclaims", ResourceNameRegex: ".*", Namespaces: []string{"bar", "foo"}, }, @@ -51,7 +51,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) { Namespace: "test-namespace", }, Data: map[string]string{ - "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupKind: deployments.apps\n resourceNameRegex: \"^test-.*$\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: add\n path: \"/spec/template/spec/containers/0\"\n value: \"{\\\"name\\\": \\\"nginx\\\", \\\"image\\\": \\\"nginx:1.14.2\\\", \\\"ports\\\": [{\\\"containerPort\\\": 80}]}\"\n - operation: copy\n from: \"/spec/template/spec/containers/0\"\n path: \"/spec/template/spec/containers/1\"\n\n\n", + "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: deployments.apps\n resourceNameRegex: \"^test-.*$\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: add\n path: \"/spec/template/spec/containers/0\"\n value: \"{\\\"name\\\": \\\"nginx\\\", \\\"image\\\": \\\"nginx:1.14.2\\\", \\\"ports\\\": [{\\\"containerPort\\\": 80}]}\"\n - operation: copy\n from: \"/spec/template/spec/containers/0\"\n path: \"/spec/template/spec/containers/1\"\n\n\n", }, } @@ -60,7 +60,7 @@ func TestGetResourceModifiersFromConfig(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", ResourceNameRegex: "^test-.*$", Namespaces: []string{"bar", "foo"}, }, @@ -86,7 +86,33 @@ func TestGetResourceModifiersFromConfig(t *testing.T) { Namespace: "test-namespace", }, Data: map[string]string{ - "sub.yml": "version1: v1\nresourceModifierRules:\n- conditions:\n groupKind: deployments.apps\n resourceNameRegex: \"^test-.*$\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: add\n path: \"/spec/template/spec/containers/0\"\n value: \"{\\\"name\\\": \\\"nginx\\\", \\\"image\\\": \\\"nginx:1.14.2\\\", \\\"ports\\\": [{\\\"containerPort\\\": 80}]}\"\n - operation: copy\n from: \"/spec/template/spec/containers/0\"\n path: \"/spec/template/spec/containers/1\"\n\n\n", + "sub.yml": "version1: v1\nresourceModifierRules:\n- conditions:\n groupResource: deployments.apps\n resourceNameRegex: \"^test-.*$\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: add\n path: \"/spec/template/spec/containers/0\"\n value: \"{\\\"name\\\": \\\"nginx\\\", \\\"image\\\": \\\"nginx:1.14.2\\\", \\\"ports\\\": [{\\\"containerPort\\\": 80}]}\"\n - operation: copy\n from: \"/spec/template/spec/containers/0\"\n path: \"/spec/template/spec/containers/1\"\n\n\n", + }, + } + + cm4 := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-configmap", + Namespace: "test-namespace", + }, + Data: map[string]string{ + "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: deployments.apps\n labelSelector:\n matchLabels:\n a: b\n", + }, + } + + rules4 := &ResourceModifiers{ + Version: "v1", + ResourceModifierRules: []ResourceModifierRule{ + { + Conditions: Conditions{ + GroupResource: "deployments.apps", + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "a": "b", + }, + }, + }, + }, }, } @@ -123,6 +149,14 @@ func TestGetResourceModifiersFromConfig(t *testing.T) { want: nil, wantErr: true, }, + { + name: "match labels", + args: args{ + cm: cm4, + }, + want: rules4, + wantErr: false, + }, { name: "nil configmap", args: args{ @@ -183,6 +217,9 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { "metadata": map[string]interface{}{ "name": "test-deployment", "namespace": "foo", + "labels": map[string]interface{}{ + "app": "nginx", + }, }, "spec": map[string]interface{}{ "replicas": int64(1), @@ -211,6 +248,9 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { "metadata": map[string]interface{}{ "name": "test-deployment", "namespace": "foo", + "labels": map[string]interface{}{ + "app": "nginx", + }, }, "spec": map[string]interface{}{ "replicas": int64(2), @@ -239,6 +279,9 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { "metadata": map[string]interface{}{ "name": "test-deployment", "namespace": "foo", + "labels": map[string]interface{}{ + "app": "nginx", + }, }, "spec": map[string]interface{}{ "replicas": int64(1), @@ -287,7 +330,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "persistentvolumeclaims", + GroupResource: "persistentvolumeclaims", ResourceNameRegex: "[a-z", Namespaces: []string{"foo"}, }, @@ -320,7 +363,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "persistentvolumeclaims", + GroupResource: "persistentvolumeclaims", ResourceNameRegex: ".*", Namespaces: []string{"foo"}, }, @@ -353,7 +396,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", ResourceNameRegex: "^test-.*$", Namespaces: []string{"foo"}, }, @@ -386,7 +429,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", ResourceNameRegex: "^test-.*$", Namespaces: []string{"foo"}, }, @@ -419,8 +462,8 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", - Namespaces: []string{"foo"}, + GroupResource: "deployments.apps", + Namespaces: []string{"foo"}, }, Patches: []JSONPatch{ { @@ -451,7 +494,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", }, Patches: []JSONPatch{ { @@ -482,7 +525,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", ResourceNameRegex: ".*", Namespaces: []string{"bar"}, }, @@ -515,7 +558,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", ResourceNameRegex: "^test-.*$", Namespaces: []string{"foo"}, }, @@ -543,7 +586,7 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "deployments.apps", + GroupResource: "deployments.apps", ResourceNameRegex: "^test-.*$", Namespaces: []string{"foo"}, }, @@ -579,6 +622,80 @@ func TestResourceModifiers_ApplyResourceModifierRules(t *testing.T) { wantErr: false, wantObj: deployNginxMysql.DeepCopy(), }, + { + name: "nginx deployment: match label selector", + fields: fields{ + Version: "v1", + ResourceModifierRules: []ResourceModifierRule{ + { + Conditions: Conditions{ + GroupResource: "deployments.apps", + Namespaces: []string{"foo"}, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "nginx", + }, + }, + }, + Patches: []JSONPatch{ + { + Operation: "test", + Path: "/spec/replicas", + Value: "1", + }, + { + Operation: "replace", + Path: "/spec/replicas", + Value: "2", + }, + }, + }, + }, + }, + args: args{ + obj: deployNginxOneReplica.DeepCopy(), + groupResource: "deployments.apps", + }, + wantErr: false, + wantObj: deployNginxTwoReplica.DeepCopy(), + }, + { + name: "nginx deployment: mismatch label selector", + fields: fields{ + Version: "v1", + ResourceModifierRules: []ResourceModifierRule{ + { + Conditions: Conditions{ + GroupResource: "deployments.apps", + Namespaces: []string{"foo"}, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "nginx-mismatch", + }, + }, + }, + Patches: []JSONPatch{ + { + Operation: "test", + Path: "/spec/replicas", + Value: "1", + }, + { + Operation: "replace", + Path: "/spec/replicas", + Value: "2", + }, + }, + }, + }, + }, + args: args{ + obj: deployNginxOneReplica.DeepCopy(), + groupResource: "deployments.apps", + }, + wantErr: false, + wantObj: deployNginxOneReplica.DeepCopy(), + }, } for _, tt := range tests { diff --git a/internal/resourcemodifiers/resource_modifiers_validator.go b/internal/resourcemodifiers/resource_modifiers_validator.go index 623989e233..24fe0dbb2e 100644 --- a/internal/resourcemodifiers/resource_modifiers_validator.go +++ b/internal/resourcemodifiers/resource_modifiers_validator.go @@ -1,9 +1,8 @@ package resourcemodifiers import ( - "strings" - "fmt" + "strings" ) func (r *ResourceModifierRule) Validate() error { @@ -48,8 +47,8 @@ func (p *JSONPatch) Validate() error { } func (c *Conditions) Validate() error { - if c.GroupKind == "" { - return fmt.Errorf("groupkind cannot be empty") + if c.GroupResource == "" { + return fmt.Errorf("groupkResource cannot be empty") } return nil } diff --git a/internal/resourcemodifiers/resource_modifiers_validator_test.go b/internal/resourcemodifiers/resource_modifiers_validator_test.go index ed640b1fff..a46c465307 100644 --- a/internal/resourcemodifiers/resource_modifiers_validator_test.go +++ b/internal/resourcemodifiers/resource_modifiers_validator_test.go @@ -21,7 +21,7 @@ func TestResourceModifiers_Validate(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "persistentvolumeclaims", + GroupResource: "persistentvolumeclaims", ResourceNameRegex: ".*", Namespaces: []string{"bar", "foo"}, }, @@ -44,7 +44,7 @@ func TestResourceModifiers_Validate(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "persistentvolumeclaims", + GroupResource: "persistentvolumeclaims", ResourceNameRegex: ".*", Namespaces: []string{"bar", "foo"}, }, @@ -75,7 +75,7 @@ func TestResourceModifiers_Validate(t *testing.T) { ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "persistentvolumeclaims", + GroupResource: "persistentvolumeclaims", ResourceNameRegex: ".*", Namespaces: []string{"bar", "foo"}, }, @@ -92,13 +92,13 @@ func TestResourceModifiers_Validate(t *testing.T) { wantErr: true, }, { - name: "Condition has empty GroupKind", + name: "Condition has empty GroupResource", fields: fields{ Version: "v1", ResourceModifierRules: []ResourceModifierRule{ { Conditions: Conditions{ - GroupKind: "", + GroupResource: "", ResourceNameRegex: ".*", Namespaces: []string{"bar", "foo"}, }, diff --git a/pkg/controller/restore_controller_test.go b/pkg/controller/restore_controller_test.go index 009bccbb51..c63918e205 100644 --- a/pkg/controller/restore_controller_test.go +++ b/pkg/controller/restore_controller_test.go @@ -760,7 +760,7 @@ func TestValidateAndCompleteWithResourceModifierSpecified(t *testing.T) { Namespace: velerov1api.DefaultNamespace, }, Data: map[string]string{ - "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupKind: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: replace\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", + "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: replace\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", }, } require.NoError(t, r.kbClient.Create(context.Background(), cm1)) @@ -788,7 +788,7 @@ func TestValidateAndCompleteWithResourceModifierSpecified(t *testing.T) { Namespace: velerov1api.DefaultNamespace, }, Data: map[string]string{ - "sub.yml": "version1: v1\nresourceModifierRules:\n- conditions:\n groupKind: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: replace\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", + "sub.yml": "version1: v1\nresourceModifierRules:\n- conditions:\n groupResource: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: replace\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", }, } require.NoError(t, r.kbClient.Create(context.Background(), invalidVersionCm)) @@ -816,7 +816,7 @@ func TestValidateAndCompleteWithResourceModifierSpecified(t *testing.T) { Namespace: velerov1api.DefaultNamespace, }, Data: map[string]string{ - "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupKind: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: invalid\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", + "sub.yml": "version: v1\nresourceModifierRules:\n- conditions:\n groupResource: persistentvolumeclaims\n resourceNameRegex: \".*\"\n namespaces:\n - bar\n - foo\n patches:\n - operation: invalid\n path: \"/spec/storageClassName\"\n value: \"premium\"\n - operation: remove\n path: \"/metadata/labels/test\"\n\n\n", }, } require.NoError(t, r.kbClient.Create(context.Background(), invalidOperatorCm)) diff --git a/site/content/docs/main/restore-resource-modifiers.md b/site/content/docs/main/restore-resource-modifiers.md index 7e0e87f6dc..18ff1e0281 100644 --- a/site/content/docs/main/restore-resource-modifiers.md +++ b/site/content/docs/main/restore-resource-modifiers.md @@ -29,11 +29,14 @@ Below is the two-step of using resource modifiers to modify the resources during version: v1 resourceModifierRules: - conditions: - groupKind: persistentvolumeclaims + groupResource: persistentvolumeclaims resourceNameRegex: "^mysql.*$" namespaces: - bar - foo + labelSelector: + matchLabels: + foo: bar patches: - operation: replace path: "/spec/storageClassName" @@ -42,9 +45,9 @@ resourceModifierRules: path: "/metadata/labels/test" ``` -- The above configmap will apply the JSON Patch to all the PVCs in the namespaces bar and foo with name starting with mysql. The JSON Patch will replace the storageClassName with "premium" and remove the label "test" from the PVCs. +- The above configmap will apply the JSON Patch to all the PVCs in the namespaces bar and foo with name starting with mysql and match label `foo: bar`. The JSON Patch will replace the storageClassName with "premium" and remove the label "test" from the PVCs. - You can specify multiple JSON Patches for a particular resource. The patches will be applied in the order specified in the configmap. A subsequent patch is applied in order and if multiple patches are specified for the same path, the last patch will override the previous patches. -- You can can specify multiple resourceModifierRules in the configmap. The rules will be applied in the order specified in the configmap. +- You can specify multiple resourceModifierRules in the configmap. The rules will be applied in the order specified in the configmap. ### Operations supported by the JSON Patch RFC: - add @@ -61,7 +64,7 @@ resourceModifierRules: version: v1 resourceModifierRules: - conditions: - groupKind: persistentvolumeclaims + groupResource: persistentvolumeclaims resourceNameRegex: ".*" namespaces: - bar @@ -80,7 +83,7 @@ resourceModifierRules: version: v1 resourceModifierRules: - conditions: - groupKind: deployments.apps + groupResource: deployments.apps resourceNameRegex: "^test-.*$" namespaces: - bar diff --git a/site/content/docs/v1.12/restore-resource-modifiers.md b/site/content/docs/v1.12/restore-resource-modifiers.md index 7e0e87f6dc..4e40d34e63 100644 --- a/site/content/docs/v1.12/restore-resource-modifiers.md +++ b/site/content/docs/v1.12/restore-resource-modifiers.md @@ -29,11 +29,14 @@ Below is the two-step of using resource modifiers to modify the resources during version: v1 resourceModifierRules: - conditions: - groupKind: persistentvolumeclaims - resourceNameRegex: "^mysql.*$" - namespaces: - - bar - - foo + groupResource: persistentvolumeclaims + resourceNameRegex: "^mysql.*$" + namespaces: + - bar + - foo + labelSelector: + matchLabels: + foo: bar patches: - operation: replace path: "/spec/storageClassName" @@ -42,9 +45,9 @@ resourceModifierRules: path: "/metadata/labels/test" ``` -- The above configmap will apply the JSON Patch to all the PVCs in the namespaces bar and foo with name starting with mysql. The JSON Patch will replace the storageClassName with "premium" and remove the label "test" from the PVCs. +- The above configmap will apply the JSON Patch to all the PVCs in the namespaces bar and foo with name starting with mysql and match label `foo: bar`. The JSON Patch will replace the storageClassName with "premium" and remove the label "test" from the PVCs. - You can specify multiple JSON Patches for a particular resource. The patches will be applied in the order specified in the configmap. A subsequent patch is applied in order and if multiple patches are specified for the same path, the last patch will override the previous patches. -- You can can specify multiple resourceModifierRules in the configmap. The rules will be applied in the order specified in the configmap. +- You can specify multiple resourceModifierRules in the configmap. The rules will be applied in the order specified in the configmap. ### Operations supported by the JSON Patch RFC: - add @@ -61,7 +64,7 @@ resourceModifierRules: version: v1 resourceModifierRules: - conditions: - groupKind: persistentvolumeclaims + groupResource: persistentvolumeclaims resourceNameRegex: ".*" namespaces: - bar @@ -80,7 +83,7 @@ resourceModifierRules: version: v1 resourceModifierRules: - conditions: - groupKind: deployments.apps + groupResource: deployments.apps resourceNameRegex: "^test-.*$" namespaces: - bar diff --git a/test/e2e/resourcemodifiers/resource_modifiers.go b/test/e2e/resourcemodifiers/resource_modifiers.go index 4df389132f..e32ce4d97d 100644 --- a/test/e2e/resourcemodifiers/resource_modifiers.go +++ b/test/e2e/resourcemodifiers/resource_modifiers.go @@ -36,7 +36,7 @@ var yamlData = ` version: v1 resourceModifierRules: - conditions: - groupKind: deployments.apps + groupResource: deployments.apps resourceNameRegex: "resource-modifiers-.*" patches: - operation: add