cleanup some dead kubectl code and narrow scope of helpers
This commit is contained in:
@@ -58,10 +58,7 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"factory_test.go",
|
||||
"helpers_test.go",
|
||||
],
|
||||
srcs = ["helpers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
@@ -90,8 +87,6 @@ filegroup(
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/kubectl/cmd/util/editor:all-srcs",
|
||||
"//pkg/kubectl/cmd/util/env:all-srcs",
|
||||
"//pkg/kubectl/cmd/util/jsonmerge:all-srcs",
|
||||
"//pkg/kubectl/cmd/util/openapi:all-srcs",
|
||||
"//pkg/kubectl/cmd/util/sanity:all-srcs",
|
||||
],
|
||||
|
@@ -18,11 +18,11 @@ go_library(
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/kubectl:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/kubectl/cmd/util/editor/crlf:go_default_library",
|
||||
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||
"//pkg/kubectl/genericclioptions/printers:go_default_library",
|
||||
"//pkg/kubectl/genericclioptions/resource:go_default_library",
|
||||
"//pkg/kubectl/scheme:go_default_library",
|
||||
"//pkg/kubectl/util/crlf:go_default_library",
|
||||
"//pkg/kubectl/util/term:go_default_library",
|
||||
"//vendor/github.com/evanphx/json-patch:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
@@ -57,7 +57,10 @@ filegroup(
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/kubectl/cmd/util/editor/crlf:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = [
|
||||
"//build/visible_to:pkg_kubectl_cmd_util_editor_CONSUMERS",
|
||||
|
25
pkg/kubectl/cmd/util/editor/crlf/BUILD
Normal file
25
pkg/kubectl/cmd/util/editor/crlf/BUILD
Normal file
@@ -0,0 +1,25 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["crlf.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
57
pkg/kubectl/cmd/util/editor/crlf/crlf.go
Normal file
57
pkg/kubectl/cmd/util/editor/crlf/crlf.go
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright 2015 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 crlf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
type crlfWriter struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
// NewCRLFWriter implements a CR/LF line ending writer used for normalizing
|
||||
// text for Windows platforms.
|
||||
func NewCRLFWriter(w io.Writer) io.Writer {
|
||||
return crlfWriter{w}
|
||||
}
|
||||
|
||||
func (w crlfWriter) Write(b []byte) (n int, err error) {
|
||||
for i, written := 0, 0; ; {
|
||||
next := bytes.Index(b[i:], []byte("\n"))
|
||||
if next == -1 {
|
||||
n, err := w.Writer.Write(b[i:])
|
||||
return written + n, err
|
||||
}
|
||||
next = next + i
|
||||
n, err := w.Writer.Write(b[i:next])
|
||||
if err != nil {
|
||||
return written + n, err
|
||||
}
|
||||
written += n
|
||||
n, err = w.Writer.Write([]byte("\r\n"))
|
||||
if err != nil {
|
||||
if n > 1 {
|
||||
n = 1
|
||||
}
|
||||
return written + n, err
|
||||
}
|
||||
written++
|
||||
i = next + 1
|
||||
}
|
||||
}
|
@@ -45,11 +45,11 @@ import (
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/crlf"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/crlf"
|
||||
)
|
||||
|
||||
// EditOptions contains all the options for running edit cli command.
|
||||
|
41
pkg/kubectl/cmd/util/env/BUILD
vendored
41
pkg/kubectl/cmd/util/env/BUILD
vendored
@@ -1,41 +0,0 @@
|
||||
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",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/env",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/api/v1/resource:go_default_library",
|
||||
"//pkg/fieldpath:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1: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",
|
||||
"//vendor/k8s.io/client-go/kubernetes: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"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["env_parse_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
18
pkg/kubectl/cmd/util/env/doc.go
vendored
18
pkg/kubectl/cmd/util/env/doc.go
vendored
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
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"
|
156
pkg/kubectl/cmd/util/env/env_parse.go
vendored
156
pkg/kubectl/cmd/util/env/env_parse.go
vendored
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
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/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
return defaultValue
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return "", false
|
||||
}
|
||||
return val, true
|
||||
}
|
||||
|
||||
var argumentEnvironment = regexp.MustCompile("(?ms)^(.+)\\=(.*)$")
|
||||
var validArgumentEnvironment = regexp.MustCompile("(?ms)^(\\w+)\\=(.*)$")
|
||||
|
||||
// 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 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 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 {
|
||||
// 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) ([]v1.EnvVar, []string, error) {
|
||||
env := []v1.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, v1.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 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) ([]v1.EnvVar, []string, error) {
|
||||
return parseIntoEnvVar(spec, defaultReader, "environment variable")
|
||||
}
|
||||
|
||||
func readEnv(r io.Reader, envVarType string) ([]v1.EnvVar, error) {
|
||||
env := []v1.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, v1.EnvVar{
|
||||
Name: parts[0],
|
||||
Value: parts[1],
|
||||
})
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
return env, nil
|
||||
}
|
96
pkg/kubectl/cmd/util/env/env_parse_test.go
vendored
96
pkg/kubectl/cmd/util/env/env_parse_test.go
vendored
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
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 nil} {AND ANOTHER nil} {FROM READER nil}] [REMOVE] <nil>
|
||||
}
|
||||
|
||||
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
|
||||
}
|
133
pkg/kubectl/cmd/util/env/env_resolve.go
vendored
133
pkg/kubectl/cmd/util/env/env_resolve.go
vendored
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubernetes/pkg/api/v1/resource"
|
||||
"k8s.io/kubernetes/pkg/fieldpath"
|
||||
)
|
||||
|
||||
// ResourceStore defines a new resource store data structure.
|
||||
type ResourceStore struct {
|
||||
SecretStore map[string]*v1.Secret
|
||||
ConfigMapStore map[string]*v1.ConfigMap
|
||||
}
|
||||
|
||||
// NewResourceStore returns a pointer to a new resource store data structure.
|
||||
func NewResourceStore() *ResourceStore {
|
||||
return &ResourceStore{
|
||||
SecretStore: make(map[string]*v1.Secret),
|
||||
ConfigMapStore: make(map[string]*v1.ConfigMap),
|
||||
}
|
||||
}
|
||||
|
||||
// getSecretRefValue returns the value of a secret in the supplied namespace
|
||||
func getSecretRefValue(client kubernetes.Interface, namespace string, store *ResourceStore, secretSelector *v1.SecretKeySelector) (string, error) {
|
||||
secret, ok := store.SecretStore[secretSelector.Name]
|
||||
if !ok {
|
||||
var err error
|
||||
secret, err = client.CoreV1().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 kubernetes.Interface, namespace string, store *ResourceStore, configMapSelector *v1.ConfigMapKeySelector) (string, error) {
|
||||
configMap, ok := store.ConfigMapStore[configMapSelector.Name]
|
||||
if !ok {
|
||||
var err error
|
||||
configMap, err = client.CoreV1().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 *v1.EnvVarSource) (string, error) {
|
||||
return fieldpath.ExtractFieldPathAsString(obj, from.FieldRef.FieldPath)
|
||||
}
|
||||
|
||||
// getResourceFieldRef returns the value of a resource in the given container
|
||||
func getResourceFieldRef(from *v1.EnvVarSource, c *v1.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 kubernetes.Interface, ns string, store *ResourceStore, from *v1.EnvVarSource, obj runtime.Object, c *v1.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 whichever field is set within the supplied EnvVarSource argument.
|
||||
func GetEnvVarRefString(from *v1.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"
|
||||
}
|
@@ -17,15 +17,10 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
@@ -73,26 +68,3 @@ type Factory interface {
|
||||
// OpenAPISchema returns the schema openapi schema definition
|
||||
OpenAPISchema() (openapi.Resources, error)
|
||||
}
|
||||
|
||||
func makePortsString(ports []api.ServicePort, useNodePort bool) string {
|
||||
pieces := make([]string, len(ports))
|
||||
for ix := range ports {
|
||||
var port int32
|
||||
if useNodePort {
|
||||
port = ports[ix].NodePort
|
||||
} else {
|
||||
port = ports[ix].Port
|
||||
}
|
||||
pieces[ix] = fmt.Sprintf("%s:%d", strings.ToLower(string(ports[ix].Protocol)), port)
|
||||
}
|
||||
return strings.Join(pieces, ",")
|
||||
}
|
||||
|
||||
// Extracts the protocols exposed by a service from the given service spec.
|
||||
func getServiceProtocols(spec api.ServiceSpec) map[string]string {
|
||||
result := make(map[string]string)
|
||||
for _, servicePort := range spec.Ports {
|
||||
result[strconv.Itoa(int(servicePort.Port))] = string(servicePort.Protocol)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@ import (
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
scaleclient "k8s.io/client-go/scale"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
@@ -189,24 +188,6 @@ func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) {
|
||||
return f.openAPIGetter.getter.Get()
|
||||
}
|
||||
|
||||
func (f *factoryImpl) ScaleClient() (scaleclient.ScalesGetter, error) {
|
||||
discoClient, err := f.clientGetter.ToDiscoveryClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
restClient, err := f.RESTClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient)
|
||||
mapper, err := f.clientGetter.ToRESTMapper()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil
|
||||
}
|
||||
|
||||
// this method exists to help us find the points still relying on internal types.
|
||||
func InternalVersionDecoder() runtime.Decoder {
|
||||
return legacyscheme.Codecs.UniversalDecoder()
|
||||
|
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
func TestMakePortsString(t *testing.T) {
|
||||
tests := []struct {
|
||||
ports []api.ServicePort
|
||||
useNodePort bool
|
||||
expectedOutput string
|
||||
}{
|
||||
{ports: nil, expectedOutput: ""},
|
||||
{ports: []api.ServicePort{}, expectedOutput: ""},
|
||||
{ports: []api.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
Protocol: "TCP",
|
||||
},
|
||||
},
|
||||
expectedOutput: "tcp:80",
|
||||
},
|
||||
{ports: []api.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
Protocol: "TCP",
|
||||
},
|
||||
{
|
||||
Port: 8080,
|
||||
Protocol: "UDP",
|
||||
},
|
||||
{
|
||||
Port: 9000,
|
||||
Protocol: "TCP",
|
||||
},
|
||||
},
|
||||
expectedOutput: "tcp:80,udp:8080,tcp:9000",
|
||||
},
|
||||
{ports: []api.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
NodePort: 9090,
|
||||
Protocol: "TCP",
|
||||
},
|
||||
{
|
||||
Port: 8080,
|
||||
NodePort: 80,
|
||||
Protocol: "UDP",
|
||||
},
|
||||
},
|
||||
useNodePort: true,
|
||||
expectedOutput: "tcp:9090,udp:80",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
output := makePortsString(test.ports, test.useNodePort)
|
||||
if output != test.expectedOutput {
|
||||
t.Errorf("expected: %s, saw: %s.", test.expectedOutput, output)
|
||||
}
|
||||
}
|
||||
}
|
@@ -62,7 +62,6 @@ const (
|
||||
ConfigMapV1GeneratorName = "configmap/v1"
|
||||
ClusterRoleBindingV1GeneratorName = "clusterrolebinding.rbac.authorization.k8s.io/v1alpha1"
|
||||
RoleBindingV1GeneratorName = "rolebinding.rbac.authorization.k8s.io/v1alpha1"
|
||||
ClusterV1Beta1GeneratorName = "cluster/v1beta1"
|
||||
PodDisruptionBudgetV1GeneratorName = "poddisruptionbudget/v1beta1"
|
||||
PodDisruptionBudgetV2GeneratorName = "poddisruptionbudget/v1beta1/v2"
|
||||
PriorityClassV1Alpha1GeneratorName = "priorityclass/v1alpha1"
|
||||
|
@@ -300,16 +300,6 @@ func IsFilenameSliceEmpty(filenames []string) bool {
|
||||
return len(filenames) == 0
|
||||
}
|
||||
|
||||
// Whether this cmd need watching objects.
|
||||
func isWatch(cmd *cobra.Command) bool {
|
||||
if w, err := cmd.Flags().GetBool("watch"); err == nil && w {
|
||||
return true
|
||||
}
|
||||
|
||||
wo, err := cmd.Flags().GetBool("watch-only")
|
||||
return err == nil && wo
|
||||
}
|
||||
|
||||
func GetFlagString(cmd *cobra.Command, flag string) string {
|
||||
s, err := cmd.Flags().GetString(flag)
|
||||
if err != nil {
|
||||
@@ -336,15 +326,6 @@ func GetFlagStringArray(cmd *cobra.Command, flag string) []string {
|
||||
return s
|
||||
}
|
||||
|
||||
// GetWideFlag is used to determine if "-o wide" is used
|
||||
func GetWideFlag(cmd *cobra.Command) bool {
|
||||
f := cmd.Flags().Lookup("output")
|
||||
if f != nil && f.Value != nil && f.Value.String() == "wide" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetFlagBool(cmd *cobra.Command, flag string) bool {
|
||||
b, err := cmd.Flags().GetBool(flag)
|
||||
if err != nil {
|
||||
|
@@ -1,32 +0,0 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["jsonmerge.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/evanphx/json-patch:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = [
|
||||
"//build/visible_to:pkg_kubectl_cmd_util_jsonmerge_CONSUMERS",
|
||||
],
|
||||
)
|
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 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 jsonmerge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/mergepatch"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
)
|
||||
|
||||
// Delta represents a change between two JSON documents.
|
||||
type Delta struct {
|
||||
original []byte
|
||||
edit []byte
|
||||
|
||||
preconditions []PreconditionFunc
|
||||
}
|
||||
|
||||
// PreconditionFunc is a test to verify that an incompatible change
|
||||
// has occurred before an Apply can be successful.
|
||||
type PreconditionFunc func(interface{}) (hold bool, message string)
|
||||
|
||||
// AddPreconditions adds precondition checks to a change which must
|
||||
// be satisfied before an Apply is considered successful. If a
|
||||
// precondition returns false, the Apply is failed with
|
||||
// ErrPreconditionFailed.
|
||||
func (d *Delta) AddPreconditions(fns ...PreconditionFunc) {
|
||||
d.preconditions = append(d.preconditions, fns...)
|
||||
}
|
||||
|
||||
// RequireKeyUnchanged creates a precondition function that fails
|
||||
// if the provided key is present in the diff (indicating its value
|
||||
// has changed).
|
||||
func RequireKeyUnchanged(key string) PreconditionFunc {
|
||||
return func(diff interface{}) (bool, string) {
|
||||
m, ok := diff.(map[string]interface{})
|
||||
if !ok {
|
||||
return true, ""
|
||||
}
|
||||
// the presence of key in a diff means that its value has been changed, therefore
|
||||
// we should fail the precondition.
|
||||
_, ok = m[key]
|
||||
if ok {
|
||||
return false, key + " should not be changed\n"
|
||||
} else {
|
||||
return true, ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RequireMetadataKeyUnchanged creates a precondition function that fails
|
||||
// if the metadata.key is present in the diff (indicating its value
|
||||
// has changed).
|
||||
func RequireMetadataKeyUnchanged(key string) PreconditionFunc {
|
||||
return func(diff interface{}) (bool, string) {
|
||||
m, ok := diff.(map[string]interface{})
|
||||
if !ok {
|
||||
return true, ""
|
||||
}
|
||||
m1, ok := m["metadata"]
|
||||
if !ok {
|
||||
return true, ""
|
||||
}
|
||||
m2, ok := m1.(map[string]interface{})
|
||||
if !ok {
|
||||
return true, ""
|
||||
}
|
||||
_, ok = m2[key]
|
||||
if ok {
|
||||
return false, "metadata." + key + " should not be changed\n"
|
||||
} else {
|
||||
return true, ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestPreconditions test if preconditions hold given the edit
|
||||
func TestPreconditionsHold(edit []byte, preconditions []PreconditionFunc) (bool, string) {
|
||||
diff := make(map[string]interface{})
|
||||
if err := json.Unmarshal(edit, &diff); err != nil {
|
||||
return false, err.Error()
|
||||
}
|
||||
for _, fn := range preconditions {
|
||||
if hold, msg := fn(diff); !hold {
|
||||
return false, msg
|
||||
}
|
||||
}
|
||||
return true, ""
|
||||
}
|
||||
|
||||
// NewDelta accepts two JSON or YAML documents and calculates the difference
|
||||
// between them. It returns a Delta object which can be used to resolve
|
||||
// conflicts against a third version with a common parent, or an error
|
||||
// if either document is in error.
|
||||
func NewDelta(from, to []byte) (*Delta, error) {
|
||||
d := &Delta{}
|
||||
before, err := yaml.ToJSON(from)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
after, err := yaml.ToJSON(to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diff, err := jsonpatch.CreateMergePatch(before, after)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(6).Infof("Patch created from:\n%s\n%s\n%s", string(before), string(after), string(diff))
|
||||
d.original = before
|
||||
d.edit = diff
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// Apply attempts to apply the changes described by Delta onto latest,
|
||||
// returning an error if the changes cannot be applied cleanly.
|
||||
// IsConflicting will be true if the changes overlap, otherwise a
|
||||
// generic error will be returned.
|
||||
func (d *Delta) Apply(latest []byte) ([]byte, error) {
|
||||
base, err := yaml.ToJSON(latest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
changes, err := jsonpatch.CreateMergePatch(d.original, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diff1 := make(map[string]interface{})
|
||||
if err := json.Unmarshal(d.edit, &diff1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diff2 := make(map[string]interface{})
|
||||
if err := json.Unmarshal(changes, &diff2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, fn := range d.preconditions {
|
||||
hold1, _ := fn(diff1)
|
||||
hold2, _ := fn(diff2)
|
||||
if !hold1 || !hold2 {
|
||||
return nil, ErrPreconditionFailed
|
||||
}
|
||||
}
|
||||
|
||||
glog.V(6).Infof("Testing for conflict between:\n%s\n%s", string(d.edit), string(changes))
|
||||
hasConflicts, err := mergepatch.HasConflicts(diff1, diff2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hasConflicts {
|
||||
return nil, ErrConflict
|
||||
}
|
||||
|
||||
return jsonpatch.MergePatch(base, d.edit)
|
||||
}
|
||||
|
||||
// IsConflicting returns true if the provided error indicates a
|
||||
// conflict exists between the original changes and the applied
|
||||
// changes.
|
||||
func IsConflicting(err error) bool {
|
||||
return err == ErrConflict
|
||||
}
|
||||
|
||||
// IsPreconditionFailed returns true if the provided error indicates
|
||||
// a Delta precondition did not succeed.
|
||||
func IsPreconditionFailed(err error) bool {
|
||||
return err == ErrPreconditionFailed
|
||||
}
|
||||
|
||||
var ErrPreconditionFailed = fmt.Errorf("a precondition failed")
|
||||
var ErrConflict = fmt.Errorf("changes are in conflict")
|
||||
|
||||
func (d *Delta) Edit() []byte {
|
||||
return d.edit
|
||||
}
|
Reference in New Issue
Block a user