Merge pull request #615 from betaincao/command_override

Command and Args Overrider
This commit is contained in:
karmada-bot 2021-08-19 20:05:33 +08:00 committed by GitHub
commit f8873c840f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 832 additions and 0 deletions

View File

@ -43,6 +43,68 @@ spec:
description: Overriders represents the override rules that would apply
on resources
properties:
argsOverrider:
description: ArgsOverrider represents the rules dedicated to handling
container args
items:
description: CommandArgsOverrider represents the rules dedicated
to handling command/args overrides.
properties:
containerName:
description: The name of container
type: string
operator:
description: Operator represents the operator which will
apply on the command/args.
enum:
- add
- remove
type: string
value:
description: Value to be applied to command/args. Items
in Value which will be appended after command/args when
Operator is 'add'. Items in Value which match in command/args
will be deleted when Operator is 'remove'. If Value is
empty, then the command/args will remain the same.
items:
type: string
type: array
required:
- containerName
- operator
type: object
type: array
commandOverrider:
description: CommandOverrider represents the rules dedicated to
handling container command
items:
description: CommandArgsOverrider represents the rules dedicated
to handling command/args overrides.
properties:
containerName:
description: The name of container
type: string
operator:
description: Operator represents the operator which will
apply on the command/args.
enum:
- add
- remove
type: string
value:
description: Value to be applied to command/args. Items
in Value which will be appended after command/args when
Operator is 'add'. Items in Value which match in command/args
will be deleted when Operator is 'remove'. If Value is
empty, then the command/args will remain the same.
items:
type: string
type: array
required:
- containerName
- operator
type: object
type: array
imageOverrider:
description: ImageOverrider represents the rules dedicated to
handling image overrides.

View File

@ -43,6 +43,68 @@ spec:
description: Overriders represents the override rules that would apply
on resources
properties:
argsOverrider:
description: ArgsOverrider represents the rules dedicated to handling
container args
items:
description: CommandArgsOverrider represents the rules dedicated
to handling command/args overrides.
properties:
containerName:
description: The name of container
type: string
operator:
description: Operator represents the operator which will
apply on the command/args.
enum:
- add
- remove
type: string
value:
description: Value to be applied to command/args. Items
in Value which will be appended after command/args when
Operator is 'add'. Items in Value which match in command/args
will be deleted when Operator is 'remove'. If Value is
empty, then the command/args will remain the same.
items:
type: string
type: array
required:
- containerName
- operator
type: object
type: array
commandOverrider:
description: CommandOverrider represents the rules dedicated to
handling container command
items:
description: CommandArgsOverrider represents the rules dedicated
to handling command/args overrides.
properties:
containerName:
description: The name of container
type: string
operator:
description: Operator represents the operator which will
apply on the command/args.
enum:
- add
- remove
type: string
value:
description: Value to be applied to command/args. Items
in Value which will be appended after command/args when
Operator is 'add'. Items in Value which match in command/args
will be deleted when Operator is 'remove'. If Value is
empty, then the command/args will remain the same.
items:
type: string
type: array
required:
- containerName
- operator
type: object
type: array
imageOverrider:
description: ImageOverrider represents the rules dedicated to
handling image overrides.

View File

@ -0,0 +1,18 @@
apiVersion: policy.karmada.io/v1alpha1
kind: OverridePolicy
metadata:
name: example-override
namespace: default
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
targetCluster:
clusterNames:
- member1
overriders:
commandOverrider:
- containerName: alpine
operator: add
value:
- test

View File

@ -49,6 +49,14 @@ type Overriders struct {
// ImageOverrider represents the rules dedicated to handling image overrides.
// +optional
ImageOverrider []ImageOverrider `json:"imageOverrider,omitempty"`
// CommandOverrider represents the rules dedicated to handling container command
// +optional
CommandOverrider []CommandArgsOverrider `json:"commandOverrider,omitempty"`
// ArgsOverrider represents the rules dedicated to handling container args
// +optional
ArgsOverrider []CommandArgsOverrider `json:"argsOverrider,omitempty"`
}
// ImageOverrider represents the rules dedicated to handling image overrides.
@ -106,6 +114,25 @@ type ImagePredicate struct {
// ImageComponent indicates the components for image.
type ImageComponent string
// CommandArgsOverrider represents the rules dedicated to handling command/args overrides.
type CommandArgsOverrider struct {
// The name of container
// +required
ContainerName string `json:"containerName"`
// Operator represents the operator which will apply on the command/args.
// +kubebuilder:validation:Enum=add;remove
// +required
Operator OverriderOperator `json:"operator"`
// Value to be applied to command/args.
// Items in Value which will be appended after command/args when Operator is 'add'.
// Items in Value which match in command/args will be deleted when Operator is 'remove'.
// If Value is empty, then the command/args will remain the same.
// +optional
Value []string `json:"value,omitempty"`
}
const (
// Registry is the registry component of an image with format '[registry/]repository[:tag]'.
Registry ImageComponent = "Registry"

View File

@ -0,0 +1,125 @@
package overridemanager
import (
"fmt"
"strings"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
"github.com/karmada-io/karmada/pkg/util"
)
const (
// CommandString command string
CommandString = "command"
// ArgsString args string
ArgsString = "args"
)
// buildCommandArgsPatches build JSON patches for the resource object according to override declaration.
func buildCommandArgsPatches(target string, rawObj *unstructured.Unstructured, commandRunOverrider *policyv1alpha1.CommandArgsOverrider) ([]overrideOption, error) {
switch rawObj.GetKind() {
case util.PodKind:
return buildCommandArgsPatchesWithPath(target, "spec/containers", rawObj, commandRunOverrider)
case util.ReplicaSetKind:
fallthrough
case util.DeploymentKind:
fallthrough
case util.DaemonSetKind:
fallthrough
case util.StatefulSetKind:
return buildCommandArgsPatchesWithPath(target, "spec/template/spec/containers", rawObj, commandRunOverrider)
}
return nil, nil
}
func buildCommandArgsPatchesWithPath(target string, specContainersPath string, rawObj *unstructured.Unstructured, commandRunOverrider *policyv1alpha1.CommandArgsOverrider) ([]overrideOption, error) {
patches := make([]overrideOption, 0)
containers, ok, err := unstructured.NestedSlice(rawObj.Object, strings.Split(specContainersPath, pathSplit)...)
if err != nil {
return nil, fmt.Errorf("failed to retrieves path(%s) from rawObj, error: %v", specContainersPath, err)
}
if !ok || len(containers) == 0 {
return nil, nil
}
klog.V(4).Infof("buildCommandArgsPatchesWithPath containers info (%+v)", containers)
for index, container := range containers {
if container.(map[string]interface{})["name"] == commandRunOverrider.ContainerName {
commandArgsPath := fmt.Sprintf("/%s/%d/%s", specContainersPath, index, target)
commandArgsValue := make([]string, 0)
var patch overrideOption
// if target is nil, to add new [target]
if container.(map[string]interface{})[target] == nil {
patch, _ = acquireAddOverrideOption(commandArgsPath, commandRunOverrider)
} else {
for _, val := range container.(map[string]interface{})[target].([]interface{}) {
commandArgsValue = append(commandArgsValue, fmt.Sprintf("%s", val))
}
patch, _ = acquireReplaceOverrideOption(commandArgsPath, commandArgsValue, commandRunOverrider)
}
klog.V(4).Infof("[buildCommandArgsPatchesWithPath] containers patch info (%+v)", patch)
patches = append(patches, patch)
}
}
return patches, nil
}
func acquireAddOverrideOption(commandArgsPath string, commandOverrider *policyv1alpha1.CommandArgsOverrider) (overrideOption, error) {
if !strings.HasPrefix(commandArgsPath, pathSplit) {
return overrideOption{}, fmt.Errorf("internal error: [acquireCommandOverrideOption] commandRunPath should be start with / character")
}
newCommandArgs, err := overrideCommandArgs([]string{}, commandOverrider)
if err != nil {
return overrideOption{}, err
}
return overrideOption{
Op: string(policyv1alpha1.OverriderOpAdd),
Path: commandArgsPath,
Value: newCommandArgs,
}, nil
}
func acquireReplaceOverrideOption(commandArgsPath string, commandArgsValue []string, commandOverrider *policyv1alpha1.CommandArgsOverrider) (overrideOption, error) {
if !strings.HasPrefix(commandArgsPath, pathSplit) {
return overrideOption{}, fmt.Errorf("internal error: [acquireCommandOverrideOption] commandRunPath should be start with / character")
}
newCommandArgs, err := overrideCommandArgs(commandArgsValue, commandOverrider)
if err != nil {
return overrideOption{}, err
}
return overrideOption{
Op: string(policyv1alpha1.OverriderOpReplace),
Path: commandArgsPath,
Value: newCommandArgs,
}, nil
}
func overrideCommandArgs(curCommandArgs []string, commandArgsOverrider *policyv1alpha1.CommandArgsOverrider) ([]string, error) {
var newCommandArgs []string
switch commandArgsOverrider.Operator {
case policyv1alpha1.OverriderOpAdd:
newCommandArgs = append(curCommandArgs, commandArgsOverrider.Value...)
case policyv1alpha1.OverriderOpRemove:
newCommandArgs = commandArgsRemove(curCommandArgs, commandArgsOverrider.Value)
default:
newCommandArgs = curCommandArgs
klog.V(4).Infof("[overrideCommandArgs], op: %s , op not supported, ignored.", policyv1alpha1.OverriderOpRemove)
}
return newCommandArgs, nil
}
func commandArgsRemove(curCommandArgs []string, removeValues []string) []string {
newCommandArgs := make([]string, 0, len(curCommandArgs))
currentSet := sets.NewString(removeValues...)
for _, val := range curCommandArgs {
if !currentSet.Has(val) {
newCommandArgs = append(newCommandArgs, val)
}
}
return newCommandArgs
}

View File

@ -0,0 +1,498 @@
package overridemanager
import (
"reflect"
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
)
func generateTestCommandDeploymentYaml() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"replicas": 1,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "nginx",
"command": []interface{}{"nginx", "-v", "-t"},
}}}}}}}
}
func generateTestArgsDeploymentYaml() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"replicas": 1,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "nginx",
"name": "nginx",
"args": []interface{}{"nginx", "-v", "-t"},
}}}}}}}
}
func generateTestCommandPodYaml() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Pod",
"metadata": map[string]interface{}{
"name": "nginx",
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "fictional.registry.example/imagename:v1.0.0",
"name": "nginx",
"command": []interface{}{"nginx", "-v", "-t"},
}}}}}
}
func generateTestCommandStatefulSetYaml() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "StatefulSet",
"metadata": map[string]interface{}{
"name": "web",
},
"spec": map[string]interface{}{
"replicas": 2,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "fictional.registry.example/imagename:v1.0.0",
"name": "nginx",
"command": []interface{}{"nginx", "-v", "-t"},
}}}}}}}
}
func generateTestCommandReplicaSetYaml() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "ReplicaSet",
"metadata": map[string]interface{}{
"name": "nginx",
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"replicas": 1,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "fictional.registry.example/imagename:v1.0.0",
"name": "nginx",
"command": []interface{}{"nginx", "-v", "-t"},
}}}}}}}
}
func generateTestCommandDaemonSetYaml() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "ReplicaSet",
"metadata": map[string]interface{}{
"name": "nginx",
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"replicas": 1,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"image": "fictional.registry.example/imagename:v1.0.0",
"name": "nginx",
"command": []interface{}{"nginx", "-v", "-t"},
}}}}}}}
}
func generateTestCommandDeploymentYamlWithTwoContainer() *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"replicas": 1,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "nginx",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "nginx",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"command": []interface{}{"nginx", "-v", "-t"},
},
map[string]interface{}{
"name": "nginx1",
"command": []interface{}{"nginx", "-v", "-t"},
}}}}}}}
}
func TestParseJSONPatchesByCommandOverrider(t *testing.T) {
type args struct {
rawObj *unstructured.Unstructured
CommandArgsOverrider *policyv1alpha1.CommandArgsOverrider
}
tests := []struct {
name string
args args
want []overrideOption
wantErr bool
}{
{
name: "CommandArgsOverrider, resource kind: Deployment, operator: add",
args: args{
rawObj: generateTestCommandDeploymentYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "add",
Value: []string{"&& echo 'hello karmada'"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v", "-t", "&& echo 'hello karmada'"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource kind: Deployment, operator: remove",
args: args{
rawObj: generateTestCommandDeploymentYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "remove",
Value: []string{"-t"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, remove value is empty, resource kind: Deployment, operator: remove",
args: args{
rawObj: generateTestCommandDeploymentYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "remove",
Value: []string{},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v", "-t"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource has more than one container",
args: args{
rawObj: generateTestCommandDeploymentYamlWithTwoContainer(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "add",
Value: []string{"echo 'hello karmada'"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v", "-t", "echo 'hello karmada'"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource has more than one container",
args: args{
rawObj: generateTestCommandDeploymentYamlWithTwoContainer(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "remove",
Value: []string{"-t"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider resource kind: Pod, operator: add",
args: args{
rawObj: generateTestCommandPodYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "add",
Value: []string{"echo 'hello karmada'"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/containers/0/command",
Value: []string{"nginx", "-v", "-t", "echo 'hello karmada'"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource kind: StatefulSet, operator: add",
args: args{
rawObj: generateTestCommandStatefulSetYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "add",
Value: []string{"echo 'hello karmada'"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v", "-t", "echo 'hello karmada'"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource kind: ReplicaSet, operator: remove",
args: args{
rawObj: generateTestCommandReplicaSetYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "remove",
Value: []string{"-t"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource kind: DaemonSet, operator: remove",
args: args{
rawObj: generateTestCommandDaemonSetYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "remove",
Value: []string{"-t"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/command",
Value: []string{"nginx", "-v"},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := buildCommandArgsPatches(CommandString, tt.args.rawObj, tt.args.CommandArgsOverrider)
if (err != nil) != tt.wantErr {
t.Errorf("buildCommandArgsPatches() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("buildCommandArgsPatches() = %v, want %v", got, tt.want)
}
})
}
}
func TestParseJSONPatchesByArgsOverrider(t *testing.T) {
type args struct {
rawObj *unstructured.Unstructured
CommandArgsOverrider *policyv1alpha1.CommandArgsOverrider
}
tests := []struct {
name string
args args
want []overrideOption
wantErr bool
}{
{
name: "CommandArgsOverrider, resource kind: Deployment, operator: replace",
args: args{
rawObj: generateTestArgsDeploymentYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "add",
Value: []string{"&& echo 'hello karmada'"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/args",
Value: []string{"nginx", "-v", "-t", "&& echo 'hello karmada'"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource kind: Deployment, operator: replace",
args: args{
rawObj: generateTestArgsDeploymentYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "remove",
Value: []string{"-t"},
},
},
want: []overrideOption{
{
Op: "replace",
Path: "/spec/template/spec/containers/0/args",
Value: []string{"nginx", "-v"},
},
},
wantErr: false,
}, {
name: "CommandArgsOverrider, resource kind: Deployment, operator: add",
args: args{
rawObj: generateTestCommandDeploymentYaml(),
CommandArgsOverrider: &policyv1alpha1.CommandArgsOverrider{
ContainerName: "nginx",
Operator: "add",
Value: []string{"-t"},
},
},
want: []overrideOption{
{
Op: "add",
Path: "/spec/template/spec/containers/0/args",
Value: []string{"-t"},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := buildCommandArgsPatches(ArgsString, tt.args.rawObj, tt.args.CommandArgsOverrider)
if (err != nil) != tt.wantErr {
t.Errorf("buildCommandPatches() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("buildCommandPatches() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -242,6 +242,14 @@ func applyPolicyOverriders(rawObj *unstructured.Unstructured, overriders policyv
if err != nil {
return err
}
// patch command
if err := applyCommandOverriders(rawObj, overriders.CommandOverrider); err != nil {
return err
}
// patch args
if err := applyArgsOverriders(rawObj, overriders.ArgsOverrider); err != nil {
return err
}
return applyJSONPatch(rawObj, parseJSONPatchesByPlaintext(overriders.Plaintext))
}
@ -262,6 +270,38 @@ func applyImageOverriders(rawObj *unstructured.Unstructured, imageOverriders []p
return nil
}
func applyCommandOverriders(rawObj *unstructured.Unstructured, commandOverriders []policyv1alpha1.CommandArgsOverrider) error {
for index := range commandOverriders {
patches, err := buildCommandArgsPatches(CommandString, rawObj, &commandOverriders[index])
if err != nil {
return err
}
klog.V(4).Infof("Parsed JSON patches by commandOverriders(%+v): %+v", commandOverriders[index], patches)
if err = applyJSONPatch(rawObj, patches); err != nil {
return err
}
}
return nil
}
func applyArgsOverriders(rawObj *unstructured.Unstructured, argsOverriders []policyv1alpha1.CommandArgsOverrider) error {
for index := range argsOverriders {
patches, err := buildCommandArgsPatches(ArgsString, rawObj, &argsOverriders[index])
if err != nil {
return err
}
klog.V(4).Infof("Parsed JSON patches by argsOverriders(%+v): %+v", argsOverriders[index], patches)
if err = applyJSONPatch(rawObj, patches); err != nil {
return err
}
}
return nil
}
func parseJSONPatchesByPlaintext(overriders []policyv1alpha1.PlaintextOverrider) []overrideOption {
patches := make([]overrideOption, 0, len(overriders))
for i := range overriders {