mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-13 11:25:19 +00:00
Add kubectl set env command
This commit is contained in:
33
pkg/kubectl/cmd/util/env/BUILD
vendored
Normal file
33
pkg/kubectl/cmd/util/env/BUILD
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"env_parse.go",
|
||||
"env_resolve.go",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/fieldpath:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
154
pkg/kubectl/cmd/util/env/env_parse.go
vendored
Normal file
154
pkg/kubectl/cmd/util/env/env_parse.go
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
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 (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// Env returns an environment variable or a default value if not specified.
|
||||
func Env(key string, defaultValue string) string {
|
||||
val := os.Getenv(key)
|
||||
if len(val) == 0 {
|
||||
return defaultValue
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// GetEnv returns an environment value if specified
|
||||
func GetEnv(key string) (string, bool) {
|
||||
val := os.Getenv(key)
|
||||
if len(val) == 0 {
|
||||
return "", false
|
||||
}
|
||||
return val, true
|
||||
}
|
||||
|
||||
var argumentEnvironment = regexp.MustCompile("(?ms)^(.+)\\=(.*)$")
|
||||
var validArgumentEnvironment = regexp.MustCompile("(?ms)^(\\w+)\\=(.*)$")
|
||||
|
||||
// IsEnvironmentArgument check str is env args
|
||||
func IsEnvironmentArgument(s string) bool {
|
||||
return argumentEnvironment.MatchString(s)
|
||||
}
|
||||
|
||||
// IsValidEnvironmentArgument check str is valid env
|
||||
func IsValidEnvironmentArgument(s string) bool {
|
||||
return validArgumentEnvironment.MatchString(s)
|
||||
}
|
||||
|
||||
// SplitEnvironmentFromResources returns resources and envargs
|
||||
func SplitEnvironmentFromResources(args []string) (resources, envArgs []string, ok bool) {
|
||||
first := true
|
||||
for _, s := range args {
|
||||
// this method also has to understand env removal syntax, i.e. KEY-
|
||||
isEnv := IsEnvironmentArgument(s) || strings.HasSuffix(s, "-")
|
||||
switch {
|
||||
case first && isEnv:
|
||||
first = false
|
||||
fallthrough
|
||||
case !first && isEnv:
|
||||
envArgs = append(envArgs, s)
|
||||
case first && !isEnv:
|
||||
resources = append(resources, s)
|
||||
case !first && !isEnv:
|
||||
return nil, nil, false
|
||||
}
|
||||
}
|
||||
return resources, envArgs, true
|
||||
}
|
||||
|
||||
// parseIntoEnvVar parses the list of key-value pairs into kubernetes EnvVar.
|
||||
// envVarType is for making errors more specific to user intentions.
|
||||
func parseIntoEnvVar(spec []string, defaultReader io.Reader, envVarType string) ([]api.EnvVar, []string, error) {
|
||||
env := []api.EnvVar{}
|
||||
exists := sets.NewString()
|
||||
var remove []string
|
||||
for _, envSpec := range spec {
|
||||
switch {
|
||||
case !IsValidEnvironmentArgument(envSpec) && !strings.HasSuffix(envSpec, "-"):
|
||||
return nil, nil, fmt.Errorf("%ss must be of the form key=value and can only contain letters, numbers, and underscores", envVarType)
|
||||
case envSpec == "-":
|
||||
if defaultReader == nil {
|
||||
return nil, nil, fmt.Errorf("when '-' is used, STDIN must be open")
|
||||
}
|
||||
fileEnv, err := readEnv(defaultReader, envVarType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
env = append(env, fileEnv...)
|
||||
case strings.Index(envSpec, "=") != -1:
|
||||
parts := strings.SplitN(envSpec, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, nil, fmt.Errorf("invalid %s: %v", envVarType, envSpec)
|
||||
}
|
||||
exists.Insert(parts[0])
|
||||
env = append(env, api.EnvVar{
|
||||
Name: parts[0],
|
||||
Value: parts[1],
|
||||
})
|
||||
case strings.HasSuffix(envSpec, "-"):
|
||||
remove = append(remove, envSpec[:len(envSpec)-1])
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unknown %s: %v", envVarType, envSpec)
|
||||
}
|
||||
}
|
||||
for _, removeLabel := range remove {
|
||||
if _, found := exists[removeLabel]; found {
|
||||
return nil, nil, fmt.Errorf("can not both modify and remove the same %s in the same command", envVarType)
|
||||
}
|
||||
}
|
||||
return env, remove, nil
|
||||
}
|
||||
|
||||
// ParseEnv parse env from reader
|
||||
func ParseEnv(spec []string, defaultReader io.Reader) ([]api.EnvVar, []string, error) {
|
||||
return parseIntoEnvVar(spec, defaultReader, "environment variable")
|
||||
}
|
||||
|
||||
func readEnv(r io.Reader, envVarType string) ([]api.EnvVar, error) {
|
||||
env := []api.EnvVar{}
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
envSpec := scanner.Text()
|
||||
if pos := strings.Index(envSpec, "#"); pos != -1 {
|
||||
envSpec = envSpec[:pos]
|
||||
}
|
||||
if strings.Index(envSpec, "=") != -1 {
|
||||
parts := strings.SplitN(envSpec, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid %s: %v", envVarType, envSpec)
|
||||
}
|
||||
env = append(env, api.EnvVar{
|
||||
Name: parts[0],
|
||||
Value: parts[1],
|
||||
})
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
133
pkg/kubectl/cmd/util/env/env_resolve.go
vendored
Normal file
133
pkg/kubectl/cmd/util/env/env_resolve.go
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/fieldpath"
|
||||
)
|
||||
|
||||
// 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
|
||||
func NewResourceStore() *ResourceStore {
|
||||
return &ResourceStore{
|
||||
SecretStore: make(map[string]*api.Secret),
|
||||
ConfigMapStore: make(map[string]*api.ConfigMap),
|
||||
}
|
||||
}
|
||||
|
||||
// getSecretRefValue returns the value of a secret in the supplied namespace
|
||||
func getSecretRefValue(client clientset.Interface, namespace string, store *ResourceStore, secretSelector *api.SecretKeySelector) (string, error) {
|
||||
secret, ok := store.SecretStore[secretSelector.Name]
|
||||
if !ok {
|
||||
var err error
|
||||
secret, err = client.Core().Secrets(namespace).Get(secretSelector.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
store.SecretStore[secretSelector.Name] = secret
|
||||
}
|
||||
if data, ok := secret.Data[secretSelector.Key]; ok {
|
||||
return string(data), nil
|
||||
}
|
||||
return "", fmt.Errorf("key %s not found in secret %s", secretSelector.Key, secretSelector.Name)
|
||||
|
||||
}
|
||||
|
||||
// getConfigMapRefValue returns the value of a configmap in the supplied namespace
|
||||
func getConfigMapRefValue(client clientset.Interface, namespace string, store *ResourceStore, configMapSelector *api.ConfigMapKeySelector) (string, error) {
|
||||
configMap, ok := store.ConfigMapStore[configMapSelector.Name]
|
||||
if !ok {
|
||||
var err error
|
||||
configMap, err = client.Core().ConfigMaps(namespace).Get(configMapSelector.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
store.ConfigMapStore[configMapSelector.Name] = configMap
|
||||
}
|
||||
if data, ok := configMap.Data[configMapSelector.Key]; ok {
|
||||
return string(data), nil
|
||||
}
|
||||
return "", fmt.Errorf("key %s not found in config map %s", configMapSelector.Key, configMapSelector.Name)
|
||||
}
|
||||
|
||||
// getFieldRef returns the value of the supplied path in the given object
|
||||
func getFieldRef(obj runtime.Object, from *api.EnvVarSource) (string, error) {
|
||||
return fieldpath.ExtractFieldPathAsString(obj, from.FieldRef.FieldPath)
|
||||
}
|
||||
|
||||
// getResourceFieldRef returns the value of a resource in the given container
|
||||
func getResourceFieldRef(from *api.EnvVarSource, c *api.Container) (string, error) {
|
||||
return resource.ExtractContainerResourceValue(from.ResourceFieldRef, c)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
if from.ConfigMapKeyRef != nil {
|
||||
return getConfigMapRefValue(kc, ns, store, from.ConfigMapKeyRef)
|
||||
}
|
||||
|
||||
if from.FieldRef != nil {
|
||||
return getFieldRef(obj, from)
|
||||
}
|
||||
|
||||
if from.ResourceFieldRef != nil {
|
||||
return getResourceFieldRef(from, c)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("invalid valueFrom")
|
||||
}
|
||||
|
||||
// GetEnvVarRefString returns a text description of the supplied envvarsource
|
||||
func GetEnvVarRefString(from *api.EnvVarSource) string {
|
||||
if from.ConfigMapKeyRef != nil {
|
||||
return fmt.Sprintf("configmap %s, key %s", from.ConfigMapKeyRef.Name, from.ConfigMapKeyRef.Key)
|
||||
}
|
||||
|
||||
if from.SecretKeyRef != nil {
|
||||
return fmt.Sprintf("secret %s, key %s", from.SecretKeyRef.Name, from.SecretKeyRef.Key)
|
||||
}
|
||||
|
||||
if from.FieldRef != nil {
|
||||
return fmt.Sprintf("field path %s", from.FieldRef.FieldPath)
|
||||
}
|
||||
|
||||
if from.ResourceFieldRef != nil {
|
||||
containerPrefix := ""
|
||||
if from.ResourceFieldRef.ContainerName != "" {
|
||||
containerPrefix = fmt.Sprintf("%s/", from.ResourceFieldRef.ContainerName)
|
||||
}
|
||||
return fmt.Sprintf("resource field %s%s", containerPrefix, from.ResourceFieldRef.Resource)
|
||||
}
|
||||
|
||||
return "invalid valueFrom"
|
||||
}
|
||||
Reference in New Issue
Block a user