From 413eaecf32064acb65dea9e168213989a06ac9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ellen=20K=C3=B6rbes?= Date: Sun, 29 Oct 2017 20:23:20 -0200 Subject: [PATCH] Added comments & examples/tests to kubectl env package --- pkg/kubectl/cmd/util/env/BUILD | 10 ++- pkg/kubectl/cmd/util/env/doc.go | 18 ++++ pkg/kubectl/cmd/util/env/env_parse.go | 14 ++-- pkg/kubectl/cmd/util/env/env_parse_test.go | 96 ++++++++++++++++++++++ pkg/kubectl/cmd/util/env/env_resolve.go | 8 +- 5 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 pkg/kubectl/cmd/util/env/doc.go create mode 100644 pkg/kubectl/cmd/util/env/env_parse_test.go diff --git a/pkg/kubectl/cmd/util/env/BUILD b/pkg/kubectl/cmd/util/env/BUILD index ccd5b4b20bb..b076b74a55a 100644 --- a/pkg/kubectl/cmd/util/env/BUILD +++ b/pkg/kubectl/cmd/util/env/BUILD @@ -1,8 +1,9 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "doc.go", "env_parse.go", "env_resolve.go", ], @@ -32,3 +33,10 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["env_parse_test.go"], + importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/env", + library = ":go_default_library", +) diff --git a/pkg/kubectl/cmd/util/env/doc.go b/pkg/kubectl/cmd/util/env/doc.go new file mode 100644 index 00000000000..39adb0adf0c --- /dev/null +++ b/pkg/kubectl/cmd/util/env/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package env provides functions to incorporate environment variables into kubectl commands. +package env // import "k8s.io/kubernetes/pkg/kubectl/cmd/util/env" diff --git a/pkg/kubectl/cmd/util/env/env_parse.go b/pkg/kubectl/cmd/util/env/env_parse.go index d9c15123dc2..6b68aacbf6b 100644 --- a/pkg/kubectl/cmd/util/env/env_parse.go +++ b/pkg/kubectl/cmd/util/env/env_parse.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api" ) -// Env returns an environment variable or a default value if not specified. +// Env returns an environment variable if not nil, or a default value. func Env(key string, defaultValue string) string { val := os.Getenv(key) if len(val) == 0 { @@ -37,7 +37,7 @@ func Env(key string, defaultValue string) string { return val } -// GetEnv returns an environment value if specified +// GetEnv returns an environment value if not nil, and an ok boolean. func GetEnv(key string) (string, bool) { val := os.Getenv(key) if len(val) == 0 { @@ -49,17 +49,18 @@ func GetEnv(key string) (string, bool) { var argumentEnvironment = regexp.MustCompile("(?ms)^(.+)\\=(.*)$") var validArgumentEnvironment = regexp.MustCompile("(?ms)^(\\w+)\\=(.*)$") -// IsEnvironmentArgument check str is env args +// IsEnvironmentArgument checks whether a string is an environment argument, that is, whether it matches the "anycharacters=anycharacters" pattern. func IsEnvironmentArgument(s string) bool { return argumentEnvironment.MatchString(s) } -// IsValidEnvironmentArgument check str is valid env +// IsValidEnvironmentArgument checks whether a string is a valid environment argument, that is, whether it matches the "wordcharacters=anycharacters" pattern. Word characters can be letters, numbers, and underscores. func IsValidEnvironmentArgument(s string) bool { return validArgumentEnvironment.MatchString(s) } -// SplitEnvironmentFromResources returns resources and envargs +// SplitEnvironmentFromResources separates resources from environment arguments. +// Resources must come first. Arguments may have the "DASH-" syntax. func SplitEnvironmentFromResources(args []string) (resources, envArgs []string, ok bool) { first := true for _, s := range args { @@ -123,7 +124,8 @@ func parseIntoEnvVar(spec []string, defaultReader io.Reader, envVarType string) return env, remove, nil } -// ParseEnv parse env from reader +// ParseEnv parses the elements of the first argument looking for environment variables in key=value form and, if one of those values is "-", it also scans the reader. +// The same environment variable cannot be both modified and removed in the same command. func ParseEnv(spec []string, defaultReader io.Reader) ([]api.EnvVar, []string, error) { return parseIntoEnvVar(spec, defaultReader, "environment variable") } diff --git a/pkg/kubectl/cmd/util/env/env_parse_test.go b/pkg/kubectl/cmd/util/env/env_parse_test.go new file mode 100644 index 00000000000..f5e780f4d41 --- /dev/null +++ b/pkg/kubectl/cmd/util/env/env_parse_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package env + +import ( + "fmt" + "io" + "os" + "strings" +) + +func ExampleEnv_defaultValue() { + fmt.Println(Env("TESTENVVAR", "default")) + // Output: default +} + +func ExampleEnv_variableExists() { + os.Setenv("TESTENVVAR", "test value") + defer os.Unsetenv("TESTENVVAR") + fmt.Println(Env("TESTENVVAR", "default")) + // Output: test value +} + +func ExampleGetEnv_variableExists() { + os.Setenv("THISVAREXISTS", "value") + defer os.Unsetenv("THISVAREXISTS") + fmt.Println(GetEnv("THISVAREXISTS")) + // Output: + // value true +} + +func ExampleGetEnv_variableDoesNotExist() { + fmt.Println(GetEnv("THISVARDOESNOTEXIST")) + // Output: + // false +} + +func ExampleIsEnvironmentArgument_true() { + test := "returns=true" + fmt.Println(IsEnvironmentArgument(test)) + // Output: true +} + +func ExampleIsEnvironmentArgument_false() { + test := "returnsfalse" + fmt.Println(IsEnvironmentArgument(test)) + // Output: false +} + +func ExampleIsValidEnvironmentArgument_true() { + test := "wordcharacters=true" + fmt.Println(IsValidEnvironmentArgument(test)) + // Output: true +} + +func ExampleIsValidEnvironmentArgument_false() { + test := "not$word^characters=test" + fmt.Println(IsValidEnvironmentArgument(test)) + // Output: false +} + +func ExampleSplitEnvironmentFromResources() { + args := []string{`resource`, "ENV\\=ARG", `ONE\=MORE`, `DASH-`} + fmt.Println(SplitEnvironmentFromResources(args)) + // Output: [resource] [ENV\=ARG ONE\=MORE DASH-] true +} + +func ExampleParseEnv_good() { + r := strings.NewReader("FROM=READER") + ss := []string{"ENV=VARIABLE", "AND=ANOTHER", "REMOVE-", "-"} + fmt.Println(ParseEnv(ss, r)) + // Output: + // [{ENV VARIABLE } {AND ANOTHER } {FROM READER }] [REMOVE] +} + +func ExampleParseEnv_bad() { + var r io.Reader + bad := []string{"This not in the key=value format."} + fmt.Println(ParseEnv(bad, r)) + // Output: + // [] [] environment variables must be of the form key=value and can only contain letters, numbers, and underscores +} diff --git a/pkg/kubectl/cmd/util/env/env_resolve.go b/pkg/kubectl/cmd/util/env/env_resolve.go index 8955fb21999..df79c4cf4f3 100644 --- a/pkg/kubectl/cmd/util/env/env_resolve.go +++ b/pkg/kubectl/cmd/util/env/env_resolve.go @@ -27,13 +27,13 @@ import ( "k8s.io/kubernetes/pkg/fieldpath" ) -// ResourceStore defines a new resource store data structure +// ResourceStore defines a new resource store data structure. type ResourceStore struct { SecretStore map[string]*api.Secret ConfigMapStore map[string]*api.ConfigMap } -// NewResourceStore returns a pointer to a new resource store data structure +// NewResourceStore returns a pointer to a new resource store data structure. func NewResourceStore() *ResourceStore { return &ResourceStore{ SecretStore: make(map[string]*api.Secret), @@ -86,7 +86,7 @@ func getResourceFieldRef(from *api.EnvVarSource, c *api.Container) (string, erro return resource.ExtractContainerResourceValue(from.ResourceFieldRef, c) } -// GetEnvVarRefValue returns the value referenced by the supplied envvarsource given the other supplied information +// GetEnvVarRefValue returns the value referenced by the supplied EnvVarSource given the other supplied information. func GetEnvVarRefValue(kc clientset.Interface, ns string, store *ResourceStore, from *api.EnvVarSource, obj runtime.Object, c *api.Container) (string, error) { if from.SecretKeyRef != nil { return getSecretRefValue(kc, ns, store, from.SecretKeyRef) @@ -107,7 +107,7 @@ func GetEnvVarRefValue(kc clientset.Interface, ns string, store *ResourceStore, return "", fmt.Errorf("invalid valueFrom") } -// GetEnvVarRefString returns a text description of the supplied envvarsource +// GetEnvVarRefString returns a text description of whichever field is set within the supplied EnvVarSource argument. func GetEnvVarRefString(from *api.EnvVarSource) string { if from.ConfigMapKeyRef != nil { return fmt.Sprintf("configmap %s, key %s", from.ConfigMapKeyRef.Name, from.ConfigMapKeyRef.Key)