From 4f915039e4ae5b5f32b54c048ef679639a442a55 Mon Sep 17 00:00:00 2001 From: deads2k Date: Mon, 16 Jan 2017 16:20:38 -0500 Subject: [PATCH] move pkg/client/transport to client-go --- cmd/kube-aggregator/pkg/apiserver/BUILD | 2 +- .../pkg/apiserver/handler_proxy.go | 2 +- hack/make-rules/test.sh | 4 + pkg/BUILD | 1 - pkg/client/restclient/BUILD | 2 +- pkg/client/restclient/transport.go | 2 +- pkg/client/transport/BUILD | 48 -- pkg/client/transport/OWNERS | 7 - pkg/client/transport/cache.go | 88 ---- pkg/client/transport/cache_test.go | 114 ----- pkg/client/transport/config.go | 94 ---- pkg/client/transport/round_trippers.go | 436 ------------------ pkg/client/transport/round_trippers_test.go | 218 --------- pkg/client/transport/transport.go | 140 ------ pkg/client/transport/transport_test.go | 204 -------- pkg/client/unversioned/remotecommand/BUILD | 2 +- .../remotecommand/remotecommand.go | 2 +- pkg/kubelet/client/BUILD | 2 +- pkg/kubelet/client/kubelet_client.go | 2 +- staging/copy.sh | 23 +- staging/godeps-json-updater.go | 3 + test/e2e/BUILD | 2 +- test/e2e/load.go | 2 +- test/integration/auth/rbac_test.go | 2 +- 24 files changed, 39 insertions(+), 1363 deletions(-) delete mode 100644 pkg/client/transport/BUILD delete mode 100755 pkg/client/transport/OWNERS delete mode 100644 pkg/client/transport/cache.go delete mode 100644 pkg/client/transport/cache_test.go delete mode 100644 pkg/client/transport/config.go delete mode 100644 pkg/client/transport/round_trippers.go delete mode 100644 pkg/client/transport/round_trippers_test.go delete mode 100644 pkg/client/transport/transport.go delete mode 100644 pkg/client/transport/transport_test.go diff --git a/cmd/kube-aggregator/pkg/apiserver/BUILD b/cmd/kube-aggregator/pkg/apiserver/BUILD index f5c36a1f5bb..c1489bf8e72 100644 --- a/cmd/kube-aggregator/pkg/apiserver/BUILD +++ b/cmd/kube-aggregator/pkg/apiserver/BUILD @@ -56,7 +56,6 @@ go_library( "//pkg/client/informers/informers_generated:go_default_library", "//pkg/client/listers/core/v1:go_default_library", "//pkg/client/restclient:go_default_library", - "//pkg/client/transport:go_default_library", "//pkg/controller:go_default_library", "//pkg/genericapiserver:go_default_library", "//pkg/genericapiserver/api/filters:go_default_library", @@ -76,6 +75,7 @@ go_library( "//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apiserver/pkg/request", + "//vendor:k8s.io/client-go/transport", ], ) diff --git a/cmd/kube-aggregator/pkg/apiserver/handler_proxy.go b/cmd/kube-aggregator/pkg/apiserver/handler_proxy.go index df6358382ca..b9b0001b001 100644 --- a/cmd/kube-aggregator/pkg/apiserver/handler_proxy.go +++ b/cmd/kube-aggregator/pkg/apiserver/handler_proxy.go @@ -23,8 +23,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" genericapirequest "k8s.io/apiserver/pkg/request" + "k8s.io/client-go/transport" "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/transport" "k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters" genericrest "k8s.io/kubernetes/pkg/registry/generic/rest" "k8s.io/kubernetes/pkg/util/httpstream/spdy" diff --git a/hack/make-rules/test.sh b/hack/make-rules/test.sh index cd2286f03d6..26714e4399c 100755 --- a/hack/make-rules/test.sh +++ b/hack/make-rules/test.sh @@ -57,6 +57,10 @@ kube::test::find_dirs() { -o -path './test/e2e_node/system/*' \ -name '*_test.go' -print0 | xargs -0n1 dirname | sed "s|^\./|${KUBE_GO_PACKAGE}/|" | LC_ALL=C sort -u + # run tests for client-go + find ./staging/src/k8s.io/client-go -name '*_test.go' \ + -name '*_test.go' -print0 | xargs -0n1 dirname | sed 's|^\./staging/src/|./vendor/|' | LC_ALL=C sort -u + # run tests for apiserver find ./staging/src/k8s.io/apiserver -name '*_test.go' \ -name '*_test.go' -print0 | xargs -0n1 dirname | sed 's|^\./staging/src/|./vendor/|' | LC_ALL=C sort -u diff --git a/pkg/BUILD b/pkg/BUILD index 2aa393a3bae..50e729d3cc5 100644 --- a/pkg/BUILD +++ b/pkg/BUILD @@ -73,7 +73,6 @@ filegroup( "//pkg/client/testdata:all-srcs", "//pkg/client/testing/cache:all-srcs", "//pkg/client/testing/core:all-srcs", - "//pkg/client/transport:all-srcs", "//pkg/client/typed/discovery:all-srcs", "//pkg/client/typed/dynamic:all-srcs", "//pkg/client/unversioned:all-srcs", diff --git a/pkg/client/restclient/BUILD b/pkg/client/restclient/BUILD index 678624aadb5..3b173cec268 100644 --- a/pkg/client/restclient/BUILD +++ b/pkg/client/restclient/BUILD @@ -27,7 +27,6 @@ go_library( "//pkg/api/validation/path:go_default_library", "//pkg/client/metrics:go_default_library", "//pkg/client/restclient/watch:go_default_library", - "//pkg/client/transport:go_default_library", "//pkg/client/unversioned/clientcmd/api:go_default_library", "//pkg/fields:go_default_library", "//pkg/util/cert:go_default_library", @@ -44,6 +43,7 @@ go_library( "//vendor:k8s.io/apimachinery/pkg/util/net", "//vendor:k8s.io/apimachinery/pkg/util/sets", "//vendor:k8s.io/apimachinery/pkg/watch", + "//vendor:k8s.io/client-go/transport", ], ) diff --git a/pkg/client/restclient/transport.go b/pkg/client/restclient/transport.go index 48e8042ee80..0b4f5b6cbbd 100644 --- a/pkg/client/restclient/transport.go +++ b/pkg/client/restclient/transport.go @@ -20,7 +20,7 @@ import ( "crypto/tls" "net/http" - "k8s.io/kubernetes/pkg/client/transport" + "k8s.io/client-go/transport" ) // TLSConfigFor returns a tls.Config that will provide the transport level security defined diff --git a/pkg/client/transport/BUILD b/pkg/client/transport/BUILD deleted file mode 100644 index d2f4eaa2d1e..00000000000 --- a/pkg/client/transport/BUILD +++ /dev/null @@ -1,48 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "cache.go", - "config.go", - "round_trippers.go", - "transport.go", - ], - tags = ["automanaged"], - deps = [ - "//vendor:github.com/golang/glog", - "//vendor:k8s.io/apimachinery/pkg/util/net", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "cache_test.go", - "round_trippers_test.go", - "transport_test.go", - ], - library = ":go_default_library", - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/client/transport/OWNERS b/pkg/client/transport/OWNERS deleted file mode 100755 index bf0ba5b9f95..00000000000 --- a/pkg/client/transport/OWNERS +++ /dev/null @@ -1,7 +0,0 @@ -reviewers: -- smarterclayton -- wojtek-t -- deads2k -- liggitt -- krousey -- caesarxuchao diff --git a/pkg/client/transport/cache.go b/pkg/client/transport/cache.go deleted file mode 100644 index 8d76def345d..00000000000 --- a/pkg/client/transport/cache.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import ( - "fmt" - "net" - "net/http" - "sync" - "time" - - utilnet "k8s.io/apimachinery/pkg/util/net" -) - -// TlsTransportCache caches TLS http.RoundTrippers different configurations. The -// same RoundTripper will be returned for configs with identical TLS options If -// the config has no custom TLS options, http.DefaultTransport is returned. -type tlsTransportCache struct { - mu sync.Mutex - transports map[string]*http.Transport -} - -const idleConnsPerHost = 25 - -var tlsCache = &tlsTransportCache{transports: make(map[string]*http.Transport)} - -func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { - key, err := tlsConfigKey(config) - if err != nil { - return nil, err - } - - // Ensure we only create a single transport for the given TLS options - c.mu.Lock() - defer c.mu.Unlock() - - // See if we already have a custom transport for this config - if t, ok := c.transports[key]; ok { - return t, nil - } - - // Get the TLS options for this client config - tlsConfig, err := TLSConfigFor(config) - if err != nil { - return nil, err - } - // The options didn't require a custom TLS config - if tlsConfig == nil { - return http.DefaultTransport, nil - } - - // Cache a single transport for these options - c.transports[key] = utilnet.SetTransportDefaults(&http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: tlsConfig, - MaxIdleConnsPerHost: idleConnsPerHost, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - }) - return c.transports[key], nil -} - -// tlsConfigKey returns a unique key for tls.Config objects returned from TLSConfigFor -func tlsConfigKey(c *Config) (string, error) { - // Make sure ca/key/cert content is loaded - if err := loadTLSFiles(c); err != nil { - return "", err - } - // Only include the things that actually affect the tls.Config - return fmt.Sprintf("%v/%x/%x/%x", c.TLS.Insecure, c.TLS.CAData, c.TLS.CertData, c.TLS.KeyData), nil -} diff --git a/pkg/client/transport/cache_test.go b/pkg/client/transport/cache_test.go deleted file mode 100644 index eb9624d7edb..00000000000 --- a/pkg/client/transport/cache_test.go +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import ( - "net/http" - "testing" -) - -func TestTLSConfigKey(t *testing.T) { - // Make sure config fields that don't affect the tls config don't affect the cache key - identicalConfigurations := map[string]*Config{ - "empty": {}, - "basic": {Username: "bob", Password: "password"}, - "bearer": {BearerToken: "token"}, - "user agent": {UserAgent: "useragent"}, - "transport": {Transport: http.DefaultTransport}, - "wrap transport": {WrapTransport: func(http.RoundTripper) http.RoundTripper { return nil }}, - } - for nameA, valueA := range identicalConfigurations { - for nameB, valueB := range identicalConfigurations { - keyA, err := tlsConfigKey(valueA) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameA, err) - continue - } - keyB, err := tlsConfigKey(valueB) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameB, err) - continue - } - if keyA != keyB { - t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB) - continue - } - } - } - - // Make sure config fields that affect the tls config affect the cache key - uniqueConfigurations := map[string]*Config{ - "no tls": {}, - "insecure": {TLS: TLSConfig{Insecure: true}}, - "cadata 1": {TLS: TLSConfig{CAData: []byte{1}}}, - "cadata 2": {TLS: TLSConfig{CAData: []byte{2}}}, - "cert 1, key 1": { - TLS: TLSConfig{ - CertData: []byte{1}, - KeyData: []byte{1}, - }, - }, - "cert 1, key 2": { - TLS: TLSConfig{ - CertData: []byte{1}, - KeyData: []byte{2}, - }, - }, - "cert 2, key 1": { - TLS: TLSConfig{ - CertData: []byte{2}, - KeyData: []byte{1}, - }, - }, - "cert 2, key 2": { - TLS: TLSConfig{ - CertData: []byte{2}, - KeyData: []byte{2}, - }, - }, - "cadata 1, cert 1, key 1": { - TLS: TLSConfig{ - CAData: []byte{1}, - CertData: []byte{1}, - KeyData: []byte{1}, - }, - }, - } - for nameA, valueA := range uniqueConfigurations { - for nameB, valueB := range uniqueConfigurations { - // Don't compare to ourselves - if nameA == nameB { - continue - } - - keyA, err := tlsConfigKey(valueA) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameA, err) - continue - } - keyB, err := tlsConfigKey(valueB) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameB, err) - continue - } - if keyA == keyB { - t.Errorf("Expected unique cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB) - continue - } - } - } -} diff --git a/pkg/client/transport/config.go b/pkg/client/transport/config.go deleted file mode 100644 index eaad99fb2f2..00000000000 --- a/pkg/client/transport/config.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import "net/http" - -// Config holds various options for establishing a transport. -type Config struct { - // UserAgent is an optional field that specifies the caller of this - // request. - UserAgent string - - // The base TLS configuration for this transport. - TLS TLSConfig - - // Username and password for basic authentication - Username string - Password string - - // Bearer token for authentication - BearerToken string - - // Impersonate is the config that this Config will impersonate using - Impersonate ImpersonationConfig - - // Transport may be used for custom HTTP behavior. This attribute may - // not be specified with the TLS client certificate options. Use - // WrapTransport for most client level operations. - Transport http.RoundTripper - - // WrapTransport will be invoked for custom HTTP behavior after the - // underlying transport is initialized (either the transport created - // from TLSClientConfig, Transport, or http.DefaultTransport). The - // config may layer other RoundTrippers on top of the returned - // RoundTripper. - WrapTransport func(rt http.RoundTripper) http.RoundTripper -} - -// ImpersonationConfig has all the available impersonation options -type ImpersonationConfig struct { - // UserName matches user.Info.GetName() - UserName string - // Groups matches user.Info.GetGroups() - Groups []string - // Extra matches user.Info.GetExtra() - Extra map[string][]string -} - -// HasCA returns whether the configuration has a certificate authority or not. -func (c *Config) HasCA() bool { - return len(c.TLS.CAData) > 0 || len(c.TLS.CAFile) > 0 -} - -// HasBasicAuth returns whether the configuration has basic authentication or not. -func (c *Config) HasBasicAuth() bool { - return len(c.Username) != 0 -} - -// HasTokenAuth returns whether the configuration has token authentication or not. -func (c *Config) HasTokenAuth() bool { - return len(c.BearerToken) != 0 -} - -// HasCertAuth returns whether the configuration has certificate authentication or not. -func (c *Config) HasCertAuth() bool { - return len(c.TLS.CertData) != 0 || len(c.TLS.CertFile) != 0 -} - -// TLSConfig holds the information needed to set up a TLS transport. -type TLSConfig struct { - CAFile string // Path of the PEM-encoded server trusted root certificates. - CertFile string // Path of the PEM-encoded client certificate. - KeyFile string // Path of the PEM-encoded client key. - - Insecure bool // Server should be accessed without verifying the certificate. For testing only. - - CAData []byte // Bytes of the PEM-encoded server trusted root certificates. Supercedes CAFile. - CertData []byte // Bytes of the PEM-encoded client certificate. Supercedes CertFile. - KeyData []byte // Bytes of the PEM-encoded client key. Supercedes KeyFile. -} diff --git a/pkg/client/transport/round_trippers.go b/pkg/client/transport/round_trippers.go deleted file mode 100644 index a6f396fbb0a..00000000000 --- a/pkg/client/transport/round_trippers.go +++ /dev/null @@ -1,436 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import ( - "fmt" - "net/http" - "strings" - "time" - - "github.com/golang/glog" -) - -// HTTPWrappersForConfig wraps a round tripper with any relevant layered -// behavior from the config. Exposed to allow more clients that need HTTP-like -// behavior but then must hijack the underlying connection (like WebSocket or -// HTTP2 clients). Pure HTTP clients should use the RoundTripper returned from -// New. -func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTripper, error) { - if config.WrapTransport != nil { - rt = config.WrapTransport(rt) - } - - rt = DebugWrappers(rt) - - // Set authentication wrappers - switch { - case config.HasBasicAuth() && config.HasTokenAuth(): - return nil, fmt.Errorf("username/password or bearer token may be set, but not both") - case config.HasTokenAuth(): - rt = NewBearerAuthRoundTripper(config.BearerToken, rt) - case config.HasBasicAuth(): - rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt) - } - if len(config.UserAgent) > 0 { - rt = NewUserAgentRoundTripper(config.UserAgent, rt) - } - if len(config.Impersonate.UserName) > 0 || - len(config.Impersonate.Groups) > 0 || - len(config.Impersonate.Extra) > 0 { - rt = NewImpersonatingRoundTripper(config.Impersonate, rt) - } - return rt, nil -} - -// DebugWrappers wraps a round tripper and logs based on the current log level. -func DebugWrappers(rt http.RoundTripper) http.RoundTripper { - switch { - case bool(glog.V(9)): - rt = newDebuggingRoundTripper(rt, debugCurlCommand, debugURLTiming, debugResponseHeaders) - case bool(glog.V(8)): - rt = newDebuggingRoundTripper(rt, debugJustURL, debugRequestHeaders, debugResponseStatus, debugResponseHeaders) - case bool(glog.V(7)): - rt = newDebuggingRoundTripper(rt, debugJustURL, debugRequestHeaders, debugResponseStatus) - case bool(glog.V(6)): - rt = newDebuggingRoundTripper(rt, debugURLTiming) - } - - return rt -} - -type requestCanceler interface { - CancelRequest(*http.Request) -} - -type authProxyRoundTripper struct { - username string - groups []string - extra map[string][]string - - rt http.RoundTripper -} - -// NewAuthProxyRoundTripper provides a roundtripper which will add auth proxy fields to requests for -// authentication terminating proxy cases -// assuming you pull the user from the context: -// username is the user.Info.GetName() of the user -// groups is the user.Info.GetGroups() of the user -// extra is the user.Info.GetExtra() of the user -// extra can contain any additional information that the authenticator -// thought was interesting, for example authorization scopes. -// In order to faithfully round-trip through an impersonation flow, these keys -// MUST be lowercase. -func NewAuthProxyRoundTripper(username string, groups []string, extra map[string][]string, rt http.RoundTripper) http.RoundTripper { - return &authProxyRoundTripper{ - username: username, - groups: groups, - extra: extra, - rt: rt, - } -} - -func (rt *authProxyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - req = cloneRequest(req) - SetAuthProxyHeaders(req, rt.username, rt.groups, rt.extra) - - return rt.rt.RoundTrip(req) -} - -// SetAuthProxyHeaders stomps the auth proxy header fields. It mutates its argument. -func SetAuthProxyHeaders(req *http.Request, username string, groups []string, extra map[string][]string) { - req.Header.Del("X-Remote-User") - req.Header.Del("X-Remote-Group") - for key := range req.Header { - if strings.HasPrefix(strings.ToLower(key), strings.ToLower("X-Remote-Extra-")) { - req.Header.Del(key) - } - } - - req.Header.Set("X-Remote-User", username) - for _, group := range groups { - req.Header.Add("X-Remote-Group", group) - } - for key, values := range extra { - for _, value := range values { - req.Header.Add("X-Remote-Extra-"+key, value) - } - } -} - -func (rt *authProxyRoundTripper) CancelRequest(req *http.Request) { - if canceler, ok := rt.rt.(requestCanceler); ok { - canceler.CancelRequest(req) - } else { - glog.Errorf("CancelRequest not implemented") - } -} - -func (rt *authProxyRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt } - -type userAgentRoundTripper struct { - agent string - rt http.RoundTripper -} - -func NewUserAgentRoundTripper(agent string, rt http.RoundTripper) http.RoundTripper { - return &userAgentRoundTripper{agent, rt} -} - -func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - if len(req.Header.Get("User-Agent")) != 0 { - return rt.rt.RoundTrip(req) - } - req = cloneRequest(req) - req.Header.Set("User-Agent", rt.agent) - return rt.rt.RoundTrip(req) -} - -func (rt *userAgentRoundTripper) CancelRequest(req *http.Request) { - if canceler, ok := rt.rt.(requestCanceler); ok { - canceler.CancelRequest(req) - } else { - glog.Errorf("CancelRequest not implemented") - } -} - -func (rt *userAgentRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt } - -type basicAuthRoundTripper struct { - username string - password string - rt http.RoundTripper -} - -// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a -// request unless it has already been set. -func NewBasicAuthRoundTripper(username, password string, rt http.RoundTripper) http.RoundTripper { - return &basicAuthRoundTripper{username, password, rt} -} - -func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - if len(req.Header.Get("Authorization")) != 0 { - return rt.rt.RoundTrip(req) - } - req = cloneRequest(req) - req.SetBasicAuth(rt.username, rt.password) - return rt.rt.RoundTrip(req) -} - -func (rt *basicAuthRoundTripper) CancelRequest(req *http.Request) { - if canceler, ok := rt.rt.(requestCanceler); ok { - canceler.CancelRequest(req) - } else { - glog.Errorf("CancelRequest not implemented") - } -} - -func (rt *basicAuthRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt } - -// These correspond to the headers used in pkg/apis/authentication. We don't want the package dependency, -// but you must not change the values. -const ( - // ImpersonateUserHeader is used to impersonate a particular user during an API server request - ImpersonateUserHeader = "Impersonate-User" - - // ImpersonateGroupHeader is used to impersonate a particular group during an API server request. - // It can be repeated multiplied times for multiple groups. - ImpersonateGroupHeader = "Impersonate-Group" - - // ImpersonateUserExtraHeaderPrefix is a prefix for a header used to impersonate an entry in the - // extra map[string][]string for user.Info. The key for the `extra` map is suffix. - // The same key can be repeated multiple times to have multiple elements in the slice under a single key. - // For instance: - // Impersonate-Extra-Foo: one - // Impersonate-Extra-Foo: two - // results in extra["Foo"] = []string{"one", "two"} - ImpersonateUserExtraHeaderPrefix = "Impersonate-Extra-" -) - -type impersonatingRoundTripper struct { - impersonate ImpersonationConfig - delegate http.RoundTripper -} - -// NewImpersonatingRoundTripper will add an Act-As header to a request unless it has already been set. -func NewImpersonatingRoundTripper(impersonate ImpersonationConfig, delegate http.RoundTripper) http.RoundTripper { - return &impersonatingRoundTripper{impersonate, delegate} -} - -func (rt *impersonatingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - // use the user header as marker for the rest. - if len(req.Header.Get(ImpersonateUserHeader)) != 0 { - return rt.delegate.RoundTrip(req) - } - req = cloneRequest(req) - req.Header.Set(ImpersonateUserHeader, rt.impersonate.UserName) - - for _, group := range rt.impersonate.Groups { - req.Header.Add(ImpersonateGroupHeader, group) - } - for k, vv := range rt.impersonate.Extra { - for _, v := range vv { - req.Header.Add(ImpersonateUserExtraHeaderPrefix+k, v) - } - } - - return rt.delegate.RoundTrip(req) -} - -func (rt *impersonatingRoundTripper) CancelRequest(req *http.Request) { - if canceler, ok := rt.delegate.(requestCanceler); ok { - canceler.CancelRequest(req) - } else { - glog.Errorf("CancelRequest not implemented") - } -} - -func (rt *impersonatingRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.delegate } - -type bearerAuthRoundTripper struct { - bearer string - rt http.RoundTripper -} - -// NewBearerAuthRoundTripper adds the provided bearer token to a request -// unless the authorization header has already been set. -func NewBearerAuthRoundTripper(bearer string, rt http.RoundTripper) http.RoundTripper { - return &bearerAuthRoundTripper{bearer, rt} -} - -func (rt *bearerAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - if len(req.Header.Get("Authorization")) != 0 { - return rt.rt.RoundTrip(req) - } - - req = cloneRequest(req) - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", rt.bearer)) - return rt.rt.RoundTrip(req) -} - -func (rt *bearerAuthRoundTripper) CancelRequest(req *http.Request) { - if canceler, ok := rt.rt.(requestCanceler); ok { - canceler.CancelRequest(req) - } else { - glog.Errorf("CancelRequest not implemented") - } -} - -func (rt *bearerAuthRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt } - -// cloneRequest returns a clone of the provided *http.Request. -// The clone is a shallow copy of the struct and its Header map. -func cloneRequest(r *http.Request) *http.Request { - // shallow copy of the struct - r2 := new(http.Request) - *r2 = *r - // deep copy of the Header - r2.Header = make(http.Header) - for k, s := range r.Header { - r2.Header[k] = s - } - return r2 -} - -// requestInfo keeps track of information about a request/response combination -type requestInfo struct { - RequestHeaders http.Header - RequestVerb string - RequestURL string - - ResponseStatus string - ResponseHeaders http.Header - ResponseErr error - - Duration time.Duration -} - -// newRequestInfo creates a new RequestInfo based on an http request -func newRequestInfo(req *http.Request) *requestInfo { - return &requestInfo{ - RequestURL: req.URL.String(), - RequestVerb: req.Method, - RequestHeaders: req.Header, - } -} - -// complete adds information about the response to the requestInfo -func (r *requestInfo) complete(response *http.Response, err error) { - if err != nil { - r.ResponseErr = err - return - } - r.ResponseStatus = response.Status - r.ResponseHeaders = response.Header -} - -// toCurl returns a string that can be run as a command in a terminal (minus the body) -func (r *requestInfo) toCurl() string { - headers := "" - for key, values := range r.RequestHeaders { - for _, value := range values { - headers += fmt.Sprintf(` -H %q`, fmt.Sprintf("%s: %s", key, value)) - } - } - - return fmt.Sprintf("curl -k -v -X%s %s %s", r.RequestVerb, headers, r.RequestURL) -} - -// debuggingRoundTripper will display information about the requests passing -// through it based on what is configured -type debuggingRoundTripper struct { - delegatedRoundTripper http.RoundTripper - - levels map[debugLevel]bool -} - -type debugLevel int - -const ( - debugJustURL debugLevel = iota - debugURLTiming - debugCurlCommand - debugRequestHeaders - debugResponseStatus - debugResponseHeaders -) - -func newDebuggingRoundTripper(rt http.RoundTripper, levels ...debugLevel) *debuggingRoundTripper { - drt := &debuggingRoundTripper{ - delegatedRoundTripper: rt, - levels: make(map[debugLevel]bool, len(levels)), - } - for _, v := range levels { - drt.levels[v] = true - } - return drt -} - -func (rt *debuggingRoundTripper) CancelRequest(req *http.Request) { - if canceler, ok := rt.delegatedRoundTripper.(requestCanceler); ok { - canceler.CancelRequest(req) - } else { - glog.Errorf("CancelRequest not implemented") - } -} - -func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - reqInfo := newRequestInfo(req) - - if rt.levels[debugJustURL] { - glog.Infof("%s %s", reqInfo.RequestVerb, reqInfo.RequestURL) - } - if rt.levels[debugCurlCommand] { - glog.Infof("%s", reqInfo.toCurl()) - - } - if rt.levels[debugRequestHeaders] { - glog.Infof("Request Headers:") - for key, values := range reqInfo.RequestHeaders { - for _, value := range values { - glog.Infof(" %s: %s", key, value) - } - } - } - - startTime := time.Now() - response, err := rt.delegatedRoundTripper.RoundTrip(req) - reqInfo.Duration = time.Since(startTime) - - reqInfo.complete(response, err) - - if rt.levels[debugURLTiming] { - glog.Infof("%s %s %s in %d milliseconds", reqInfo.RequestVerb, reqInfo.RequestURL, reqInfo.ResponseStatus, reqInfo.Duration.Nanoseconds()/int64(time.Millisecond)) - } - if rt.levels[debugResponseStatus] { - glog.Infof("Response Status: %s in %d milliseconds", reqInfo.ResponseStatus, reqInfo.Duration.Nanoseconds()/int64(time.Millisecond)) - } - if rt.levels[debugResponseHeaders] { - glog.Infof("Response Headers:") - for key, values := range reqInfo.ResponseHeaders { - for _, value := range values { - glog.Infof(" %s: %s", key, value) - } - } - } - - return response, err -} - -func (rt *debuggingRoundTripper) WrappedRoundTripper() http.RoundTripper { - return rt.delegatedRoundTripper -} diff --git a/pkg/client/transport/round_trippers_test.go b/pkg/client/transport/round_trippers_test.go deleted file mode 100644 index d5ffc6bde30..00000000000 --- a/pkg/client/transport/round_trippers_test.go +++ /dev/null @@ -1,218 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import ( - "net/http" - "reflect" - "strings" - "testing" -) - -type testRoundTripper struct { - Request *http.Request - Response *http.Response - Err error -} - -func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - rt.Request = req - return rt.Response, rt.Err -} - -func TestBearerAuthRoundTripper(t *testing.T) { - rt := &testRoundTripper{} - req := &http.Request{} - NewBearerAuthRoundTripper("test", rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("unexpected nil request: %v", rt) - } - if rt.Request == req { - t.Fatalf("round tripper should have copied request object: %#v", rt.Request) - } - if rt.Request.Header.Get("Authorization") != "Bearer test" { - t.Errorf("unexpected authorization header: %#v", rt.Request) - } -} - -func TestBasicAuthRoundTripper(t *testing.T) { - for n, tc := range map[string]struct { - user string - pass string - }{ - "basic": {user: "user", pass: "pass"}, - "no pass": {user: "user"}, - } { - rt := &testRoundTripper{} - req := &http.Request{} - NewBasicAuthRoundTripper(tc.user, tc.pass, rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("%s: unexpected nil request: %v", n, rt) - } - if rt.Request == req { - t.Fatalf("%s: round tripper should have copied request object: %#v", n, rt.Request) - } - if user, pass, found := rt.Request.BasicAuth(); !found || user != tc.user || pass != tc.pass { - t.Errorf("%s: unexpected authorization header: %#v", n, rt.Request) - } - } -} - -func TestUserAgentRoundTripper(t *testing.T) { - rt := &testRoundTripper{} - req := &http.Request{ - Header: make(http.Header), - } - req.Header.Set("User-Agent", "other") - NewUserAgentRoundTripper("test", rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("unexpected nil request: %v", rt) - } - if rt.Request != req { - t.Fatalf("round tripper should not have copied request object: %#v", rt.Request) - } - if rt.Request.Header.Get("User-Agent") != "other" { - t.Errorf("unexpected user agent header: %#v", rt.Request) - } - - req = &http.Request{} - NewUserAgentRoundTripper("test", rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("unexpected nil request: %v", rt) - } - if rt.Request == req { - t.Fatalf("round tripper should have copied request object: %#v", rt.Request) - } - if rt.Request.Header.Get("User-Agent") != "test" { - t.Errorf("unexpected user agent header: %#v", rt.Request) - } -} - -func TestImpersonationRoundTripper(t *testing.T) { - tcs := []struct { - name string - impersonationConfig ImpersonationConfig - expected map[string][]string - }{ - { - name: "all", - impersonationConfig: ImpersonationConfig{ - UserName: "user", - Groups: []string{"one", "two"}, - Extra: map[string][]string{ - "first": {"A", "a"}, - "second": {"B", "b"}, - }, - }, - expected: map[string][]string{ - ImpersonateUserHeader: {"user"}, - ImpersonateGroupHeader: {"one", "two"}, - ImpersonateUserExtraHeaderPrefix + "First": {"A", "a"}, - ImpersonateUserExtraHeaderPrefix + "Second": {"B", "b"}, - }, - }, - } - - for _, tc := range tcs { - rt := &testRoundTripper{} - req := &http.Request{ - Header: make(http.Header), - } - NewImpersonatingRoundTripper(tc.impersonationConfig, rt).RoundTrip(req) - - for k, v := range rt.Request.Header { - expected, ok := tc.expected[k] - if !ok { - t.Errorf("%v missing %v=%v", tc.name, k, v) - continue - } - if !reflect.DeepEqual(expected, v) { - t.Errorf("%v expected %v: %v, got %v", tc.name, k, expected, v) - } - } - for k, v := range tc.expected { - expected, ok := rt.Request.Header[k] - if !ok { - t.Errorf("%v missing %v=%v", tc.name, k, v) - continue - } - if !reflect.DeepEqual(expected, v) { - t.Errorf("%v expected %v: %v, got %v", tc.name, k, expected, v) - } - } - } -} - -func TestAuthProxyRoundTripper(t *testing.T) { - for n, tc := range map[string]struct { - username string - groups []string - extra map[string][]string - }{ - "allfields": { - username: "user", - groups: []string{"groupA", "groupB"}, - extra: map[string][]string{ - "one": {"alpha", "bravo"}, - "two": {"charlie", "delta"}, - }, - }, - } { - rt := &testRoundTripper{} - req := &http.Request{} - NewAuthProxyRoundTripper(tc.username, tc.groups, tc.extra, rt).RoundTrip(req) - if rt.Request == nil { - t.Errorf("%s: unexpected nil request: %v", n, rt) - continue - } - if rt.Request == req { - t.Errorf("%s: round tripper should have copied request object: %#v", n, rt.Request) - continue - } - - actualUsernames, ok := rt.Request.Header["X-Remote-User"] - if !ok { - t.Errorf("%s missing value", n) - continue - } - if e, a := []string{tc.username}, actualUsernames; !reflect.DeepEqual(e, a) { - t.Errorf("%s expected %v, got %v", n, e, a) - continue - } - actualGroups, ok := rt.Request.Header["X-Remote-Group"] - if !ok { - t.Errorf("%s missing value", n) - continue - } - if e, a := tc.groups, actualGroups; !reflect.DeepEqual(e, a) { - t.Errorf("%s expected %v, got %v", n, e, a) - continue - } - - actualExtra := map[string][]string{} - for key, values := range rt.Request.Header { - if strings.HasPrefix(strings.ToLower(key), strings.ToLower("X-Remote-Extra-")) { - extraKey := strings.ToLower(key[len("X-Remote-Extra-"):]) - actualExtra[extraKey] = append(actualExtra[key], values...) - } - } - if e, a := tc.extra, actualExtra; !reflect.DeepEqual(e, a) { - t.Errorf("%s expected %v, got %v", n, e, a) - continue - } - } -} diff --git a/pkg/client/transport/transport.go b/pkg/client/transport/transport.go deleted file mode 100644 index 9c5b9ef3c32..00000000000 --- a/pkg/client/transport/transport.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import ( - "crypto/tls" - "crypto/x509" - "fmt" - "io/ioutil" - "net/http" -) - -// New returns an http.RoundTripper that will provide the authentication -// or transport level security defined by the provided Config. -func New(config *Config) (http.RoundTripper, error) { - // Set transport level security - if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || config.TLS.Insecure) { - return nil, fmt.Errorf("using a custom transport with TLS certificate options or the insecure flag is not allowed") - } - - var ( - rt http.RoundTripper - err error - ) - - if config.Transport != nil { - rt = config.Transport - } else { - rt, err = tlsCache.get(config) - if err != nil { - return nil, err - } - } - - return HTTPWrappersForConfig(config, rt) -} - -// TLSConfigFor returns a tls.Config that will provide the transport level security defined -// by the provided Config. Will return nil if no transport level security is requested. -func TLSConfigFor(c *Config) (*tls.Config, error) { - if !(c.HasCA() || c.HasCertAuth() || c.TLS.Insecure) { - return nil, nil - } - if c.HasCA() && c.TLS.Insecure { - return nil, fmt.Errorf("specifying a root certificates file with the insecure flag is not allowed") - } - if err := loadTLSFiles(c); err != nil { - return nil, err - } - - tlsConfig := &tls.Config{ - // Can't use SSLv3 because of POODLE and BEAST - // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher - // Can't use TLSv1.1 because of RC4 cipher usage - MinVersion: tls.VersionTLS12, - InsecureSkipVerify: c.TLS.Insecure, - } - - if c.HasCA() { - tlsConfig.RootCAs = rootCertPool(c.TLS.CAData) - } - - if c.HasCertAuth() { - cert, err := tls.X509KeyPair(c.TLS.CertData, c.TLS.KeyData) - if err != nil { - return nil, err - } - tlsConfig.Certificates = []tls.Certificate{cert} - } - - return tlsConfig, nil -} - -// loadTLSFiles copies the data from the CertFile, KeyFile, and CAFile fields into the CertData, -// KeyData, and CAFile fields, or returns an error. If no error is returned, all three fields are -// either populated or were empty to start. -func loadTLSFiles(c *Config) error { - var err error - c.TLS.CAData, err = dataFromSliceOrFile(c.TLS.CAData, c.TLS.CAFile) - if err != nil { - return err - } - - c.TLS.CertData, err = dataFromSliceOrFile(c.TLS.CertData, c.TLS.CertFile) - if err != nil { - return err - } - - c.TLS.KeyData, err = dataFromSliceOrFile(c.TLS.KeyData, c.TLS.KeyFile) - if err != nil { - return err - } - return nil -} - -// dataFromSliceOrFile returns data from the slice (if non-empty), or from the file, -// or an error if an error occurred reading the file -func dataFromSliceOrFile(data []byte, file string) ([]byte, error) { - if len(data) > 0 { - return data, nil - } - if len(file) > 0 { - fileData, err := ioutil.ReadFile(file) - if err != nil { - return []byte{}, err - } - return fileData, nil - } - return nil, nil -} - -// rootCertPool returns nil if caData is empty. When passed along, this will mean "use system CAs". -// When caData is not empty, it will be the ONLY information used in the CertPool. -func rootCertPool(caData []byte) *x509.CertPool { - // What we really want is a copy of x509.systemRootsPool, but that isn't exposed. It's difficult to build (see the go - // code for a look at the platform specific insanity), so we'll use the fact that RootCAs == nil gives us the system values - // It doesn't allow trusting either/or, but hopefully that won't be an issue - if len(caData) == 0 { - return nil - } - - // if we have caData, use it - certPool := x509.NewCertPool() - certPool.AppendCertsFromPEM(caData) - return certPool -} diff --git a/pkg/client/transport/transport_test.go b/pkg/client/transport/transport_test.go deleted file mode 100644 index 4d2d78f86ce..00000000000 --- a/pkg/client/transport/transport_test.go +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package transport - -import ( - "net/http" - "testing" -) - -const ( - rootCACert = `-----BEGIN CERTIFICATE----- -MIIC4DCCAcqgAwIBAgIBATALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu -MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIxNTczN1oXDTE2MDExNTIxNTcz -OFowIzEhMB8GA1UEAwwYMTAuMTMuMTI5LjEwNkAxNDIxMzU5MDU4MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunDRXGwsiYWGFDlWH6kjGun+PshDGeZX -xtx9lUnL8pIRWH3wX6f13PO9sktaOWW0T0mlo6k2bMlSLlSZgG9H6og0W6gLS3vq -s4VavZ6DbXIwemZG2vbRwsvR+t4G6Nbwelm6F8RFnA1Fwt428pavmNQ/wgYzo+T1 -1eS+HiN4ACnSoDSx3QRWcgBkB1g6VReofVjx63i0J+w8Q/41L9GUuLqquFxu6ZnH -60vTB55lHgFiDLjA1FkEz2dGvGh/wtnFlRvjaPC54JH2K1mPYAUXTreoeJtLJKX0 -ycoiyB24+zGCniUmgIsmQWRPaOPircexCp1BOeze82BT1LCZNTVaxQIDAQABoyMw -ITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/BAUwAwEB/zALBgkqhkiG9w0BAQsD -ggEBADMxsUuAFlsYDpF4fRCzXXwrhbtj4oQwcHpbu+rnOPHCZupiafzZpDu+rw4x -YGPnCb594bRTQn4pAu3Ac18NbLD5pV3uioAkv8oPkgr8aUhXqiv7KdDiaWm6sbAL -EHiXVBBAFvQws10HMqMoKtO8f1XDNAUkWduakR/U6yMgvOPwS7xl0eUTqyRB6zGb -K55q2dejiFWaFqB/y78txzvz6UlOZKE44g2JAVoJVM6kGaxh33q8/FmrL4kuN3ut -W+MmJCVDvd4eEqPwbp7146ZWTqpIJ8lvA6wuChtqV8lhAPka2hD/LMqY8iXNmfXD -uml0obOEy+ON91k+SWTJ3ggmF/U= ------END CERTIFICATE-----` - - certData = `-----BEGIN CERTIFICATE----- -MIIC6jCCAdSgAwIBAgIBCzALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu -MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIyMDEzMVoXDTE2MDExNTIyMDEz -MlowGzEZMBcGA1UEAxMQb3BlbnNoaWZ0LWNsaWVudDCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKtdhz0+uCLXw5cSYns9rU/XifFSpb/x24WDdrm72S/v -b9BPYsAStiP148buylr1SOuNi8sTAZmlVDDIpIVwMLff+o2rKYDicn9fjbrTxTOj -lI4pHJBH+JU3AJ0tbajupioh70jwFS0oYpwtneg2zcnE2Z4l6mhrj2okrc5Q1/X2 -I2HChtIU4JYTisObtin10QKJX01CLfYXJLa8upWzKZ4/GOcHG+eAV3jXWoXidtjb -1Usw70amoTZ6mIVCkiu1QwCoa8+ycojGfZhvqMsAp1536ZcCul+Na+AbCv4zKS7F -kQQaImVrXdUiFansIoofGlw/JNuoKK6ssVpS5Ic3pgcCAwEAAaM1MDMwDgYDVR0P -AQH/BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJ -KoZIhvcNAQELA4IBAQCKLREH7bXtXtZ+8vI6cjD7W3QikiArGqbl36bAhhWsJLp/ -p/ndKz39iFNaiZ3GlwIURWOOKx3y3GA0x9m8FR+Llthf0EQ8sUjnwaknWs0Y6DQ3 -jjPFZOpV3KPCFrdMJ3++E3MgwFC/Ih/N2ebFX9EcV9Vcc6oVWMdwT0fsrhu683rq -6GSR/3iVX1G/pmOiuaR0fNUaCyCfYrnI4zHBDgSfnlm3vIvN2lrsR/DQBakNL8DJ -HBgKxMGeUPoneBv+c8DMXIL0EhaFXRlBv9QW45/GiAIOuyFJ0i6hCtGZpJjq4OpQ -BRjCI+izPzFTjsxD4aORE+WOkyWFCGPWKfNejfw0 ------END CERTIFICATE-----` - - keyData = `-----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAq12HPT64ItfDlxJiez2tT9eJ8VKlv/HbhYN2ubvZL+9v0E9i -wBK2I/Xjxu7KWvVI642LyxMBmaVUMMikhXAwt9/6jaspgOJyf1+NutPFM6OUjikc -kEf4lTcAnS1tqO6mKiHvSPAVLShinC2d6DbNycTZniXqaGuPaiStzlDX9fYjYcKG -0hTglhOKw5u2KfXRAolfTUIt9hcktry6lbMpnj8Y5wcb54BXeNdaheJ22NvVSzDv -RqahNnqYhUKSK7VDAKhrz7JyiMZ9mG+oywCnXnfplwK6X41r4BsK/jMpLsWRBBoi -ZWtd1SIVqewiih8aXD8k26gorqyxWlLkhzemBwIDAQABAoIBAD2XYRs3JrGHQUpU -FkdbVKZkvrSY0vAZOqBTLuH0zUv4UATb8487anGkWBjRDLQCgxH+jucPTrztekQK -aW94clo0S3aNtV4YhbSYIHWs1a0It0UdK6ID7CmdWkAj6s0T8W8lQT7C46mWYVLm -5mFnCTHi6aB42jZrqmEpC7sivWwuU0xqj3Ml8kkxQCGmyc9JjmCB4OrFFC8NNt6M -ObvQkUI6Z3nO4phTbpxkE1/9dT0MmPIF7GhHVzJMS+EyyRYUDllZ0wvVSOM3qZT0 -JMUaBerkNwm9foKJ1+dv2nMKZZbJajv7suUDCfU44mVeaEO+4kmTKSGCGjjTBGkr -7L1ySDECgYEA5ElIMhpdBzIivCuBIH8LlUeuzd93pqssO1G2Xg0jHtfM4tz7fyeI -cr90dc8gpli24dkSxzLeg3Tn3wIj/Bu64m2TpZPZEIlukYvgdgArmRIPQVxerYey -OkrfTNkxU1HXsYjLCdGcGXs5lmb+K/kuTcFxaMOs7jZi7La+jEONwf8CgYEAwCs/ -rUOOA0klDsWWisbivOiNPII79c9McZCNBqncCBfMUoiGe8uWDEO4TFHN60vFuVk9 -8PkwpCfvaBUX+ajvbafIfHxsnfk1M04WLGCeqQ/ym5Q4sQoQOcC1b1y9qc/xEWfg -nIUuia0ukYRpl7qQa3tNg+BNFyjypW8zukUAC/kCgYB1/Kojuxx5q5/oQVPrx73k -2bevD+B3c+DYh9MJqSCNwFtUpYIWpggPxoQan4LwdsmO0PKzocb/ilyNFj4i/vII -NToqSc/WjDFpaDIKyuu9oWfhECye45NqLWhb/6VOuu4QA/Nsj7luMhIBehnEAHW+ -GkzTKM8oD1PxpEG3nPKXYQKBgQC6AuMPRt3XBl1NkCrpSBy/uObFlFaP2Enpf39S -3OZ0Gv0XQrnSaL1kP8TMcz68rMrGX8DaWYsgytstR4W+jyy7WvZwsUu+GjTJ5aMG -77uEcEBpIi9CBzivfn7hPccE8ZgqPf+n4i6q66yxBJflW5xhvafJqDtW2LcPNbW/ -bvzdmQKBgExALRUXpq+5dbmkdXBHtvXdRDZ6rVmrnjy4nI5bPw+1GqQqk6uAR6B/ -F6NmLCQOO4PDG/cuatNHIr2FrwTmGdEL6ObLUGWn9Oer9gJhHVqqsY5I4sEPo4XX -stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa ------END RSA PRIVATE KEY-----` -) - -func TestNew(t *testing.T) { - testCases := map[string]struct { - Config *Config - Err bool - TLS bool - Default bool - }{ - "default transport": { - Default: true, - Config: &Config{}, - }, - - "ca transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - }, - }, - }, - "bad ca file transport": { - Err: true, - Config: &Config{ - TLS: TLSConfig{ - CAFile: "invalid file", - }, - }, - }, - "ca data overriding bad ca file transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CAFile: "invalid file", - }, - }, - }, - - "cert transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyData: []byte(keyData), - }, - }, - }, - "bad cert data transport": { - Err: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyData: []byte("bad key data"), - }, - }, - }, - "bad file cert transport": { - Err: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyFile: "invalid file", - }, - }, - }, - "key data overriding bad file cert transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyData: []byte(keyData), - KeyFile: "invalid file", - }, - }, - }, - } - for k, testCase := range testCases { - transport, err := New(testCase.Config) - switch { - case testCase.Err && err == nil: - t.Errorf("%s: unexpected non-error", k) - continue - case !testCase.Err && err != nil: - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - - switch { - case testCase.Default && transport != http.DefaultTransport: - t.Errorf("%s: expected the default transport, got %#v", k, transport) - continue - case !testCase.Default && transport == http.DefaultTransport: - t.Errorf("%s: expected non-default transport, got %#v", k, transport) - continue - } - - // We only know how to check TLSConfig on http.Transports - if transport, ok := transport.(*http.Transport); ok { - switch { - case testCase.TLS && transport.TLSClientConfig == nil: - t.Errorf("%s: expected TLSClientConfig, got %#v", k, transport) - continue - case !testCase.TLS && transport.TLSClientConfig != nil: - t.Errorf("%s: expected no TLSClientConfig, got %#v", k, transport) - continue - } - } - } -} diff --git a/pkg/client/unversioned/remotecommand/BUILD b/pkg/client/unversioned/remotecommand/BUILD index 1f886caa269..7cdd440e724 100644 --- a/pkg/client/unversioned/remotecommand/BUILD +++ b/pkg/client/unversioned/remotecommand/BUILD @@ -23,7 +23,6 @@ go_library( deps = [ "//pkg/api:go_default_library", "//pkg/client/restclient:go_default_library", - "//pkg/client/transport:go_default_library", "//pkg/kubelet/server/remotecommand:go_default_library", "//pkg/util/exec:go_default_library", "//pkg/util/httpstream:go_default_library", @@ -32,6 +31,7 @@ go_library( "//vendor:github.com/golang/glog", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/util/runtime", + "//vendor:k8s.io/client-go/transport", ], ) diff --git a/pkg/client/unversioned/remotecommand/remotecommand.go b/pkg/client/unversioned/remotecommand/remotecommand.go index 0cee2285648..dd4fd5ed6e4 100644 --- a/pkg/client/unversioned/remotecommand/remotecommand.go +++ b/pkg/client/unversioned/remotecommand/remotecommand.go @@ -24,8 +24,8 @@ import ( "github.com/golang/glog" + "k8s.io/client-go/transport" "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/transport" "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" "k8s.io/kubernetes/pkg/util/httpstream" "k8s.io/kubernetes/pkg/util/httpstream/spdy" diff --git a/pkg/kubelet/client/BUILD b/pkg/kubelet/client/BUILD index 7da01585534..d6b57b7b651 100644 --- a/pkg/kubelet/client/BUILD +++ b/pkg/kubelet/client/BUILD @@ -15,11 +15,11 @@ go_library( deps = [ "//pkg/api/v1:go_default_library", "//pkg/client/restclient:go_default_library", - "//pkg/client/transport:go_default_library", "//pkg/util/node:go_default_library", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/util/net", + "//vendor:k8s.io/client-go/transport", ], ) diff --git a/pkg/kubelet/client/kubelet_client.go b/pkg/kubelet/client/kubelet_client.go index d004e28e798..3df67c78681 100644 --- a/pkg/kubelet/client/kubelet_client.go +++ b/pkg/kubelet/client/kubelet_client.go @@ -24,9 +24,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" + "k8s.io/client-go/transport" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/transport" nodeutil "k8s.io/kubernetes/pkg/util/node" ) diff --git a/staging/copy.sh b/staging/copy.sh index 3ea89cf658e..c48b1f6ebe1 100755 --- a/staging/copy.sh +++ b/staging/copy.sh @@ -55,11 +55,29 @@ echo "creating the tmp directory" mkdir -p "${CLIENT_REPO_TEMP}" cd "${CLIENT_REPO}" +# there are two classes of package in staging/client-go, those which are authoritative (client-go has the only copy) +# and those which are copied and rewritten (client-go is not authoritative). +# we first copy out the authoritative packages to the temp location, then copy non-authoritative packages +# then save over the original + + +# save copies code from client-go into the temp folder to make sure we don't lose it by accident +# TODO this is temporary until everything in certain directories is authoritative +function save() { + cp -r "${CLIENT_REPO}/$1" "${CLIENT_REPO_TEMP}" +} + +# save everything for which the staging directory is the source of truth +save "/transport" + + + # mkcp copies file from the main repo to the client repo, it creates the directory if it doesn't exist in the client repo. function mkcp() { mkdir -p "${CLIENT_REPO_TEMP}/$2" && cp -r "${MAIN_REPO}/$1" "${CLIENT_REPO_TEMP}/$2" } +# assemble all the other parts of the staging directory echo "copying client packages" mkcp "pkg/client/clientset_generated/${CLIENTSET}" "pkg/client/clientset_generated" mkcp "/pkg/client/record" "/pkg/client" @@ -70,7 +88,6 @@ mkcp "/pkg/client/restclient" "/pkg/client" mkcp "/pkg/client/testing" "/pkg/client" # remove this test because it imports the internal clientset rm "${CLIENT_REPO_TEMP}"/pkg/client/testing/core/fake_test.go -mkcp "/pkg/client/transport" "/pkg/client" mkcp "/pkg/client/typed" "/pkg/client" mkcp "/pkg/client/unversioned/auth" "/pkg/client/unversioned" @@ -170,7 +187,6 @@ function mvfolder { mvfolder "pkg/client/clientset_generated/${CLIENTSET}" kubernetes mvfolder pkg/client/typed/discovery discovery mvfolder pkg/client/typed/dynamic dynamic -mvfolder pkg/client/transport transport mvfolder pkg/client/record tools/record mvfolder pkg/client/restclient rest mvfolder pkg/client/cache tools/cache @@ -202,6 +218,9 @@ find "${CLIENT_REPO_TEMP}" -type f \( \ -name "*.sh" \ \) -delete +echo "remove cyclical godep" +rm -rf "${CLIENT_REPO_TEMP}/_vendor/k8s.io/client-go" + if [ "${VERIFYONLY}" = true ]; then echo "running verify-only" ret=0 diff --git a/staging/godeps-json-updater.go b/staging/godeps-json-updater.go index a9a66d379f6..7f8fbe985d3 100644 --- a/staging/godeps-json-updater.go +++ b/staging/godeps-json-updater.go @@ -70,6 +70,9 @@ func main() { if strings.Contains(dep.ImportPath, "k8s.io/kubernetes") { continue } + if strings.Contains(dep.ImportPath, "k8s.io/client-go") { + continue + } g.Deps[i] = dep i++ } diff --git a/test/e2e/BUILD b/test/e2e/BUILD index 6dfbc020a3e..b096ea06deb 100644 --- a/test/e2e/BUILD +++ b/test/e2e/BUILD @@ -135,7 +135,6 @@ go_library( "//pkg/client/clientset_generated/clientset/typed/extensions/v1beta1:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/restclient:go_default_library", - "//pkg/client/transport:go_default_library", "//pkg/client/unversioned/clientcmd:go_default_library", "//pkg/client/unversioned/clientcmd/api:go_default_library", "//pkg/cloudprovider:go_default_library", @@ -213,6 +212,7 @@ go_library( "//vendor:k8s.io/client-go/pkg/apis/extensions/v1beta1", "//vendor:k8s.io/client-go/pkg/apis/policy/v1beta1", "//vendor:k8s.io/client-go/pkg/util/intstr", + "//vendor:k8s.io/client-go/transport", ], ) diff --git a/test/e2e/load.go b/test/e2e/load.go index b33f5787a84..4c6afc0ebb7 100644 --- a/test/e2e/load.go +++ b/test/e2e/load.go @@ -31,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" utilnet "k8s.io/apimachinery/pkg/util/net" + "k8s.io/client-go/transport" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/apis/batch" @@ -38,7 +39,6 @@ import ( "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/transport" "k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/test/e2e/framework" testutils "k8s.io/kubernetes/test/utils" diff --git a/test/integration/auth/rbac_test.go b/test/integration/auth/rbac_test.go index 066919b551c..8c82542d2bd 100644 --- a/test/integration/auth/rbac_test.go +++ b/test/integration/auth/rbac_test.go @@ -36,12 +36,12 @@ import ( "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/request/bearertoken" "k8s.io/apiserver/pkg/authorization/authorizer" + "k8s.io/client-go/transport" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" rbacapi "k8s.io/kubernetes/pkg/apis/rbac" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/transport" "k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole"