Add option to allow enviornment variables using file (#1433)

* 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 <boaz.shuster.github@gmail.com>
This commit is contained in:
Boaz Shuster 2021-09-21 21:41:38 +03:00 committed by GitHub
parent 5d4b4f3759
commit 539a5a97a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 153 additions and 15 deletions

View File

@ -16,6 +16,10 @@
|===
| | Description | PR
| 🎁
| Add `--env-file` option to function create/update command
| https://github.com/knative/client/pull/1423[#1419]
| ✨
| Remove `DeprecatedImageDigest` field
| https://github.com/knative/client/pull/1454[#1454]

View File

@ -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 -.

View File

@ -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 -.

View File

@ -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 -.

View File

@ -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 -.

View File

@ -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 -.

View File

@ -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 -.

View File

@ -32,6 +32,7 @@ type PodSpecFlags struct {
Env []string
EnvFrom []string
EnvValueFrom []string
EnvFile string
Mount []string
Volume []string
@ -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. "+
@ -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)
@ -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
}

View File

@ -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) {
@ -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()
}
}
}
@ -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)

View File

@ -51,7 +51,7 @@ func TestUpdateEnvVarsNew(t *testing.T) {
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
assert.NilError(t, err)
args := append([]string{"command"}, argsEnv...)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{}, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, spec.Containers[0].Env)
}
@ -71,7 +71,7 @@ func TestUpdateEnvVarsMixedEnvOrder(t *testing.T) {
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
assert.NilError(t, err)
args := append([]string{"command"}, argsEnv...)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{}, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, spec.Containers[0].Env)
}
@ -121,7 +121,7 @@ func TestUpdateEnvVarsValueFromNew(t *testing.T) {
args := append([]string{"command"}, argsEnvValueFrom...)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, spec.Containers[0].Env)
}
@ -162,7 +162,7 @@ func TestUpdateEnvVarsAllNew(t *testing.T) {
assert.NilError(t, err)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, spec.Containers[0].Env)
}
@ -197,7 +197,7 @@ func TestUpdateEnvVarsValueFromValidate(t *testing.T) {
args := append([]string{"command"}, input...)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(input, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
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)
@ -482,7 +482,7 @@ func TestUpdateEnvVarsModify(t *testing.T) {
args := append([]string{"command"}, argsEnv...)
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnv, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{}, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, container.Env)
}
@ -516,7 +516,7 @@ func TestUpdateEnvVarsValueFromModify(t *testing.T) {
args := append([]string{"command"}, argsEnvValueFrom...)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, container.Env)
}
@ -557,7 +557,7 @@ func TestUpdateEnvVarsAllModify(t *testing.T) {
assert.NilError(t, err)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
assert.DeepEqual(t, expected, container.Env)
}
@ -572,7 +572,7 @@ func TestUpdateEnvVarsRemove(t *testing.T) {
args := append([]string{"command"}, remove...)
envToUpdate, envToRemove, err := util.OrderedMapAndRemovalListFromArray(remove, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{})
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, util.NewOrderedMap(), []string{}, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
expected := []corev1.EnvVar{
@ -606,7 +606,7 @@ func TestUpdateEnvVarsValueFromRemove(t *testing.T) {
args := append([]string{"command"}, remove...)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(remove, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, util.NewOrderedMap(), []string{}, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
expected := []corev1.EnvVar{
@ -659,7 +659,7 @@ func TestUpdateEnvVarsAllRemove(t *testing.T) {
assert.NilError(t, err)
envValueFromToUpdate, envValueFromToRemove, err := util.OrderedMapAndRemovalListFromArray(argsEnvValueFrom, "=")
assert.NilError(t, err)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove)
err = UpdateEnvVars(spec, args, envToUpdate, envToRemove, envValueFromToUpdate, envValueFromToRemove, "", util.NewOrderedMap(), []string{})
assert.NilError(t, err)
expected := []corev1.EnvVar{

View File

@ -28,6 +28,7 @@ import (
"github.com/spf13/cobra"
"gotest.tools/v3/assert"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"knative.dev/client/pkg/util"
"knative.dev/pkg/ptr"
)
@ -285,3 +286,45 @@ func TestPodSpecResolveReturnError(t *testing.T) {
out := outBuf.String()
assert.Assert(t, util.ContainsAll(out, "Invalid", "mount"))
}
func TestPodSpecResolveWithEnvFile(t *testing.T) {
file, err := ioutil.TempFile("", "envfile.env")
assert.NilError(t, err)
file.WriteString("svcOwner=James\nsvcAuthor=James")
defer os.Remove(file.Name())
inputArgs := []string{"--image", "repo/user/imageID:tag", "--env", "svcOwner=David",
"--env-file", file.Name(), "--port", "8080", "--cmd", "/app/start", "--arg", "myArg1"}
expectedPodSpec := corev1.PodSpec{
Containers: []corev1.Container{
{
Image: "repo/user/imageID:tag",
Command: []string{"/app/start"},
Args: []string{"myArg1"},
Ports: []corev1.ContainerPort{
{
ContainerPort: 8080,
},
},
Env: []corev1.EnvVar{{Name: "svcOwner", Value: "James"}, {Name: "svcAuthor", Value: "James"}},
Resources: v1.ResourceRequirements{
Limits: v1.ResourceList{},
Requests: v1.ResourceList{},
},
},
},
}
flags := &PodSpecFlags{}
testCmd := &cobra.Command{
Use: "test",
Run: func(cmd *cobra.Command, args []string) {
podSpec := &corev1.PodSpec{Containers: []corev1.Container{{}}}
err := flags.ResolvePodSpec(podSpec, cmd.Flags(), inputArgs)
assert.NilError(t, err, "PodSpec cannot be resolved.")
assert.DeepEqual(t, expectedPodSpec, *podSpec)
},
}
testCmd.SetArgs(inputArgs)
flags.AddFlags(testCmd.Flags())
testCmd.Execute()
}

View File

@ -15,7 +15,9 @@
package util
import (
"bufio"
"fmt"
"os"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -23,6 +25,25 @@ import (
"knative.dev/pkg/tracker"
)
// GetEnvsFromFile transform a path to a file containing environment variable into a list of key-value pair.
// If there is an issue reading the file or parsing the content in the file an error value will be returned.
func GetEnvsFromFile(filepath string, delimiter string) ([]string, error) {
envs := []string{}
file, err := os.Open(filepath)
if err != nil {
return envs, err
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if len(line) == 0 {
continue
}
envs = append(envs, scanner.Text())
}
return envs, nil
}
// OrderedMapAndRemovalListFromArray creates a list of key-value pair using MapFromArrayAllowingSingles, and a list of removal entries
func OrderedMapAndRemovalListFromArray(arr []string, delimiter string) (*OrderedMap, []string, error) {
orderedMap := NewOrderedMap()

View File

@ -16,6 +16,8 @@ package util
import (
"fmt"
"io/ioutil"
"os"
"testing"
"gotest.tools/v3/assert"
@ -186,3 +188,25 @@ func testToTrackerReference(t *testing.T, input, namespace string, expected *tra
func funcRef(ref func(t *testing.T, err error)) *func(*testing.T, error) {
return &ref
}
func TestGetEnvsFromFile(t *testing.T) {
file, err := ioutil.TempFile("", "test-1")
assert.NilError(t, err)
file.WriteString(`
name=service-1
target=hello-world
`)
defer os.Remove(file.Name())
envs, err := GetEnvsFromFile(file.Name(), "=")
assert.NilError(t, err)
assert.DeepEqual(t, envs, []string{"name=service-1", "target=hello-world"})
}
func TestGetEnvsFromFileErrorNotFound(t *testing.T) {
envs, err := GetEnvsFromFile("/tmp/somerandom/path/bla/bla", "=")
assert.ErrorContains(t, err, "no such file or directory")
assert.DeepEqual(t, envs, []string{})
}