mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
vendor files
This commit is contained in:
54
vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"umask.go",
|
||||
"util.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
||||
"umask_windows.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util",
|
||||
visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"],
|
||||
deps = [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/kubectl/util/crlf:all-srcs",
|
||||
"//pkg/kubectl/util/hash:all-srcs",
|
||||
"//pkg/kubectl/util/i18n:all-srcs",
|
||||
"//pkg/kubectl/util/logs:all-srcs",
|
||||
"//pkg/kubectl/util/slice:all-srcs",
|
||||
"//pkg/kubectl/util/term:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util",
|
||||
library = ":go_default_library",
|
||||
)
|
25
vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/BUILD
generated
vendored
Normal file
25
vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/BUILD
generated
vendored
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/util/crlf",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
57
vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/crlf.go
generated
vendored
Normal file
57
vendor/k8s.io/kubernetes/pkg/kubectl/util/crlf/crlf.go
generated
vendored
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 += 1
|
||||
i = next + 1
|
||||
}
|
||||
}
|
35
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/BUILD
generated
vendored
Normal file
35
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/BUILD
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["hash_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/hash",
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["hash.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/hash",
|
||||
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
110
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash.go
generated
vendored
Normal file
110
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
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 hash
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// ConfigMapHash returns a hash of the ConfigMap.
|
||||
// The Data, Kind, and Name are taken into account.
|
||||
func ConfigMapHash(cm *v1.ConfigMap) (string, error) {
|
||||
encoded, err := encodeConfigMap(cm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
h, err := encodeHash(hash(encoded))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// SecretHash returns a hash of the Secret.
|
||||
// The Data, Kind, Name, and Type are taken into account.
|
||||
func SecretHash(sec *v1.Secret) (string, error) {
|
||||
encoded, err := encodeSecret(sec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
h, err := encodeHash(hash(encoded))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// encodeConfigMap encodes a ConfigMap.
|
||||
// Data, Kind, and Name are taken into account.
|
||||
func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
|
||||
// json.Marshal sorts the keys in a stable order in the encoding
|
||||
data, err := json.Marshal(map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
// encodeSecret encodes a Secret.
|
||||
// Data, Kind, Name, and Type are taken into account.
|
||||
func encodeSecret(sec *v1.Secret) (string, error) {
|
||||
// json.Marshal sorts the keys in a stable order in the encoding
|
||||
data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
// encodeHash extracts the first 40 bits of the hash from the hex string
|
||||
// (1 hex char represents 4 bits), and then maps vowels and vowel-like hex
|
||||
// characters to consonants to prevent bad words from being formed (the theory
|
||||
// is that no vowels makes it really hard to make bad words). Since the string
|
||||
// is hex, the only vowels it can contain are 'a' and 'e'.
|
||||
// We picked some arbitrary consonants to map to from the same character set as GenerateName.
|
||||
// See: https://github.com/kubernetes/apimachinery/blob/dc1f89aff9a7509782bde3b68824c8043a3e58cc/pkg/util/rand/rand.go#L75
|
||||
// If the hex string contains fewer than ten characters, returns an error.
|
||||
func encodeHash(hex string) (string, error) {
|
||||
if len(hex) < 10 {
|
||||
return "", fmt.Errorf("the hex string must contain at least 10 characters")
|
||||
}
|
||||
enc := []rune(hex[:10])
|
||||
for i := range enc {
|
||||
switch enc[i] {
|
||||
case '0':
|
||||
enc[i] = 'g'
|
||||
case '1':
|
||||
enc[i] = 'h'
|
||||
case '3':
|
||||
enc[i] = 'k'
|
||||
case 'a':
|
||||
enc[i] = 'm'
|
||||
case 'e':
|
||||
enc[i] = 't'
|
||||
}
|
||||
}
|
||||
return string(enc), nil
|
||||
}
|
||||
|
||||
// hash hashes `data` with sha256 and returns the hex string
|
||||
func hash(data string) string {
|
||||
return fmt.Sprintf("%x", sha256.Sum256([]byte(data)))
|
||||
}
|
178
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash_test.go
generated
vendored
Normal file
178
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/hash_test.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
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 hash
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func TestConfigMapHash(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
cm *v1.ConfigMap
|
||||
hash string
|
||||
err string
|
||||
}{
|
||||
// empty map
|
||||
{"empty data", &v1.ConfigMap{Data: map[string]string{}}, "42745tchd9", ""},
|
||||
// one key
|
||||
{"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, "9g67k2htb6", ""},
|
||||
// three keys (tests sorting order)
|
||||
{"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, "f5h7t85m9b", ""},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
h, err := ConfigMapHash(c.cm)
|
||||
if SkipRest(t, c.desc, err, c.err) {
|
||||
continue
|
||||
}
|
||||
if c.hash != h {
|
||||
t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretHash(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
secret *v1.Secret
|
||||
hash string
|
||||
err string
|
||||
}{
|
||||
// empty map
|
||||
{"empty data", &v1.Secret{Type: "my-type", Data: map[string][]byte{}}, "t75bgf6ctb", ""},
|
||||
// one key
|
||||
{"one key", &v1.Secret{Type: "my-type", Data: map[string][]byte{"one": []byte("")}}, "74bd68bm66", ""},
|
||||
// three keys (tests sorting order)
|
||||
{"three keys", &v1.Secret{Type: "my-type", Data: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "dgcb6h9tmk", ""},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
h, err := SecretHash(c.secret)
|
||||
if SkipRest(t, c.desc, err, c.err) {
|
||||
continue
|
||||
}
|
||||
if c.hash != h {
|
||||
t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeConfigMap(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
cm *v1.ConfigMap
|
||||
expect string
|
||||
err string
|
||||
}{
|
||||
// empty map
|
||||
{"empty data", &v1.ConfigMap{Data: map[string]string{}}, `{"data":{},"kind":"ConfigMap","name":""}`, ""},
|
||||
// one key
|
||||
{"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
|
||||
// three keys (tests sorting order)
|
||||
{"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, `{"data":{"one":"","three":"3","two":"2"},"kind":"ConfigMap","name":""}`, ""},
|
||||
}
|
||||
for _, c := range cases {
|
||||
s, err := encodeConfigMap(c.cm)
|
||||
if SkipRest(t, c.desc, err, c.err) {
|
||||
continue
|
||||
}
|
||||
if s != c.expect {
|
||||
t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.cm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeSecret(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
secret *v1.Secret
|
||||
expect string
|
||||
err string
|
||||
}{
|
||||
// empty map
|
||||
{"empty data", &v1.Secret{Type: "my-type", Data: map[string][]byte{}}, `{"data":{},"kind":"Secret","name":"","type":"my-type"}`, ""},
|
||||
// one key
|
||||
{"one key", &v1.Secret{Type: "my-type", Data: map[string][]byte{"one": []byte("")}}, `{"data":{"one":""},"kind":"Secret","name":"","type":"my-type"}`, ""},
|
||||
// three keys (tests sorting order) - note json.Marshal base64 encodes the values because they come in as []byte
|
||||
{"three keys", &v1.Secret{Type: "my-type", Data: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, `{"data":{"one":"","three":"Mw==","two":"Mg=="},"kind":"Secret","name":"","type":"my-type"}`, ""},
|
||||
}
|
||||
for _, c := range cases {
|
||||
s, err := encodeSecret(c.secret)
|
||||
if SkipRest(t, c.desc, err, c.err) {
|
||||
continue
|
||||
}
|
||||
if s != c.expect {
|
||||
t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.secret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
// hash the empty string to be sure that sha256 is being used
|
||||
expect := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
sum := hash("")
|
||||
if expect != sum {
|
||||
t.Errorf("expected hash %q but got %q", expect, sum)
|
||||
}
|
||||
}
|
||||
|
||||
// warn devs who change types that they might have to update a hash function
|
||||
// not perfect, as it only checks the number of top-level fields
|
||||
func TestTypeStability(t *testing.T) {
|
||||
errfmt := `case %q, expected %d fields but got %d
|
||||
Depending on the field(s) you added, you may need to modify the hash function for this type.
|
||||
To guide you: the hash function targets fields that comprise the contents of objects,
|
||||
not their metadata (e.g. the Data of a ConfigMap, but nothing in ObjectMeta).
|
||||
`
|
||||
cases := []struct {
|
||||
typeName string
|
||||
obj interface{}
|
||||
expect int
|
||||
}{
|
||||
{"ConfigMap", v1.ConfigMap{}, 3},
|
||||
{"Secret", v1.Secret{}, 5},
|
||||
}
|
||||
for _, c := range cases {
|
||||
val := reflect.ValueOf(c.obj)
|
||||
if num := val.NumField(); c.expect != num {
|
||||
t.Errorf(errfmt, c.typeName, c.expect, num)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SkipRest returns true if there was a non-nil error or if we expected an error that didn't happen,
|
||||
// and logs the appropriate error on the test object.
|
||||
// The return value indicates whether we should skip the rest of the test case due to the error result.
|
||||
func SkipRest(t *testing.T, desc string, err error, contains string) bool {
|
||||
if err != nil {
|
||||
if len(contains) == 0 {
|
||||
t.Errorf("case %q, expect nil error but got %q", desc, err.Error())
|
||||
} else if !strings.Contains(err.Error(), contains) {
|
||||
t.Errorf("case %q, expect error to contain %q but got %q", desc, contains, err.Error())
|
||||
}
|
||||
return true
|
||||
} else if len(contains) > 0 {
|
||||
t.Errorf("case %q, expect error to contain %q but got nil error", desc, contains)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
38
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/BUILD
generated
vendored
Normal file
38
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/BUILD
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["i18n.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/i18n",
|
||||
deps = [
|
||||
"//pkg/generated:go_default_library",
|
||||
"//vendor/github.com/chai2010/gettext-go/gettext:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["i18n_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/i18n",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
139
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go
generated
vendored
Normal file
139
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2016 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 i18n
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/generated"
|
||||
|
||||
"github.com/chai2010/gettext-go/gettext"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
var knownTranslations = map[string][]string{
|
||||
"kubectl": {
|
||||
"default",
|
||||
"en_US",
|
||||
"fr_FR",
|
||||
"zh_CN",
|
||||
"ja_JP",
|
||||
"zh_TW",
|
||||
"it_IT",
|
||||
"de_DE",
|
||||
},
|
||||
// only used for unit tests.
|
||||
"test": {
|
||||
"default",
|
||||
"en_US",
|
||||
},
|
||||
}
|
||||
|
||||
func loadSystemLanguage() string {
|
||||
langStr := os.Getenv("LANG")
|
||||
if langStr == "" {
|
||||
glog.V(3).Infof("Couldn't find the LANG environment variable, defaulting to en_US")
|
||||
return "default"
|
||||
}
|
||||
pieces := strings.Split(langStr, ".")
|
||||
if len(pieces) != 2 {
|
||||
glog.V(3).Infof("Unexpected system language (%s), defaulting to en_US", langStr)
|
||||
return "default"
|
||||
}
|
||||
return pieces[0]
|
||||
}
|
||||
|
||||
func findLanguage(root string, getLanguageFn func() string) string {
|
||||
langStr := getLanguageFn()
|
||||
|
||||
translations := knownTranslations[root]
|
||||
if translations != nil {
|
||||
for ix := range translations {
|
||||
if translations[ix] == langStr {
|
||||
return langStr
|
||||
}
|
||||
}
|
||||
}
|
||||
glog.V(3).Infof("Couldn't find translations for %s, using default", langStr)
|
||||
return "default"
|
||||
}
|
||||
|
||||
// LoadTranslations loads translation files. getLanguageFn should return a language
|
||||
// string (e.g. 'en-US'). If getLanguageFn is nil, then the loadSystemLanguage function
|
||||
// is used, which uses the 'LANG' environment variable.
|
||||
func LoadTranslations(root string, getLanguageFn func() string) error {
|
||||
if getLanguageFn == nil {
|
||||
getLanguageFn = loadSystemLanguage
|
||||
}
|
||||
|
||||
langStr := findLanguage(root, getLanguageFn)
|
||||
translationFiles := []string{
|
||||
fmt.Sprintf("%s/%s/LC_MESSAGES/k8s.po", root, langStr),
|
||||
fmt.Sprintf("%s/%s/LC_MESSAGES/k8s.mo", root, langStr),
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Setting language to %s", langStr)
|
||||
// TODO: list the directory and load all files.
|
||||
buf := new(bytes.Buffer)
|
||||
w := zip.NewWriter(buf)
|
||||
|
||||
// Make sure to check the error on Close.
|
||||
for _, file := range translationFiles {
|
||||
filename := "translations/" + file
|
||||
f, err := w.Create(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := generated.Asset(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.Write(data); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
gettext.BindTextdomain("k8s", root+".zip", buf.Bytes())
|
||||
gettext.Textdomain("k8s")
|
||||
gettext.SetLocale(langStr)
|
||||
return nil
|
||||
}
|
||||
|
||||
// T translates a string, possibly substituting arguments into it along
|
||||
// the way. If len(args) is > 0, args1 is assumed to be the plural value
|
||||
// and plural translation is used.
|
||||
func T(defaultValue string, args ...int) string {
|
||||
if len(args) == 0 {
|
||||
return gettext.PGettext("", defaultValue)
|
||||
}
|
||||
return fmt.Sprintf(gettext.PNGettext("", defaultValue, defaultValue+".plural", args[0]),
|
||||
args[0])
|
||||
}
|
||||
|
||||
// Errorf produces an error with a translated error string.
|
||||
// Substitution is performed via the `T` function above, following
|
||||
// the same rules.
|
||||
func Errorf(defaultValue string, args ...int) error {
|
||||
return errors.New(T(defaultValue, args...))
|
||||
}
|
64
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n_test.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n_test.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2016 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 i18n
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTranslation(t *testing.T) {
|
||||
err := LoadTranslations("test", func() string { return "default" })
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
result := T("test_string")
|
||||
if result != "foo" {
|
||||
t.Errorf("expected: %s, saw: %s", "foo", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranslationPlural(t *testing.T) {
|
||||
err := LoadTranslations("test", func() string { return "default" })
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
result := T("test_plural", 3)
|
||||
if result != "there were 3 items" {
|
||||
t.Errorf("expected: %s, saw: %s", "there were 3 items", result)
|
||||
}
|
||||
|
||||
result = T("test_plural", 1)
|
||||
if result != "there was 1 item" {
|
||||
t.Errorf("expected: %s, saw: %s", "there was 1 item", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranslationEnUSEnv(t *testing.T) {
|
||||
os.Setenv("LANG", "en_US.UTF-8")
|
||||
err := LoadTranslations("test", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
result := T("test_string")
|
||||
if result != "baz" {
|
||||
t.Errorf("expected: %s, saw: %s", "baz", result)
|
||||
}
|
||||
}
|
30
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/BUILD
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/BUILD
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["logs.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/logs",
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
61
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go
generated
vendored
Normal file
61
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
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 logs
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
var logFlushFreq = pflag.Duration("log-flush-frequency", 5*time.Second, "Maximum number of seconds between log flushes")
|
||||
|
||||
// TODO(thockin): This is temporary until we agree on log dirs and put those into each cmd.
|
||||
func init() {
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
// GlogWriter serves as a bridge between the standard log package and the glog package.
|
||||
type GlogWriter struct{}
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (writer GlogWriter) Write(data []byte) (n int, err error) {
|
||||
glog.Info(string(data))
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
// InitLogs initializes logs the way we want for kubernetes.
|
||||
func InitLogs() {
|
||||
log.SetOutput(GlogWriter{})
|
||||
log.SetFlags(0)
|
||||
// The default glog flush interval is 30 seconds, which is frighteningly long.
|
||||
go wait.Until(glog.Flush, *logFlushFreq, wait.NeverStop)
|
||||
}
|
||||
|
||||
// FlushLogs flushes logs immediately.
|
||||
func FlushLogs() {
|
||||
glog.Flush()
|
||||
}
|
||||
|
||||
// NewLogger creates a new log.Logger which sends logs to glog.Info.
|
||||
func NewLogger(prefix string) *log.Logger {
|
||||
return log.New(GlogWriter{}, prefix, 0)
|
||||
}
|
33
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/BUILD
generated
vendored
Normal file
33
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/BUILD
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["slice.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/slice",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["slice_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/slice",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
32
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/slice.go
generated
vendored
Normal file
32
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/slice.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
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 slice
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Int64Slice attaches the methods of Interface to []int64,
|
||||
// sorting in increasing order.
|
||||
type Int64Slice []int64
|
||||
|
||||
func (p Int64Slice) Len() int { return len(p) }
|
||||
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
|
||||
func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// Sorts []int64 in increasing order
|
||||
func SortInts64(a []int64) { sort.Sort(Int64Slice(a)) }
|
31
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/slice_test.go
generated
vendored
Normal file
31
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/slice_test.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
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 slice
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSortInts64(t *testing.T) {
|
||||
src := []int64{10, 1, 2, 3, 4, 5, 6}
|
||||
expected := []int64{1, 2, 3, 4, 5, 6, 10}
|
||||
SortInts64(src)
|
||||
if !reflect.DeepEqual(src, expected) {
|
||||
t.Errorf("func Ints64 didnt sort correctly, %v !- %v", src, expected)
|
||||
}
|
||||
}
|
51
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/BUILD
generated
vendored
Normal file
51
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/BUILD
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"resize.go",
|
||||
"resizeevents.go",
|
||||
"term.go",
|
||||
"term_writer.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
||||
"resizeevents_windows.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/term",
|
||||
deps = [
|
||||
"//pkg/util/interrupt:go_default_library",
|
||||
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
|
||||
"//vendor/github.com/mitchellh/go-wordwrap:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["term_writer_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/term",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
132
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/resize.go
generated
vendored
Normal file
132
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/resize.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright 2016 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 term
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
||||
// GetSize returns the current size of the user's terminal. If it isn't a terminal,
|
||||
// nil is returned.
|
||||
func (t TTY) GetSize() *remotecommand.TerminalSize {
|
||||
outFd, isTerminal := term.GetFdInfo(t.Out)
|
||||
if !isTerminal {
|
||||
return nil
|
||||
}
|
||||
return GetSize(outFd)
|
||||
}
|
||||
|
||||
// GetSize returns the current size of the terminal associated with fd.
|
||||
func GetSize(fd uintptr) *remotecommand.TerminalSize {
|
||||
winsize, err := term.GetWinsize(fd)
|
||||
if err != nil {
|
||||
runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err))
|
||||
return nil
|
||||
}
|
||||
|
||||
return &remotecommand.TerminalSize{Width: winsize.Width, Height: winsize.Height}
|
||||
}
|
||||
|
||||
// MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with
|
||||
// initialSizes, or nil if there's no TTY present.
|
||||
func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecommand.TerminalSizeQueue {
|
||||
outFd, isTerminal := term.GetFdInfo(t.Out)
|
||||
if !isTerminal {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.sizeQueue = &sizeQueue{
|
||||
t: *t,
|
||||
// make it buffered so we can send the initial terminal sizes without blocking, prior to starting
|
||||
// the streaming below
|
||||
resizeChan: make(chan remotecommand.TerminalSize, len(initialSizes)),
|
||||
stopResizing: make(chan struct{}),
|
||||
}
|
||||
|
||||
t.sizeQueue.monitorSize(outFd, initialSizes...)
|
||||
|
||||
return t.sizeQueue
|
||||
}
|
||||
|
||||
// sizeQueue implements remotecommand.TerminalSizeQueue
|
||||
type sizeQueue struct {
|
||||
t TTY
|
||||
// resizeChan receives a Size each time the user's terminal is resized.
|
||||
resizeChan chan remotecommand.TerminalSize
|
||||
stopResizing chan struct{}
|
||||
}
|
||||
|
||||
// make sure sizeQueue implements the resize.TerminalSizeQueue interface
|
||||
var _ remotecommand.TerminalSizeQueue = &sizeQueue{}
|
||||
|
||||
// monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each
|
||||
// new event, it sends the current terminal size to resizeChan.
|
||||
func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.TerminalSize) {
|
||||
// send the initial sizes
|
||||
for i := range initialSizes {
|
||||
if initialSizes[i] != nil {
|
||||
s.resizeChan <- *initialSizes[i]
|
||||
}
|
||||
}
|
||||
|
||||
resizeEvents := make(chan remotecommand.TerminalSize, 1)
|
||||
|
||||
monitorResizeEvents(outFd, resizeEvents, s.stopResizing)
|
||||
|
||||
// listen for resize events in the background
|
||||
go func() {
|
||||
defer runtime.HandleCrash()
|
||||
|
||||
for {
|
||||
select {
|
||||
case size, ok := <-resizeEvents:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
// try to send the size to resizeChan, but don't block
|
||||
case s.resizeChan <- size:
|
||||
// send successful
|
||||
default:
|
||||
// unable to send / no-op
|
||||
}
|
||||
case <-s.stopResizing:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Next returns the new terminal size after the terminal has been resized. It returns nil when
|
||||
// monitoring has been stopped.
|
||||
func (s *sizeQueue) Next() *remotecommand.TerminalSize {
|
||||
size, ok := <-s.resizeChan
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return &size
|
||||
}
|
||||
|
||||
// stop stops the background goroutine that is monitoring for terminal resizes.
|
||||
func (s *sizeQueue) stop() {
|
||||
close(s.stopResizing)
|
||||
}
|
61
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/resizeevents.go
generated
vendored
Normal file
61
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/resizeevents.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2016 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 term
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
||||
// monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the
|
||||
// terminal has resized). After receiving a SIGWINCH, this gets the terminal size and tries to send
|
||||
// it to the resizeEvents channel. The goroutine stops when the stop channel is closed.
|
||||
func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) {
|
||||
go func() {
|
||||
defer runtime.HandleCrash()
|
||||
|
||||
winch := make(chan os.Signal, 1)
|
||||
signal.Notify(winch, unix.SIGWINCH)
|
||||
defer signal.Stop(winch)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-winch:
|
||||
size := GetSize(fd)
|
||||
if size == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// try to send size
|
||||
select {
|
||||
case resizeEvents <- *size:
|
||||
// success
|
||||
default:
|
||||
// not sent
|
||||
}
|
||||
case <-stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
62
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/resizeevents_windows.go
generated
vendored
Normal file
62
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/resizeevents_windows.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2016 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 term
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
||||
// monitorResizeEvents spawns a goroutine that periodically gets the terminal size and tries to send
|
||||
// it to the resizeEvents channel if the size has changed. The goroutine stops when the stop channel
|
||||
// is closed.
|
||||
func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) {
|
||||
go func() {
|
||||
defer runtime.HandleCrash()
|
||||
|
||||
size := GetSize(fd)
|
||||
if size == nil {
|
||||
return
|
||||
}
|
||||
lastSize := *size
|
||||
|
||||
for {
|
||||
// see if we need to stop running
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
size := GetSize(fd)
|
||||
if size == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size.Height != lastSize.Height || size.Width != lastSize.Width {
|
||||
lastSize.Height = size.Height
|
||||
lastSize.Width = size.Width
|
||||
resizeEvents <- *size
|
||||
}
|
||||
|
||||
// sleep to avoid hot looping
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
}
|
110
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/term.go
generated
vendored
Normal file
110
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/term.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 2016 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 term
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/pkg/term"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/interrupt"
|
||||
)
|
||||
|
||||
// SafeFunc is a function to be invoked by TTY.
|
||||
type SafeFunc func() error
|
||||
|
||||
// TTY helps invoke a function and preserve the state of the terminal, even if the process is
|
||||
// terminated during execution. It also provides support for terminal resizing for remote command
|
||||
// execution/attachment.
|
||||
type TTY struct {
|
||||
// In is a reader representing stdin. It is a required field.
|
||||
In io.Reader
|
||||
// Out is a writer representing stdout. It must be set to support terminal resizing. It is an
|
||||
// optional field.
|
||||
Out io.Writer
|
||||
// Raw is true if the terminal should be set raw.
|
||||
Raw bool
|
||||
// TryDev indicates the TTY should try to open /dev/tty if the provided input
|
||||
// is not a file descriptor.
|
||||
TryDev bool
|
||||
// Parent is an optional interrupt handler provided to this function - if provided
|
||||
// it will be invoked after the terminal state is restored. If it is not provided,
|
||||
// a signal received during the TTY will result in os.Exit(0) being invoked.
|
||||
Parent *interrupt.Handler
|
||||
|
||||
// sizeQueue is set after a call to MonitorSize() and is used to monitor SIGWINCH signals when the
|
||||
// user's terminal resizes.
|
||||
sizeQueue *sizeQueue
|
||||
}
|
||||
|
||||
// IsTerminalIn returns true if t.In is a terminal. Does not check /dev/tty
|
||||
// even if TryDev is set.
|
||||
func (t TTY) IsTerminalIn() bool {
|
||||
return IsTerminal(t.In)
|
||||
}
|
||||
|
||||
// IsTerminalOut returns true if t.Out is a terminal. Does not check /dev/tty
|
||||
// even if TryDev is set.
|
||||
func (t TTY) IsTerminalOut() bool {
|
||||
return IsTerminal(t.Out)
|
||||
}
|
||||
|
||||
// IsTerminal returns whether the passed object is a terminal or not
|
||||
func IsTerminal(i interface{}) bool {
|
||||
_, terminal := term.GetFdInfo(i)
|
||||
return terminal
|
||||
}
|
||||
|
||||
// Safe invokes the provided function and will attempt to ensure that when the
|
||||
// function returns (or a termination signal is sent) that the terminal state
|
||||
// is reset to the condition it was in prior to the function being invoked. If
|
||||
// t.Raw is true the terminal will be put into raw mode prior to calling the function.
|
||||
// If the input file descriptor is not a TTY and TryDev is true, the /dev/tty file
|
||||
// will be opened (if available).
|
||||
func (t TTY) Safe(fn SafeFunc) error {
|
||||
inFd, isTerminal := term.GetFdInfo(t.In)
|
||||
|
||||
if !isTerminal && t.TryDev {
|
||||
if f, err := os.Open("/dev/tty"); err == nil {
|
||||
defer f.Close()
|
||||
inFd = f.Fd()
|
||||
isTerminal = term.IsTerminal(inFd)
|
||||
}
|
||||
}
|
||||
if !isTerminal {
|
||||
return fn()
|
||||
}
|
||||
|
||||
var state *term.State
|
||||
var err error
|
||||
if t.Raw {
|
||||
state, err = term.MakeRaw(inFd)
|
||||
} else {
|
||||
state, err = term.SaveState(inFd)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return interrupt.Chain(t.Parent, func() {
|
||||
if t.sizeQueue != nil {
|
||||
t.sizeQueue.stop()
|
||||
}
|
||||
|
||||
term.RestoreTerminal(inFd, state)
|
||||
}).Run(fn)
|
||||
}
|
124
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/term_writer.go
generated
vendored
Normal file
124
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/term_writer.go
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright 2016 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 term
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/pkg/term"
|
||||
wordwrap "github.com/mitchellh/go-wordwrap"
|
||||
)
|
||||
|
||||
type wordWrapWriter struct {
|
||||
limit uint
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
// NewResponsiveWriter creates a Writer that detects the column width of the
|
||||
// terminal we are in, and adjusts every line width to fit and use recommended
|
||||
// terminal sizes for better readability. Does proper word wrapping automatically.
|
||||
// if terminal width >= 120 columns use 120 columns
|
||||
// if terminal width >= 100 columns use 100 columns
|
||||
// if terminal width >= 80 columns use 80 columns
|
||||
// In case we're not in a terminal or if it's smaller than 80 columns width,
|
||||
// doesn't do any wrapping.
|
||||
func NewResponsiveWriter(w io.Writer) io.Writer {
|
||||
file, ok := w.(*os.File)
|
||||
if !ok {
|
||||
return w
|
||||
}
|
||||
fd := file.Fd()
|
||||
if !term.IsTerminal(fd) {
|
||||
return w
|
||||
}
|
||||
|
||||
terminalSize := GetSize(fd)
|
||||
if terminalSize == nil {
|
||||
return w
|
||||
}
|
||||
|
||||
var limit uint
|
||||
switch {
|
||||
case terminalSize.Width >= 120:
|
||||
limit = 120
|
||||
case terminalSize.Width >= 100:
|
||||
limit = 100
|
||||
case terminalSize.Width >= 80:
|
||||
limit = 80
|
||||
}
|
||||
|
||||
return NewWordWrapWriter(w, limit)
|
||||
}
|
||||
|
||||
// NewWordWrapWriter is a Writer that supports a limit of characters on every line
|
||||
// and does auto word wrapping that respects that limit.
|
||||
func NewWordWrapWriter(w io.Writer, limit uint) io.Writer {
|
||||
return &wordWrapWriter{
|
||||
limit: limit,
|
||||
writer: w,
|
||||
}
|
||||
}
|
||||
|
||||
func (w wordWrapWriter) Write(p []byte) (nn int, err error) {
|
||||
if w.limit == 0 {
|
||||
return w.writer.Write(p)
|
||||
}
|
||||
original := string(p)
|
||||
wrapped := wordwrap.WrapString(original, w.limit)
|
||||
return w.writer.Write([]byte(wrapped))
|
||||
}
|
||||
|
||||
// NewPunchCardWriter is a NewWordWrapWriter that limits the line width to 80 columns.
|
||||
func NewPunchCardWriter(w io.Writer) io.Writer {
|
||||
return NewWordWrapWriter(w, 80)
|
||||
}
|
||||
|
||||
type maxWidthWriter struct {
|
||||
maxWidth uint
|
||||
currentWidth uint
|
||||
written uint
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
// NewMaxWidthWriter is a Writer that supports a limit of characters on every
|
||||
// line, but doesn't do any word wrapping automatically.
|
||||
func NewMaxWidthWriter(w io.Writer, maxWidth uint) io.Writer {
|
||||
return &maxWidthWriter{
|
||||
maxWidth: maxWidth,
|
||||
writer: w,
|
||||
}
|
||||
}
|
||||
|
||||
func (m maxWidthWriter) Write(p []byte) (nn int, err error) {
|
||||
for _, b := range p {
|
||||
if m.currentWidth == m.maxWidth {
|
||||
m.writer.Write([]byte{'\n'})
|
||||
m.currentWidth = 0
|
||||
}
|
||||
if b == '\n' {
|
||||
m.currentWidth = 0
|
||||
}
|
||||
_, err := m.writer.Write([]byte{b})
|
||||
if err != nil {
|
||||
return int(m.written), err
|
||||
}
|
||||
m.written++
|
||||
m.currentWidth++
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
98
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/term_writer_test.go
generated
vendored
Normal file
98
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/term_writer_test.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright 2016 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 term
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const test = "Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube Kube"
|
||||
|
||||
func TestWordWrapWriter(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
input string
|
||||
maxWidth uint
|
||||
}{
|
||||
"max 10": {input: test, maxWidth: 10},
|
||||
"max 80": {input: test, maxWidth: 80},
|
||||
"max 120": {input: test, maxWidth: 120},
|
||||
"max 5000": {input: test, maxWidth: 5000},
|
||||
}
|
||||
for k, tc := range testcases {
|
||||
b := bytes.NewBufferString("")
|
||||
w := NewWordWrapWriter(b, tc.maxWidth)
|
||||
_, err := w.Write([]byte(tc.input))
|
||||
if err != nil {
|
||||
t.Errorf("%s: Unexpected error: %v", k, err)
|
||||
}
|
||||
result := b.String()
|
||||
if !strings.Contains(result, "Kube") {
|
||||
t.Errorf("%s: Expected to contain \"Kube\"", k)
|
||||
}
|
||||
if len(result) < len(tc.input) {
|
||||
t.Errorf("%s: Unexpectedly short string, got %d wanted at least %d chars: %q", k, len(result), len(tc.input), result)
|
||||
}
|
||||
for _, line := range strings.Split(result, "\n") {
|
||||
if len(line) > int(tc.maxWidth) {
|
||||
t.Errorf("%s: Every line must be at most %d chars long, got %d: %q", k, tc.maxWidth, len(line), line)
|
||||
}
|
||||
}
|
||||
for _, word := range strings.Split(result, " ") {
|
||||
if !strings.Contains(word, "Kube") {
|
||||
t.Errorf("%s: Unexpected broken word: %q", k, word)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxWidthWriter(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
input string
|
||||
maxWidth uint
|
||||
}{
|
||||
"max 10": {input: test, maxWidth: 10},
|
||||
"max 80": {input: test, maxWidth: 80},
|
||||
"max 120": {input: test, maxWidth: 120},
|
||||
"max 5000": {input: test, maxWidth: 5000},
|
||||
}
|
||||
for k, tc := range testcases {
|
||||
b := bytes.NewBufferString("")
|
||||
w := NewMaxWidthWriter(b, tc.maxWidth)
|
||||
_, err := w.Write([]byte(tc.input))
|
||||
if err != nil {
|
||||
t.Errorf("%s: Unexpected error: %v", k, err)
|
||||
}
|
||||
result := b.String()
|
||||
if !strings.Contains(result, "Kube") {
|
||||
t.Errorf("%s: Expected to contain \"Kube\"", k)
|
||||
}
|
||||
if len(result) < len(tc.input) {
|
||||
t.Errorf("%s: Unexpectedly short string, got %d wanted at least %d chars: %q", k, len(result), len(tc.input), result)
|
||||
}
|
||||
lines := strings.Split(result, "\n")
|
||||
for i, line := range lines {
|
||||
if len(line) > int(tc.maxWidth) {
|
||||
t.Errorf("%s: Every line must be at most %d chars long, got %d: %q", k, tc.maxWidth, len(line), line)
|
||||
}
|
||||
if i < len(lines)-1 && len(line) != int(tc.maxWidth) {
|
||||
t.Errorf("%s: Lines except the last one are expected to be exactly %d chars long, got %d: %q", k, tc.maxWidth, len(line), line)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask.go
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
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 (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func Umask(mask int) (old int, err error) {
|
||||
return unix.Umask(mask), nil
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask_windows.go
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask_windows.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
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 (
|
||||
"errors"
|
||||
)
|
||||
|
||||
func Umask(mask int) (int, error) {
|
||||
return 0, errors.New("platform and architecture is not supported")
|
||||
}
|
91
vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go
generated
vendored
Normal file
91
vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// ParseRFC3339 parses an RFC3339 date in either RFC3339Nano or RFC3339 format.
|
||||
func ParseRFC3339(s string, nowFn func() metav1.Time) (metav1.Time, error) {
|
||||
if t, timeErr := time.Parse(time.RFC3339Nano, s); timeErr == nil {
|
||||
return metav1.Time{Time: t}, nil
|
||||
}
|
||||
t, err := time.Parse(time.RFC3339, s)
|
||||
if err != nil {
|
||||
return metav1.Time{}, err
|
||||
}
|
||||
return metav1.Time{Time: t}, nil
|
||||
}
|
||||
|
||||
func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
|
||||
data, err := runtime.Encode(codec, obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%x", md5.Sum(data)), nil
|
||||
}
|
||||
|
||||
// ParseFileSource parses the source given.
|
||||
//
|
||||
// Acceptable formats include:
|
||||
// 1. source-path: the basename will become the key name
|
||||
// 2. source-name=source-path: the source-name will become the key name and
|
||||
// source-path is the path to the key file.
|
||||
//
|
||||
// Key names cannot include '='.
|
||||
func ParseFileSource(source string) (keyName, filePath string, err error) {
|
||||
numSeparators := strings.Count(source, "=")
|
||||
switch {
|
||||
case numSeparators == 0:
|
||||
return path.Base(source), source, nil
|
||||
case numSeparators == 1 && strings.HasPrefix(source, "="):
|
||||
return "", "", fmt.Errorf("key name for file path %v missing.", strings.TrimPrefix(source, "="))
|
||||
case numSeparators == 1 && strings.HasSuffix(source, "="):
|
||||
return "", "", fmt.Errorf("file path for key name %v missing.", strings.TrimSuffix(source, "="))
|
||||
case numSeparators > 1:
|
||||
return "", "", errors.New("Key names or file paths cannot contain '='.")
|
||||
default:
|
||||
components := strings.Split(source, "=")
|
||||
return components[0], components[1], nil
|
||||
}
|
||||
}
|
||||
|
||||
// ParseLiteralSource parses the source key=val pair into its component pieces.
|
||||
// This functionality is distinguished from strings.SplitN(source, "=", 2) since
|
||||
// it returns an error in the case of empty keys, values, or a missing equals sign.
|
||||
func ParseLiteralSource(source string) (keyName, value string, err error) {
|
||||
// leading equal is invalid
|
||||
if strings.Index(source, "=") == 0 {
|
||||
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
|
||||
}
|
||||
// split after the first equal (so values can have the = character)
|
||||
items := strings.SplitN(source, "=", 2)
|
||||
if len(items) != 2 {
|
||||
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
|
||||
}
|
||||
|
||||
return items[0], items[1], nil
|
||||
}
|
198
vendor/k8s.io/kubernetes/pkg/kubectl/util/util_test.go
generated
vendored
Normal file
198
vendor/k8s.io/kubernetes/pkg/kubectl/util/util_test.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
Copyright 2016 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"
|
||||
|
||||
func TestParseFileSource(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
input string
|
||||
key string
|
||||
filepath string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "success 1",
|
||||
input: "boo=zoo",
|
||||
key: "boo",
|
||||
filepath: "zoo",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "success 2",
|
||||
input: "boo=/path/to/zoo",
|
||||
key: "boo",
|
||||
filepath: "/path/to/zoo",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "success 3",
|
||||
input: "boo-2=/1/2/3/4/5/zab.txt",
|
||||
key: "boo-2",
|
||||
filepath: "/1/2/3/4/5/zab.txt",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "success 4",
|
||||
input: "boo-=this/seems/weird.txt",
|
||||
key: "boo-",
|
||||
filepath: "this/seems/weird.txt",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "success 5",
|
||||
input: "-key=some/path",
|
||||
key: "-key",
|
||||
filepath: "some/path",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "invalid 1",
|
||||
input: "key==some/path",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "invalid 2",
|
||||
input: "=key=some/path",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "invalid 3",
|
||||
input: "==key=/some/other/path",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "invalid 4",
|
||||
input: "=key",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "invalid 5",
|
||||
input: "key=",
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
key, filepath, err := ParseFileSource(tc.input)
|
||||
if err != nil {
|
||||
if tc.err {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if tc.err {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.key, key; e != a {
|
||||
t.Errorf("%v: expected key %v; got %v", tc.name, e, a)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.filepath, filepath; e != a {
|
||||
t.Errorf("%v: expected filepath %v; got %v", tc.name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseLiteralSource(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
input string
|
||||
key string
|
||||
value string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "success 1",
|
||||
input: "key=value",
|
||||
key: "key",
|
||||
value: "value",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "success 2",
|
||||
input: "key=value/with/slashes",
|
||||
key: "key",
|
||||
value: "value/with/slashes",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "err 1",
|
||||
input: "key==value",
|
||||
key: "key",
|
||||
value: "=value",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "err 2",
|
||||
input: "key=value=",
|
||||
key: "key",
|
||||
value: "value=",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "err 3",
|
||||
input: "key2=value==",
|
||||
key: "key2",
|
||||
value: "value==",
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "err 4",
|
||||
input: "==key",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "err 5",
|
||||
input: "=key=",
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
key, value, err := ParseLiteralSource(tc.input)
|
||||
if err != nil {
|
||||
if tc.err {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if tc.err {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.key, key; e != a {
|
||||
t.Errorf("%v: expected key %v; got %v", tc.name, e, a)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.value, value; e != a {
|
||||
t.Errorf("%v: expected value %v; got %v", tc.name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user