Compare commits

..

23 Commits

Author SHA1 Message Date
Kubernetes Publisher
cae8ad7d6b Update dependencies to v0.22.0-beta.0 tag 2021-06-22 23:25:53 +00:00
Kubernetes Publisher
3fae6f05ac Merge pull request #103010 from BenTheElder/ansi-386-overflow
update Azure/go-ansiterm to v0.0.0-20210617225240-d185dfc1b5a1

Kubernetes-commit: 2ff70c77c98fdd3230ade470b319309f34909215
2021-06-19 07:19:03 +00:00
Benjamin Elder
eadbc45beb update Azure/go-ansiterm to v0.0.0-20210617225240-d185dfc1b5a1
fixes constant overflow on windows/386

Kubernetes-commit: 35e9d97f3e02a8757e5cc698142037c5a95487d9
2021-06-18 15:11:48 -07:00
Kubernetes Publisher
ca46d47734 Merge pull request #103007 from smira/error-wrapping
fix: properly wrap errors when reading response body in the client

Kubernetes-commit: d283d92121e88d282d4158d7834a7eccdb8774dc
2021-06-18 14:48:05 -07:00
Andrey Smirnov
c8b4c1e4bd fix: properly wrap errors when reading response body in the client
As `%v` doesn't allow error unwrapping, checks like `errors.Is` are not
working properly.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>

Kubernetes-commit: 6c0463bd2b616d0f22f47905bb26d66fa3b04e37
2021-06-18 23:35:31 +03:00
Kubernetes Publisher
848310b833 Merge pull request #102783 from mcbenjemaa/update-dep-gnostic
Update gnostic to the latest version

Kubernetes-commit: e9c6ec639cc5ca93a3f6e01ff4215f6b68d6142d
2021-06-18 19:19:10 +00:00
Kubernetes Publisher
0634aae869 Merge pull request #102946 from ahmed-mez/patch-1
Fix ServerGroupsAndResources docs typo

Kubernetes-commit: 48b7492f92997ac8cbb8b6c559a0c68cba3021ab
2021-06-18 04:36:04 -07:00
Mohamed chiheb Ben jemaa
68eb0a2b5d update vendor
Kubernetes-commit: 9571b1f884480879de54d5ff993ca336d61874b2
2021-06-17 17:24:43 +01:00
Ahmed Mezghani
eecff020f2 Fix ServerGroupsAndResources docs typo
Rename ServerResources -> ServerGroupsAndResources in ServerGroupsAndResources's doc-string.

Kubernetes-commit: c673e166383abff887f63900d3aff8bb2b58fb55
2021-06-17 12:26:05 +02:00
Kubernetes Publisher
0a7756a242 Merge pull request #102441 from feiskyer/update-vendor
Update Azure Go SDK to v55.0.0

Kubernetes-commit: 122d6352452f3f4a2d52bdb8b114b6e0ec49358e
2021-06-17 02:01:31 +00:00
Mohamed chiheb Ben jemaa
77d744302e Update github.com/googleapis/gnostic to v0.5.5 and updating transitive dependencies go-cmp, protobuf,, to adapt the latest gnostic release which cosists of [Update protos for Go protoc plugin compatibility]
Kubernetes-commit: c691386fef727a5494e3ab02b99196d8f6418241
2021-06-13 17:25:55 +01:00
Pengfei Ni
5e7391919a Update Azure Go SDK to v55.0.0
Kubernetes-commit: b98824c55d95b8b3a1cf79adac44154bd1702e46
2021-06-01 01:30:43 +00:00
Kubernetes Publisher
ef2d8844e4 Merge pull request #102897 from liggitt/etcd-ga
Update to etcd v3.5.0 client

Kubernetes-commit: f5cf74ddff818236b8435370afa41a51f23dd532
2021-06-16 06:01:16 +00:00
Jordan Liggitt
ead3c96c7d Update to etcd v3.5.0 client
Kubernetes-commit: 6448181d95c8d6486ba8e9a2a92b4a8172ca1f8f
2021-06-15 19:01:32 -04:00
Kubernetes Publisher
80617fc032 Merge pull request #100488 from liggitt/protobuf
update etcd, grpc, protobuf dependencies

Kubernetes-commit: 3a47ddccdfb09e73758cebb2690ad2a014f67e23
2021-06-15 22:01:06 +00:00
Kubernetes Publisher
d412730e5f Merge pull request #99310 from ankeesler/exec-plugin-interactive
exec credential provider: InteractiveMode support

Kubernetes-commit: 37da905c0c673c9cb07ca724384d37e725602a0c
2021-06-15 09:46:01 -07:00
Jordan Liggitt
0ba74ec6bf Update protobuf,grpc,etcd dependencies
1. Updated etcd/protobuf/grpc dependencies:

echo "
hack/pin-dependency.sh github.com/golang/protobuf latest
hack/pin-dependency.sh google.golang.org/protobuf latest
hack/pin-dependency.sh go.etcd.io/etcd/api/v3 v3.5.0-rc.0
hack/pin-dependency.sh go.etcd.io/etcd/client/v3 v3.5.0-rc.0
hack/pin-dependency.sh go.etcd.io/etcd/client/pkg/v3 v3.5.0-rc.0
hack/pin-dependency.sh go.etcd.io/etcd/pkg/v3 v3.5.0-rc.0
hack/pin-dependency.sh go.etcd.io/etcd/server/v3 v3.5.0-rc.0
hack/pin-dependency.sh go.etcd.io/etcd/tests/v3 v3.5.0-rc.0
hack/pin-dependency.sh google.golang.org/grpc latest
" | bash

2. Linted transitive dependencies until versions are clean:

hack/lint-dependencies.sh  | grep "  hack/pin-dependency.sh" | bash

3. Linted dependencies until dropped versions are clean:

hack/lint-dependencies.sh  | grep "dropreplace" | bash

4. Updated vendor and internal modules:

hack/update-vendor.sh
hack/update-internal-modules.sh

Repeated steps 2-4 until clean

Kubernetes-commit: 5cfc39ef5e90002080ff1f2bc4b7ade674c225f1
2021-06-15 10:06:09 -04:00
Andrew Keesler
37ed584bed exec credential provider: InteractiveMode support
The value here is that the exec plugin author can use the kubeconfig to assert
how standard input is treated with respect to the exec plugin, e.g.,
- an exec plugin author can ensure that kubectl fails if it cannot provide
  standard input to an exec plugin that needs it (Always)
- an exec plugin author can ensure that an client-go process will still call an
  exec plugin that prefers standard input even if standard input is not
  available (IfAvailable)

Signed-off-by: Andrew Keesler <akeesler@vmware.com>

Kubernetes-commit: cd83d89ac94c5b61fdd38840098e7223e5af0d34
2021-06-14 17:15:36 -04:00
Kubernetes Publisher
1bccfc8c60 Merge pull request #102788 from pohly/reflector-log-level
client-go: reduce log level of reflector again

Kubernetes-commit: 60a4cbfdf617b94a28a76b302fd4cf04a704667c
2021-06-11 01:40:49 +00:00
Patrick Ohly
67de95ce2f client-go: reduce log level of reflector again
https://github.com/kubernetes/kubernetes/pull/87795 most likely
unintentionally increased the log level of "Starting reflector" and
"Stopping reflector", with the result that since Kubernetes 1.21
clients have printed that message by default. This is undesirable, we
should use the original level 3 again.

