From 7b1f9a193bb6e2c94285e4cbb48e3ab840785c2d Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Fri, 14 Apr 2017 14:45:03 -0700 Subject: [PATCH] remove references to client-go/pkg/api Kubernetes-commit: d978f22e04519f6eecfde839110c398dc28d4e8e --- kubernetes/BUILD | 14 --- kubernetes/import_known_versions.go | 42 --------- pkg/apis/authentication/v1/types.go | 15 ++++ rest/BUILD | 5 +- rest/client_test.go | 39 ++++---- rest/config_test.go | 10 +-- rest/request_test.go | 133 ++++++++++++++-------------- rest/watch/BUILD | 5 +- rest/watch/decoder_test.go | 24 +++-- rest/watch/encoder_test.go | 28 +++--- tools/record/BUILD | 3 +- tools/record/event_test.go | 17 ++-- 12 files changed, 151 insertions(+), 184 deletions(-) delete mode 100644 kubernetes/import_known_versions.go diff --git a/kubernetes/BUILD b/kubernetes/BUILD index 5bf970cb..26e43863 100644 --- a/kubernetes/BUILD +++ b/kubernetes/BUILD @@ -12,7 +12,6 @@ go_library( srcs = [ "clientset.go", "doc.go", - "import_known_versions.go", ], tags = ["automanaged"], deps = [ @@ -36,19 +35,6 @@ go_library( "//vendor/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", "//vendor/k8s.io/client-go/kubernetes/typed/storage/v1beta1:go_default_library", - "//vendor/k8s.io/client-go/pkg/api:go_default_library", - "//vendor/k8s.io/client-go/pkg/api/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/apps/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/authentication/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/authorization/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/autoscaling/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/batch/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/certificates/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/extensions/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/policy/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/rbac/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/settings/install:go_default_library", - "//vendor/k8s.io/client-go/pkg/apis/storage/install:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", ], diff --git a/kubernetes/import_known_versions.go b/kubernetes/import_known_versions.go deleted file mode 100644 index 297466b0..00000000 --- a/kubernetes/import_known_versions.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubernetes - -// These imports are the API groups the client will support. -import ( - "fmt" - - "k8s.io/client-go/pkg/api" - _ "k8s.io/client-go/pkg/api/install" - _ "k8s.io/client-go/pkg/apis/apps/install" - _ "k8s.io/client-go/pkg/apis/authentication/install" - _ "k8s.io/client-go/pkg/apis/authorization/install" - _ "k8s.io/client-go/pkg/apis/autoscaling/install" - _ "k8s.io/client-go/pkg/apis/batch/install" - _ "k8s.io/client-go/pkg/apis/certificates/install" - _ "k8s.io/client-go/pkg/apis/extensions/install" - _ "k8s.io/client-go/pkg/apis/policy/install" - _ "k8s.io/client-go/pkg/apis/rbac/install" - _ "k8s.io/client-go/pkg/apis/settings/install" - _ "k8s.io/client-go/pkg/apis/storage/install" -) - -func init() { - if missingVersions := api.Registry.ValidateEnvRequestedVersions(); len(missingVersions) != 0 { - panic(fmt.Sprintf("KUBE_API_VERSIONS contains versions that are not installed: %q.", missingVersions)) - } -} diff --git a/pkg/apis/authentication/v1/types.go b/pkg/apis/authentication/v1/types.go index e6ff5870..21051f13 100644 --- a/pkg/apis/authentication/v1/types.go +++ b/pkg/apis/authentication/v1/types.go @@ -22,6 +22,21 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +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 any header used to impersonate an entry in the + // extra map[string][]string for user.Info. The key will be every after the prefix. + // It can be repeated multiplied times for multiple map keys and the same key can be repeated multiple + // times to have multiple elements in the slice under a single key + ImpersonateUserExtraHeaderPrefix = "Impersonate-Extra-" +) + // +genclient=true // +nonNamespaced=true // +noMethods=true diff --git a/rest/BUILD b/rest/BUILD index b36a5f29..97e53ae6 100644 --- a/rest/BUILD +++ b/rest/BUILD @@ -29,15 +29,16 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/pkg/api:go_default_library", - "//vendor/k8s.io/client-go/pkg/api/install:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library", + "//vendor/k8s.io/client-go/pkg/apis/extensions/v1beta1:go_default_library", "//vendor/k8s.io/client-go/rest/watch:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/k8s.io/client-go/util/clock:go_default_library", diff --git a/rest/client_test.go b/rest/client_test.go index 91eb8c8a..71707d43 100644 --- a/rest/client_test.go +++ b/rest/client_test.go @@ -30,14 +30,13 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/client-go/pkg/api" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/pkg/api/v1" + v1beta1 "k8s.io/client-go/pkg/apis/extensions/v1beta1" utiltesting "k8s.io/client-go/util/testing" - - _ "k8s.io/client-go/pkg/api/install" ) type TestParam struct { @@ -50,12 +49,13 @@ type TestParam struct { testBodyErrorIsNotNil bool } -// TestSerializer makes sure that you're always able to decode an unversioned API object +// TestSerializer makes sure that you're always able to decode metav1.Status func TestSerializer(t *testing.T) { + gv := v1beta1.SchemeGroupVersion contentConfig := ContentConfig{ ContentType: "application/json", - GroupVersion: &schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, - NegotiatedSerializer: api.Codecs, + GroupVersion: &gv, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, } serializer, err := createSerializers(contentConfig) @@ -93,7 +93,7 @@ func TestDoRequestFailed(t *testing.T) { Message: " \"\" not found", Details: &metav1.StatusDetails{}, } - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), status) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), status) fakeHandler := utiltesting.FakeHandler{ StatusCode: 404, ResponseBody: string(expectedBody), @@ -132,7 +132,7 @@ func TestDoRawRequestFailed(t *testing.T) { }, }, } - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), status) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), status) fakeHandler := utiltesting.FakeHandler{ StatusCode: 404, ResponseBody: string(expectedBody), @@ -231,12 +231,13 @@ func validate(testParam TestParam, t *testing.T, body []byte, fakeHandler *utilt t.Errorf("Expected object not to be created") } } - statusOut, err := runtime.Decode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), body) + statusOut, err := runtime.Decode(scheme.Codecs.UniversalDeserializer(), body) if testParam.testBody { - if testParam.testBodyErrorIsNotNil { - if err == nil { - t.Errorf("Expected Error") - } + if testParam.testBodyErrorIsNotNil && err == nil { + t.Errorf("Expected Error") + } + if !testParam.testBodyErrorIsNotNil && err != nil { + t.Errorf("Unexpected Error: %v", err) } } @@ -245,7 +246,7 @@ func validate(testParam TestParam, t *testing.T, body []byte, fakeHandler *utilt t.Errorf("Unexpected mis-match. Expected %#v. Saw %#v", testParam.expStatus, statusOut) } } - fakeHandler.ValidateRequest(t, "/"+api.Registry.GroupOrDie(api.GroupName).GroupVersion.String()+"/test", "GET", nil) + fakeHandler.ValidateRequest(t, "/"+v1.SchemeGroupVersion.String()+"/test", "GET", nil) } @@ -317,8 +318,8 @@ func TestCreateBackoffManager(t *testing.T) { } func testServerEnv(t *testing.T, statusCode int) (*httptest.Server, *utiltesting.FakeHandler, *metav1.Status) { - status := &metav1.Status{Status: fmt.Sprintf("%s", metav1.StatusSuccess)} - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), status) + status := &metav1.Status{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Status"}, Status: fmt.Sprintf("%s", metav1.StatusSuccess)} + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), status) fakeHandler := utiltesting.FakeHandler{ StatusCode: statusCode, ResponseBody: string(expectedBody), @@ -332,8 +333,8 @@ func restClient(testServer *httptest.Server) (*RESTClient, error) { c, err := RESTClientFor(&Config{ Host: testServer.URL, ContentConfig: ContentConfig{ - GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: api.Codecs, + GroupVersion: &v1.SchemeGroupVersion, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, }, Username: "user", Password: "pass", diff --git a/rest/config_test.go b/rest/config_test.go index 913493bd..784a1ed8 100644 --- a/rest/config_test.go +++ b/rest/config_test.go @@ -29,12 +29,12 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/client-go/pkg/api" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/pkg/api/v1" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/flowcontrol" "github.com/stretchr/testify/assert" - _ "k8s.io/client-go/pkg/api/install" ) func TestIsConfigTransportTLS(t *testing.T) { @@ -139,13 +139,13 @@ func TestDefaultKubernetesUserAgent(t *testing.T) { } func TestRESTClientRequires(t *testing.T) { - if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{NegotiatedSerializer: api.Codecs}}); err == nil { + if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{NegotiatedSerializer: scheme.Codecs}}); err == nil { t.Errorf("unexpected non-error") } - if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion}}); err == nil { + if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{GroupVersion: &v1.SchemeGroupVersion}}); err == nil { t.Errorf("unexpected non-error") } - if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, NegotiatedSerializer: api.Codecs}}); err != nil { + if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{GroupVersion: &v1.SchemeGroupVersion, NegotiatedSerializer: scheme.Codecs}}); err != nil { t.Errorf("unexpected error: %v", err) } } diff --git a/rest/request_test.go b/rest/request_test.go index b5c664a6..b4a7e683 100755 --- a/rest/request_test.go +++ b/rest/request_test.go @@ -40,19 +40,18 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/pkg/api" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/pkg/api/v1" restclientwatch "k8s.io/client-go/rest/watch" "k8s.io/client-go/util/clock" "k8s.io/client-go/util/flowcontrol" utiltesting "k8s.io/client-go/util/testing" - - _ "k8s.io/client-go/pkg/api/install" ) func TestNewRequestSetsAccept(t *testing.T) { @@ -84,7 +83,7 @@ func TestRequestSetsHeaders(t *testing.T) { }) config := defaultContentConfig() config.ContentType = "application/other" - serializers := defaultSerializers() + serializers := defaultSerializers(t) r := NewRequest(server, "get", &url.URL{Path: "/path"}, "", config, serializers, nil, nil) // Check if all "issue" methods are setting headers. @@ -94,9 +93,10 @@ func TestRequestSetsHeaders(t *testing.T) { } func TestRequestWithErrorWontChange(t *testing.T) { + gvCopy := v1.SchemeGroupVersion original := Request{ err: errors.New("test"), - content: ContentConfig{GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion}, + content: ContentConfig{GroupVersion: &gvCopy}, } r := original changed := r.Param("foo", "bar"). @@ -231,7 +231,7 @@ func TestRequestVersionedParams(t *testing.T) { if !reflect.DeepEqual(r.params, url.Values{"foo": []string{"a"}}) { t.Errorf("should have set a param: %#v", r) } - r.VersionedParams(&api.PodLogOptions{Follow: true, Container: "bar"}, api.ParameterCodec) + r.VersionedParams(&v1.PodLogOptions{Follow: true, Container: "bar"}, scheme.ParameterCodec) if !reflect.DeepEqual(r.params, url.Values{ "foo": []string{"a"}, @@ -244,7 +244,7 @@ func TestRequestVersionedParams(t *testing.T) { func TestRequestVersionedParamsFromListOptions(t *testing.T) { r := &Request{content: ContentConfig{GroupVersion: &v1.SchemeGroupVersion}} - r.VersionedParams(&metav1.ListOptions{ResourceVersion: "1"}, api.ParameterCodec) + r.VersionedParams(&metav1.ListOptions{ResourceVersion: "1"}, scheme.ParameterCodec) if !reflect.DeepEqual(r.params, url.Values{ "resourceVersion": []string{"1"}, }) { @@ -252,7 +252,7 @@ func TestRequestVersionedParamsFromListOptions(t *testing.T) { } var timeout int64 = 10 - r.VersionedParams(&metav1.ListOptions{ResourceVersion: "2", TimeoutSeconds: &timeout}, api.ParameterCodec) + r.VersionedParams(&metav1.ListOptions{ResourceVersion: "2", TimeoutSeconds: &timeout}, scheme.ParameterCodec) if !reflect.DeepEqual(r.params, url.Values{ "resourceVersion": []string{"1", "2"}, "timeoutSeconds": []string{"10"}, @@ -279,22 +279,21 @@ func (obj NotAnAPIObject) GroupVersionKind() *schema.GroupVersionKind { re func (obj NotAnAPIObject) SetGroupVersionKind(gvk *schema.GroupVersionKind) {} func defaultContentConfig() ContentConfig { + gvCopy := v1.SchemeGroupVersion return ContentConfig{ - GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: api.Codecs, + ContentType: "application/json", + GroupVersion: &gvCopy, + NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}, } } -func defaultSerializers() Serializers { - return Serializers{ - Encoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), - Decoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), - StreamingSerializer: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), - Framer: runtime.DefaultFramer, - RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) { - return api.Codecs.LegacyCodec(v1.SchemeGroupVersion), nil - }, +func defaultSerializers(t *testing.T) Serializers { + config := defaultContentConfig() + serializers, err := createSerializers(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) } + return *serializers } func TestRequestBody(t *testing.T) { @@ -325,7 +324,7 @@ func TestRequestBody(t *testing.T) { func TestResultIntoWithErrReturnsErr(t *testing.T) { res := Result{err: errors.New("test")} - if err := res.Into(&api.Pod{}); err != res.err { + if err := res.Into(&v1.Pod{}); err != res.err { t.Errorf("should have returned exact error from result") } } @@ -394,7 +393,7 @@ func TestTransformResponse(t *testing.T) { {Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid}, } for i, test := range testCases { - r := NewRequest(nil, "", uri, "", defaultContentConfig(), defaultSerializers(), nil, nil) + r := NewRequest(nil, "", uri, "", defaultContentConfig(), defaultSerializers(t), nil, nil) if test.Response.Body == nil { test.Response.Body = ioutil.NopCloser(bytes.NewReader([]byte{})) } @@ -475,7 +474,7 @@ func TestTransformResponseNegotiate(t *testing.T) { Header: http.Header{"Content-Type": []string{"application/protobuf"}}, Body: ioutil.NopCloser(bytes.NewReader(invalid)), }, - Decoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + Decoder: scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), Called: true, ExpectContentType: "application/protobuf", @@ -491,7 +490,7 @@ func TestTransformResponseNegotiate(t *testing.T) { StatusCode: 500, Header: http.Header{"Content-Type": []string{"application/,others"}}, }, - Decoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + Decoder: scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), Error: true, ErrFn: func(err error) bool { @@ -505,7 +504,7 @@ func TestTransformResponseNegotiate(t *testing.T) { Header: http.Header{"Content-Type": []string{"text/any"}}, Body: ioutil.NopCloser(bytes.NewReader(invalid)), }, - Decoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + Decoder: scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), }, { // no negotiation when no response content type specified @@ -514,7 +513,7 @@ func TestTransformResponseNegotiate(t *testing.T) { StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid)), }, - Decoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + Decoder: scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), }, { // unrecognized content type is not handled @@ -524,7 +523,7 @@ func TestTransformResponseNegotiate(t *testing.T) { Header: http.Header{"Content-Type": []string{"application/unrecognized"}}, Body: ioutil.NopCloser(bytes.NewReader(invalid)), }, - Decoder: api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + Decoder: scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), NegotiateErr: fmt.Errorf("aaaa"), Called: true, @@ -537,7 +536,7 @@ func TestTransformResponseNegotiate(t *testing.T) { }, } for i, test := range testCases { - serializers := defaultSerializers() + serializers := defaultSerializers(t) negotiator := &renegotiator{ decoder: test.Decoder, err: test.NegotiateErr, @@ -675,7 +674,7 @@ func TestTransformUnstructuredError(t *testing.T) { for i, testCase := range testCases { r := &Request{ content: defaultContentConfig(), - serializers: defaultSerializers(), + serializers: defaultSerializers(t), resourceName: testCase.Name, resource: testCase.Resource, } @@ -711,7 +710,7 @@ func TestTransformUnstructuredError(t *testing.T) { } // verify result.Into properly handles the error - if err := result.Into(&api.Pod{}); !reflect.DeepEqual(expect, err) { + if err := result.Into(&v1.Pod{}); !reflect.DeepEqual(expect, err) { t.Errorf("%d: unexpected error on Into(): %s", i, diff.ObjectReflectDiff(expect, err)) } @@ -749,7 +748,7 @@ func TestRequestWatch(t *testing.T) { { Request: &Request{ content: defaultContentConfig(), - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusForbidden, @@ -766,7 +765,7 @@ func TestRequestWatch(t *testing.T) { { Request: &Request{ content: defaultContentConfig(), - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusUnauthorized, @@ -783,11 +782,11 @@ func TestRequestWatch(t *testing.T) { { Request: &Request{ content: defaultContentConfig(), - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusUnauthorized, - Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), &metav1.Status{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), &metav1.Status{ Status: metav1.StatusFailure, Reason: metav1.StatusReasonUnauthorized, })))), @@ -802,7 +801,7 @@ func TestRequestWatch(t *testing.T) { }, { Request: &Request{ - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, io.EOF }), @@ -812,7 +811,7 @@ func TestRequestWatch(t *testing.T) { }, { Request: &Request{ - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, &url.Error{Err: io.EOF} }), @@ -822,7 +821,7 @@ func TestRequestWatch(t *testing.T) { }, { Request: &Request{ - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, errors.New("http: can't write HTTP request on broken connection") }), @@ -832,7 +831,7 @@ func TestRequestWatch(t *testing.T) { }, { Request: &Request{ - serializers: defaultSerializers(), + serializers: defaultSerializers(t), client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, errors.New("foo: connection reset by peer") }), @@ -894,14 +893,14 @@ func TestRequestStream(t *testing.T) { client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusUnauthorized, - Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), &metav1.Status{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), &metav1.Status{ Status: metav1.StatusFailure, Reason: metav1.StatusReasonUnauthorized, })))), }, nil }), content: defaultContentConfig(), - serializers: defaultSerializers(), + serializers: defaultSerializers(t), baseURL: &url.URL{}, }, Err: true, @@ -915,7 +914,7 @@ func TestRequestStream(t *testing.T) { }, nil }), content: defaultContentConfig(), - serializers: defaultSerializers(), + serializers: defaultSerializers(t), baseURL: &url.URL{}, }, Err: true, @@ -1018,12 +1017,12 @@ func TestRequestDo(t *testing.T) { func TestDoRequestNewWay(t *testing.T) { reqBody := "request body" - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ + expectedObj := &v1.Service{Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), @@ -1247,14 +1246,14 @@ func BenchmarkCheckRetryClosesBody(b *testing.B) { } func TestDoRequestNewWayReader(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - reqBodyExpected, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ + reqObj := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + reqBodyExpected, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) + expectedObj := &v1.Service{Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), @@ -1282,19 +1281,19 @@ func TestDoRequestNewWayReader(t *testing.T) { } tmpStr := string(reqBodyExpected) requestURL := defaultResourcePathWithPrefix("foo", "bar", "", "baz") - requestURL += "?" + metav1.LabelSelectorQueryParam(api.Registry.GroupOrDie(api.GroupName).GroupVersion.String()) + "=name%3Dfoo&timeout=1s" + requestURL += "?" + metav1.LabelSelectorQueryParam(v1.SchemeGroupVersion.String()) + "=name%3Dfoo&timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) } func TestDoRequestNewWayObj(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - reqBodyExpected, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ + reqObj := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + reqBodyExpected, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) + expectedObj := &v1.Service{Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), @@ -1322,13 +1321,13 @@ func TestDoRequestNewWayObj(t *testing.T) { } tmpStr := string(reqBodyExpected) requestURL := defaultResourcePathWithPrefix("", "foo", "", "bar/baz") - requestURL += "?" + metav1.LabelSelectorQueryParam(api.Registry.GroupOrDie(api.GroupName).GroupVersion.String()) + "=name%3Dfoo&timeout=1s" + requestURL += "?" + metav1.LabelSelectorQueryParam(v1.SchemeGroupVersion.String()) + "=name%3Dfoo&timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) } func TestDoRequestNewWayFile(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - reqBodyExpected, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) + reqObj := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + reqBodyExpected, err := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -1345,12 +1344,12 @@ func TestDoRequestNewWayFile(t *testing.T) { t.Errorf("unexpected error: %v", err) } - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ + expectedObj := &v1.Service{Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), @@ -1384,18 +1383,18 @@ func TestDoRequestNewWayFile(t *testing.T) { } func TestWasCreated(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - reqBodyExpected, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) + reqObj := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + reqBodyExpected, err := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), reqObj) if err != nil { t.Errorf("unexpected error: %v", err) } - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ + expectedObj := &v1.Service{Spec: v1.ServiceSpec{Ports: []v1.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} - expectedBody, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) + expectedBody, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 201, ResponseBody: string(expectedBody), @@ -1521,8 +1520,8 @@ func TestUnacceptableParamNames(t *testing.T) { func TestBody(t *testing.T) { const data = "test payload" - obj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} - bodyExpected, _ := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), obj) + obj := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + bodyExpected, _ := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), obj) f, err := ioutil.TempFile("", "test_body") if err != nil { @@ -1534,7 +1533,7 @@ func TestBody(t *testing.T) { f.Close() defer os.Remove(f.Name()) - var nilObject *api.DeleteOptions + var nilObject *v1.DeleteOptions typedObject := interface{}(nilObject) c := testRESTClient(t, nil) tests := []struct { @@ -1585,9 +1584,9 @@ func TestWatch(t *testing.T) { t watch.EventType obj runtime.Object }{ - {watch.Added, &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "first"}}}, - {watch.Modified, &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "second"}}}, - {watch.Deleted, &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "last"}}}, + {watch.Added, &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "first"}}}, + {watch.Modified, &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "second"}}}, + {watch.Deleted, &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "last"}}}, } testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -1600,7 +1599,7 @@ func TestWatch(t *testing.T) { w.WriteHeader(http.StatusOK) flusher.Flush() - encoder := restclientwatch.NewEncoder(streaming.NewEncoder(w, api.Codecs.LegacyCodec(v1.SchemeGroupVersion)), api.Codecs.LegacyCodec(v1.SchemeGroupVersion)) + encoder := restclientwatch.NewEncoder(streaming.NewEncoder(w, scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion)), scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion)) for _, item := range table { if err := encoder.Encode(&watch.Event{Type: item.t, Object: item.obj}); err != nil { panic(err) diff --git a/rest/watch/BUILD b/rest/watch/BUILD index 3e93f100..c78dcce1 100644 --- a/rest/watch/BUILD +++ b/rest/watch/BUILD @@ -34,11 +34,12 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", - "//vendor/k8s.io/client-go/pkg/api:go_default_library", - "//vendor/k8s.io/client-go/pkg/api/install:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library", "//vendor/k8s.io/client-go/rest/watch:go_default_library", ], diff --git a/rest/watch/decoder_test.go b/rest/watch/decoder_test.go index 5d443531..d78da56a 100644 --- a/rest/watch/decoder_test.go +++ b/rest/watch/decoder_test.go @@ -25,28 +25,35 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + runtimejson "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/pkg/api" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/pkg/api/v1" restclientwatch "k8s.io/client-go/rest/watch" - - _ "k8s.io/client-go/pkg/api/install" ) +// getDecoder mimics how k8s.io/client-go/rest.createSerializers creates a decoder +func getDecoder() runtime.Decoder { + jsonSerializer := runtimejson.NewSerializer(runtimejson.DefaultMetaFactory, scheme.Scheme, scheme.Scheme, false) + directCodecFactory := serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + return directCodecFactory.DecoderToVersion(jsonSerializer, v1.SchemeGroupVersion) +} + func TestDecoder(t *testing.T) { table := []watch.EventType{watch.Added, watch.Deleted, watch.Modified, watch.Error} for _, eventType := range table { out, in := io.Pipe() - codec := api.Codecs.LegacyCodec(v1.SchemeGroupVersion) - decoder := restclientwatch.NewDecoder(streaming.NewDecoder(out, codec), codec) - expect := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + decoder := restclientwatch.NewDecoder(streaming.NewDecoder(out, getDecoder()), getDecoder()) + + expect := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} encoder := json.NewEncoder(in) go func() { - data, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), expect) + data, err := runtime.Encode(scheme.Codecs.LegacyCodec(v1.SchemeGroupVersion), expect) if err != nil { t.Fatalf("Unexpected error %v", err) } @@ -93,8 +100,7 @@ func TestDecoder(t *testing.T) { func TestDecoder_SourceClose(t *testing.T) { out, in := io.Pipe() - codec := api.Codecs.LegacyCodec(v1.SchemeGroupVersion) - decoder := restclientwatch.NewDecoder(streaming.NewDecoder(out, codec), codec) + decoder := restclientwatch.NewDecoder(streaming.NewDecoder(out, getDecoder()), getDecoder()) done := make(chan struct{}) diff --git a/rest/watch/encoder_test.go b/rest/watch/encoder_test.go index f2e5aaa7..b9381b46 100644 --- a/rest/watch/encoder_test.go +++ b/rest/watch/encoder_test.go @@ -24,49 +24,51 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + runtimejson "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/pkg/api" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/pkg/api/v1" restclientwatch "k8s.io/client-go/rest/watch" - - _ "k8s.io/client-go/pkg/api/install" ) +// getEncoder mimics how k8s.io/client-go/rest.createSerializers creates a encoder +func getEncoder() runtime.Encoder { + jsonSerializer := runtimejson.NewSerializer(runtimejson.DefaultMetaFactory, scheme.Scheme, scheme.Scheme, false) + directCodecFactory := serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + return directCodecFactory.EncoderForVersion(jsonSerializer, v1.SchemeGroupVersion) +} + func TestEncodeDecodeRoundTrip(t *testing.T) { testCases := []struct { Type watch.EventType Object runtime.Object - Codec runtime.Codec }{ { watch.Added, - &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, }, { watch.Modified, - &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, }, { watch.Deleted, - &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - api.Codecs.LegacyCodec(v1.SchemeGroupVersion), + &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, }, } for i, testCase := range testCases { buf := &bytes.Buffer{} - codec := testCase.Codec - encoder := restclientwatch.NewEncoder(streaming.NewEncoder(buf, codec), codec) + encoder := restclientwatch.NewEncoder(streaming.NewEncoder(buf, getEncoder()), getEncoder()) if err := encoder.Encode(&watch.Event{Type: testCase.Type, Object: testCase.Object}); err != nil { t.Errorf("%d: unexpected error: %v", i, err) continue } rc := ioutil.NopCloser(buf) - decoder := restclientwatch.NewDecoder(streaming.NewDecoder(rc, codec), codec) + decoder := restclientwatch.NewDecoder(streaming.NewDecoder(rc, getDecoder()), getDecoder()) event, obj, err := decoder.Decode() if err != nil { t.Errorf("%d: unexpected error: %v", i, err) diff --git a/tools/record/BUILD b/tools/record/BUILD index 0e39f0a9..5bca6489 100644 --- a/tools/record/BUILD +++ b/tools/record/BUILD @@ -22,8 +22,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library", - "//vendor/k8s.io/client-go/pkg/api:go_default_library", - "//vendor/k8s.io/client-go/pkg/api/install:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/pkg/api/v1:go_default_library", "//vendor/k8s.io/client-go/pkg/api/v1/ref:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", diff --git a/tools/record/event_test.go b/tools/record/event_test.go index c50bd91f..92599081 100644 --- a/tools/record/event_test.go +++ b/tools/record/event_test.go @@ -29,8 +29,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sruntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/strategicpatch" - "k8s.io/client-go/pkg/api" - _ "k8s.io/client-go/pkg/api/install" // To register api.Pod used in tests below + "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/pkg/api/v1" "k8s.io/client-go/pkg/api/v1/ref" restclient "k8s.io/client-go/rest" @@ -120,8 +119,8 @@ func TestEventf(t *testing.T) { UID: "differentUid", }, } - testRef, err := ref.GetPartialReference(api.Scheme, testPod, "spec.containers[2]") - testRef2, err := ref.GetPartialReference(api.Scheme, testPod2, "spec.containers[3]") + testRef, err := ref.GetPartialReference(scheme.Scheme, testPod, "spec.containers[2]") + testRef2, err := ref.GetPartialReference(scheme.Scheme, testPod2, "spec.containers[3]") if err != nil { t.Fatal(err) } @@ -376,7 +375,7 @@ func TestEventf(t *testing.T) { } func recorderWithFakeClock(eventSource v1.EventSource, eventBroadcaster EventBroadcaster, clock clock.Clock) EventRecorder { - return &recorderImpl{api.Scheme, eventSource, eventBroadcaster.(*eventBroadcasterImpl).Broadcaster, clock} + return &recorderImpl{scheme.Scheme, eventSource, eventBroadcaster.(*eventBroadcasterImpl).Broadcaster, clock} } func TestWriteEventError(t *testing.T) { @@ -497,7 +496,7 @@ func TestLotsOfEvents(t *testing.T) { logWatcher := eventBroadcaster.StartLogging(func(formatter string, args ...interface{}) { loggerCalled <- struct{}{} }) - recorder := eventBroadcaster.NewRecorder(api.Scheme, v1.EventSource{Component: "eventTest"}) + recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "eventTest"}) ref := &v1.ObjectReference{ Kind: "Pod", Name: "foo", @@ -532,7 +531,7 @@ func TestEventfNoNamespace(t *testing.T) { UID: "bar", }, } - testRef, err := ref.GetPartialReference(api.Scheme, testPod, "spec.containers[2]") + testRef, err := ref.GetPartialReference(scheme.Scheme, testPod, "spec.containers[2]") if err != nil { t.Fatal(err) } @@ -638,8 +637,8 @@ func TestMultiSinkCache(t *testing.T) { UID: "differentUid", }, } - testRef, err := ref.GetPartialReference(api.Scheme, testPod, "spec.containers[2]") - testRef2, err := ref.GetPartialReference(api.Scheme, testPod2, "spec.containers[3]") + testRef, err := ref.GetPartialReference(scheme.Scheme, testPod, "spec.containers[2]") + testRef2, err := ref.GetPartialReference(scheme.Scheme, testPod2, "spec.containers[3]") if err != nil { t.Fatal(err) }