diff options
10 files changed, 997 insertions, 8 deletions
diff --git a/build/crds/apps/apps_v1alpha1_edgeapplication.yaml b/build/crds/apps/apps_v1alpha1_edgeapplication.yaml index 4114dceec..ce3e48f5f 100644 --- a/build/crds/apps/apps_v1alpha1_edgeapplication.yaml +++ b/build/crds/apps/apps_v1alpha1_edgeapplication.yaml @@ -57,6 +57,222 @@ spec: description: Overriders represents the override rules that would apply on workload. properties: + argsOverriders: + description: ArgsOverriders 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 + commandOverriders: + description: CommandOverriders 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 + envOverrides: + description: EnvOverrides will override the env field + of the container + items: + description: EnvOverrider represents the rules dedicated + to handling env overrides. + properties: + containerName: + description: The name of container + type: string + operator: + description: Operator represents the operator + which will apply on the env. + enum: + - add + - remove + - replace + type: string + value: + description: Value to be applied to env. Must + not be empty when operator is 'add' or 'replace'. + When the operator is 'remove', the matched value + in env will be deleted and only the name of + the value will be matched. If Value is empty, + then the env will remain the same. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) + are expanded using the previously defined + environment variables in the container + and any service environment variables. + If a variable cannot be resolved, the + reference in the input string will be + unchanged. Double $$ are reduced to a + single $, which allows for escaping the + $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" + will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, + regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. + apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`, + spec.nodeName, spec.serviceAccountName, + status.hostIP, status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + description: 'Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. + apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + required: + - containerName + - operator + type: object + type: array imageOverriders: description: ImageOverriders represents the rules dedicated to handling image overrides. @@ -122,6 +338,76 @@ spec: description: Replicas will override the replicas field of deployment type: integer + resourcesOverrides: + description: ResourcesOverrides will override the resources + field of the container + items: + description: ResourcesOverrider represents the rules + dedicated to handling resources overrides. + properties: + containerName: + description: The name of container + type: string + value: + description: Value to be applied to resources. + Must not be empty + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are + used by this container. \n This is an alpha + field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name + of one entry in pod.spec.resourceClaims + of the Pod where this field is used. + It makes that resource available inside + a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. If + Requests is omitted for a container, it + defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - containerName + type: object + type: array type: object required: - name diff --git a/cloud/pkg/controllermanager/controllermanager.go b/cloud/pkg/controllermanager/controllermanager.go index 141da5730..52781e843 100644 --- a/cloud/pkg/controllermanager/controllermanager.go +++ b/cloud/pkg/controllermanager/controllermanager.go @@ -66,6 +66,8 @@ func setupControllers(ctx context.Context, mgr manager.Manager) error { &overridemanager.ReplicasOverrider{}, &overridemanager.ImageOverrider{}, &overridemanager.NodeSelectorOverrider{}, + &overridemanager.CommandOverrider{}, + &overridemanager.ArgsOverrider{}, }, }, } diff --git a/cloud/pkg/controllermanager/edgeapplication/overridemanager/argsoverrider.go b/cloud/pkg/controllermanager/edgeapplication/overridemanager/argsoverrider.go new file mode 100644 index 000000000..ceb8b3691 --- /dev/null +++ b/cloud/pkg/controllermanager/edgeapplication/overridemanager/argsoverrider.go @@ -0,0 +1,31 @@ +/* +CHANGELOG +KubeEdge Authors: +- This File is drived from github.com/karmada-io/karmada/pkg/util/overridemanager/argsoverride.go +- refactor argsOverrider as a struct that implements the Overrider interface +*/ +package overridemanager + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/klog/v2" +) + +type ArgsOverrider struct{} + +func (o *ArgsOverrider) ApplyOverrides(rawObj *unstructured.Unstructured, overriders OverriderInfo) error { + argsOverriders := overriders.Overriders.ArgsOverriders + 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 +} diff --git a/cloud/pkg/controllermanager/edgeapplication/overridemanager/commandoverrider.go b/cloud/pkg/controllermanager/edgeapplication/overridemanager/commandoverrider.go new file mode 100644 index 000000000..bbdd12753 --- /dev/null +++ b/cloud/pkg/controllermanager/edgeapplication/overridemanager/commandoverrider.go @@ -0,0 +1,136 @@ +/* +CHANGELOG +KubeEdge Authors: +- This File is drived from github.com/karmada-io/karmada/pkg/util/overridemanager/commandoverride.go +- refactor commandOverrider as a struct that implements the Overrider interface +*/ +package overridemanager + +import ( + "fmt" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/klog/v2" + + "github.com/kubeedge/kubeedge/pkg/apis/apps/v1alpha1" +) + +type CommandOverrider struct{} + +func (o *CommandOverrider) ApplyOverrides(rawObj *unstructured.Unstructured, overriders OverriderInfo) error { + commandOverriders := overriders.Overriders.CommandOverriders + 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 +} + +// buildCommandArgsPatches build JSON patches for the resource object according to override declaration. +func buildCommandArgsPatches(target string, rawObj *unstructured.Unstructured, commandRunOverrider *v1alpha1.CommandArgsOverrider) ([]overrideOption, error) { + switch rawObj.GetKind() { + case PodKind: + return buildCommandArgsPatchesWithPath(target, "spec/containers", rawObj, commandRunOverrider) + case ReplicaSetKind: + fallthrough + case DeploymentKind: + fallthrough + case DaemonSetKind: + fallthrough + case JobKind: + fallthrough + case StatefulSetKind: + return buildCommandArgsPatchesWithPath(target, "spec/template/spec/containers", rawObj, commandRunOverrider) + } + return nil, nil +} +func buildCommandArgsPatchesWithPath(target string, specContainersPath string, rawObj *unstructured.Unstructured, commandRunOverrider *v1alpha1.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 *v1alpha1.CommandArgsOverrider) (overrideOption, error) { + if !strings.HasPrefix(commandArgsPath, pathSplit) { + return overrideOption{}, fmt.Errorf("internal error: [acquireCommandOverrideOption] commandRunPath should be start with / character") + } + newCommandArgs := overrideCommandArgs([]string{}, commandOverrider) + return overrideOption{ + Op: string(v1alpha1.OverriderOpAdd), + Path: commandArgsPath, + Value: newCommandArgs, + }, nil +} + +func acquireReplaceOverrideOption(commandArgsPath string, commandArgsValue []string, commandOverrider *v1alpha1.CommandArgsOverrider) (overrideOption, error) { + if !strings.HasPrefix(commandArgsPath, pathSplit) { + return overrideOption{}, fmt.Errorf("internal error: [acquireCommandOverrideOption] commandRunPath should be start with / character") + } + newCommandArgs := overrideCommandArgs(commandArgsValue, commandOverrider) + return overrideOption{ + Op: string(v1alpha1.OverriderOpReplace), + Path: commandArgsPath, + Value: newCommandArgs, + }, nil +} + +func overrideCommandArgs(curCommandArgs []string, commandArgsOverrider *v1alpha1.CommandArgsOverrider) []string { + var newCommandArgs []string + switch commandArgsOverrider.Operator { + case v1alpha1.OverriderOpAdd: + newCommandArgs = append(curCommandArgs, commandArgsOverrider.Value...) + case v1alpha1.OverriderOpRemove: + newCommandArgs = commandArgsRemove(curCommandArgs, commandArgsOverrider.Value) + default: + newCommandArgs = curCommandArgs + klog.V(4).Infof("[overrideCommandArgs], op: %s , op not supported, ignored.", v1alpha1.OverriderOpRemove) + } + return newCommandArgs +} + +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 +} diff --git a/cloud/pkg/controllermanager/edgeapplication/overridemanager/constants.go b/cloud/pkg/controllermanager/edgeapplication/overridemanager/constants.go index f4bb7d9fb..3f95dce9d 100644 --- a/cloud/pkg/controllermanager/edgeapplication/overridemanager/constants.go +++ b/cloud/pkg/controllermanager/edgeapplication/overridemanager/constants.go @@ -21,3 +21,16 @@ const ( // DaemonSetKind indicates the target resource is a daemonset DaemonSetKind = "DaemonSet" ) + +const ( + pathSplit = "/" + podSpecPrefix = "/spec" + podTemplatePrefix = "/spec/template/spec" +) + +const ( + // CommandString command string + CommandString = "command" + // ArgsString args string + ArgsString = "args" +) diff --git a/cloud/pkg/controllermanager/edgeapplication/overridemanager/imageoverrider.go b/cloud/pkg/controllermanager/edgeapplication/overridemanager/imageoverrider.go index e4d1e9dc7..5e6dbb31a 100644 --- a/cloud/pkg/controllermanager/edgeapplication/overridemanager/imageoverrider.go +++ b/cloud/pkg/controllermanager/edgeapplication/overridemanager/imageoverrider.go @@ -19,12 +19,6 @@ import ( appsv1alpha1 "github.com/kubeedge/kubeedge/pkg/apis/apps/v1alpha1" ) -const ( - pathSplit = "/" - podSpecPrefix = "/spec" - podTemplatePrefix = "/spec/template/spec" -) - type ImageOverrider struct{} var _ Overrider = &ImageOverrider{} diff --git a/docs/proposals/node-group-management.md b/docs/proposals/node-group-management.md index f58192387..6f860b49f 100644 --- a/docs/proposals/node-group-management.md +++ b/docs/proposals/node-group-management.md @@ -166,12 +166,76 @@ type ResourceTemplate struct { type Overriders struct { // Replicas will override the replicas field of deployment // +optional - Replicas int `json:"replicas,omitempty"` + Replicas *int `json:"replicas,omitempty"` // ImageOverriders represents the rules dedicated to handling image overrides. // +optional - ImageOverrider []ImageOverrider `json:"imageOverriders,omitempty"` + ImageOverriders []ImageOverrider `json:"imageOverriders,omitempty"` + // EnvOverrides will override the env field of the container + // +optional + EnvOverrides []EnvOverrider `json:"envOverrides,omitempty"` + // CommandOverriders represents the rules dedicated to handling container command + // +optional + CommandOverriders []CommandArgsOverrider `json:"commandOverriders,omitempty"` + // ArgsOverriders represents the rules dedicated to handling container args + // +optional + ArgsOverriders []CommandArgsOverrider `json:"argsOverriders,omitempty"` + // ResourcesOverrides will override the resources field of the container + // +optional + ResourcesOverrides []ResourcesOverrider `json:"resourcesOverrides,omitempty"` +} + +// 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"` } +// EnvOverrider represents the rules dedicated to handling env overrides. +type EnvOverrider struct { + // The name of container + // +required + ContainerName string `json:"containerName"` + + // Operator represents the operator which will apply on the env. + // +kubebuilder:validation:Enum=add;remove;replace + // +required + Operator OverriderOperator `json:"operator"` + + // Value to be applied to env. + // Must not be empty when operator is 'add' or 'replace'. + // When the operator is 'remove', the matched value in env will be deleted + // and only the name of the value will be matched. + // If Value is empty, then the env will remain the same. + // +optional + Value []corev1.EnvVar `json:"value,omitempty"` +} + +// ResourcesOverrider represents the rules dedicated to handling resources overrides. +type ResourcesOverrider struct { + // The name of container + // +required + ContainerName string `json:"containerName"` + + // Value to be applied to resources. + // Must not be empty + // +required + Value corev1.ResourceRequirements `json:"value,omitempty"` +} + + // ImageOverrider represents the rules dedicated to handling image overrides. type ImageOverrider struct { // Predicate filters images before applying the rule. @@ -380,6 +444,29 @@ spec: - component: "Registry" operator: "replace" value: "hangzhou.registry.io" + envOverrides: + - containerName: "nginx" + operator: "add" + value: + - name: "env1" + value: "test1" + commandOverriders: + - containerName: "nginx" + operator: "add" + value: ["your-command-1"] + argsOverriders: + - containerName: "nginx" + operator: "add" + value: ["your-args-1"] + resourcesOverrides: + - containerName: "nginx" + value: + limits: + cpu: 250m + memory: 512Mi + requests: + cpu: 250m + memory: 512Mi - name: beijing overriders: replicas: 3 diff --git a/manifests/charts/cloudcore/crds/apps_v1alpha1_edgeapplication.yaml b/manifests/charts/cloudcore/crds/apps_v1alpha1_edgeapplication.yaml index 4114dceec..ce3e48f5f 100644 --- a/manifests/charts/cloudcore/crds/apps_v1alpha1_edgeapplication.yaml +++ b/manifests/charts/cloudcore/crds/apps_v1alpha1_edgeapplication.yaml @@ -57,6 +57,222 @@ spec: description: Overriders represents the override rules that would apply on workload. properties: + argsOverriders: + description: ArgsOverriders 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 + commandOverriders: + description: CommandOverriders 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 + envOverrides: + description: EnvOverrides will override the env field + of the container + items: + description: EnvOverrider represents the rules dedicated + to handling env overrides. + properties: + containerName: + description: The name of container + type: string + operator: + description: Operator represents the operator + which will apply on the env. + enum: + - add + - remove + - replace + type: string + value: + description: Value to be applied to env. Must + not be empty when operator is 'add' or 'replace'. + When the operator is 'remove', the matched value + in env will be deleted and only the name of + the value will be matched. If Value is empty, + then the env will remain the same. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) + are expanded using the previously defined + environment variables in the container + and any service environment variables. + If a variable cannot be resolved, the + reference in the input string will be + unchanged. Double $$ are reduced to a + single $, which allows for escaping the + $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" + will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, + regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. + apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`, + spec.nodeName, spec.serviceAccountName, + status.hostIP, status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + description: 'Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. + apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + required: + - containerName + - operator + type: object + type: array imageOverriders: description: ImageOverriders represents the rules dedicated to handling image overrides. @@ -122,6 +338,76 @@ spec: description: Replicas will override the replicas field of deployment type: integer + resourcesOverrides: + description: ResourcesOverrides will override the resources + field of the container + items: + description: ResourcesOverrider represents the rules + dedicated to handling resources overrides. + properties: + containerName: + description: The name of container + type: string + value: + description: Value to be applied to resources. + Must not be empty + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are + used by this container. \n This is an alpha + field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name + of one entry in pod.spec.resourceClaims + of the Pod where this field is used. + It makes that resource available inside + a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. If + Requests is omitted for a container, it + defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - containerName + type: object + type: array type: object required: - name diff --git a/pkg/apis/apps/v1alpha1/edgeapplication_types.go b/pkg/apis/apps/v1alpha1/edgeapplication_types.go index 52f069bc5..639e17193 100644 --- a/pkg/apis/apps/v1alpha1/edgeapplication_types.go +++ b/pkg/apis/apps/v1alpha1/edgeapplication_types.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -62,6 +63,69 @@ type Overriders struct { // ImageOverriders represents the rules dedicated to handling image overrides. // +optional ImageOverriders []ImageOverrider `json:"imageOverriders,omitempty"` + // EnvOverrides will override the env field of the container + // +optional + EnvOverrides []EnvOverrider `json:"envOverrides,omitempty"` + // CommandOverriders represents the rules dedicated to handling container command + // +optional + CommandOverriders []CommandArgsOverrider `json:"commandOverriders,omitempty"` + // ArgsOverriders represents the rules dedicated to handling container args + // +optional + ArgsOverriders []CommandArgsOverrider `json:"argsOverriders,omitempty"` + // ResourcesOverrides will override the resources field of the container + // +optional + ResourcesOverrides []ResourcesOverrider `json:"resourcesOverrides,omitempty"` +} + +// 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"` +} + +// EnvOverrider represents the rules dedicated to handling env overrides. +type EnvOverrider struct { + // The name of container + // +required + ContainerName string `json:"containerName"` + + // Operator represents the operator which will apply on the env. + // +kubebuilder:validation:Enum=add;remove;replace + // +required + Operator OverriderOperator `json:"operator"` + + // Value to be applied to env. + // Must not be empty when operator is 'add' or 'replace'. + // When the operator is 'remove', the matched value in env will be deleted + // and only the name of the value will be matched. + // If Value is empty, then the env will remain the same. + // +optional + Value []corev1.EnvVar `json:"value,omitempty"` +} + +// ResourcesOverrider represents the rules dedicated to handling resources overrides. +type ResourcesOverrider struct { + // The name of container + // +required + ContainerName string `json:"containerName"` + + // Value to be applied to resources. + // Must not be empty + // +required + Value corev1.ResourceRequirements `json:"value,omitempty"` } // ImageOverrider represents the rules dedicated to handling image overrides. diff --git a/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go index fd29a409a..6a227ce24 100644 --- a/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -22,10 +22,32 @@ limitations under the License. package v1alpha1 import ( + v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommandArgsOverrider) DeepCopyInto(out *CommandArgsOverrider) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandArgsOverrider. +func (in *CommandArgsOverrider) DeepCopy() *CommandArgsOverrider { + if in == nil { + return nil + } + out := new(CommandArgsOverrider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EdgeApplication) DeepCopyInto(out *EdgeApplication) { *out = *in out.TypeMeta = in.TypeMeta @@ -126,6 +148,29 @@ func (in *EdgeApplicationStatus) DeepCopy() *EdgeApplicationStatus { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvOverrider) DeepCopyInto(out *EnvOverrider) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvOverrider. +func (in *EnvOverrider) DeepCopy() *EnvOverrider { + if in == nil { + return nil + } + out := new(EnvOverrider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageOverrider) DeepCopyInto(out *ImageOverrider) { *out = *in if in.Predicate != nil { @@ -337,6 +382,34 @@ func (in *Overriders) DeepCopyInto(out *Overriders) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.EnvOverrides != nil { + in, out := &in.EnvOverrides, &out.EnvOverrides + *out = make([]EnvOverrider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CommandOverriders != nil { + in, out := &in.CommandOverriders, &out.CommandOverriders + *out = make([]CommandArgsOverrider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ArgsOverriders != nil { + in, out := &in.ArgsOverriders, &out.ArgsOverriders + *out = make([]CommandArgsOverrider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ResourcesOverrides != nil { + in, out := &in.ResourcesOverrides, &out.ResourcesOverrides + *out = make([]ResourcesOverrider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -390,6 +463,23 @@ func (in *ResourceTemplate) DeepCopy() *ResourceTemplate { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourcesOverrider) DeepCopyInto(out *ResourcesOverrider) { + *out = *in + in.Value.DeepCopyInto(&out.Value) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourcesOverrider. +func (in *ResourcesOverrider) DeepCopy() *ResourcesOverrider { + if in == nil { + return nil + } + out := new(ResourcesOverrider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TargetNodeGroup) DeepCopyInto(out *TargetNodeGroup) { *out = *in in.Overriders.DeepCopyInto(&out.Overriders) |
