Skip to content

Commit

Permalink
Add option to allow enviornment variables using file
Browse files Browse the repository at this point in the history
* Add `GetEnvsFromFile` to `util`
* Add to `podspec` flags `--env-file` and `EnvFile` to `PodSpec`.
* If `env-file` is specified load env vars from file to memory,
  convert them into ordered map and pass them to UpdateEnvVars function
  by setting custom args for each one of them instead of using command line args.

Signed-off-by: Boaz <[email protected]>
  • Loading branch information
boaz0 committed Sep 19, 2021
1 parent e89bdc7 commit 8cf886f
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
|===
| | Description | PR

| 🎁
| Add `--env-file` option to function create/update command
| https://github.com/knative/client/pull/1423[#1419]

| ✨
| Reuse conflict retry loop from client-go/util/retry
| https://github.com/knative/client/pull/1441[#1441]
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_container_add.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ kn container add NAME
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
--cmd stringArray Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start or --cmd sh --cmd /app/start.sh or --cmd /app/start --arg myArg to pass additional arguments.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--env-file string Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--env-value-from stringArray Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. You can use this flag multiple times. To unset a value from a ConfigMap/Secret key reference, append "-" to the key, e.g. --env-value-from ENV-.
--extra-containers string Specify path to file including definition for additional containers, alternatively use '-' to read from stdin. Example: --extra-containers ./containers.yaml or --extra-containers -.
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_service_apply.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ kn service apply s0 --filename my-svc.yml
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
--concurrency-utilization int Percentage of concurrent requests utilization before scaling up. (default 70)
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--env-file string Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--env-value-from stringArray Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. You can use this flag multiple times. To unset a value from a ConfigMap/Secret key reference, append "-" to the key, e.g. --env-value-from ENV-.
--extra-containers string Specify path to file including definition for additional containers, alternatively use '-' to read from stdin. Example: --extra-containers ./containers.yaml or --extra-containers -.
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_service_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ kn service create NAME --image IMAGE
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
--concurrency-utilization int Percentage of concurrent requests utilization before scaling up. (default 70)
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--env-file string Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--env-value-from stringArray Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. You can use this flag multiple times. To unset a value from a ConfigMap/Secret key reference, append "-" to the key, e.g. --env-value-from ENV-.
--extra-containers string Specify path to file including definition for additional containers, alternatively use '-' to read from stdin. Example: --extra-containers ./containers.yaml or --extra-containers -.
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_service_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ kn service update NAME
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
--concurrency-utilization int Percentage of concurrent requests utilization before scaling up. (default 70)
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--env-file string Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--env-value-from stringArray Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. You can use this flag multiple times. To unset a value from a ConfigMap/Secret key reference, append "-" to the key, e.g. --env-value-from ENV-.
--extra-containers string Specify path to file including definition for additional containers, alternatively use '-' to read from stdin. Example: --extra-containers ./containers.yaml or --extra-containers -.
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_source_container_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ kn source container create NAME --image IMAGE --sink SINK
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
--cmd stringArray Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start or --cmd sh --cmd /app/start.sh or --cmd /app/start --arg myArg to pass additional arguments.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--env-file string Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--env-value-from stringArray Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. You can use this flag multiple times. To unset a value from a ConfigMap/Secret key reference, append "-" to the key, e.g. --env-value-from ENV-.
--extra-containers string Specify path to file including definition for additional containers, alternatively use '-' to read from stdin. Example: --extra-containers ./containers.yaml or --extra-containers -.
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_source_container_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ kn source container update NAME --image IMAGE
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
--cmd stringArray Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start or --cmd sh --cmd /app/start.sh or --cmd /app/start --arg myArg to pass additional arguments.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--env-file string Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--env-value-from stringArray Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. You can use this flag multiple times. To unset a value from a ConfigMap/Secret key reference, append "-" to the key, e.g. --env-value-from ENV-.
--extra-containers string Specify path to file including definition for additional containers, alternatively use '-' to read from stdin. Example: --extra-containers ./containers.yaml or --extra-containers -.
Expand Down
25 changes: 23 additions & 2 deletions pkg/kn/flags/podspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type PodSpecFlags struct {
Env []string
EnvFrom []string
EnvValueFrom []string
EnvFile string
Mount []string
Volume []string

Expand Down Expand Up @@ -85,6 +86,9 @@ func (p *PodSpecFlags) AddFlags(flagset *pflag.FlagSet) []string {
"To unset, specify the environment variable name followed by a \"-\" (e.g., NAME-).")
flagNames = append(flagNames, "env")

flagset.StringVarP(&p.EnvFile, "env-file", "", "", "Path to a file containing environment variables (e.g. --env-file=/home/knative/service1/env).")
flagNames = append(flagNames, "env-file")

flagset.StringArrayVarP(&p.EnvValueFrom, "env-value-from", "", []string{},
"Add environment variable from a value of key in ConfigMap (prefix cm: or config-map:) or a Secret (prefix sc: or secret:). "+
"Example: --env-value-from NAME=cm:myconfigmap:key or --env-value-from NAME=secret:mysecret:key. "+
Expand Down Expand Up @@ -169,7 +173,7 @@ func (p *PodSpecFlags) AddFlags(flagset *pflag.FlagSet) []string {
func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.FlagSet, allArgs []string) error {
var err error

if flags.Changed("env") || flags.Changed("env-value-from") {
if flags.Changed("env") || flags.Changed("env-value-from") || flags.Changed("env-file") {
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(p.Env, "=")
if err != nil {
return fmt.Errorf("Invalid --env: %w", err)
Expand All @@ -180,7 +184,24 @@ func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.Flag
return fmt.Errorf("Invalid --env-value-from: %w", err)
}

err = UpdateEnvVars(podSpec, allArgs, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
envsFileToUpdate := util.NewOrderedMap()
envsFileToRemove := []string{}
if p.EnvFile != "" {
envsFromFile, err := util.GetEnvsFromFile(p.EnvFile, "=")
if err != nil {
return fmt.Errorf("Invalid --env-file: %w", err)
}
envsFileToUpdate, envsFileToRemove, err = util.OrderedMapAndRemovalListFromArray(envsFromFile, "=")
if err != nil {
return fmt.Errorf("Invalid --env: %w", err)
}
}

err = UpdateEnvVars(
podSpec, allArgs, envToUpdate, envToRemove,
envValueFromToUpdate, envValueFromToRemove,
p.EnvFile, envsFileToUpdate, envsFileToRemove,
)
if err != nil {
return err
}
Expand Down
23 changes: 21 additions & 2 deletions pkg/kn/flags/podspec_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,22 @@ func containerOfPodSpec(spec *corev1.PodSpec) *corev1.Container {
// UpdateEnvVars gives the configuration all the env var values listed in the given map of
// vars. Does not touch any environment variables not mentioned, but it can add
// new env vars and change the values of existing ones.
func UpdateEnvVars(spec *corev1.PodSpec,
allArgs []string, envToUpdate *util.OrderedMap, envToRemove []string, envValueFromToUpdate *util.OrderedMap, envValueFromToRemove []string) error {
func UpdateEnvVars(spec *corev1.PodSpec, allArgs []string,
envToUpdate *util.OrderedMap, envToRemove []string,
envValueFromToUpdate *util.OrderedMap, envValueFromToRemove []string,
envFileName string, envValueFileToUpdate *util.OrderedMap, envValueFileToRemove []string,
) error {
container := containerOfPodSpec(spec)

allEnvsToUpdate := util.NewOrderedMap()

envIterator := envToUpdate.Iterator()
envValueFromIterator := envValueFromToUpdate.Iterator()
envValueFileIterator := envValueFileToUpdate.Iterator()

envKey, envValue, envExists := envIterator.NextString()
envValueFromKey, envValueFromValue, envValueFromExists := envValueFromIterator.NextString()
envValueFileKey, envValueFileValue, envValueFileExists := envValueFileIterator.NextString()
for _, arg := range allArgs {
// envs are stored as NAME=value
if envExists && isValidEnvArg(arg, envKey, envValue) {
Expand All @@ -86,6 +91,14 @@ func UpdateEnvVars(spec *corev1.PodSpec,
ValueFrom: envVarSource,
})
envValueFromKey, envValueFromValue, envValueFromExists = envValueFromIterator.NextString()
} else if envValueFileExists && isValidEnvValueFileArg(arg, envFileName) {
for envValueFileExists {
allEnvsToUpdate.Set(envValueFileKey, corev1.EnvVar{
Name: envValueFileKey,
Value: envValueFileValue,
})
envValueFileKey, envValueFileValue, envValueFileExists = envValueFileIterator.NextString()
}
}
}

Expand All @@ -109,6 +122,12 @@ func isValidEnvValueFromArg(arg, envValueFromKey, envValueFromValue string) bool
return strings.HasPrefix(arg, envValueFromKey+"="+envValueFromValue) || strings.HasPrefix(arg, "--env-value-from="+envValueFromKey+"="+envValueFromValue)
}

// isValidEnvValueFileArg checks that the input arg is a valid argument for specifying env from value,
// ie. stored as NAME=secret:sercretName:key or NAME=config-map:cmName:key
func isValidEnvValueFileArg(arg, envFileName string) bool {
return strings.HasPrefix(arg, envFileName) || strings.HasPrefix(arg, "--env-file="+envFileName)
}

// UpdateEnvFrom updates envFrom
func UpdateEnvFrom(spec *corev1.PodSpec, toUpdate []string, toRemove []string) error {
container := containerOfPodSpec(spec)
Expand Down
Loading

0 comments on commit 8cf886f

Please sign in to comment.