Commit cf234ab6 authored by k8s-merge-robot's avatar k8s-merge-robot

Merge pull request #26251 from caesarxuchao/add-serializer

Automatic merge from submit-queue Add direct serializer Fix #25589. Implemented a direct codec that doesn't do conversion, but sets the group, version and kind before serialization as Clayton suggested [here](https://github.com/kubernetes/kubernetes/issues/25589#issuecomment-219168009). First commit is cherry-picked from #24826. @kubernetes/sig-api-machinery
parents 8dcedbab f32f3966
...@@ -61,6 +61,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer ...@@ -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 pkgRESTClient = "k8s.io/kubernetes/pkg/client/restclient"
const pkgRegistered = "k8s.io/kubernetes/pkg/apimachinery/registered" const pkgRegistered = "k8s.io/kubernetes/pkg/apimachinery/registered"
const pkgAPI = "k8s.io/kubernetes/pkg/api" const pkgAPI = "k8s.io/kubernetes/pkg/api"
const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer"
apiPath := func(group string) string { apiPath := func(group string) string {
if group == "core" { if group == "core" {
return `"/api"` return `"/api"`
...@@ -93,6 +94,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer ...@@ -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"}), "GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}),
"apiPath": apiPath(g.group), "apiPath": apiPath(g.group),
"codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}), "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"}), "Errorf": c.Universe.Variable(types.Name{Package: "fmt", Name: "Errorf"}),
} }
sw.Do(groupInterfaceTemplate, m) sw.Do(groupInterfaceTemplate, m)
...@@ -240,7 +242,7 @@ func setConfigDefaults(config *$.Config|raw$) error { ...@@ -240,7 +242,7 @@ func setConfigDefaults(config *$.Config|raw$) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = $.codecs|raw$ config.NegotiatedSerializer = $.directCodecFactory|raw${CodecFactory: $.codecs|raw$}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
api "k8s.io/kubernetes/pkg/api" api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered" registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient" restclient "k8s.io/kubernetes/pkg/client/restclient"
serializer "k8s.io/kubernetes/pkg/runtime/serializer"
) )
type CoreInterface interface { type CoreInterface interface {
...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { ...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = api.Codecs config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
api "k8s.io/kubernetes/pkg/api" api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered" registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient" restclient "k8s.io/kubernetes/pkg/client/restclient"
serializer "k8s.io/kubernetes/pkg/runtime/serializer"
) )
type FederationInterface interface { type FederationInterface interface {
...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { ...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = api.Codecs config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
api "k8s.io/kubernetes/pkg/api" api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered" registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient" restclient "k8s.io/kubernetes/pkg/client/restclient"
serializer "k8s.io/kubernetes/pkg/runtime/serializer"
) )
type AutoscalingInterface interface { type AutoscalingInterface interface {
...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { ...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = api.Codecs config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
api "k8s.io/kubernetes/pkg/api" api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered" registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient" restclient "k8s.io/kubernetes/pkg/client/restclient"
serializer "k8s.io/kubernetes/pkg/runtime/serializer"
) )
type BatchInterface interface { type BatchInterface interface {
...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error { ...@@ -80,7 +81,7 @@ func setConfigDefaults(config *restclient.Config) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = api.Codecs config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
api "k8s.io/kubernetes/pkg/api" api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered" registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient" restclient "k8s.io/kubernetes/pkg/client/restclient"
serializer "k8s.io/kubernetes/pkg/runtime/serializer"
) )
type CoreInterface interface { type CoreInterface interface {
...@@ -150,7 +151,7 @@ func setConfigDefaults(config *restclient.Config) error { ...@@ -150,7 +151,7 @@ func setConfigDefaults(config *restclient.Config) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = api.Codecs config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
api "k8s.io/kubernetes/pkg/api" api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered" registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient" restclient "k8s.io/kubernetes/pkg/client/restclient"
serializer "k8s.io/kubernetes/pkg/runtime/serializer"
) )
type ExtensionsInterface interface { type ExtensionsInterface interface {
...@@ -120,7 +121,7 @@ func setConfigDefaults(config *restclient.Config) error { ...@@ -120,7 +121,7 @@ func setConfigDefaults(config *restclient.Config) error {
config.GroupVersion = &copyGroupVersion config.GroupVersion = &copyGroupVersion
//} //}
config.NegotiatedSerializer = api.Codecs config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
if config.QPS == 0 { if config.QPS == 0 {
config.QPS = 5 config.QPS = 5
......
/*
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
}
/*
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
}
...@@ -17,6 +17,8 @@ limitations under the License. ...@@ -17,6 +17,8 @@ limitations under the License.
package serializer package serializer
import ( import (
"io"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/json" "k8s.io/kubernetes/pkg/runtime/serializer/json"
...@@ -308,3 +310,55 @@ func (f CodecFactory) SerializerForFileExtension(extension string) (runtime.Seri ...@@ -308,3 +310,55 @@ func (f CodecFactory) SerializerForFileExtension(extension string) (runtime.Seri
} }
return nil, false 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
}
...@@ -398,3 +398,49 @@ func TestBadJSONRejection(t *testing.T) { ...@@ -398,3 +398,49 @@ func TestBadJSONRejection(t *testing.T) {
t.Errorf("Did not give error for empty data") 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)
}
}
...@@ -31,8 +31,6 @@ import ( ...@@ -31,8 +31,6 @@ import (
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2"
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3"
client "k8s.io/kubernetes/pkg/client/unversioned" 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/fields"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/metrics" "k8s.io/kubernetes/pkg/metrics"
...@@ -130,7 +128,6 @@ func (f *Framework) BeforeEach() { ...@@ -130,7 +128,6 @@ func (f *Framework) BeforeEach() {
// The fact that we need this feels like a bug in ginkgo. // The fact that we need this feels like a bug in ginkgo.
// https://github.com/onsi/ginkgo/issues/222 // https://github.com/onsi/ginkgo/issues/222
f.cleanupHandle = AddCleanupAction(f.AfterEach) f.cleanupHandle = AddCleanupAction(f.AfterEach)
if f.Client == nil { if f.Client == nil {
By("Creating a kubernetes client") By("Creating a kubernetes client")
config, err := LoadConfig() config, err := LoadConfig()
...@@ -143,11 +140,12 @@ func (f *Framework) BeforeEach() { ...@@ -143,11 +140,12 @@ func (f *Framework) BeforeEach() {
c, err := loadClientFromConfig(config) c, err := loadClientFromConfig(config)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
f.Client = c 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 { if f.federated && f.FederationClient == nil {
By("Creating a federated kubernetes client") By("Creating a federated kubernetes client")
var err error var err error
......
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
...@@ -74,7 +75,7 @@ func observePodCreation(w watch.Interface) { ...@@ -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 deleted := false
timeout := false timeout := false
timer := time.After(60 * time.Second) timer := time.After(60 * time.Second)
...@@ -82,7 +83,7 @@ func observePodDeletion(w watch.Interface) (lastPod *api.Pod) { ...@@ -82,7 +83,7 @@ func observePodDeletion(w watch.Interface) (lastPod *api.Pod) {
select { select {
case event, _ := <-w.ResultChan(): case event, _ := <-w.ResultChan():
if event.Type == watch.Deleted { if event.Type == watch.Deleted {
lastPod = event.Object.(*api.Pod) obj = event.Object
deleted = true deleted = true
} }
case <-timer: case <-timer:
...@@ -155,7 +156,8 @@ var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() { ...@@ -155,7 +156,8 @@ var _ = framework.KubeDescribe("Generated release_1_2 clientset", func() {
} }
By("verifying pod deletion was observed") By("verifying pod deletion was observed")
lastPod := observePodDeletion(w) obj := observeObjectDeletion(w)
lastPod := obj.(*api.Pod)
Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) Expect(lastPod.DeletionTimestamp).ToNot(BeNil())
Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero()) Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero())
...@@ -228,7 +230,8 @@ var _ = framework.KubeDescribe("Generated release_1_3 clientset", func() { ...@@ -228,7 +230,8 @@ var _ = framework.KubeDescribe("Generated release_1_3 clientset", func() {
} }
By("verifying pod deletion was observed") By("verifying pod deletion was observed")
lastPod := observePodDeletion(w) obj := observeObjectDeletion(w)
lastPod := obj.(*v1.Pod)
Expect(lastPod.DeletionTimestamp).ToNot(BeNil()) Expect(lastPod.DeletionTimestamp).ToNot(BeNil())
Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero()) Expect(lastPod.Spec.TerminationGracePeriodSeconds).ToNot(BeZero())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment