126 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
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
 | 
						|
}
 |