Kubernetes-commit: fd972934e4916879b04508686302659ce82cfa75
2021-06-10 20:36:02 +02:00
Kubernetes Publisher
25e061e062 sync: remove Godeps/ 2021-06-09 11:58:24 +00:00
Kubernetes Publisher
3ecbde32b7 Merge pull request #102454 from wzshiming/clean/remove-godeps
Remove Godeps

Kubernetes-commit: 09a9e612947bb2d940224245890048d3e60d4c5d
2021-06-08 23:48:38 +00:00
Shiming Zhang
b7739d8a13 Remove Godeps
Kubernetes-commit: 1431eab36d3e0468482aa234651ab878022a49e1
2021-05-31 17:44:41 +08:00
27 changed files with 715 additions and 664 deletions

526
Godeps/Godeps.json generated
View File

@@ -1,526 +0,0 @@
{
"ImportPath": "k8s.io/client-go",
"GoVersion": "unknown",
"GodepVersion": "gen-godeps",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "cloud.google.com/go",
"Rev": "v0.54.0"
},
{
"ImportPath": "cloud.google.com/go/bigquery",
"Rev": "v1.4.0"
},
{
"ImportPath": "cloud.google.com/go/datastore",
"Rev": "v1.1.0"
},
{
"ImportPath": "cloud.google.com/go/pubsub",
"Rev": "v1.2.0"
},
{
"ImportPath": "cloud.google.com/go/storage",
"Rev": "v1.6.0"
},
{
"ImportPath": "dmitri.shuralyov.com/gpu/mtl",
"Rev": "666a987793e9"
},
{
"ImportPath": "github.com/Azure/go-autorest",
"Rev": "v14.2.0"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest",
"Rev": "v0.11.17"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/adal",
"Rev": "v0.9.10"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/date",
"Rev": "v0.3.0"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/mocks",
"Rev": "v0.4.1"
},
{
"ImportPath": "github.com/Azure/go-autorest/logger",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/Azure/go-autorest/tracing",
"Rev": "v0.6.0"
},
{
"ImportPath": "github.com/BurntSushi/toml",
"Rev": "v0.3.1"
},
{
"ImportPath": "github.com/BurntSushi/xgb",
"Rev": "27f122750802"
},
{
"ImportPath": "github.com/NYTimes/gziphandler",
"Rev": "56545f4a5d46"
},
{
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "v1.1.1"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "de5bf2ad4578"
},
{
"ImportPath": "github.com/asaskevich/govalidator",
"Rev": "f61b66f89f4a"
},
{
"ImportPath": "github.com/census-instrumentation/opencensus-proto",
"Rev": "v0.2.1"
},
{
"ImportPath": "github.com/chzyer/logex",
"Rev": "v1.1.10"
},
{
"ImportPath": "github.com/chzyer/readline",
"Rev": "2972be24d48e"
},
{
"ImportPath": "github.com/chzyer/test",
"Rev": "a1ea475d72b1"
},
{
"ImportPath": "github.com/client9/misspell",
"Rev": "v0.3.4"
},
{
"ImportPath": "github.com/creack/pty",
"Rev": "v1.1.9"
},
{
"ImportPath": "github.com/davecgh/go-spew",
"Rev": "v1.1.1"
},
{
"ImportPath": "github.com/docopt/docopt-go",
"Rev": "ee0de3bc6815"
},
{
"ImportPath": "github.com/elazarl/goproxy",
"Rev": "947c36da3153"
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a20633"
},
{
"ImportPath": "github.com/envoyproxy/go-control-plane",
"Rev": "5f8ba28d4473"
},
{
"ImportPath": "github.com/envoyproxy/protoc-gen-validate",
"Rev": "v0.1.0"
},
{
"ImportPath": "github.com/evanphx/json-patch",
"Rev": "v4.11.0"
},
{
"ImportPath": "github.com/form3tech-oss/jwt-go",
"Rev": "v3.2.2"
},
{
"ImportPath": "github.com/fsnotify/fsnotify",
"Rev": "v1.4.9"
},
{
"ImportPath": "github.com/go-gl/glfw",
"Rev": "e6da0acd62b1"
},
{
"ImportPath": "github.com/go-gl/glfw/v3.3/glfw",
"Rev": "6f7a984d4dc4"
},
{
"ImportPath": "github.com/go-logr/logr",
"Rev": "v0.4.0"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "v0.19.3"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "v0.19.3"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "v0.19.5"
},
{
"ImportPath": "github.com/gogo/protobuf",
"Rev": "v1.3.2"
},
{
"ImportPath": "github.com/golang/glog",
"Rev": "23def4e6c14b"
},
{
"ImportPath": "github.com/golang/groupcache",
"Rev": "8c9f03a8e57e"
},
{
"ImportPath": "github.com/golang/mock",
"Rev": "v1.4.1"
},
{
"ImportPath": "github.com/golang/protobuf",
"Rev": "v1.4.3"
},
{
"ImportPath": "github.com/google/btree",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/google/go-cmp",
"Rev": "v0.5.4"
},
{
"ImportPath": "github.com/google/gofuzz",
"Rev": "v1.1.0"
},
{
"ImportPath": "github.com/google/martian",
"Rev": "v2.1.0"
},
{
"ImportPath": "github.com/google/pprof",
"Rev": "1ebb73c60ed3"
},
{
"ImportPath": "github.com/google/renameio",
"Rev": "v0.1.0"
},
{
"ImportPath": "github.com/google/uuid",
"Rev": "v1.1.2"
},
{
"ImportPath": "github.com/googleapis/gax-go/v2",
"Rev": "v2.0.5"
},
{
"ImportPath": "github.com/googleapis/gnostic",
"Rev": "v0.5.1"
},
{
"ImportPath": "github.com/gorilla/websocket",
"Rev": "v1.4.2"
},
{
"ImportPath": "github.com/gregjones/httpcache",
"Rev": "9cad4c3443a7"
},
{
"ImportPath": "github.com/hashicorp/golang-lru",
"Rev": "v0.5.1"
},
{
"ImportPath": "github.com/hpcloud/tail",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/ianlancetaylor/demangle",
"Rev": "5e5cf60278f6"
},
{
"ImportPath": "github.com/imdario/mergo",
"Rev": "v0.3.5"
},
{
"ImportPath": "github.com/json-iterator/go",
"Rev": "v1.1.10"
},
{
"ImportPath": "github.com/jstemmer/go-junit-report",
"Rev": "v0.9.1"
},
{
"ImportPath": "github.com/kisielk/errcheck",
"Rev": "v1.5.0"
},
{
"ImportPath": "github.com/kisielk/gotool",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/kr/pretty",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/kr/pty",
"Rev": "v1.1.1"
},
{
"ImportPath": "github.com/kr/text",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/mailru/easyjson",
"Rev": "b2ccc519800e"
},
{
"ImportPath": "github.com/mitchellh/mapstructure",
"Rev": "v1.1.2"
},
{
"ImportPath": "github.com/moby/spdystream",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/modern-go/concurrent",
"Rev": "bacd9c7ef1dd"
},
{
"ImportPath": "github.com/modern-go/reflect2",
"Rev": "v1.0.1"
},
{
"ImportPath": "github.com/munnerz/goautoneg",
"Rev": "a547fc61f48d"
},
{
"ImportPath": "github.com/mxk/go-flowrate",
"Rev": "cca7078d478f"
},
{
"ImportPath": "github.com/niemeyer/pretty",
"Rev": "a10e7caefd8e"
},
{
"ImportPath": "github.com/nxadm/tail",
"Rev": "v1.4.4"
},
{
"ImportPath": "github.com/onsi/ginkgo",
"Rev": "v1.14.0"
},
{
"ImportPath": "github.com/onsi/gomega",
"Rev": "v1.10.1"
},
{
"ImportPath": "github.com/peterbourgon/diskv",
"Rev": "v2.0.1"
},
{
"ImportPath": "github.com/pkg/errors",
"Rev": "v0.9.1"
},
{
"ImportPath": "github.com/pmezard/go-difflib",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/prometheus/client_model",
"Rev": "14fe0d1b01d4"
},
{
"ImportPath": "github.com/rogpeppe/go-internal",
"Rev": "v1.3.0"
},
{
"ImportPath": "github.com/spf13/afero",
"Rev": "v1.2.2"
},
{
"ImportPath": "github.com/spf13/pflag",
"Rev": "v1.0.5"
},
{
"ImportPath": "github.com/stoewer/go-strcase",
"Rev": "v1.2.0"
},
{
"ImportPath": "github.com/stretchr/objx",
"Rev": "v0.1.0"
},
{
"ImportPath": "github.com/stretchr/testify",
"Rev": "v1.7.0"
},
{
"ImportPath": "github.com/yuin/goldmark",
"Rev": "v1.2.1"
},
{
"ImportPath": "go.opencensus.io",
"Rev": "v0.22.3"
},
{
"ImportPath": "golang.org/x/crypto",
"Rev": "5ea612d1eb83"
},
{
"ImportPath": "golang.org/x/exp",
"Rev": "6cc2880d07d6"
},
{
"ImportPath": "golang.org/x/image",
"Rev": "cff245a6509b"
},
{
"ImportPath": "golang.org/x/lint",
"Rev": "738671d3881b"
},
{
"ImportPath": "golang.org/x/mobile",
"Rev": "d2bd2a29d028"
},
{
"ImportPath": "golang.org/x/mod",
"Rev": "v0.3.0"
},
{
"ImportPath": "golang.org/x/net",
"Rev": "3d97a244fca7"
},
{
"ImportPath": "golang.org/x/oauth2",
"Rev": "bf48bf16ab8d"
},
{
"ImportPath": "golang.org/x/sync",
"Rev": "67f06af15bc9"
},
{
"ImportPath": "golang.org/x/sys",
"Rev": "d19ff857e887"
},
{
"ImportPath": "golang.org/x/term",
"Rev": "6a3ed077a48d"
},
{
"ImportPath": "golang.org/x/text",
"Rev": "v0.3.6"
},
{
"ImportPath": "golang.org/x/time",
"Rev": "f8bda1e9f3ba"
},
{
"ImportPath": "golang.org/x/tools",
"Rev": "113979e3529a"
},
{
"ImportPath": "golang.org/x/xerrors",
"Rev": "5ec99f83aff1"
},
{
"ImportPath": "google.golang.org/api",
"Rev": "v0.20.0"
},
{
"ImportPath": "google.golang.org/appengine",
"Rev": "v1.6.5"
},
{
"ImportPath": "google.golang.org/genproto",
"Rev": "cb27e3aa2013"
},
{
"ImportPath": "google.golang.org/grpc",
"Rev": "v1.27.1"
},
{
"ImportPath": "google.golang.org/protobuf",
"Rev": "v1.25.0"
},
{
"ImportPath": "gopkg.in/check.v1",
"Rev": "8fa46927fb4f"
},
{
"ImportPath": "gopkg.in/errgo.v2",
"Rev": "v2.1.0"
},
{
"ImportPath": "gopkg.in/fsnotify.v1",
"Rev": "v1.4.7"
},
{
"ImportPath": "gopkg.in/inf.v0",
"Rev": "v0.9.1"
},
{
"ImportPath": "gopkg.in/tomb.v1",
"Rev": "dd632973f1e7"
},
{
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "v2.4.0"
},
{
"ImportPath": "gopkg.in/yaml.v3",
"Rev": "eeeca48fe776"
},
{
"ImportPath": "honnef.co/go/tools",
"Rev": "v0.0.1-2020.1.3"
},
{
"ImportPath": "k8s.io/api",
"Rev": "v0.22.0-alpha.3"
},
{
"ImportPath": "k8s.io/apimachinery",
"Rev": "v0.22.0-alpha.3"
},
{
"ImportPath": "k8s.io/gengo",
"Rev": "3a45101e95ac"
},
{
"ImportPath": "k8s.io/klog/v2",
"Rev": "v2.9.0"
},
{
"ImportPath": "k8s.io/kube-openapi",
"Rev": "95288971da7e"
},
{
"ImportPath": "k8s.io/utils",
"Rev": "da695404a2bc"
},
{
"ImportPath": "rsc.io/binaryregexp",
"Rev": "v0.2.0"
},
{
"ImportPath": "rsc.io/quote/v3",
"Rev": "v3.1.0"
},
{
"ImportPath": "rsc.io/sampler",
"Rev": "v1.3.0"
},
{
"ImportPath": "sigs.k8s.io/structured-merge-diff/v4",
"Rev": "v4.1.1"
},
{
"ImportPath": "sigs.k8s.io/yaml",
"Rev": "v1.2.0"
}
]
}

4
Godeps/OWNERS generated
View File

@@ -1,4 +0,0 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- dep-approvers

5
Godeps/Readme generated
View File

@@ -1,5 +0,0 @@
This directory tree is generated automatically by godep.
Please do not edit.
See https://github.com/tools/godep for more information.

View File

@@ -96,7 +96,7 @@ type ServerResourcesInterface interface {
//
// Deprecated: use ServerGroupsAndResources instead.
ServerResources() ([]*metav1.APIResourceList, error)
// ServerResources returns the supported groups and resources for all groups and versions.
// ServerGroupsAndResources returns the supported groups and resources for all groups and versions.
//
// The returned group and resource lists might be non-nil with partial results even in the
// case of non-nil error.

26
go.mod
View File

@@ -6,30 +6,32 @@ go 1.16
require (
cloud.google.com/go v0.54.0 // indirect
github.com/Azure/go-autorest/autorest v0.11.17
github.com/Azure/go-autorest/autorest/adal v0.9.10
github.com/Azure/go-autorest/autorest v0.11.18
github.com/Azure/go-autorest/autorest/adal v0.9.13
github.com/davecgh/go-spew v1.1.1
github.com/evanphx/json-patch v4.11.0+incompatible
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/gogo/protobuf v1.3.2
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
github.com/golang/protobuf v1.4.3
github.com/google/go-cmp v0.5.4
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
github.com/golang/protobuf v1.5.2
github.com/google/btree v1.0.1 // indirect
github.com/google/go-cmp v0.5.5
github.com/google/gofuzz v1.1.0
github.com/google/uuid v1.1.2
github.com/googleapis/gnostic v0.5.1
github.com/googleapis/gnostic v0.5.5
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7
github.com/imdario/mergo v0.3.5
github.com/peterbourgon/diskv v2.0.1+incompatible
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
google.golang.org/protobuf v1.25.0
k8s.io/api v0.22.0-alpha.3
k8s.io/apimachinery v0.22.0-alpha.3
google.golang.org/protobuf v1.26.0
k8s.io/api v0.22.0-beta.0
k8s.io/apimachinery v0.22.0-beta.0
k8s.io/klog/v2 v2.9.0
k8s.io/utils v0.0.0-20210521133846-da695404a2bc
sigs.k8s.io/structured-merge-diff/v4 v4.1.1
@@ -37,6 +39,6 @@ require (
)
replace (
k8s.io/api => k8s.io/api v0.22.0-alpha.3
k8s.io/apimachinery => k8s.io/apimachinery v0.22.0-alpha.3
k8s.io/api => k8s.io/api v0.22.0-beta.0
k8s.io/apimachinery => k8s.io/apimachinery v0.22.0-beta.0
)

66
go.sum
View File

@@ -24,17 +24,16 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.17 h1:2zCdHwNgRH+St1J+ZMf66xI8aLr/5KMy+wWLH97zwYM=
github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.10 h1:r6fZHMaHD8B6LDCn0o5vyBFHIHrM6Ywwx7mb49lPItI=
github.com/Azure/go-autorest/autorest/adal v0.9.10/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -60,8 +59,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -79,8 +79,9 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -98,18 +99,19 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -125,8 +127,9 @@ github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -138,8 +141,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -261,8 +264,8 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM=
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -303,8 +306,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
@@ -393,6 +397,7 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -408,8 +413,10 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -429,18 +436,19 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.22.0-alpha.3 h1:rE7mI2nvuTyiSo3+C7iiVxWh1lmOqBTUVLloX+c9s4c=
k8s.io/api v0.22.0-alpha.3/go.mod h1:1XKmwk4lbdJRku2EqAElh5amCLsl9JvjSbQzUteQ1ac=
k8s.io/apimachinery v0.22.0-alpha.3 h1:VIzKYyrRYpaPQDwhH6SZVy/04OR69ZKhovidSU+KjvY=
k8s.io/apimachinery v0.22.0-alpha.3/go.mod h1:5zcgojGmAy5Bo3S4mgZWAt6HwoKzaSh4MV3ITvlcOVM=
k8s.io/api v0.22.0-beta.0 h1:Icf4R7+a0zV6GexTqOXlcLw4OojdQVZE263bd4ui8ms=
k8s.io/api v0.22.0-beta.0/go.mod h1:qORVa/3lcMBQXyTmjzpk8IN3VRg619iFNr8d16VXkUQ=
k8s.io/apimachinery v0.22.0-beta.0 h1:y7EnOS9n+ZhCrk9nlwW7kwIr67syKFkGWj/HPAiE+XI=
k8s.io/apimachinery v0.22.0-beta.0/go.mod h1:AZCsxGyiXb/4yTvUIiY+4LESjQ12B77LFrbW2xd61is=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM=

View File

@@ -47,7 +47,7 @@ type ExecCredentialSpec struct {
Response *Response
// Interactive is true when the transport detects the command is being called from an
// interactive prompt.
// interactive prompt, i.e., when stdin has been passed to this exec plugin.
// +optional
Interactive bool

View File

@@ -22,7 +22,7 @@ import (
)
func Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error {
// This conversion intentionally omits the Response and Interactive fields, which were only
// This conversion intentionally omits the Response field, which were only
// supported in v1alpha1.
return autoConvert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in, out, s)
}

View File

@@ -46,6 +46,9 @@ type ExecCredentialSpec struct {
// ExecConfig.ProvideClusterInfo).
// +optional
Cluster *Cluster `json:"cluster,omitempty"`
// Interactive declares whether stdin has been passed to this exec plugin.
Interactive bool `json:"interactive"`
}
// ExecCredentialStatus holds credentials for the transport to use.

View File

@@ -149,6 +149,7 @@ func autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredenti
} else {
out.Cluster = nil
}
out.Interactive = in.Interactive
return nil
}
@@ -159,7 +160,7 @@ func Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSp
func autoConvert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error {
// WARNING: in.Response requires manual conversion: does not exist in peer-type
// WARNING: in.Interactive requires manual conversion: does not exist in peer-type
out.Interactive = in.Interactive
if in.Cluster != nil {
in, out := &in.Cluster, &out.Cluster
*out = new(Cluster)

View File

@@ -162,10 +162,10 @@ func (s *sometimes) Do(f func()) {
// GetAuthenticator returns an exec-based plugin for providing client credentials.
func GetAuthenticator(config *api.ExecConfig, cluster *clientauthentication.Cluster) (*Authenticator, error) {
return newAuthenticator(globalCache, config, cluster)
return newAuthenticator(globalCache, term.IsTerminal, config, cluster)
}
func newAuthenticator(c *cache, config *api.ExecConfig, cluster *clientauthentication.Cluster) (*Authenticator, error) {
func newAuthenticator(c *cache, isTerminalFunc func(int) bool, config *api.ExecConfig, cluster *clientauthentication.Cluster) (*Authenticator, error) {
key := cacheKey(config, cluster)
if a, ok := c.get(key); ok {
return a, nil
@@ -196,11 +196,11 @@ func newAuthenticator(c *cache, config *api.ExecConfig, cluster *clientauthentic
clock: clock.RealClock{},
},
stdin: os.Stdin,
stderr: os.Stderr,
interactive: term.IsTerminal(int(os.Stdin.Fd())),
now: time.Now,
environ: os.Environ,
stdin: os.Stdin,
stderr: os.Stderr,
interactiveFunc: func() (bool, error) { return isInteractive(isTerminalFunc, config) },
now: time.Now,
environ: os.Environ,
defaultDialer: defaultDialer,
connTracker: connTracker,
@@ -213,6 +213,33 @@ func newAuthenticator(c *cache, config *api.ExecConfig, cluster *clientauthentic
return c.put(key, a), nil
}
func isInteractive(isTerminalFunc func(int) bool, config *api.ExecConfig) (bool, error) {
var shouldBeInteractive bool
switch config.InteractiveMode {
case api.NeverExecInteractiveMode:
shouldBeInteractive = false
case api.IfAvailableExecInteractiveMode:
shouldBeInteractive = !config.StdinUnavailable && isTerminalFunc(int(os.Stdin.Fd()))
case api.AlwaysExecInteractiveMode:
if !isTerminalFunc(int(os.Stdin.Fd())) {
return false, errors.New("standard input is not a terminal")
}
if config.StdinUnavailable {
suffix := ""
if len(config.StdinUnavailableMessage) > 0 {
// only print extra ": <message>" if the user actually specified a message
suffix = fmt.Sprintf(": %s", config.StdinUnavailableMessage)
}
return false, fmt.Errorf("standard input is unavailable%s", suffix)
}
shouldBeInteractive = true
default:
return false, fmt.Errorf("unknown interactiveMode: %q", config.InteractiveMode)
}
return shouldBeInteractive, nil
}
// Authenticator is a client credential provider that rotates credentials by executing a plugin.
// The plugin input and output are defined by the API group client.authentication.k8s.io.
type Authenticator struct {
@@ -231,11 +258,11 @@ type Authenticator struct {
installHint string
// Stubbable for testing
stdin io.Reader
stderr io.Writer
interactive bool
now func() time.Time
environ func() []string
stdin io.Reader
stderr io.Writer
interactiveFunc func() (bool, error)
now func() time.Time
environ func() []string
// defaultDialer is used for clients which don't specify a custom dialer
defaultDialer *connrotation.Dialer
@@ -376,10 +403,15 @@ func (a *Authenticator) maybeRefreshCreds(creds *credentials, r *clientauthentic
// refreshCredsLocked executes the plugin and reads the credentials from
// stdout. It must be called while holding the Authenticator's mutex.
func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) error {
interactive, err := a.interactiveFunc()
if err != nil {
return fmt.Errorf("exec plugin cannot support interactive mode: %w", err)
}
cred := &clientauthentication.ExecCredential{
Spec: clientauthentication.ExecCredentialSpec{
Response: r,
Interactive: a.interactive,
Interactive: interactive,
},
}
if a.provideClusterInfo {
@@ -398,7 +430,7 @@ func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) err
cmd.Env = env
cmd.Stderr = a.stderr
cmd.Stdout = stdout
if a.interactive {
if interactive {
cmd.Stdin = a.stdin
}

View File

@@ -244,12 +244,25 @@ func TestCacheKey(t *testing.T) {
APIVersion: "client.authentication.k8s.io/v1alpha1",
}
// c7 should be the same as c6, except c7 has stdin marked as unavailable
c7 := &api.ExecConfig{
Command: "foo-bar",
Args: []string{"1", "2"},
Env: []api.ExecEnvVar{
{Name: "3", Value: "4"},
{Name: "5", Value: "6"},
},
APIVersion: "client.authentication.k8s.io/v1alpha1",
StdinUnavailable: true,
}
key1 := cacheKey(c1, c1c)
key2 := cacheKey(c2, c2c)
key3 := cacheKey(c3, c3c)
key4 := cacheKey(c4, c4c)
key5 := cacheKey(c5, c5c)
key6 := cacheKey(c6, nil)
key7 := cacheKey(c7, nil)
if key1 != key2 {
t.Error("key1 and key2 didn't match")
}
@@ -268,6 +281,9 @@ func TestCacheKey(t *testing.T) {
if key6 == key4 {
t.Error("key6 and key4 matched")
}
if key6 == key7 {
t.Error("key6 and key7 matched")
}
}
func compJSON(t *testing.T, got, want []byte) {
@@ -290,23 +306,25 @@ func compJSON(t *testing.T, got, want []byte) {
func TestRefreshCreds(t *testing.T) {
tests := []struct {
name string
config api.ExecConfig
exitCode int
cluster *clientauthentication.Cluster
output string
interactive bool
response *clientauthentication.Response
wantInput string
wantCreds credentials
wantExpiry time.Time
wantErr bool
wantErrSubstr string
name string
config api.ExecConfig
stdinUnavailable bool
exitCode int
cluster *clientauthentication.Cluster
output string
isTerminal bool
response *clientauthentication.Response
wantInput string
wantCreds credentials
wantExpiry time.Time
wantErr bool
wantErrSubstr string
}{
{
name: "basic-request",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -325,9 +343,10 @@ func TestRefreshCreds(t *testing.T) {
{
name: "interactive",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
interactive: true,
isTerminal: true,
wantInput: `{
"kind":"ExecCredential",
"apiVersion":"client.authentication.k8s.io/v1alpha1",
@@ -347,7 +366,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "response",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
response: &clientauthentication.Response{
Header: map[string][]string{
@@ -381,7 +401,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "expiry",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -402,7 +423,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "no-group-version",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -420,7 +442,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "no-status",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -436,7 +459,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "no-creds",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -453,7 +477,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "TLS credentials",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -473,7 +498,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "bad TLS credentials",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -493,7 +519,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "cert but no key",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind":"ExecCredential",
@@ -512,12 +539,207 @@ func TestRefreshCreds(t *testing.T) {
{
name: "beta-basic-request",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {}
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-never-interactive-mode",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.NeverExecInteractiveMode,
},
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-never-interactive-mode-and-stdin-unavailable",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.NeverExecInteractiveMode,
StdinUnavailable: true,
},
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-if-available-interactive-mode",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-if-available-interactive-mode-and-stdin-unavailable",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
StdinUnavailable: true,
},
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-if-available-interactive-mode-and-terminal",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
isTerminal: true,
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": true
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-if-available-interactive-mode-and-terminal-and-stdin-unavailable",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
StdinUnavailable: true,
},
isTerminal: true,
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"status": {
"token": "foo-bar"
}
}`,
wantCreds: credentials{token: "foo-bar"},
},
{
name: "beta-basic-request-with-always-interactive-mode",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.AlwaysExecInteractiveMode,
},
wantErr: true,
wantErrSubstr: "exec plugin cannot support interactive mode: standard input is not a terminal",
},
{
name: "beta-basic-request-with-always-interactive-mode-and-terminal-and-stdin-unavailable",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.AlwaysExecInteractiveMode,
StdinUnavailable: true,
},
isTerminal: true,
wantErr: true,
wantErrSubstr: "exec plugin cannot support interactive mode: standard input is unavailable",
},
{
name: "beta-basic-request-with-always-interactive-mode-and-terminal-and-stdin-unavailable-with-message",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.AlwaysExecInteractiveMode,
StdinUnavailable: true,
StdinUnavailableMessage: "some message",
},
isTerminal: true,
wantErr: true,
wantErrSubstr: "exec plugin cannot support interactive mode: standard input is unavailable: some message",
},
{
name: "beta-basic-request-with-always-interactive-mode-and-terminal",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.AlwaysExecInteractiveMode,
},
isTerminal: true,
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {
"interactive": true
}
}`,
output: `{
"kind": "ExecCredential",
@@ -531,12 +753,15 @@ func TestRefreshCreds(t *testing.T) {
{
name: "beta-expiry",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantInput: `{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1beta1",
"spec": {}
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
@@ -552,7 +777,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "beta-no-group-version",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
output: `{
"kind": "ExecCredential",
@@ -565,7 +791,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "beta-no-status",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
output: `{
"kind": "ExecCredential",
@@ -576,7 +803,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "beta-no-token",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
output: `{
"kind": "ExecCredential",
@@ -588,9 +816,10 @@ func TestRefreshCreds(t *testing.T) {
{
name: "unknown-binary",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
Command: "does not exist",
InstallHint: "some install hint",
APIVersion: "client.authentication.k8s.io/v1beta1",
Command: "does not exist",
InstallHint: "some install hint",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
wantErr: true,
wantErrSubstr: "some install hint",
@@ -598,7 +827,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "binary-fails",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
exitCode: 73,
wantErr: true,
@@ -607,7 +837,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "alpha-with-cluster-is-ignored",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
cluster: &clientauthentication.Cluster{
Server: "foo",
@@ -657,6 +888,7 @@ func TestRefreshCreds(t *testing.T) {
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
ProvideClusterInfo: true,
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
cluster: &clientauthentication.Cluster{
Server: "foo",
@@ -693,7 +925,8 @@ func TestRefreshCreds(t *testing.T) {
"audience": "snorlax"
}
}
}
},
"interactive": false
}
}`,
output: `{
@@ -708,7 +941,8 @@ func TestRefreshCreds(t *testing.T) {
{
name: "beta-with-cluster-and-without-provide-cluster-info-is-not-serialized",
config: api.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
},
cluster: &clientauthentication.Cluster{
Server: "foo",
@@ -733,7 +967,9 @@ func TestRefreshCreds(t *testing.T) {
wantInput: `{
"kind":"ExecCredential",
"apiVersion":"client.authentication.k8s.io/v1beta1",
"spec": {}
"spec": {
"interactive": false
}
}`,
output: `{
"kind": "ExecCredential",
@@ -762,14 +998,13 @@ func TestRefreshCreds(t *testing.T) {
})
}
a, err := newAuthenticator(newCache(), &c, test.cluster)
a, err := newAuthenticator(newCache(), func(_ int) bool { return test.isTerminal }, &c, test.cluster)
if err != nil {
t.Fatal(err)
}
stderr := &bytes.Buffer{}
a.stderr = stderr
a.interactive = test.interactive
a.environ = func() []string { return nil }
if err := a.refreshCredsLocked(test.response); err != nil {
@@ -837,10 +1072,11 @@ func TestRoundTripper(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(handler))
c := api.ExecConfig{
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1alpha1",
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
}
a, err := newAuthenticator(newCache(), &c, nil)
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &c, nil)
if err != nil {
t.Fatal(err)
}
@@ -943,7 +1179,7 @@ func TestAuthorizationHeaderPresentCancelsExecAction(t *testing.T) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
a, err := newAuthenticator(newCache(), &api.ExecConfig{
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &api.ExecConfig{
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1alpha1",
}, nil)
@@ -985,9 +1221,10 @@ func TestTLSCredentials(t *testing.T) {
server.StartTLS()
defer server.Close()
a, err := newAuthenticator(newCache(), &api.ExecConfig{
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1alpha1",
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &api.ExecConfig{
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
}, nil)
if err != nil {
t.Fatal(err)
@@ -1078,7 +1315,7 @@ func TestConcurrentUpdateTransportConfig(t *testing.T) {
Command: "./testdata/test-plugin.sh",
APIVersion: "client.authentication.k8s.io/v1alpha1",
}
a, err := newAuthenticator(newCache(), &c, nil)
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &c, nil)
if err != nil {
t.Fatal(err)
}
@@ -1141,11 +1378,12 @@ func TestInstallHintRateLimit(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
c := api.ExecConfig{
Command: "does not exist",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InstallHint: "some install hint",
Command: "does not exist",
APIVersion: "client.authentication.k8s.io/v1alpha1",
InstallHint: "some install hint",
InteractiveMode: api.IfAvailableExecInteractiveMode,
}
a, err := newAuthenticator(newCache(), &c, nil)
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &c, nil)
if err != nil {
t.Fatal(err)
}

View File

@@ -140,9 +140,10 @@ func TestCallsMetric(t *testing.T) {
{Name: "TEST_EXIT_CODE", Value: fmt.Sprintf("%d", exitCode)},
{Name: "TEST_OUTPUT", Value: goodOutput},
},
InteractiveMode: api.IfAvailableExecInteractiveMode,
}
a, err := newAuthenticator(newCache(), &c, nil)
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &c, nil)
if err != nil {
t.Fatal(err)
}
@@ -171,10 +172,11 @@ func TestCallsMetric(t *testing.T) {
// metric values.
refreshCreds := func(command string) {
c := api.ExecConfig{
Command: "does not exist",
APIVersion: "client.authentication.k8s.io/v1beta1",
Command: "does not exist",
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: api.IfAvailableExecInteractiveMode,
}
a, err := newAuthenticator(newCache(), &c, nil)
a, err := newAuthenticator(newCache(), func(_ int) bool { return false }, &c, nil)
if err != nil {
t.Fatal(err)
}

View File

@@ -626,7 +626,7 @@ func TestConfigSprint(t *testing.T) {
Proxy: fakeProxyFunc,
}
want := fmt.Sprintf(
`&rest.Config{Host:"localhost:8080", APIPath:"v1", ContentConfig:rest.ContentConfig{AcceptContentTypes:"application/json", ContentType:"application/json", GroupVersion:(*schema.GroupVersion)(nil), NegotiatedSerializer:runtime.NegotiatedSerializer(nil)}, Username:"gopher", Password:"--- REDACTED ---", BearerToken:"--- REDACTED ---", BearerTokenFile:"", Impersonate:rest.ImpersonationConfig{UserName:"gopher2", Groups:[]string(nil), Extra:map[string][]string(nil)}, AuthProvider:api.AuthProviderConfig{Name: "gopher", Config: map[string]string{--- REDACTED ---}}, AuthConfigPersister:rest.AuthProviderConfigPersister(--- REDACTED ---), ExecProvider:api.ExecConfig{Command: "sudo", Args: []string{"--- REDACTED ---"}, Env: []ExecEnvVar{--- REDACTED ---}, APIVersion: "", ProvideClusterInfo: true, Config: runtime.Object(--- REDACTED ---)}, TLSClientConfig:rest.sanitizedTLSClientConfig{Insecure:false, ServerName:"", CertFile:"a.crt", KeyFile:"a.key", CAFile:"", CertData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, KeyData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x52, 0x45, 0x44, 0x41, 0x43, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, CAData:[]uint8(nil), NextProtos:[]string{"h2", "http/1.1"}}, UserAgent:"gobot", DisableCompression:false, Transport:(*rest.fakeRoundTripper)(%p), WrapTransport:(transport.WrapperFunc)(%p), QPS:1, Burst:2, RateLimiter:(*rest.fakeLimiter)(%p), WarningHandler:rest.fakeWarningHandler{}, Timeout:3000000000, Dial:(func(context.Context, string, string) (net.Conn, error))(%p), Proxy:(func(*http.Request) (*url.URL, error))(%p)}`,
`&rest.Config{Host:"localhost:8080", APIPath:"v1", ContentConfig:rest.ContentConfig{AcceptContentTypes:"application/json", ContentType:"application/json", GroupVersion:(*schema.GroupVersion)(nil), NegotiatedSerializer:runtime.NegotiatedSerializer(nil)}, Username:"gopher", Password:"--- REDACTED ---", BearerToken:"--- REDACTED ---", BearerTokenFile:"", Impersonate:rest.ImpersonationConfig{UserName:"gopher2", Groups:[]string(nil), Extra:map[string][]string(nil)}, AuthProvider:api.AuthProviderConfig{Name: "gopher", Config: map[string]string{--- REDACTED ---}}, AuthConfigPersister:rest.AuthProviderConfigPersister(--- REDACTED ---), ExecProvider:api.ExecConfig{Command: "sudo", Args: []string{"--- REDACTED ---"}, Env: []ExecEnvVar{--- REDACTED ---}, APIVersion: "", ProvideClusterInfo: true, Config: runtime.Object(--- REDACTED ---), StdinUnavailable: false}, TLSClientConfig:rest.sanitizedTLSClientConfig{Insecure:false, ServerName:"", CertFile:"a.crt", KeyFile:"a.key", CAFile:"", CertData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, KeyData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x52, 0x45, 0x44, 0x41, 0x43, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, CAData:[]uint8(nil), NextProtos:[]string{"h2", "http/1.1"}}, UserAgent:"gobot", DisableCompression:false, Transport:(*rest.fakeRoundTripper)(%p), WrapTransport:(transport.WrapperFunc)(%p), QPS:1, Burst:2, RateLimiter:(*rest.fakeLimiter)(%p), WarningHandler:rest.fakeWarningHandler{}, Timeout:3000000000, Dial:(func(context.Context, string, string) (net.Conn, error))(%p), Proxy:(func(*http.Request) (*url.URL, error))(%p)}`,
c.Transport, fakeWrapperFunc, c.RateLimiter, fakeDialFunc, fakeProxyFunc,
)

View File

@@ -1077,13 +1077,13 @@ func (r *Request) transformResponse(resp *http.Response, req *http.Request) Resu
// 3. Apiserver closes connection.
// 4. client-go should catch this and return an error.
klog.V(2).Infof("Stream error %#v when reading response body, may be caused by closed connection.", err)
streamErr := fmt.Errorf("stream error when reading response body, may be caused by closed connection. Please retry. Original error: %v", err)
streamErr := fmt.Errorf("stream error when reading response body, may be caused by closed connection. Please retry. Original error: %w", err)
return Result{
err: streamErr,
}
default:
klog.Errorf("Unexpected error when reading response body: %v", err)
unexpectedErr := fmt.Errorf("unexpected error when reading response body. Please retry. Original error: %v", err)
unexpectedErr := fmt.Errorf("unexpected error when reading response body. Please retry. Original error: %w", err)
return Result{
err: unexpectedErr,
}

View File

@@ -216,13 +216,13 @@ var internalPackages = []string{"client-go/tools/cache/"}
// objects and subsequent deltas.
// Run will exit when stopCh is closed.
func (r *Reflector) Run(stopCh <-chan struct{}) {
klog.V(2).Infof("Starting reflector %s (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
klog.V(3).Infof("Starting reflector %s (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
wait.BackoffUntil(func() {
if err := r.ListAndWatch(stopCh); err != nil {
r.watchErrorHandler(r, err)
}
}, r.backoffManager, true, stopCh)
klog.V(2).Infof("Stopping reflector %s (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
klog.V(3).Infof("Stopping reflector %s (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
}
var (

View File

@@ -245,6 +245,33 @@ type ExecConfig struct {
// to be stored directly in the kubeconfig.
// +k8s:conversion-gen=false
Config runtime.Object
// InteractiveMode determines this plugin's relationship with standard input. Valid
// values are "Never" (this exec plugin never uses standard input), "IfAvailable" (this
// exec plugin wants to use standard input if it is available), or "Always" (this exec
// plugin requires standard input to function). See ExecInteractiveMode values for more
// details.
//
// If APIVersion is client.authentication.k8s.io/v1alpha1 or
// client.authentication.k8s.io/v1beta1, then this field is optional and defaults
// to "IfAvailable" when unset. Otherwise, this field is required.
// +optional
InteractiveMode ExecInteractiveMode
// StdinUnavailable indicates whether the exec authenticator can pass standard
// input through to this exec plugin. For example, a higher level entity might be using
// standard input for something else and therefore it would not be safe for the exec
// plugin to use standard input. This is kept here in order to keep all of the exec configuration
// together, but it is never serialized.
// +k8s:conversion-gen=false
StdinUnavailable bool
// StdinUnavailableMessage is an optional message to be displayed when the exec authenticator
// cannot successfully run this exec plugin because it needs to use standard input and
// StdinUnavailable is true. For example, a process that is already using standard input to
// read user instructions might set this to "used by my-program to read user instructions".
// +k8s:conversion-gen=false
StdinUnavailableMessage string
}
var _ fmt.Stringer = new(ExecConfig)
@@ -271,7 +298,7 @@ func (c ExecConfig) String() string {
if c.Config != nil {
config = "runtime.Object(--- REDACTED ---)"
}
return fmt.Sprintf("api.ExecConfig{Command: %q, Args: %#v, Env: %s, APIVersion: %q, ProvideClusterInfo: %t, Config: %s}", c.Command, args, env, c.APIVersion, c.ProvideClusterInfo, config)
return fmt.Sprintf("api.ExecConfig{Command: %q, Args: %#v, Env: %s, APIVersion: %q, ProvideClusterInfo: %t, Config: %s, StdinUnavailable: %t}", c.Command, args, env, c.APIVersion, c.ProvideClusterInfo, config, c.StdinUnavailable)
}
// ExecEnvVar is used for setting environment variables when executing an exec-based
@@ -281,6 +308,26 @@ type ExecEnvVar struct {
Value string `json:"value"`
}
// ExecInteractiveMode is a string that describes an exec plugin's relationship with standard input.
type ExecInteractiveMode string
const (
// NeverExecInteractiveMode declares that this exec plugin never needs to use standard
// input, and therefore the exec plugin will be run regardless of whether standard input is
// available for user input.
NeverExecInteractiveMode ExecInteractiveMode = "Never"
// IfAvailableExecInteractiveMode declares that this exec plugin would like to use standard input
// if it is available, but can still operate if standard input is not available. Therefore, the
// exec plugin will be run regardless of whether stdin is available for user input. If standard
// input is available for user input, then it will be provided to this exec plugin.
IfAvailableExecInteractiveMode ExecInteractiveMode = "IfAvailable"
// AlwaysExecInteractiveMode declares that this exec plugin requires standard input in order to
// run, and therefore the exec plugin will only be run if standard input is available for user
// input. If standard input is not available for user input, then the exec plugin will not be run
// and an error will be returned by the exec plugin runner.
AlwaysExecInteractiveMode ExecInteractiveMode = "Always"
)
// NewConfig is a convenience function that returns a new Config object with non-nil maps
func NewConfig() *Config {
return &Config{

View File

@@ -0,0 +1,37 @@
/*
Copyright 2021 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 v1
import (
"k8s.io/apimachinery/pkg/runtime"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}
func SetDefaults_ExecConfig(exec *ExecConfig) {
if len(exec.InteractiveMode) == 0 {
switch exec.APIVersion {
case "client.authentication.k8s.io/v1beta1", "client.authentication.k8s.io/v1alpha1":
// default to IfAvailableExecInteractiveMode for backwards compatibility
exec.InteractiveMode = IfAvailableExecInteractiveMode
default:
// require other versions to explicitly declare whether they want stdin or not
}
}
}

View File

@@ -0,0 +1,84 @@
/*
Copyright 2021 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 v1
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestSetDefaults_Config(t *testing.T) {
tests := []struct {
name string
in, wantOut *ExecConfig
}{
{
name: "alpha exec API with empty interactive mode",
in: &ExecConfig{APIVersion: "client.authentication.k8s.io/v1alpha1"},
wantOut: &ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: IfAvailableExecInteractiveMode,
},
},
{
name: "beta exec API with empty interactive mode",
in: &ExecConfig{APIVersion: "client.authentication.k8s.io/v1beta1"},
wantOut: &ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: IfAvailableExecInteractiveMode,
},
},
{
name: "alpha exec API with set interactive mode",
in: &ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: NeverExecInteractiveMode,
},
wantOut: &ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
InteractiveMode: NeverExecInteractiveMode,
},
},
{
name: "beta exec API with set interactive mode",
in: &ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: NeverExecInteractiveMode,
},
wantOut: &ExecConfig{
APIVersion: "client.authentication.k8s.io/v1beta1",
InteractiveMode: NeverExecInteractiveMode,
},
},
{
name: "v1 exec API with empty interactive mode",
in: &ExecConfig{APIVersion: "client.authentication.k8s.io/v1"},
wantOut: &ExecConfig{APIVersion: "client.authentication.k8s.io/v1"},
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
gotOut := test.in.DeepCopy()
SetDefaults_ExecConfig(gotOut)
if diff := cmp.Diff(test.wantOut, gotOut); diff != "" {
t.Errorf("unexpected defaulting; -want, +got:\n %s", diff)
}
})
}
}

View File

@@ -16,5 +16,6 @@ limitations under the License.
// +k8s:conversion-gen=k8s.io/client-go/tools/clientcmd/api
// +k8s:deepcopy-gen=package
// +k8s:defaulter-gen=Kind
package v1

View File

@@ -37,7 +37,7 @@ func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
}
func addKnownTypes(scheme *runtime.Scheme) error {

View File

@@ -221,6 +221,18 @@ type ExecConfig struct {
// to false. Package k8s.io/client-go/tools/auth/exec provides helper methods for
// reading this environment variable.
ProvideClusterInfo bool `json:"provideClusterInfo"`
// InteractiveMode determines this plugin's relationship with standard input. Valid
// values are "Never" (this exec plugin never uses standard input), "IfAvailable" (this
// exec plugin wants to use standard input if it is available), or "Always" (this exec
// plugin requires standard input to function). See ExecInteractiveMode values for more
// details.
//
// If APIVersion is client.authentication.k8s.io/v1alpha1 or
// client.authentication.k8s.io/v1beta1, then this field is optional and defaults
// to "IfAvailable" when unset. Otherwise, this field is required.
//+optional
InteractiveMode ExecInteractiveMode `json:"interactiveMode,omitempty"`
}
// ExecEnvVar is used for setting environment variables when executing an exec-based
@@ -229,3 +241,23 @@ type ExecEnvVar struct {
Name string `json:"name"`
Value string `json:"value"`
}
// ExecInteractiveMode is a string that describes an exec plugin's relationship with standard input.
type ExecInteractiveMode string
const (
// NeverExecInteractiveMode declares that this exec plugin never needs to use standard
// input, and therefore the exec plugin will be run regardless of whether standard input is
// available for user input.
NeverExecInteractiveMode ExecInteractiveMode = "Never"
// IfAvailableExecInteractiveMode declares that this exec plugin would like to use standard input
// if it is available, but can still operate if standard input is not available. Therefore, the
// exec plugin will be run regardless of whether stdin is available for user input. If standard
// input is available for user input, then it will be provided to this exec plugin.
IfAvailableExecInteractiveMode ExecInteractiveMode = "IfAvailable"
// AlwaysExecInteractiveMode declares that this exec plugin requires standard input in order to
// run, and therefore the exec plugin will only be run if standard input is available for user
// input. If standard input is not available for user input, then the exec plugin will not be run
// and an error will be returned by the exec plugin runner.
AlwaysExecInteractiveMode ExecInteractiveMode = "Always"
)

View File

@@ -376,6 +376,7 @@ func autoConvert_v1_ExecConfig_To_api_ExecConfig(in *ExecConfig, out *api.ExecCo
out.APIVersion = in.APIVersion
out.InstallHint = in.InstallHint
out.ProvideClusterInfo = in.ProvideClusterInfo
out.InteractiveMode = api.ExecInteractiveMode(in.InteractiveMode)
return nil
}
@@ -392,6 +393,9 @@ func autoConvert_api_ExecConfig_To_v1_ExecConfig(in *api.ExecConfig, out *ExecCo
out.InstallHint = in.InstallHint
out.ProvideClusterInfo = in.ProvideClusterInfo
// INFO: in.Config opted out of conversion generation
out.InteractiveMode = ExecInteractiveMode(in.InteractiveMode)
// INFO: in.StdinUnavailable opted out of conversion generation
// INFO: in.StdinUnavailableMessage opted out of conversion generation
return nil
}

View File

@@ -0,0 +1,42 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by defaulter-gen. DO NOT EDIT.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&Config{}, func(obj interface{}) { SetObjectDefaults_Config(obj.(*Config)) })
return nil
}
func SetObjectDefaults_Config(in *Config) {
for i := range in.AuthInfos {
a := &in.AuthInfos[i]
if a.AuthInfo.Exec != nil {
SetDefaults_ExecConfig(a.AuthInfo.Exec)
}
}
}

View File

@@ -630,9 +630,10 @@ func TestCreateAuthConfigExecInstallHintCleanup(t *testing.T) {
clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{
AuthInfo: clientcmdapi.AuthInfo{
Exec: &clientcmdapi.ExecConfig{
APIVersion: "client.authentication.k8s.io/v1alpha1",
Command: "some-command",
InstallHint: "some install hint with \x1b[1mcontrol chars\x1b[0m\nand a newline",
APIVersion: "client.authentication.k8s.io/v1alpha1",
Command: "some-command",
InstallHint: "some install hint with \x1b[1mcontrol chars\x1b[0m\nand a newline",
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
},
},
}, nil)

View File

@@ -308,6 +308,14 @@ func validateAuthInfo(authInfoName string, authInfo clientcmdapi.AuthInfo) []err
validationErrors = append(validationErrors, fmt.Errorf("env variable name must be specified for %v to use exec authentication plugin", authInfoName))
}
}
switch authInfo.Exec.InteractiveMode {
case "":
validationErrors = append(validationErrors, fmt.Errorf("interactiveMode must be specified for %v to use exec authentication plugin", authInfoName))
case clientcmdapi.NeverExecInteractiveMode, clientcmdapi.IfAvailableExecInteractiveMode, clientcmdapi.AlwaysExecInteractiveMode:
// These are valid
default:
validationErrors = append(validationErrors, fmt.Errorf("invalid interactiveMode for %v: %q", authInfoName, authInfo.Exec.InteractiveMode))
}
}
// authPath also provides information for the client to identify the server, so allow multiple auth methods in that case

View File

@@ -377,6 +377,7 @@ func TestValidateAuthInfoExec(t *testing.T) {
Env: []clientcmdapi.ExecEnvVar{
{Name: "foo", Value: "bar"},
},
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
},
}
test := configValidationTest{
@@ -391,7 +392,8 @@ func TestValidateAuthInfoExecNoVersion(t *testing.T) {
config := clientcmdapi.NewConfig()
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
Exec: &clientcmdapi.ExecConfig{
Command: "/bin/example",
Command: "/bin/example",
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
},
}
test := configValidationTest{
@@ -409,7 +411,8 @@ func TestValidateAuthInfoExecNoCommand(t *testing.T) {
config := clientcmdapi.NewConfig()
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
Exec: &clientcmdapi.ExecConfig{
APIVersion: "clientauthentication.k8s.io/v1alpha1",
APIVersion: "clientauthentication.k8s.io/v1alpha1",
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
},
}
test := configValidationTest{
@@ -430,8 +433,9 @@ func TestValidateAuthInfoExecWithAuthProvider(t *testing.T) {
Name: "oidc",
},
Exec: &clientcmdapi.ExecConfig{
Command: "/bin/example",
APIVersion: "clientauthentication.k8s.io/v1alpha1",
Command: "/bin/example",
APIVersion: "clientauthentication.k8s.io/v1alpha1",
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
},
}
test := configValidationTest{
@@ -454,6 +458,7 @@ func TestValidateAuthInfoExecNoEnv(t *testing.T) {
Env: []clientcmdapi.ExecEnvVar{
{Name: "foo", Value: ""},
},
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
},
}
test := configValidationTest{
@@ -464,6 +469,45 @@ func TestValidateAuthInfoExecNoEnv(t *testing.T) {
test.testConfig(t)
}
func TestValidateAuthInfoExecInteractiveModeMissing(t *testing.T) {
config := clientcmdapi.NewConfig()
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
Exec: &clientcmdapi.ExecConfig{
Command: "/bin/example",
APIVersion: "clientauthentication.k8s.io/v1alpha1",
},
}
test := configValidationTest{
config: config,
expectedErrorSubstring: []string{
"interactiveMode must be specified for user to use exec authentication plugin",
},
}
test.testAuthInfo("user", t)
test.testConfig(t)
}
func TestValidateAuthInfoExecInteractiveModeInvalid(t *testing.T) {
config := clientcmdapi.NewConfig()
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
Exec: &clientcmdapi.ExecConfig{
Command: "/bin/example",
APIVersion: "clientauthentication.k8s.io/v1alpha1",
InteractiveMode: "invalid",
},
}
test := configValidationTest{
config: config,
expectedErrorSubstring: []string{
`invalid interactiveMode for user: "invalid"`,
},
}
test.testAuthInfo("user", t)
test.testConfig(t)
}
type configValidationTest struct {
config *clientcmdapi.Config
expectedErrorSubstring []string