From f32f3966d69b83c0d3dbb8903b205c79e81210e4 Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Tue, 24 May 2016 23:19:46 -0700 Subject: [PATCH] add DirectCodec; use it in release_1_3 clientset --- .../generators/generator_for_group.go | 4 +- .../typed/core/v1/core_client.go | 3 +- .../federation/v1alpha1/federation_client.go | 3 +- .../autoscaling/v1/autoscaling_client.go | 3 +- .../typed/batch/v1/batch_client.go | 3 +- .../release_1_3/typed/core/v1/core_client.go | 3 +- .../extensions/v1beta1/extensions_client.go | 3 +- .../release_1_2/clientset_adaption.go | 50 ----------------- .../release_1_3/clientset_adaption.go | 50 ----------------- pkg/runtime/serializer/codec_factory.go | 54 +++++++++++++++++++ pkg/runtime/serializer/codec_test.go | 46 ++++++++++++++++ test/e2e/framework/framework.go | 10 ++-- test/e2e/generated_clientset.go | 11 ++-- 13 files changed, 126 insertions(+), 117 deletions(-) delete mode 100644 pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go delete mode 100644 pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go diff --git a/cmd/libs/go2idl/client-gen/generators/generator_for_group.go b/cmd/libs/go2idl/client-gen/generators/generator_for_group.go index e3e932b38c9..7ae31d9fafe 100644 --- a/cmd/libs/go2idl/client-gen/generators/generator_for_group.go +++ b/cmd/libs/go2idl/client-gen/generators/generator_for_group.go @@ -61,6 +61,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer const pkgRESTClient = "k8s.io/kubernetes/pkg/client/restclient" const pkgRegistered = "k8s.io/kubernetes/pkg/apimachinery/registered" const pkgAPI = "k8s.io/kubernetes/pkg/api" + const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer" apiPath := func(group string) string { if group == "core" { return `"/api"` @@ -93,6 +94,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer "GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}), "apiPath": apiPath(g.group), "codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}), + "directCodecFactory": c.Universe.Variable(types.Name{Package: pkgSerializer, Name: "DirectCodecFactory"}), "Errorf": c.Universe.Variable(types.Name{Package: "fmt", Name: "Errorf"}), } sw.Do(groupInterfaceTemplate, m) @@ -240,7 +242,7 @@ func setConfigDefaults(config *$.Config|raw$) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = $.codecs|raw$ + config.NegotiatedSerializer = $.directCodecFactory|raw${CodecFactory: $.codecs|raw$} if config.QPS == 0 { config.QPS = 5 diff --git a/federation/client/clientset_generated/federation_release_1_3/typed/core/v1/core_client.go b/federation/client/clientset_generated/federation_release_1_3/typed/core/v1/core_client.go index 8d0682720d0..19593ab6799 100644 --- a/federation/client/clientset_generated/federation_release_1_3/typed/core/v1/core_client.go +++ b/federation/client/clientset_generated/federation_release_1_3/typed/core/v1/core_client.go @@ -20,6 +20,7 @@ import ( api "k8s.io/kubernetes/pkg/api" registered "k8s.io/kubernetes/pkg/apimachinery/registered" restclient "k8s.io/kubernetes/pkg/client/restclient" + serializer "k8s.io/kubernetes/pkg/runtime/serializer" ) type CoreInterface interface { @@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = api.Codecs + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} if config.QPS == 0 { config.QPS = 5 diff --git a/federation/client/clientset_generated/federation_release_1_3/typed/federation/v1alpha1/federation_client.go b/federation/client/clientset_generated/federation_release_1_3/typed/federation/v1alpha1/federation_client.go index 57ce4bc4efc..1d2e782c011 100644 --- a/federation/client/clientset_generated/federation_release_1_3/typed/federation/v1alpha1/federation_client.go +++ b/federation/client/clientset_generated/federation_release_1_3/typed/federation/v1alpha1/federation_client.go @@ -20,6 +20,7 @@ import ( api "k8s.io/kubernetes/pkg/api" registered "k8s.io/kubernetes/pkg/apimachinery/registered" restclient "k8s.io/kubernetes/pkg/client/restclient" + serializer "k8s.io/kubernetes/pkg/runtime/serializer" ) type FederationInterface interface { @@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = api.Codecs + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} if config.QPS == 0 { config.QPS = 5 diff --git a/pkg/client/clientset_generated/release_1_3/typed/autoscaling/v1/autoscaling_client.go b/pkg/client/clientset_generated/release_1_3/typed/autoscaling/v1/autoscaling_client.go index 330ce852bc4..a0fb01144ee 100644 --- a/pkg/client/clientset_generated/release_1_3/typed/autoscaling/v1/autoscaling_client.go +++ b/pkg/client/clientset_generated/release_1_3/typed/autoscaling/v1/autoscaling_client.go @@ -20,6 +20,7 @@ import ( api "k8s.io/kubernetes/pkg/api" registered "k8s.io/kubernetes/pkg/apimachinery/registered" restclient "k8s.io/kubernetes/pkg/client/restclient" + serializer "k8s.io/kubernetes/pkg/runtime/serializer" ) type AutoscalingInterface interface { @@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = api.Codecs + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} if config.QPS == 0 { config.QPS = 5 diff --git a/pkg/client/clientset_generated/release_1_3/typed/batch/v1/batch_client.go b/pkg/client/clientset_generated/release_1_3/typed/batch/v1/batch_client.go index 0e566ed3aa3..018d2c688ac 100644 --- a/pkg/client/clientset_generated/release_1_3/typed/batch/v1/batch_client.go +++ b/pkg/client/clientset_generated/release_1_3/typed/batch/v1/batch_client.go @@ -20,6 +20,7 @@ import ( api "k8s.io/kubernetes/pkg/api" registered "k8s.io/kubernetes/pkg/apimachinery/registered" restclient "k8s.io/kubernetes/pkg/client/restclient" + serializer "k8s.io/kubernetes/pkg/runtime/serializer" ) type BatchInterface interface { @@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = api.Codecs + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} if config.QPS == 0 { config.QPS = 5 diff --git a/pkg/client/clientset_generated/release_1_3/typed/core/v1/core_client.go b/pkg/client/clientset_generated/release_1_3/typed/core/v1/core_client.go index c670a0f2a1e..3804b8cb3b6 100644 --- a/pkg/client/clientset_generated/release_1_3/typed/core/v1/core_client.go +++ b/pkg/client/clientset_generated/release_1_3/typed/core/v1/core_client.go @@ -20,6 +20,7 @@ import ( api "k8s.io/kubernetes/pkg/api" registered "k8s.io/kubernetes/pkg/apimachinery/registered" restclient "k8s.io/kubernetes/pkg/client/restclient" + serializer "k8s.io/kubernetes/pkg/runtime/serializer" ) type CoreInterface interface { @@ -150,7 +151,7 @@ func setConfigDefaults(config *restclient.Config) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = api.Codecs + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} if config.QPS == 0 { config.QPS = 5 diff --git a/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1/extensions_client.go b/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1/extensions_client.go index 6b6d9114023..23aa5b219ed 100644 --- a/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1/extensions_client.go +++ b/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1/extensions_client.go @@ -20,6 +20,7 @@ import ( api "k8s.io/kubernetes/pkg/api" registered "k8s.io/kubernetes/pkg/apimachinery/registered" restclient "k8s.io/kubernetes/pkg/client/restclient" + serializer "k8s.io/kubernetes/pkg/runtime/serializer" ) type ExtensionsInterface interface { @@ -120,7 +121,7 @@ func setConfigDefaults(config *restclient.Config) error { config.GroupVersion = ©GroupVersion //} - config.NegotiatedSerializer = api.Codecs + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} if config.QPS == 0 { config.QPS = 5 diff --git a/pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go b/pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go deleted file mode 100644 index 9e33ccd1978..00000000000 --- a/pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -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 release_1_2 - -import ( - "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2" - v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2/typed/core/v1" - v1beta1extensions "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2/typed/extensions/v1beta1" - "k8s.io/kubernetes/pkg/client/typed/discovery" - "k8s.io/kubernetes/pkg/client/unversioned" -) - -// FromUnversionedClient adapts a unversioned.Client to a release_1_2.Clientset. -// This function is temporary. We will remove it when everyone has moved to using -// Clientset. New code should NOT use this function. -func FromUnversionedClient(c *unversioned.Client) *release_1_2.Clientset { - var clientset release_1_2.Clientset - if c != nil { - clientset.CoreClient = v1core.New(c.RESTClient) - } else { - clientset.CoreClient = v1core.New(nil) - } - if c != nil && c.ExtensionsClient != nil { - clientset.ExtensionsClient = v1beta1extensions.New(c.ExtensionsClient.RESTClient) - } else { - clientset.ExtensionsClient = v1beta1extensions.New(nil) - } - - if c != nil && c.DiscoveryClient != nil { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(c.DiscoveryClient.RESTClient) - } else { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(nil) - } - - return &clientset -} diff --git a/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go b/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go deleted file mode 100644 index 3f4b86fb4b8..00000000000 --- a/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -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 release_1_3 - -import ( - "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" - v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3/typed/core/v1" - v1beta1extensions "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1" - "k8s.io/kubernetes/pkg/client/typed/discovery" - "k8s.io/kubernetes/pkg/client/unversioned" -) - -// FromUnversionedClient adapts a unversioned.Client to a release_1_3.Clientset. -// This function is temporary. We will remove it when everyone has moved to using -// Clientset. New code should NOT use this function. -func FromUnversionedClient(c *unversioned.Client) *release_1_3.Clientset { - var clientset release_1_3.Clientset - if c != nil { - clientset.CoreClient = v1core.New(c.RESTClient) - } else { - clientset.CoreClient = v1core.New(nil) - } - if c != nil && c.ExtensionsClient != nil { - clientset.ExtensionsClient = v1beta1extensions.New(c.ExtensionsClient.RESTClient) - } else { - clientset.ExtensionsClient = v1beta1extensions.New(nil) - } - - if c != nil && c.DiscoveryClient != nil { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(c.DiscoveryClient.RESTClient) - } else { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(nil) - } - - return &clientset -} diff --git a/pkg/runtime/serializer/codec_factory.go b/pkg/runtime/serializer/codec_factory.go index 96af0cfd354..ccd146770ad 100644 --- a/pkg/runtime/serializer/codec_factory.go +++ b/pkg/runtime/serializer/codec_factory.go @@ -17,6 +17,8 @@ limitations under the License. package serializer import ( + "io" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime/serializer/json" @@ -308,3 +310,55 @@ func (f CodecFactory) SerializerForFileExtension(extension string) (runtime.Seri } return nil, false } + +// DirectCodecFactory provides methods for retrieving "DirectCodec"s, which do not do conversion. +type DirectCodecFactory struct { + CodecFactory +} + +// EncoderForVersion returns an encoder that does not do conversion. gv is ignored. +func (f DirectCodecFactory) EncoderForVersion(serializer runtime.Encoder, gv unversioned.GroupVersion) runtime.Encoder { + return DirectCodec{ + runtime.NewCodec(serializer, nil), + f.CodecFactory.scheme, + } +} + +// DecoderToVersion returns an decoder that does not do conversion. gv is ignored. +func (f DirectCodecFactory) DecoderToVersion(serializer runtime.Decoder, gv unversioned.GroupVersion) runtime.Decoder { + return DirectCodec{ + runtime.NewCodec(nil, serializer), + nil, + } +} + +// DirectCodec is a codec that does not do conversion. It sets the gvk during serialization, and removes the gvk during deserialization. +type DirectCodec struct { + runtime.Serializer + runtime.ObjectTyper +} + +// EncodeToStream does not do conversion. It sets the gvk during serialization. overrides are ignored. +func (c DirectCodec) EncodeToStream(obj runtime.Object, stream io.Writer, overrides ...unversioned.GroupVersion) error { + gvks, _, err := c.ObjectTyper.ObjectKinds(obj) + if err != nil { + return err + } + kind := obj.GetObjectKind() + oldGVK := kind.GroupVersionKind() + kind.SetGroupVersionKind(gvks[0]) + err = c.Serializer.EncodeToStream(obj, stream, overrides...) + kind.SetGroupVersionKind(oldGVK) + return err +} + +// Decode does not do conversion. It removes the gvk during deserialization. +func (c DirectCodec) Decode(data []byte, defaults *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { + obj, gvk, err := c.Serializer.Decode(data, defaults, into) + if obj != nil { + kind := obj.GetObjectKind() + // clearing the gvk is just a convention of a codec + kind.SetGroupVersionKind(unversioned.GroupVersionKind{}) + } + return obj, gvk, err +} diff --git a/pkg/runtime/serializer/codec_test.go b/pkg/runtime/serializer/codec_test.go index e1307d3c8e5..861efffd7c2 100644 --- a/pkg/runtime/serializer/codec_test.go +++ b/pkg/runtime/serializer/codec_test.go @@ -398,3 +398,49 @@ func TestBadJSONRejection(t *testing.T) { t.Errorf("Did not give error for empty data") } } + +// Returns a new Scheme set up with the test objects needed by TestDirectCodec. +func GetDirectCodecTestScheme() *runtime.Scheme { + internalGV := unversioned.GroupVersion{Version: runtime.APIVersionInternal} + externalGV := unversioned.GroupVersion{Version: "v1"} + + s := runtime.NewScheme() + // Ordinarily, we wouldn't add TestType2, but because this is a test and + // both types are from the same package, we need to get it into the system + // so that converter will match it with ExternalType2. + s.AddKnownTypes(internalGV, &TestType1{}) + s.AddKnownTypes(externalGV, &ExternalTestType1{}) + + s.AddUnversionedTypes(externalGV, &unversioned.Status{}) + return s +} + +func TestDirectCodec(t *testing.T) { + s := GetDirectCodecTestScheme() + cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) + serializer, _ := cf.SerializerForFileExtension("json") + df := DirectCodecFactory{cf} + ignoredGV, err := unversioned.ParseGroupVersion("ignored group/ignored version") + if err != nil { + t.Fatal(err) + } + directEncoder := df.EncoderForVersion(serializer, ignoredGV) + directDecoder := df.DecoderToVersion(serializer, ignoredGV) + out, err := runtime.Encode(directEncoder, &ExternalTestType1{}, ignoredGV) + if err != nil { + t.Fatal(err) + } + if string(out) != `{"myVersionKey":"v1","myKindKey":"ExternalTestType1"}`+"\n" { + t.Fatal(string(out)) + } + a, _, err := directDecoder.Decode(out, nil, nil) + e := &ExternalTestType1{ + MyWeirdCustomEmbeddedVersionKindField: MyWeirdCustomEmbeddedVersionKindField{ + APIVersion: "v1", + ObjectKind: "ExternalTestType1", + }, + } + if !semantic.DeepEqual(e, a) { + t.Fatalf("expect %v, got %v", e, a) + } +} diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 69bd5d7dbd7..9e9c76e1fcc 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -31,8 +31,6 @@ import ( "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" client "k8s.io/kubernetes/pkg/client/unversioned" - adapter_1_2 "k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_2" - adapter_1_3 "k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_3" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/metrics" @@ -130,7 +128,6 @@ func (f *Framework) BeforeEach() { // The fact that we need this feels like a bug in ginkgo. // https://github.com/onsi/ginkgo/issues/222 f.cleanupHandle = AddCleanupAction(f.AfterEach) - if f.Client == nil { By("Creating a kubernetes client") config, err := LoadConfig() @@ -143,11 +140,12 @@ func (f *Framework) BeforeEach() { c, err := loadClientFromConfig(config) Expect(err).NotTo(HaveOccurred()) f.Client = c + f.Clientset_1_2, err = release_1_2.NewForConfig(config) + Expect(err).NotTo(HaveOccurred()) + f.Clientset_1_3, err = release_1_3.NewForConfig(config) + Expect(err).NotTo(HaveOccurred()) } - f.Clientset_1_2 = adapter_1_2.FromUnversionedClient(f.Client) - f.Clientset_1_3 = adapter_1_3.FromUnversionedClient(f.Client) - if f.federated && f.FederationClient == nil { By("Creating a federated kubernetes client") var err error diff --git a/test/e2e/generated_clientset.go b/test/e2e/generated_clientset.go index 952bcc18f7f..1432144dace 100644 --- a/test/e2e/generated_clientset.go +++ b/test/e2e/generated_clientset.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/watch" @@ -74,7 +75,7 @@ func observePodCreation(w watch.Interface) { } } -func observePodDeletion(w watch.Interface) (lastPod *api.Pod) { +func observeObjectDeletion(w watch.Interface) (obj runtime.Object) { deleted := false timeout := false timer := time.After(60 * time.Second) @@ -82,7 +83,7 @@ func observePodDeletion(w watch.Interface) (lastPod *api.Pod) { select { case event, _ := <-w.ResultChan(): if event.Type == watch.Deleted { - lastPod = event.Object.(*api.Pod) + obj = event.Object deleted = true } case <-timer: @@ -155,7 +156,8 @@ var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() { } By("verifying pod deletion was observed") - lastPod := observePodDeletion(w) + obj := observeObjectDeletion(w) + lastPod := obj.(*api.Pod) Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero()) @@ -228,7 +230,8 @@ var _ = framework.KubeDescribe("Generated release_1_3 clientset", func() { } By("verifying pod deletion was observed") - lastPod := observePodDeletion(w) + obj := observeObjectDeletion(w) + lastPod := obj.(*v1.Pod) Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero())