mirror of https://github.com/knative/client.git
Add `env-value-from` flag & keep order of env vars in created/updated services (#1328)
* Add --env-value-from & preserve env var order Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * add e2e test for checking Service Env Vars Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * update changelog Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * refactor UpdateEnvVars() Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * apply review suggestions Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * fix typo Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * improve test cases names Signed-off-by: Zbynek Roubalik <zroubali@redhat.com>
This commit is contained in:
parent
ab537bc731
commit
a086cc9707
|
@ -20,6 +20,10 @@
|
|||
| Prettify printing of webhook warnings
|
||||
| https://github.com/knative/client/pull/1353[#1353]
|
||||
|
||||
| 🎁
|
||||
| Add `env-value-from` flag & keep order of env vars in created/updated Services
|
||||
| https://github.com/knative/client/pull/1328[#1328]
|
||||
|
||||
## v0.23.0 (2021-05-18)
|
||||
[cols="1,10,3", options="header", width="100%"]
|
||||
|===
|
||||
|
@ -1350,6 +1354,5 @@ Ignore PRs:
|
|||
[cols="1,10,3", options="header", width="100%"]
|
||||
|===
|
||||
| | Description | PR
|
||||
|
||||
|===
|
||||
////
|
||||
|
|
|
@ -41,6 +41,7 @@ kn service apply s0 --filename my-svc.yml
|
|||
--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-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-.
|
||||
-f, --filename string Create a service from file. The created service can be further modified by combining with other options. For example, -f /path/to/file --env NAME=value adds also an environment variable.
|
||||
--force Create service forcefully, replaces existing service if any.
|
||||
-h, --help help for apply
|
||||
|
|
|
@ -66,6 +66,7 @@ kn service create NAME --image IMAGE
|
|||
--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-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-.
|
||||
-f, --filename string Create a service from file. The created service can be further modified by combining with other options. For example, -f /path/to/file --env NAME=value adds also an environment variable.
|
||||
--force Create service forcefully, replaces existing service if any.
|
||||
-h, --help help for create
|
||||
|
|
|
@ -51,6 +51,7 @@ kn service update NAME
|
|||
--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-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-.
|
||||
-h, --help help for update
|
||||
--image string Image to run.
|
||||
-l, --label stringArray Labels to set for both Service and Revision. name=value; you may provide this flag any number of times to set multiple labels. To unset, specify the label name followed by a "-" (e.g., name-).
|
||||
|
|
|
@ -17,22 +17,23 @@ kn source container create NAME --image IMAGE --sink SINK
|
|||
### Options
|
||||
|
||||
```
|
||||
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
|
||||
--cmd string Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start 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-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-.
|
||||
-h, --help help for create
|
||||
--image string Image to run.
|
||||
--limit strings The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
|
||||
--mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
|
||||
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
|
||||
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
|
||||
--service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace.
|
||||
-s, --sink string Addressable sink for events. You can specify a broker, channel, Knative service or URI. Examples: '--sink broker:nest' for a broker 'nest', '--sink channel:pipe' for a channel 'pipe', '--sink ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', '--sink https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, '--sink ksvc:receiver' or simply '--sink receiver' for a Knative service 'receiver' in the current namespace. If a prefix is not provided, it is considered as a Knative service in the current namespace. If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly.
|
||||
--user int The user ID to run the container (e.g., 1001).
|
||||
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
|
||||
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
|
||||
--cmd string Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start 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-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-.
|
||||
-h, --help help for create
|
||||
--image string Image to run.
|
||||
--limit strings The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
|
||||
--mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
|
||||
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
|
||||
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
|
||||
--service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace.
|
||||
-s, --sink string Addressable sink for events. You can specify a broker, channel, Knative service or URI. Examples: '--sink broker:nest' for a broker 'nest', '--sink channel:pipe' for a channel 'pipe', '--sink ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', '--sink https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, '--sink ksvc:receiver' or simply '--sink receiver' for a Knative service 'receiver' in the current namespace. If a prefix is not provided, it is considered as a Knative service in the current namespace. If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly.
|
||||
--user int The user ID to run the container (e.g., 1001).
|
||||
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
@ -17,22 +17,23 @@ kn source container update NAME --image IMAGE
|
|||
### Options
|
||||
|
||||
```
|
||||
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
|
||||
--cmd string Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start 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-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-.
|
||||
-h, --help help for update
|
||||
--image string Image to run.
|
||||
--limit strings The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
|
||||
--mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
|
||||
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
|
||||
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
|
||||
--service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace.
|
||||
-s, --sink string Addressable sink for events. You can specify a broker, channel, Knative service or URI. Examples: '--sink broker:nest' for a broker 'nest', '--sink channel:pipe' for a channel 'pipe', '--sink ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', '--sink https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, '--sink ksvc:receiver' or simply '--sink receiver' for a Knative service 'receiver' in the current namespace. If a prefix is not provided, it is considered as a Knative service in the current namespace. If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly.
|
||||
--user int The user ID to run the container (e.g., 1001).
|
||||
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
|
||||
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
|
||||
--cmd string Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start 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-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-.
|
||||
-h, --help help for update
|
||||
--image string Image to run.
|
||||
--limit strings The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
|
||||
--mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
-p, --port string The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
|
||||
--pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
|
||||
--request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'.
|
||||
--service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace.
|
||||
-s, --sink string Addressable sink for events. You can specify a broker, channel, Knative service or URI. Examples: '--sink broker:nest' for a broker 'nest', '--sink channel:pipe' for a channel 'pipe', '--sink ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', '--sink https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, '--sink ksvc:receiver' or simply '--sink receiver' for a Knative service 'receiver' in the current namespace. If a prefix is not provided, it is considered as a Knative service in the current namespace. If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly.
|
||||
--user int The user ID to run the container (e.g., 1001).
|
||||
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
@ -16,6 +16,7 @@ package service
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -199,7 +200,7 @@ func (p *ConfigurationEditFlags) Apply(
|
|||
|
||||
template := &service.Spec.Template
|
||||
|
||||
err := p.PodSpecFlags.ResolvePodSpec(&template.Spec.PodSpec, cmd.Flags())
|
||||
err := p.PodSpecFlags.ResolvePodSpec(&template.Spec.PodSpec, cmd.Flags(), os.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ func TestServiceCreateEnvMock(t *testing.T) {
|
|||
template.Annotations = map[string]string{servinglib.UserImageAnnotationKey: "gcr.io/foo/bar:baz"}
|
||||
r.CreateService(service, nil)
|
||||
|
||||
output, err := executeServiceCommand(client, "create", "foo", "--image", "gcr.io/foo/bar:baz", "-e", "a=mouse", "--env", "b=cookie", "--env=empty", "--no-wait", "--revision-name=")
|
||||
output, err := executeServiceCommand(client, "create", "foo", "--image", "gcr.io/foo/bar:baz", "-e", "a=mouse", "--env", "b=cookie", "--env", "empty=", "--no-wait", "--revision-name=")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, util.ContainsAll(output, "created", "foo", "default"))
|
||||
|
||||
|
|
|
@ -207,9 +207,18 @@ func TestServiceCreateArg(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestServiceCreateEnv(t *testing.T) {
|
||||
action, created, _, err := fakeServiceCreate([]string{
|
||||
|
||||
// we need to temporary reset os.Args, becase it is being used for evaluation
|
||||
// of order of envs set by --env and --env-value-from
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
|
||||
args := []string{
|
||||
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz",
|
||||
"-e", "A=DOGS", "--env", "B=WOLVES", "--env=EMPTY", "--no-wait"}, false)
|
||||
"-e", "A=DOGS", "--env", "B=WOLVES", "--env", "EMPTY=", "--no-wait"}
|
||||
os.Args = args
|
||||
|
||||
action, created, _, err := fakeServiceCreate(args, false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -708,15 +717,28 @@ func TestServiceCreateImageForce(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestServiceCreateEnvForce(t *testing.T) {
|
||||
_, _, _, err := fakeServiceCreate([]string{
|
||||
|
||||
// we need to temporary reset os.Args, becase it is being used for evaluation
|
||||
// of order of envs set by --env and --env-value-from
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
|
||||
args := []string{
|
||||
"service", "create", "foo", "--image", "gcr.io/foo/bar:v1",
|
||||
"-e", "A=DOGS", "--env", "B=WOLVES", "--no-wait"}, false)
|
||||
"-e", "A=DOGS", "--env", "B=WOLVES", "--no-wait"}
|
||||
os.Args = args
|
||||
|
||||
_, _, _, err := fakeServiceCreate(args, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
action, created, output, err := fakeServiceCreate([]string{
|
||||
|
||||
args = []string{
|
||||
"service", "create", "foo", "--force", "--image", "gcr.io/foo/bar:v2",
|
||||
"-e", "A=CATS", "--env", "B=LIONS", "--no-wait"}, false)
|
||||
"-e", "A=CATS", "--env", "B=LIONS", "--no-wait"}
|
||||
os.Args = args
|
||||
|
||||
action, created, output, err := fakeServiceCreate(args, false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -961,8 +983,16 @@ func TestServiceCreateFromYAMLWithOverride(t *testing.T) {
|
|||
expectedEnvVars := map[string]string{
|
||||
"TARGET": "Go Sample v1",
|
||||
"FOO": "BAR"}
|
||||
action, created, _, err := fakeServiceCreate([]string{
|
||||
"service", "create", "foo", "--filename", tempFile, "--env", "FOO=BAR"}, false)
|
||||
|
||||
// we need to temporary reset os.Args, becase it is being used for evaluation
|
||||
// of order of envs set by --env and --env-value-from
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
|
||||
args := []string{"service", "create", "foo", "--filename", tempFile, "--env", "FOO=BAR"}
|
||||
os.Args = args
|
||||
|
||||
action, created, _, err := fakeServiceCreate(args, false)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, action.Matches("create", "services"))
|
||||
assert.Equal(t, created.Name, "foo")
|
||||
|
@ -975,8 +1005,11 @@ func TestServiceCreateFromYAMLWithOverride(t *testing.T) {
|
|||
expectedEnvVars = map[string]string{
|
||||
"TARGET": "FOOBAR",
|
||||
"FOO": "BAR"}
|
||||
action, created, _, err = fakeServiceCreate([]string{
|
||||
"service", "create", "foo", "--filename", tempFile, "--env", "TARGET=FOOBAR", "--env", "FOO=BAR"}, false)
|
||||
|
||||
args = []string{"service", "create", "foo", "--filename", tempFile, "--env", "TARGET=FOOBAR", "--env", "FOO=BAR"}
|
||||
os.Args = args
|
||||
|
||||
action, created, _, err = fakeServiceCreate(args, false)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, action.Matches("create", "services"))
|
||||
assert.Equal(t, created.Name, "foo")
|
||||
|
@ -988,8 +1021,11 @@ func TestServiceCreateFromYAMLWithOverride(t *testing.T) {
|
|||
// Remove existing env vars
|
||||
expectedEnvVars = map[string]string{
|
||||
"FOO": "BAR"}
|
||||
action, created, _, err = fakeServiceCreate([]string{
|
||||
"service", "create", "foo", "--filename", tempFile, "--env", "TARGET-", "--env", "FOO=BAR"}, false)
|
||||
|
||||
args = []string{"service", "create", "foo", "--filename", tempFile, "--env", "TARGET-", "--env", "FOO=BAR"}
|
||||
os.Args = args
|
||||
|
||||
action, created, _, err = fakeServiceCreate(args, false)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, action.Matches("create", "services"))
|
||||
assert.Equal(t, created.Name, "foo")
|
||||
|
@ -1001,8 +1037,12 @@ func TestServiceCreateFromYAMLWithOverride(t *testing.T) {
|
|||
// Multiple edit flags
|
||||
expectedAnnotations := map[string]string{
|
||||
"foo": "bar"}
|
||||
action, created, _, err = fakeServiceCreate([]string{"service", "create", "foo", "--filename", tempFile,
|
||||
"--service-account", "foo", "--cmd", "/foo/bar", "-a", "foo=bar"}, false)
|
||||
|
||||
args = []string{"service", "create", "foo", "--filename", tempFile,
|
||||
"--service-account", "foo", "--cmd", "/foo/bar", "-a", "foo=bar"}
|
||||
os.Args = args
|
||||
|
||||
action, created, _, err = fakeServiceCreate(args, false)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, action.Matches("create", "services"))
|
||||
assert.Equal(t, created.Name, "foo")
|
||||
|
|
|
@ -16,6 +16,7 @@ package service
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
@ -54,6 +55,12 @@ func executeServiceCommand(client clientservingv1.KnServingClient, args ...strin
|
|||
knParams := &commands.KnParams{}
|
||||
knParams.ClientConfig = blankConfig
|
||||
|
||||
// we need to temporary reset os.Args, becase it is being used for evaluation
|
||||
// of order of envs set by --env and --env-value-from
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = args
|
||||
|
||||
output := new(bytes.Buffer)
|
||||
knParams.Output = output
|
||||
knParams.NewServingClient = func(namespace string) (clientservingv1.KnServingClient, error) {
|
||||
|
|
|
@ -56,7 +56,7 @@ func TestServiceUpdateEnvMock(t *testing.T) {
|
|||
r := client.Recorder()
|
||||
recordServiceUpdateWithSuccess(r, "foo", service, updated)
|
||||
|
||||
output, err := executeServiceCommand(client, "create", "foo", "--image", "gcr.io/foo/bar:baz", "-e", "a=mouse", "--env", "b=cookie", "--env=empty", "--no-wait", "--revision-name=")
|
||||
output, err := executeServiceCommand(client, "create", "foo", "--image", "gcr.io/foo/bar:baz", "-e", "a=mouse", "--env", "b=cookie", "--env", "empty=", "--no-wait", "--revision-name=")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, util.ContainsAll(output, "created", "foo", "default"))
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package service
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -655,8 +656,16 @@ func TestServiceUpdateEnv(t *testing.T) {
|
|||
|
||||
flags.UpdateImage(&template.Spec.PodSpec, "gcr.io/foo/bar:baz")
|
||||
|
||||
action, updated, _, err := fakeServiceUpdate(orig, []string{
|
||||
"service", "update", "foo", "-e", "TARGET=Awesome", "--env", "EXISTING-", "--env=OTHEREXISTING-=whatever", "--no-wait"})
|
||||
// we need to temporary reset os.Args, becase it is being used for evaluation
|
||||
// of order of envs set by --env and --env-value-from
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
|
||||
args := []string{
|
||||
"service", "update", "foo", "-e", "TARGET=Awesome", "--env", "EXISTING-", "--env", "OTHEREXISTING-", "--no-wait"}
|
||||
os.Args = args
|
||||
|
||||
action, updated, _, err := fakeServiceUpdate(orig, args)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -19,6 +19,7 @@ package container
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"knative.dev/client/pkg/kn/commands/flags"
|
||||
|
@ -67,7 +68,7 @@ func NewContainerCreateCommand(p *commands.KnParams) *cobra.Command {
|
|||
}
|
||||
|
||||
podSpec := &corev1.PodSpec{Containers: []corev1.Container{{}}}
|
||||
err = podFlags.ResolvePodSpec(podSpec, cmd.Flags())
|
||||
err = podFlags.ResolvePodSpec(podSpec, cmd.Flags(), os.Args)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"cannot create ContainerSource '%s' in namespace '%s' "+
|
||||
|
|
|
@ -19,6 +19,7 @@ package container
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"knative.dev/client/pkg/kn/commands/flags"
|
||||
|
@ -69,7 +70,7 @@ func NewContainerUpdateCommand(p *commands.KnParams) *cobra.Command {
|
|||
|
||||
b := v1.NewContainerSourceBuilderFromExisting(source)
|
||||
podSpec := b.Build().Spec.Template.Spec
|
||||
err = podFlags.ResolvePodSpec(&podSpec, cmd.Flags())
|
||||
err = podFlags.ResolvePodSpec(&podSpec, cmd.Flags(), os.Args)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"cannot update ContainerSource '%s' in namespace '%s' "+
|
||||
|
|
|
@ -28,11 +28,12 @@ import (
|
|||
// PodSpecFlags to hold the container resource requirements values
|
||||
type PodSpecFlags struct {
|
||||
// Direct field manipulation
|
||||
Image uniqueStringArg
|
||||
Env []string
|
||||
EnvFrom []string
|
||||
Mount []string
|
||||
Volume []string
|
||||
Image uniqueStringArg
|
||||
Env []string
|
||||
EnvFrom []string
|
||||
EnvValueFrom []string
|
||||
Mount []string
|
||||
Volume []string
|
||||
|
||||
Command string
|
||||
Arg []string
|
||||
|
@ -82,6 +83,13 @@ 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.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. "+
|
||||
"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-.")
|
||||
flagNames = append(flagNames, "env-value-from")
|
||||
|
||||
flagset.StringArrayVarP(&p.EnvFrom, "env-from", "", []string{},
|
||||
"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. "+
|
||||
|
@ -150,17 +158,22 @@ func (p *PodSpecFlags) AddFlags(flagset *pflag.FlagSet) []string {
|
|||
return flagNames
|
||||
}
|
||||
|
||||
// ResolvePodSpec will create corev1.PodSpec based on the flag inputs
|
||||
func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.FlagSet) error {
|
||||
// ResolvePodSpec will create corev1.PodSpec based on the flag inputs and all input arguments
|
||||
func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.FlagSet, allArgs []string) error {
|
||||
var err error
|
||||
if flags.Changed("env") {
|
||||
envMap, err := util.MapFromArrayAllowingSingles(p.Env, "=")
|
||||
|
||||
if flags.Changed("env") || flags.Changed("env-value-from") {
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(p.Env, "=")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid --env: %w", err)
|
||||
}
|
||||
|
||||
envToRemove := util.ParseMinusSuffix(envMap)
|
||||
err = UpdateEnvVars(podSpec, envMap, envToRemove)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(p.EnvValueFrom, "=")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid --env-value-from: %w", err)
|
||||
}
|
||||
|
||||
err = UpdateEnvVars(podSpec, allArgs, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package flags
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -53,20 +52,60 @@ 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, then sort by env key name.
|
||||
func UpdateEnvVars(spec *corev1.PodSpec, toUpdate map[string]string, toRemove []string) error {
|
||||
// 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 {
|
||||
container := containerOfPodSpec(spec)
|
||||
updated := updateEnvVarsFromMap(container.Env, toUpdate)
|
||||
updated = removeEnvVars(updated, toRemove)
|
||||
// Sort by env key name
|
||||
sort.SliceStable(updated, func(i, j int) bool {
|
||||
return updated[i].Name < updated[j].Name
|
||||
})
|
||||
|
||||
allEnvsToUpdate := util.NewOrderedMap()
|
||||
|
||||
envIterator := envToUpdate.Iterator()
|
||||
envValueFromIterator := envValueFromToUpdate.Iterator()
|
||||
|
||||
envKey, envValue, envExists := envIterator.NextString()
|
||||
envValueFromKey, envValueFromValue, envValueFromExists := envValueFromIterator.NextString()
|
||||
for _, arg := range allArgs {
|
||||
// envs are stored as NAME=value
|
||||
if envExists && isValidEnvArg(arg, envKey, envValue) {
|
||||
allEnvsToUpdate.Set(envKey, corev1.EnvVar{
|
||||
Name: envKey,
|
||||
Value: envValue,
|
||||
})
|
||||
envKey, envValue, envExists = envIterator.NextString()
|
||||
} else if envValueFromExists && isValidEnvValueFromArg(arg, envValueFromKey, envValueFromValue) {
|
||||
// envs are stored as NAME=secret:sercretName:key or NAME=config-map:cmName:key
|
||||
envVarSource, err := createEnvVarSource(envValueFromValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allEnvsToUpdate.Set(envValueFromKey, corev1.EnvVar{
|
||||
Name: envValueFromKey,
|
||||
ValueFrom: envVarSource,
|
||||
})
|
||||
envValueFromKey, envValueFromValue, envValueFromExists = envValueFromIterator.NextString()
|
||||
}
|
||||
}
|
||||
|
||||
updated := updateEnvVarsFromMap(container.Env, allEnvsToUpdate)
|
||||
updated = removeEnvVars(updated, append(envToRemove, envValueFromToRemove...))
|
||||
|
||||
container.Env = updated
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isValidEnvArg checks that the input arg is a valid argument for specifying env value,
|
||||
// ie. stored as NAME=value
|
||||
func isValidEnvArg(arg, envKey, envValue string) bool {
|
||||
return strings.HasPrefix(arg, envKey+"="+envValue) || strings.HasPrefix(arg, "-e="+envKey+"="+envValue) || strings.HasPrefix(arg, "--env="+envKey+"="+envValue)
|
||||
}
|
||||
|
||||
// isValidEnvValueFromArg 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 isValidEnvValueFromArg(arg, envValueFromKey, envValueFromValue string) bool {
|
||||
return strings.HasPrefix(arg, envValueFromKey+"="+envValueFromValue) || strings.HasPrefix(arg, "--env-value-from="+envValueFromKey+"="+envValueFromValue)
|
||||
}
|
||||
|
||||
// UpdateEnvFrom updates envFrom
|
||||
func UpdateEnvFrom(spec *corev1.PodSpec, toUpdate []string, toRemove []string) error {
|
||||
container := containerOfPodSpec(spec)
|
||||
|
@ -217,18 +256,20 @@ func UpdateImagePullSecrets(spec *corev1.PodSpec, pullsecrets string) {
|
|||
}
|
||||
|
||||
// =======================================================================================
|
||||
func updateEnvVarsFromMap(env []corev1.EnvVar, toUpdate map[string]string) []corev1.EnvVar {
|
||||
set := sets.NewString()
|
||||
func updateEnvVarsFromMap(env []corev1.EnvVar, toUpdate *util.OrderedMap) []corev1.EnvVar {
|
||||
updated := sets.NewString()
|
||||
|
||||
for i := range env {
|
||||
envVar := &env[i]
|
||||
if val, ok := toUpdate[envVar.Name]; ok {
|
||||
envVar.Value = val
|
||||
set.Insert(envVar.Name)
|
||||
object, present := toUpdate.Get(env[i].Name)
|
||||
if present {
|
||||
env[i] = object.(corev1.EnvVar)
|
||||
updated.Insert(env[i].Name)
|
||||
}
|
||||
}
|
||||
for name, val := range toUpdate {
|
||||
if !set.Has(name) {
|
||||
env = append(env, corev1.EnvVar{Name: name, Value: val})
|
||||
it := toUpdate.Iterator()
|
||||
for name, envVar, ok := it.Next(); ok; name, envVar, ok = it.Next() {
|
||||
if !updated.Has(name) {
|
||||
env = append(env, envVar.(corev1.EnvVar))
|
||||
}
|
||||
}
|
||||
return env
|
||||
|
@ -246,6 +287,50 @@ func removeEnvVars(env []corev1.EnvVar, toRemove []string) []corev1.EnvVar {
|
|||
return env
|
||||
}
|
||||
|
||||
func createEnvVarSource(spec string) (*corev1.EnvVarSource, error) {
|
||||
slices := strings.SplitN(spec, ":", 3)
|
||||
if len(slices) != 3 {
|
||||
return nil, fmt.Errorf("argument requires a value in form \"resourceType:name:key\" where \"resourceType\" can be one of \"config-map\" (\"cm\") or \"secret\" (\"sc\"); got %q", spec)
|
||||
}
|
||||
|
||||
typeString := strings.TrimSpace(slices[0])
|
||||
sourceName := strings.TrimSpace(slices[1])
|
||||
sourceKey := strings.TrimSpace(slices[2])
|
||||
|
||||
var sourceType string
|
||||
envVarSource := corev1.EnvVarSource{}
|
||||
|
||||
switch typeString {
|
||||
case "config-map", "cm":
|
||||
sourceType = "ConfigMap"
|
||||
envVarSource.ConfigMapKeyRef = &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: sourceName,
|
||||
},
|
||||
Key: sourceKey}
|
||||
case "secret", "sc":
|
||||
sourceType = "Secret"
|
||||
envVarSource.SecretKeyRef = &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: sourceName,
|
||||
},
|
||||
Key: sourceKey}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported env source type \"%q\"; supported source types are \"config-map\" (\"cm\") and \"secret\" (\"sc\")", slices[0])
|
||||
}
|
||||
|
||||
if len(sourceName) == 0 {
|
||||
return nil, fmt.Errorf("the name of %s cannot be an empty string", sourceType)
|
||||
}
|
||||
|
||||
if len(sourceKey) == 0 {
|
||||
return nil, fmt.Errorf("the key referenced by resource %s \"%s\" cannot be an empty string", sourceType, sourceName)
|
||||
}
|
||||
|
||||
return &envVarSource, nil
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
func updateEnvFrom(envFromSources []corev1.EnvFromSource, toUpdate []string) ([]corev1.EnvFromSource, error) {
|
||||
existingNameSet := make(map[string]bool)
|
||||
|
||||
|
|
|
@ -35,15 +35,169 @@ func getPodSpec() (*corev1.PodSpec, *corev1.Container) {
|
|||
|
||||
func TestUpdateEnvVarsNew(t *testing.T) {
|
||||
spec, _ := getPodSpec()
|
||||
env := []corev1.EnvVar{
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", Value: "foo"},
|
||||
{Name: "b", Value: "bar"},
|
||||
}
|
||||
found, err := util.EnvToMap(env)
|
||||
argsEnv := []string{
|
||||
"a=foo",
|
||||
"b=bar",
|
||||
}
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, found, []string{})
|
||||
args := append([]string{"command"}, argsEnv...)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, env, spec.Containers[0].Env)
|
||||
assert.DeepEqual(t, expected, spec.Containers[0].Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsMixedEnvOrder(t *testing.T) {
|
||||
spec, _ := getPodSpec()
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "z", Value: "foo"},
|
||||
{Name: "a", Value: "bar"},
|
||||
{Name: "x", Value: "baz"},
|
||||
}
|
||||
argsEnv := []string{
|
||||
"z=foo",
|
||||
"a=bar",
|
||||
"x=baz",
|
||||
}
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
|
||||
assert.NilError(t, err)
|
||||
args := append([]string{"command"}, argsEnv...)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, spec.Containers[0].Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsValueFromNew(t *testing.T) {
|
||||
spec, _ := getPodSpec()
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "b", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "bar",
|
||||
},
|
||||
Key: "key2",
|
||||
},
|
||||
}},
|
||||
{Name: "c", ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "baz",
|
||||
},
|
||||
Key: "key3",
|
||||
},
|
||||
}},
|
||||
{Name: "d", ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "goo",
|
||||
},
|
||||
Key: "key4",
|
||||
},
|
||||
}},
|
||||
}
|
||||
argsEnvValueFrom := []string{
|
||||
"a=secret:foo:key",
|
||||
"b=sc:bar:key2",
|
||||
"c=config-map:baz:key3",
|
||||
"d=cm:goo:key4",
|
||||
}
|
||||
args := append([]string{"command"}, argsEnvValueFrom...)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, spec.Containers[0].Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsAllNew(t *testing.T) {
|
||||
spec, _ := getPodSpec()
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "b", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "bar",
|
||||
},
|
||||
Key: "key2",
|
||||
},
|
||||
}},
|
||||
{Name: "c", Value: "baz"},
|
||||
{Name: "d", Value: "goo"},
|
||||
}
|
||||
argsEnvValueFrom := []string{
|
||||
"a=secret:foo:key",
|
||||
"b=sc:bar:key2",
|
||||
}
|
||||
argsEnv := []string{
|
||||
"c=baz",
|
||||
"d=goo",
|
||||
}
|
||||
|
||||
args := append([]string{"command"}, append(argsEnvValueFrom, argsEnv...)...)
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
|
||||
assert.NilError(t, err)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, spec.Containers[0].Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsValueFromValidate(t *testing.T) {
|
||||
spec, _ := getPodSpec()
|
||||
envValueFromWrongInput := [][]string{
|
||||
{"foo=foo"},
|
||||
{"foo=bar:"},
|
||||
{"foo=foo:bar"},
|
||||
{"foo=foo:bar:"},
|
||||
{"foo=foo:bar:baz"},
|
||||
{"foo=secret"},
|
||||
{"foo=sec"},
|
||||
{"foo=secret:"},
|
||||
{"foo=sec:"},
|
||||
{"foo=secret:name"},
|
||||
{"foo=sec:name"},
|
||||
{"foo=secret:name"},
|
||||
{"foo=sec:name:"},
|
||||
{"foo=config-map"},
|
||||
{"foo=cm"},
|
||||
{"foo=config-map:"},
|
||||
{"foo=cm:"},
|
||||
{"foo=config-map:name"},
|
||||
{"foo=cm:name"},
|
||||
{"foo=config-map:name:"},
|
||||
{"foo=cm:name:"},
|
||||
}
|
||||
|
||||
for _, input := range envValueFromWrongInput {
|
||||
args := append([]string{"command"}, input...)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(input, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
|
||||
fmt.Println()
|
||||
msg := fmt.Sprintf("input \"%s\" should fail, as it is not valid entry for containers.env.valueFrom", input[0])
|
||||
assert.ErrorContains(t, err, " ", msg)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestUpdateEnvFrom(t *testing.T) {
|
||||
|
@ -313,19 +467,94 @@ func TestUpdateEnvVarsModify(t *testing.T) {
|
|||
spec, container := getPodSpec()
|
||||
container.Env = []corev1.EnvVar{
|
||||
{Name: "a", Value: "foo"}}
|
||||
env := map[string]string{
|
||||
"a": "fancy",
|
||||
}
|
||||
err := UpdateEnvVars(spec, env, []string{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := map[string]string{
|
||||
"a": "fancy",
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", Value: "bar"},
|
||||
}
|
||||
argsEnv := []string{
|
||||
"a=bar",
|
||||
}
|
||||
args := append([]string{"command"}, argsEnv...)
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, container.Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsValueFromModify(t *testing.T) {
|
||||
spec, container := getPodSpec()
|
||||
container.Env = []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
found, err := util.EnvToMap(container.Env)
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "bar",
|
||||
},
|
||||
Key: "key2",
|
||||
},
|
||||
}},
|
||||
}
|
||||
argsEnvValueFrom := []string{
|
||||
"a=secret:bar:key2",
|
||||
}
|
||||
args := append([]string{"command"}, argsEnvValueFrom...)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, found)
|
||||
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, container.Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsAllModify(t *testing.T) {
|
||||
spec, container := getPodSpec()
|
||||
container.Env = []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "b", Value: "bar"},
|
||||
}
|
||||
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "bar",
|
||||
},
|
||||
Key: "key2",
|
||||
},
|
||||
}},
|
||||
{Name: "b", Value: "goo"},
|
||||
}
|
||||
argsEnvValueFrom := []string{
|
||||
"a=secret:bar:key2",
|
||||
}
|
||||
argsEnv := []string{
|
||||
"b=goo",
|
||||
}
|
||||
args := append([]string{"command"}, append(argsEnvValueFrom, argsEnv...)...)
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
|
||||
assert.NilError(t, err)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, container.Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsRemove(t *testing.T) {
|
||||
|
@ -334,8 +563,11 @@ func TestUpdateEnvVarsRemove(t *testing.T) {
|
|||
{Name: "a", Value: "foo"},
|
||||
{Name: "b", Value: "bar"},
|
||||
}
|
||||
remove := []string{"b"}
|
||||
err := UpdateEnvVars(spec, map[string]string{}, remove)
|
||||
remove := []string{"b-"}
|
||||
args := append([]string{"command"}, remove...)
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(remove, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := []corev1.EnvVar{
|
||||
|
@ -344,3 +576,190 @@ func TestUpdateEnvVarsRemove(t *testing.T) {
|
|||
|
||||
assert.DeepEqual(t, expected, container.Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsValueFromRemove(t *testing.T) {
|
||||
spec, container := getPodSpec()
|
||||
container.Env = []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "b", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "bar",
|
||||
},
|
||||
Key: "key2",
|
||||
},
|
||||
}},
|
||||
}
|
||||
remove := []string{"b-"}
|
||||
args := append([]string{"command"}, remove...)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(remove, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, expected, container.Env)
|
||||
}
|
||||
|
||||
func TestUpdateEnvVarsAllRemove(t *testing.T) {
|
||||
spec, container := getPodSpec()
|
||||
container.Env = []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "b", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "bar",
|
||||
},
|
||||
Key: "key2",
|
||||
},
|
||||
}},
|
||||
{Name: "c", Value: "baz"},
|
||||
{Name: "d", Value: "goo"},
|
||||
}
|
||||
argsEnvValueFrom := []string{
|
||||
"a=secret:foo:key",
|
||||
"b-",
|
||||
}
|
||||
argsEnv := []string{
|
||||
"c=baz",
|
||||
"d-",
|
||||
}
|
||||
|
||||
args := append([]string{"command"}, append(argsEnvValueFrom, argsEnv...)...)
|
||||
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
|
||||
assert.NilError(t, err)
|
||||
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
|
||||
assert.NilError(t, err)
|
||||
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := []corev1.EnvVar{
|
||||
{Name: "a", ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "foo",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "c", Value: "baz"},
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, expected, container.Env)
|
||||
}
|
||||
|
||||
func Test_isValidEnvArg(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
arg string
|
||||
envKey string
|
||||
envValue string
|
||||
isValid bool
|
||||
}{{
|
||||
name: "valid env arg specified",
|
||||
arg: "FOO=bar",
|
||||
envKey: "FOO",
|
||||
envValue: "bar",
|
||||
isValid: true,
|
||||
}, {
|
||||
name: "invalid env arg specified",
|
||||
arg: "FOObar",
|
||||
envKey: "FOO",
|
||||
envValue: "bar",
|
||||
isValid: false,
|
||||
}, {
|
||||
name: "valid env arg specified: -e",
|
||||
arg: "-e=FOO=bar",
|
||||
envKey: "FOO",
|
||||
envValue: "bar",
|
||||
isValid: true,
|
||||
}, {
|
||||
name: "invalid env arg specified: -e",
|
||||
arg: "-e=FOObar",
|
||||
envKey: "FOO",
|
||||
envValue: "bar",
|
||||
isValid: false,
|
||||
}, {
|
||||
name: "valid env arg specified: --env",
|
||||
arg: "--env=FOO=bar",
|
||||
envKey: "FOO",
|
||||
envValue: "bar",
|
||||
isValid: true,
|
||||
}, {
|
||||
name: "invalid env arg specified: --env",
|
||||
arg: "--env=FOObar",
|
||||
envKey: "FOO",
|
||||
envValue: "bar",
|
||||
isValid: false,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := isValidEnvArg(tc.arg, tc.envKey, tc.envValue)
|
||||
assert.Equal(t, result, tc.isValid)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_isValidEnvValueFromArg(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
arg string
|
||||
envValueFromKey string
|
||||
envValueFromValue string
|
||||
isValid bool
|
||||
}{{
|
||||
name: "valid env value from arg specified",
|
||||
arg: "FOO=secret:sercretName:key",
|
||||
envValueFromKey: "FOO",
|
||||
envValueFromValue: "secret:sercretName:key",
|
||||
isValid: true,
|
||||
}, {
|
||||
name: "invalid env value from arg specified",
|
||||
arg: "FOOsecret:sercretName:key",
|
||||
envValueFromKey: "FOO",
|
||||
envValueFromValue: "secret:sercretName:key",
|
||||
isValid: false,
|
||||
}, {
|
||||
name: "valid env value from arg specified: --env-value-from",
|
||||
arg: "--env-value-from=FOO=secret:sercretName:key",
|
||||
envValueFromKey: "FOO",
|
||||
envValueFromValue: "secret:sercretName:key",
|
||||
isValid: true,
|
||||
}, {
|
||||
name: "invalid env value from arg specified: --env-value-from",
|
||||
arg: "--env-value-from=FOOsecret:sercretName:key",
|
||||
envValueFromKey: "FOO",
|
||||
envValueFromValue: "secret:sercretName:key",
|
||||
isValid: false,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := isValidEnvValueFromArg(tc.arg, tc.envValueFromKey, tc.envValueFromValue)
|
||||
assert.Equal(t, result, tc.isValid)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,12 +29,13 @@ import (
|
|||
func TestPodSpecFlags(t *testing.T) {
|
||||
args := []string{"--image", "repo/user/imageID:tag", "--env", "b=c"}
|
||||
wantedPod := &PodSpecFlags{
|
||||
Image: "repo/user/imageID:tag",
|
||||
Env: []string{"b=c"},
|
||||
EnvFrom: []string{},
|
||||
Mount: []string{},
|
||||
Volume: []string{},
|
||||
Arg: []string{},
|
||||
Image: "repo/user/imageID:tag",
|
||||
Env: []string{"b=c"},
|
||||
EnvFrom: []string{},
|
||||
EnvValueFrom: []string{},
|
||||
Mount: []string{},
|
||||
Volume: []string{},
|
||||
Arg: []string{},
|
||||
}
|
||||
flags := &PodSpecFlags{}
|
||||
testCmd := &cobra.Command{
|
||||
|
@ -56,7 +57,7 @@ func TestUniqueStringArg(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPodSpecResolve(t *testing.T) {
|
||||
args := []string{"--image", "repo/user/imageID:tag", "--env", "b=c",
|
||||
inputArgs := []string{"--image", "repo/user/imageID:tag", "--env", "b=c",
|
||||
"--port", "8080", "--limit", "cpu=1000m", "--limit", "memory=1024Mi",
|
||||
"--cmd", "/app/start", "--arg", "myArg1", "--service-account", "foo-bar-account",
|
||||
"--mount", "/mount/path=volume-name", "--volume", "volume-name=cm:config-map-name",
|
||||
|
@ -114,12 +115,12 @@ func TestPodSpecResolve(t *testing.T) {
|
|||
Use: "test",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
podSpec := &corev1.PodSpec{Containers: []corev1.Container{{}}}
|
||||
err := flags.ResolvePodSpec(podSpec, cmd.Flags())
|
||||
err := flags.ResolvePodSpec(podSpec, cmd.Flags(), inputArgs)
|
||||
assert.NilError(t, err, "PodSpec cannot be resolved.")
|
||||
assert.DeepEqual(t, expectedPodSpec, *podSpec)
|
||||
},
|
||||
}
|
||||
testCmd.SetArgs(args)
|
||||
testCmd.SetArgs(inputArgs)
|
||||
flags.AddFlags(testCmd.Flags())
|
||||
testCmd.Execute()
|
||||
}
|
||||
|
@ -127,18 +128,18 @@ func TestPodSpecResolve(t *testing.T) {
|
|||
func TestPodSpecResolveReturnError(t *testing.T) {
|
||||
outBuf := bytes.Buffer{}
|
||||
flags := &PodSpecFlags{}
|
||||
inputArgs := []string{"--mount", "123456"}
|
||||
testCmd := &cobra.Command{
|
||||
Use: "test",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
podSpec := &corev1.PodSpec{Containers: []corev1.Container{{}}}
|
||||
err := flags.ResolvePodSpec(podSpec, cmd.Flags())
|
||||
err := flags.ResolvePodSpec(podSpec, cmd.Flags(), inputArgs)
|
||||
fmt.Fprint(cmd.OutOrStdout(), "Return error: ", err)
|
||||
},
|
||||
}
|
||||
testCmd.SetOut(&outBuf)
|
||||
|
||||
args := []string{"--mount", "123456"}
|
||||
testCmd.SetArgs(args)
|
||||
testCmd.SetArgs(inputArgs)
|
||||
flags.AddFlags(testCmd.Flags())
|
||||
testCmd.Execute()
|
||||
out := outBuf.String()
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"knative.dev/serving/pkg/apis/autoscaling"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"knative.dev/client/lib/test"
|
||||
"knative.dev/client/pkg/util"
|
||||
|
@ -43,11 +44,12 @@ func TestServiceOptions(t *testing.T) {
|
|||
assert.NilError(t, it.Teardown())
|
||||
}()
|
||||
|
||||
kubectl := test.NewKubectl(it.Namespace())
|
||||
r := test.NewKnRunResultCollector(t, it)
|
||||
|
||||
t.Log("create and validate service with concurrency options")
|
||||
defer r.DumpIfFailed()
|
||||
|
||||
t.Log("create and validate service with concurrency options")
|
||||
serviceCreateWithOptions(r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300", "--concurrency-utilization", "50")
|
||||
validateServiceConcurrencyTarget(r, "svc1", "300")
|
||||
validateServiceConcurrencyLimit(r, "svc1", "250")
|
||||
|
@ -178,6 +180,55 @@ func TestServiceOptions(t *testing.T) {
|
|||
serviceCreateWithOptions(r, "svc14", "--annotation-revision", "rev=helloworld-rev")
|
||||
validateServiceAndRevisionAnnotations(r, "svc14", nil, map[string]string{"rev": "helloworld-rev"})
|
||||
test.ServiceDelete(r, "svc14")
|
||||
|
||||
t.Log("create and validate service env vars")
|
||||
env := []corev1.EnvVar{
|
||||
{Name: "EXAMPLE", Value: "foo"},
|
||||
{Name: "EXAMPLE2", Value: "bar"},
|
||||
}
|
||||
serviceCreateWithOptions(r, "svc15", "--env", "EXAMPLE=foo", "--env", "EXAMPLE2=bar")
|
||||
validateServiceEnvVariables(r, "svc15", env)
|
||||
test.ServiceDelete(r, "svc15")
|
||||
|
||||
t.Log("create and validate service env-value-from vars")
|
||||
_, err = kubectl.Run("create", "-n", it.Namespace(), "configmap", "test-cm", "--from-literal=key=value")
|
||||
assert.NilError(t, err)
|
||||
env2 := []corev1.EnvVar{
|
||||
{Name: "EXAMPLE", ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "test-cm",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
}
|
||||
serviceCreateWithOptions(r, "svc16", "--env-value-from", "EXAMPLE=cm:test-cm:key")
|
||||
validateServiceEnvVariables(r, "svc16", env2)
|
||||
test.ServiceDelete(r, "svc16")
|
||||
_, err = kubectl.Run("delete", "-n", it.Namespace(), "configmap", "test-cm")
|
||||
assert.NilError(t, err)
|
||||
|
||||
t.Log("create and validate service env vars and env-value-from vars")
|
||||
_, err = kubectl.Run("create", "-n", it.Namespace(), "configmap", "test-cm2", "--from-literal=key=value")
|
||||
assert.NilError(t, err)
|
||||
env3 := []corev1.EnvVar{
|
||||
{Name: "EXAMPLE", Value: "foo"},
|
||||
{Name: "EXAMPLE2", ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "test-cm2",
|
||||
},
|
||||
Key: "key",
|
||||
},
|
||||
}},
|
||||
{Name: "EXAMPLE3", Value: "bar"},
|
||||
}
|
||||
serviceCreateWithOptions(r, "svc17", "--env", "EXAMPLE=foo", "--env-value-from", "EXAMPLE2=config-map:test-cm2:key", "--env", "EXAMPLE3=bar")
|
||||
validateServiceEnvVariables(r, "svc17", env3)
|
||||
test.ServiceDelete(r, "svc17")
|
||||
_, err = kubectl.Run("delete", "-n", it.Namespace(), "configmap", "test-cm2")
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func serviceCreateWithOptions(r *test.KnRunResultCollector, serviceName string, options ...string) {
|
||||
|
@ -315,3 +366,19 @@ func validatePort(r *test.KnRunResultCollector, serviceName string, portNumber i
|
|||
assert.Equal(r.T(), svc.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort, portNumber)
|
||||
assert.Equal(r.T(), svc.Spec.Template.Spec.Containers[0].Ports[0].Name, portName)
|
||||
}
|
||||
|
||||
func validateServiceEnvVariables(r *test.KnRunResultCollector, serviceName string, envVar []corev1.EnvVar) {
|
||||
svc := test.GetServiceFromKNServiceDescribe(r, serviceName)
|
||||
for i, env := range svc.Spec.Template.Spec.Containers[0].Env {
|
||||
assert.Equal(r.T(), env.Name, envVar[i].Name)
|
||||
if envVar[i].ValueFrom != nil {
|
||||
if envVar[i].ValueFrom.ConfigMapKeyRef != nil {
|
||||
assert.Equal(r.T(), env.ValueFrom.ConfigMapKeyRef.Key, envVar[i].ValueFrom.ConfigMapKeyRef.Key)
|
||||
} else if envVar[i].ValueFrom.SecretKeyRef != nil {
|
||||
assert.Equal(r.T(), env.ValueFrom.SecretKeyRef.Key, envVar[i].ValueFrom.SecretKeyRef.Key)
|
||||
}
|
||||
} else {
|
||||
assert.Equal(r.T(), env.Value, envVar[i].Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue