Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new option "env-from" for kubectl run command. #48684

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion pkg/kubectl/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ var (
# Start a single instance of hazelcast and set environment variables "DNS_DOMAIN=cluster" and "POD_NAMESPACE=default" in the container.
kubectl run hazelcast --image=hazelcast --env="DNS_DOMAIN=cluster" --env="POD_NAMESPACE=default"

# Start a single instance of hazelcast and set environment variables from ConfigMap named "ConfigMapA" and "ConfigMapB" in the container.
kubectl run hazelcast --image=hazelcast --env-from="ConfigMapRef=ConfigMapA" --env-from="ConfigMapB"

# Start a single instance of hazelcast and set environment variables from Secret name "SecretsA" and "SecretsB" in the container.
kubectl run hazelcast --image=hazelcast --env-from="SecretRef=SecretsA" --env-from="SecretsB"

# Start a replicated instance of nginx.
kubectl run nginx --image=nginx --replicas=5

Expand Down Expand Up @@ -95,7 +101,7 @@ type RunObject struct {

func NewCmdRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "run NAME --image=image [--env=\"key=value\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]",
Use: "run NAME --image=image [--env=\"key=value\"] [--env-from=\"ConfigMapRef|SecretRef=name\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]",
Short: i18n.T("Run a particular image on the cluster"),
Long: runLong,
Example: runExample,
Expand Down Expand Up @@ -124,6 +130,7 @@ func addRunFlags(cmd *cobra.Command) {
cmd.Flags().Bool("rm", false, "If true, delete resources created in this command for attached containers.")
cmd.Flags().String("overrides", "", i18n.T("An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field."))
cmd.Flags().StringArray("env", []string{}, "Environment variables to set in the container")
cmd.Flags().StringArray("env-from", []string{}, "Environment variables to set from ConfigMap or Secret in the container")
cmd.Flags().String("serviceaccount", "", "Service account to set in the pod spec")
cmd.Flags().String("port", "", i18n.T("The port that this container exposes. If --expose is true, this is also the port used by the service that is created."))
cmd.Flags().Int("hostport", -1, "The host port mapping for the container port. To demonstrate a single-machine container.")
Expand Down Expand Up @@ -260,6 +267,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c
}

params["env"] = cmdutil.GetFlagStringArray(cmd, "env")
params["env-from"] = cmdutil.GetFlagStringArray(cmd, "env-from")

var runObjectMap = map[string]*RunObject{}
runObject, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace)
Expand Down
114 changes: 107 additions & 7 deletions pkg/kubectl/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (DeploymentV1Beta1) ParamNames() []GeneratorParam {
{"command", false},
{"args", false},
{"env", false},
{"env-from", false},
{"requests", false},
{"limits", false},
{"serviceaccount", false},
Expand All @@ -67,6 +68,11 @@ func (DeploymentV1Beta1) Generate(genericParams map[string]interface{}) (runtime
return nil, err
}

envFroms, err := getEnvFroms(genericParams)
if err != nil {
return nil, err
}

params, err := getParams(genericParams)
if err != nil {
return nil, err
Expand All @@ -93,7 +99,7 @@ func (DeploymentV1Beta1) Generate(genericParams map[string]interface{}) (runtime
}

imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
if err = updatePodContainers(params, args, envs, envFroms, imagePullPolicy, podSpec); err != nil {
return nil, err
}

Expand Down Expand Up @@ -140,6 +146,7 @@ func (DeploymentAppsV1Beta1) ParamNames() []GeneratorParam {
{"command", false},
{"args", false},
{"env", false},
{"env-from", false},
{"requests", false},
{"limits", false},
{"serviceaccount", false},
Expand All @@ -157,6 +164,11 @@ func (DeploymentAppsV1Beta1) Generate(genericParams map[string]interface{}) (run
return nil, err
}

envFroms, err := getEnvFroms(genericParams)
if err != nil {
return nil, err
}

params, err := getParams(genericParams)
if err != nil {
return nil, err
Expand All @@ -183,7 +195,7 @@ func (DeploymentAppsV1Beta1) Generate(genericParams map[string]interface{}) (run
}

imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
if err = updatePodContainers(params, args, envs, envFroms, imagePullPolicy, podSpec); err != nil {
return nil, err
}

Expand Down Expand Up @@ -288,6 +300,25 @@ func getEnvs(genericParams map[string]interface{}) ([]v1.EnvVar, error) {
return envs, nil
}

// getEnvFroms returns EnvFrom variables.
func getEnvFroms(genericParams map[string]interface{}) ([]v1.EnvFromSource, error) {
var envFroms []v1.EnvFromSource
envFromStrings, found := genericParams["env-from"]
if found {
if envFromStringArray, isArray := envFromStrings.([]string); isArray {
var err error
envFroms, err = parseEnvFroms(envFromStringArray)
if err != nil {
return nil, err
}
delete(genericParams, "env-from")
} else {
return nil, fmt.Errorf("expected []string, found: %T", envFromStrings)
}
}
return envFroms, nil
}

type JobV1 struct{}

func (JobV1) ParamNames() []GeneratorParam {
Expand All @@ -305,6 +336,7 @@ func (JobV1) ParamNames() []GeneratorParam {
{"command", false},
{"args", false},
{"env", false},
{"env-from", false},
{"requests", false},
{"limits", false},
{"restart", false},
Expand All @@ -323,6 +355,11 @@ func (JobV1) Generate(genericParams map[string]interface{}) (runtime.Object, err
return nil, err
}

envFroms, err := getEnvFroms(genericParams)
if err != nil {
return nil, err
}

params, err := getParams(genericParams)
if err != nil {
return nil, err
Expand All @@ -344,7 +381,7 @@ func (JobV1) Generate(genericParams map[string]interface{}) (runtime.Object, err
}

imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
if err = updatePodContainers(params, args, envs, envFroms, imagePullPolicy, podSpec); err != nil {
return nil, err
}

Expand Down Expand Up @@ -399,6 +436,7 @@ func (CronJobV2Alpha1) ParamNames() []GeneratorParam {
{"command", false},
{"args", false},
{"env", false},
{"env-from", false},
{"requests", false},
{"limits", false},
{"restart", false},
Expand All @@ -418,6 +456,11 @@ func (CronJobV2Alpha1) Generate(genericParams map[string]interface{}) (runtime.O
return nil, err
}

envFroms, err := getEnvFroms(genericParams)
if err != nil {
return nil, err
}

params, err := getParams(genericParams)
if err != nil {
return nil, err
Expand All @@ -439,7 +482,7 @@ func (CronJobV2Alpha1) Generate(genericParams map[string]interface{}) (runtime.O
}

imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
if err = updatePodContainers(params, args, envs, envFroms, imagePullPolicy, podSpec); err != nil {
return nil, err
}

Expand Down Expand Up @@ -500,6 +543,7 @@ func (BasicReplicationController) ParamNames() []GeneratorParam {
{"command", false},
{"args", false},
{"env", false},
{"env-from", false},
{"requests", false},
{"limits", false},
{"serviceaccount", false},
Expand Down Expand Up @@ -633,6 +677,11 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
return nil, err
}

envFroms, err := getEnvFroms(genericParams)
if err != nil {
return nil, err
}

params, err := getParams(genericParams)
if err != nil {
return nil, err
Expand All @@ -659,7 +708,7 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
}

imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil {
if err = updatePodContainers(params, args, envs, envFroms, imagePullPolicy, podSpec); err != nil {
return nil, err
}

Expand Down Expand Up @@ -688,7 +737,7 @@ func (BasicReplicationController) Generate(genericParams map[string]interface{})
}

// updatePodContainers updates PodSpec.Containers with passed parameters.
func updatePodContainers(params map[string]string, args []string, envs []v1.EnvVar, imagePullPolicy v1.PullPolicy, podSpec *v1.PodSpec) error {
func updatePodContainers(params map[string]string, args []string, envs []v1.EnvVar, envFroms []v1.EnvFromSource, imagePullPolicy v1.PullPolicy, podSpec *v1.PodSpec) error {
if len(args) > 0 {
command, err := GetBool(params, "command", false)
if err != nil {
Expand All @@ -705,6 +754,10 @@ func updatePodContainers(params map[string]string, args []string, envs []v1.EnvV
podSpec.Containers[0].Env = envs
}

if len(envFroms) > 0 {
podSpec.Containers[0].EnvFrom = envFroms
}

if len(imagePullPolicy) > 0 {
// imagePullPolicy should be valid here since we have verified it before.
podSpec.Containers[0].ImagePullPolicy = imagePullPolicy
Expand Down Expand Up @@ -765,6 +818,7 @@ func (BasicPod) ParamNames() []GeneratorParam {
{"command", false},
{"args", false},
{"env", false},
{"env-from", false},
{"requests", false},
{"limits", false},
{"serviceaccount", false},
Expand All @@ -782,6 +836,11 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
return nil, err
}

envFroms, err := getEnvFroms(genericParams)
if err != nil {
return nil, err
}

params, err := getParams(genericParams)
if err != nil {
return nil, err
Expand Down Expand Up @@ -845,7 +904,7 @@ func (BasicPod) Generate(genericParams map[string]interface{}) (runtime.Object,
},
}
imagePullPolicy := v1.PullPolicy(params["image-pull-policy"])
if err = updatePodContainers(params, args, envs, imagePullPolicy, &pod.Spec); err != nil {
if err = updatePodContainers(params, args, envs, envFroms, imagePullPolicy, &pod.Spec); err != nil {
return nil, err
}

Expand Down Expand Up @@ -876,3 +935,44 @@ func parseEnvs(envArray []string) ([]v1.EnvVar, error) {
}
return envs, nil
}

// parseEnvFroms converts string into EnvFromSource objects.
func parseEnvFroms(envFromArray []string) ([]v1.EnvFromSource, error) {
envFroms := make([]v1.EnvFromSource, 0, len(envFromArray))
for _, envFromString := range envFromArray {
pos := strings.Index(envFromString, "=")
if pos == -1 {
return nil, fmt.Errorf("invalid env-from: %v", envFromString)
}
refType := envFromString[:pos]
name := envFromString[pos+1:]
if len(refType) == 0 || len(name) == 0 {
return nil, fmt.Errorf("invalid env-from: %v", envFromString)
}

var envFrom v1.EnvFromSource
switch refType {
case "ConfigMapRef":
envFrom = v1.EnvFromSource{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
},
}
case "SecretRef":
envFrom = v1.EnvFromSource{
SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
},
}
default:
return nil, fmt.Errorf("env-from can only be 'ConfigMapRef' or 'SecretRef': %v", envFrom)
}

envFroms = append(envFroms, envFrom)
}
return envFroms, nil
}
Loading