mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Merge pull request #98194 from julianvmodesto/dry-run-openapi
Cache the OpenAPI schema for kubectl server-side dry run
This commit is contained in:
commit
da85ff10cc
@ -27,17 +27,10 @@ import (
|
|||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VerifyDryRun returns nil if a resource group-version-kind supports
|
func NewDryRunVerifier(dynamicClient dynamic.Interface, openAPIGetter discovery.OpenAPISchemaInterface) *DryRunVerifier {
|
||||||
// server-side dry-run. Otherwise, an error is returned.
|
|
||||||
func VerifyDryRun(gvk schema.GroupVersionKind, dynamicClient dynamic.Interface, discoveryClient discovery.DiscoveryInterface) error {
|
|
||||||
verifier := NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
return verifier.HasSupport(gvk)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDryRunVerifier(dynamicClient dynamic.Interface, discoveryClient discovery.DiscoveryInterface) *DryRunVerifier {
|
|
||||||
return &DryRunVerifier{
|
return &DryRunVerifier{
|
||||||
finder: NewCRDFinder(CRDFromDynamic(dynamicClient)),
|
finder: NewCRDFinder(CRDFromDynamic(dynamicClient)),
|
||||||
openAPIGetter: discoveryClient,
|
openAPIGetter: openAPIGetter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,11 +178,7 @@ func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.dryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.dryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -218,11 +218,7 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(o.DynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(o.DynamicClient, discoveryClient)
|
|
||||||
o.FieldManager = GetApplyFieldManagerFlag(cmd, o.ServerSideApply)
|
o.FieldManager = GetApplyFieldManagerFlag(cmd, o.ServerSideApply)
|
||||||
|
|
||||||
if o.ForceConflicts && !o.ServerSideApply {
|
if o.ForceConflicts && !o.ServerSideApply {
|
||||||
|
@ -128,11 +128,7 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
o.output = cmdutil.GetFlagString(cmd, "output")
|
o.output = cmdutil.GetFlagString(cmd, "output")
|
||||||
o.shortOutput = o.output == "name"
|
o.shortOutput = o.output == "name"
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
@ -41,6 +42,7 @@ import (
|
|||||||
sptest "k8s.io/apimachinery/pkg/util/strategicpatch/testing"
|
sptest "k8s.io/apimachinery/pkg/util/strategicpatch/testing"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
dynamicfakeclient "k8s.io/client-go/dynamic/fake"
|
dynamicfakeclient "k8s.io/client-go/dynamic/fake"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
@ -52,21 +54,38 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fakeSchema = sptest.Fake{Path: filepath.Join("..", "..", "..", "testdata", "openapi", "swagger.json")}
|
fakeSchema = sptest.Fake{Path: filepath.Join("..", "..", "..", "testdata", "openapi", "swagger.json")}
|
||||||
testingOpenAPISchemaFns = []func() (openapi.Resources, error){nil, AlwaysErrorOpenAPISchemaFn, openAPISchemaFn}
|
testingOpenAPISchemas = []testOpenAPISchema{{OpenAPIGetter: &fakeSchema}, AlwaysErrorsOpenAPISchema, FakeOpenAPISchema}
|
||||||
AlwaysErrorOpenAPISchemaFn = func() (openapi.Resources, error) {
|
AlwaysErrorsOpenAPISchema = testOpenAPISchema{
|
||||||
return nil, errors.New("cannot get openapi spec")
|
OpenAPISchemaFn: func() (openapi.Resources, error) {
|
||||||
|
return nil, errors.New("cannot get openapi spec")
|
||||||
|
},
|
||||||
|
OpenAPIGetter: &alwaysErrorsOpenAPISchema{},
|
||||||
}
|
}
|
||||||
openAPISchemaFn = func() (openapi.Resources, error) {
|
FakeOpenAPISchema = testOpenAPISchema{
|
||||||
s, err := fakeSchema.OpenAPISchema()
|
OpenAPISchemaFn: func() (openapi.Resources, error) {
|
||||||
if err != nil {
|
s, err := fakeSchema.OpenAPISchema()
|
||||||
return nil, err
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
return openapi.NewOpenAPIData(s)
|
}
|
||||||
|
return openapi.NewOpenAPIData(s)
|
||||||
|
},
|
||||||
|
OpenAPIGetter: &fakeSchema,
|
||||||
}
|
}
|
||||||
codec = scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
|
codec = scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type testOpenAPISchema struct {
|
||||||
|
OpenAPISchemaFn func() (openapi.Resources, error)
|
||||||
|
OpenAPIGetter discovery.OpenAPISchemaInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
type alwaysErrorsOpenAPISchema struct{}
|
||||||
|
|
||||||
|
func (o *alwaysErrorsOpenAPISchema) OpenAPISchema() (*openapi_v2.Document, error) {
|
||||||
|
return nil, errors.New("cannot get openapi schema")
|
||||||
|
}
|
||||||
|
|
||||||
func TestApplyExtraArgsFail(t *testing.T) {
|
func TestApplyExtraArgsFail(t *testing.T) {
|
||||||
f := cmdtesting.NewTestFactory()
|
f := cmdtesting.NewTestFactory()
|
||||||
defer f.Cleanup()
|
defer f.Cleanup()
|
||||||
@ -518,7 +537,7 @@ func TestApplyObject(t *testing.T) {
|
|||||||
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
|
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
|
||||||
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
|
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply when a local object is specified", func(t *testing.T) {
|
t.Run("test apply when a local object is specified", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -540,7 +559,8 @@ func TestApplyObject(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -566,7 +586,7 @@ func TestApplyPruneObjects(t *testing.T) {
|
|||||||
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
|
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
|
||||||
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
|
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply returns correct output", func(t *testing.T) {
|
t.Run("test apply returns correct output", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -588,7 +608,8 @@ func TestApplyPruneObjects(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -631,7 +652,7 @@ func TestApplyObjectOutput(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply returns correct output", func(t *testing.T) {
|
t.Run("test apply returns correct output", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -653,7 +674,8 @@ func TestApplyObjectOutput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -680,7 +702,7 @@ func TestApplyRetry(t *testing.T) {
|
|||||||
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
|
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
|
||||||
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
|
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply retries on conflict error", func(t *testing.T) {
|
t.Run("test apply retries on conflict error", func(t *testing.T) {
|
||||||
firstPatch := true
|
firstPatch := true
|
||||||
retry := false
|
retry := false
|
||||||
@ -714,7 +736,8 @@ func TestApplyRetry(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -860,7 +883,7 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
|
|||||||
nameSVC, currentSVC := readAndAnnotateService(t, filenameSVC)
|
nameSVC, currentSVC := readAndAnnotateService(t, filenameSVC)
|
||||||
pathSVC := "/namespaces/test/services/" + nameSVC
|
pathSVC := "/namespaces/test/services/" + nameSVC
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply on multiple objects", func(t *testing.T) {
|
t.Run("test apply on multiple objects", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -889,7 +912,8 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -941,7 +965,7 @@ func TestApplyNULLPreservation(t *testing.T) {
|
|||||||
verifiedPatch := false
|
verifiedPatch := false
|
||||||
deploymentBytes := readDeploymentFromFile(t, filenameDeployObjServerside)
|
deploymentBytes := readDeploymentFromFile(t, filenameDeployObjServerside)
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply preserves NULL fields", func(t *testing.T) {
|
t.Run("test apply preserves NULL fields", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -984,7 +1008,8 @@ func TestApplyNULLPreservation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -1016,7 +1041,7 @@ func TestUnstructuredApply(t *testing.T) {
|
|||||||
|
|
||||||
verifiedPatch := false
|
verifiedPatch := false
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply works correctly with unstructured objects", func(t *testing.T) {
|
t.Run("test apply works correctly with unstructured objects", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -1050,7 +1075,8 @@ func TestUnstructuredApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -1084,7 +1110,7 @@ func TestUnstructuredIdempotentApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
path := "/namespaces/test/widgets/widget"
|
path := "/namespaces/test/widgets/widget"
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test repeated apply operations on an unstructured object", func(t *testing.T) {
|
t.Run("test repeated apply operations on an unstructured object", func(t *testing.T) {
|
||||||
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
tf := cmdtesting.NewTestFactory().WithNamespace("test")
|
||||||
defer tf.Cleanup()
|
defer tf.Cleanup()
|
||||||
@ -1115,7 +1141,8 @@ func TestUnstructuredIdempotentApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
|
||||||
|
|
||||||
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
|
||||||
@ -1275,7 +1302,7 @@ func TestForceApply(t *testing.T) {
|
|||||||
"post": 1,
|
"post": 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fn := range testingOpenAPISchemaFns {
|
for _, testingOpenAPISchema := range testingOpenAPISchemas {
|
||||||
t.Run("test apply with --force", func(t *testing.T) {
|
t.Run("test apply with --force", func(t *testing.T) {
|
||||||
deleted := false
|
deleted := false
|
||||||
isScaledDownToZero := false
|
isScaledDownToZero := false
|
||||||
@ -1357,7 +1384,8 @@ func TestForceApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
fakeDynamicClient := dynamicfakeclient.NewSimpleDynamicClient(scheme)
|
fakeDynamicClient := dynamicfakeclient.NewSimpleDynamicClient(scheme)
|
||||||
tf.FakeDynamicClient = fakeDynamicClient
|
tf.FakeDynamicClient = fakeDynamicClient
|
||||||
tf.OpenAPISchemaFunc = fn
|
tf.OpenAPISchemaFunc = testingOpenAPISchema.OpenAPISchemaFn
|
||||||
|
tf.FakeOpenAPIGetter = testingOpenAPISchema.OpenAPIGetter
|
||||||
tf.Client = tf.UnstructuredClient
|
tf.Client = tf.UnstructuredClient
|
||||||
tf.ClientConfigVal = &restclient.Config{}
|
tf.ClientConfigVal = &restclient.Config{}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||||
o.builder = f.NewBuilder()
|
o.builder = f.NewBuilder()
|
||||||
o.scaleKindResolver = scale.NewDiscoveryScaleKindResolver(discoveryClient)
|
o.scaleKindResolver = scale.NewDiscoveryScaleKindResolver(discoveryClient)
|
||||||
|
@ -206,11 +206,7 @@ func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -387,11 +383,7 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
@ -131,11 +131,7 @@ func (o *ClusterRoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Comma
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -151,11 +151,7 @@ func (o *CreateCronJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -156,11 +156,7 @@ func (o *CreateDeploymentOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -62,7 +62,7 @@ var (
|
|||||||
Create an ingress with the specified name.`))
|
Create an ingress with the specified name.`))
|
||||||
|
|
||||||
ingressExample = templates.Examples(i18n.T(`
|
ingressExample = templates.Examples(i18n.T(`
|
||||||
# Create a single ingress called 'simple' that directs requests to foo.com/bar to svc
|
# Create a single ingress called 'simple' that directs requests to foo.com/bar to svc
|
||||||
# svc1:8080 with a tls secret "my-cert"
|
# svc1:8080 with a tls secret "my-cert"
|
||||||
kubectl create ingress simple --rule="foo.com/bar=svc1:8080,tls=my-cert"
|
kubectl create ingress simple --rule="foo.com/bar=svc1:8080,tls=my-cert"
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ var (
|
|||||||
--annotation ingress.annotation2=bla
|
--annotation ingress.annotation2=bla
|
||||||
|
|
||||||
# Create an ingress with the same host and multiple paths
|
# Create an ingress with the same host and multiple paths
|
||||||
kubectl create ingress multipath --class=default \
|
kubectl create ingress multipath --class=default \
|
||||||
--rule="foo.com/=svc:port" \
|
--rule="foo.com/=svc:port" \
|
||||||
--rule="foo.com/admin/=svcadmin:portadmin"
|
--rule="foo.com/admin/=svcadmin:portadmin"
|
||||||
|
|
||||||
@ -88,11 +88,11 @@ var (
|
|||||||
kubectl create ingress ingtls --class=default \
|
kubectl create ingress ingtls --class=default \
|
||||||
--rule="foo.com/=svc:https,tls" \
|
--rule="foo.com/=svc:https,tls" \
|
||||||
--rule="foo.com/path/subpath*=othersvc:8080"
|
--rule="foo.com/path/subpath*=othersvc:8080"
|
||||||
|
|
||||||
# Create an ingress with TLS enabled using a specific secret and pathType as Prefix
|
# Create an ingress with TLS enabled using a specific secret and pathType as Prefix
|
||||||
kubectl create ingress ingsecret --class=default \
|
kubectl create ingress ingsecret --class=default \
|
||||||
--rule="foo.com/*=svc:8080,tls=secret1"
|
--rule="foo.com/*=svc:8080,tls=secret1"
|
||||||
|
|
||||||
# Create an ingress with a default backend
|
# Create an ingress with a default backend
|
||||||
kubectl create ingress ingdefault --class=default \
|
kubectl create ingress ingdefault --class=default \
|
||||||
--default-backend=defaultsvc:http \
|
--default-backend=defaultsvc:http \
|
||||||
@ -198,11 +198,7 @@ func (o *CreateIngressOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -146,11 +146,7 @@ func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -138,11 +138,7 @@ func (o *PriorityClassOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -136,11 +136,7 @@ func (o *QuotaOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resourcecli.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resourcecli.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -250,11 +250,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
o.OutputFormat = cmdutil.GetFlagString(cmd, "output")
|
o.OutputFormat = cmdutil.GetFlagString(cmd, "output")
|
||||||
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||||
|
|
||||||
|
@ -140,11 +140,7 @@ func (o *RoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicCient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicCient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -118,11 +118,7 @@ func (o *ServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -128,11 +128,7 @@ func (o *ServiceAccountOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -188,11 +188,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
if len(o.Raw) == 0 {
|
if len(o.Raw) == 0 {
|
||||||
r := f.NewBuilder().
|
r := f.NewBuilder().
|
||||||
|
@ -487,7 +487,7 @@ func (o *DiffOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(o.DynamicClient, o.DiscoveryClient)
|
o.DryRunVerifier = resource.NewDryRunVerifier(o.DynamicClient, f.OpenAPIGetter())
|
||||||
|
|
||||||
o.CmdNamespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
o.CmdNamespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -222,11 +222,7 @@ func (o *DrainCmdOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.drainer.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.drainer.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
if o.drainer.Client, err = f.KubernetesClientSet(); err != nil {
|
if o.drainer.Client, err = f.KubernetesClientSet(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -178,11 +178,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -175,11 +175,7 @@ func (o *LabelOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.dryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.dryRunStrategy)
|
||||||
o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
|
o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {
|
||||||
|
@ -167,11 +167,7 @@ func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -156,11 +156,7 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -114,11 +114,7 @@ func (o *UndoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []str
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
if o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {
|
if o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -226,11 +226,7 @@ func (o *RunOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
attachFlag := cmd.Flags().Lookup("attach")
|
attachFlag := cmd.Flags().Lookup("attach")
|
||||||
if !attachFlag.Changed && o.Interactive {
|
if !attachFlag.Changed && o.Interactive {
|
||||||
|
@ -157,11 +157,7 @@ func (o *ScaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -229,11 +229,7 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.dryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.dryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -149,11 +149,7 @@ func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
o.Output = cmdutil.GetFlagString(cmd, "output")
|
o.Output = cmdutil.GetFlagString(cmd, "output")
|
||||||
o.ResolveImage = resolveImageFunc
|
o.ResolveImage = resolveImageFunc
|
||||||
|
|
||||||
|
@ -161,11 +161,7 @@ func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -140,11 +140,7 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
o.resources, o.selector, err = getResourcesAndSelector(args)
|
o.resources, o.selector, err = getResourcesAndSelector(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,11 +142,7 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.dryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
o.output = cmdutil.GetFlagString(cmd, "output")
|
o.output = cmdutil.GetFlagString(cmd, "output")
|
||||||
o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn
|
o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn
|
||||||
|
|
||||||
|
@ -132,11 +132,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
@ -147,11 +147,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
discoveryClient, err := f.ToDiscoveryClient()
|
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, f.OpenAPIGetter())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.DryRunVerifier = resource.NewDryRunVerifier(dynamicClient, discoveryClient)
|
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
// retrieves resource and taint args from args
|
// retrieves resource and taint args from args
|
||||||
|
@ -50,6 +50,8 @@ import (
|
|||||||
"k8s.io/kubectl/pkg/util/openapi"
|
"k8s.io/kubectl/pkg/util/openapi"
|
||||||
openapitesting "k8s.io/kubectl/pkg/util/openapi/testing"
|
openapitesting "k8s.io/kubectl/pkg/util/openapi/testing"
|
||||||
"k8s.io/kubectl/pkg/validation"
|
"k8s.io/kubectl/pkg/validation"
|
||||||
|
|
||||||
|
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InternalType is the schema for internal type
|
// InternalType is the schema for internal type
|
||||||
@ -398,6 +400,7 @@ type TestFactory struct {
|
|||||||
|
|
||||||
UnstructuredClientForMappingFunc resource.FakeClientFunc
|
UnstructuredClientForMappingFunc resource.FakeClientFunc
|
||||||
OpenAPISchemaFunc func() (openapi.Resources, error)
|
OpenAPISchemaFunc func() (openapi.Resources, error)
|
||||||
|
FakeOpenAPIGetter discovery.OpenAPISchemaInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTestFactory returns an initialized TestFactory instance
|
// NewTestFactory returns an initialized TestFactory instance
|
||||||
@ -502,6 +505,23 @@ func (f *TestFactory) OpenAPISchema() (openapi.Resources, error) {
|
|||||||
return openapitesting.EmptyResources{}, nil
|
return openapitesting.EmptyResources{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EmptyOpenAPI struct{}
|
||||||
|
|
||||||
|
func (EmptyOpenAPI) OpenAPISchema() (*openapi_v2.Document, error) {
|
||||||
|
return &openapi_v2.Document{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *TestFactory) OpenAPIGetter() discovery.OpenAPISchemaInterface {
|
||||||
|
if f.FakeOpenAPIGetter != nil {
|
||||||
|
return f.FakeOpenAPIGetter
|
||||||
|
}
|
||||||
|
client, err := f.ToDiscoveryClient()
|
||||||
|
if err != nil {
|
||||||
|
return EmptyOpenAPI{}
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
// NewBuilder returns an initialized resource.Builder instance
|
// NewBuilder returns an initialized resource.Builder instance
|
||||||
func (f *TestFactory) NewBuilder() *resource.Builder {
|
func (f *TestFactory) NewBuilder() *resource.Builder {
|
||||||
return resource.NewFakeBuilder(
|
return resource.NewFakeBuilder(
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
@ -61,6 +62,8 @@ type Factory interface {
|
|||||||
|
|
||||||
// Returns a schema that can validate objects stored on disk.
|
// Returns a schema that can validate objects stored on disk.
|
||||||
Validator(validate bool) (validation.Schema, error)
|
Validator(validate bool) (validation.Schema, error)
|
||||||
// OpenAPISchema returns the schema openapi schema definition
|
// OpenAPISchema returns the parsed openapi schema definition
|
||||||
OpenAPISchema() (openapi.Resources, error)
|
OpenAPISchema() (openapi.Resources, error)
|
||||||
|
// OpenAPIGetter returns a getter for the openapi schema document
|
||||||
|
OpenAPIGetter() discovery.OpenAPISchemaInterface
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@ -38,20 +39,17 @@ import (
|
|||||||
type factoryImpl struct {
|
type factoryImpl struct {
|
||||||
clientGetter genericclioptions.RESTClientGetter
|
clientGetter genericclioptions.RESTClientGetter
|
||||||
|
|
||||||
// openAPIGetter loads and caches openapi specs
|
// Caches OpenAPI document and parsed resources
|
||||||
openAPIGetter openAPIGetter
|
openAPIParser *openapi.CachedOpenAPIParser
|
||||||
}
|
openAPIGetter *openapi.CachedOpenAPIGetter
|
||||||
|
parser sync.Once
|
||||||
type openAPIGetter struct {
|
getter sync.Once
|
||||||
once sync.Once
|
|
||||||
getter openapi.Getter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFactory(clientGetter genericclioptions.RESTClientGetter) Factory {
|
func NewFactory(clientGetter genericclioptions.RESTClientGetter) Factory {
|
||||||
if clientGetter == nil {
|
if clientGetter == nil {
|
||||||
panic("attempt to instantiate client_access_factory with nil clientGetter")
|
panic("attempt to instantiate client_access_factory with nil clientGetter")
|
||||||
}
|
}
|
||||||
|
|
||||||
f := &factoryImpl{
|
f := &factoryImpl{
|
||||||
clientGetter: clientGetter,
|
clientGetter: clientGetter,
|
||||||
}
|
}
|
||||||
@ -159,19 +157,32 @@ func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenAPISchema returns metadata and structural information about Kubernetes object definitions.
|
// OpenAPISchema returns metadata and structural information about
|
||||||
|
// Kubernetes object definitions.
|
||||||
func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) {
|
func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) {
|
||||||
discovery, err := f.clientGetter.ToDiscoveryClient()
|
openAPIGetter := f.OpenAPIGetter()
|
||||||
if err != nil {
|
if openAPIGetter == nil {
|
||||||
return nil, err
|
return nil, errors.New("no openapi getter")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lazily initialize the OpenAPIGetter once
|
// Lazily initialize the OpenAPIParser once
|
||||||
f.openAPIGetter.once.Do(func() {
|
f.parser.Do(func() {
|
||||||
// Create the caching OpenAPIGetter
|
// Create the caching OpenAPIParser
|
||||||
f.openAPIGetter.getter = openapi.NewOpenAPIGetter(discovery)
|
f.openAPIParser = openapi.NewOpenAPIParser(f.OpenAPIGetter())
|
||||||
})
|
})
|
||||||
|
|
||||||
// Delegate to the OpenAPIGetter
|
// Delegate to the OpenAPIPArser
|
||||||
return f.openAPIGetter.getter.Get()
|
return f.openAPIParser.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *factoryImpl) OpenAPIGetter() discovery.OpenAPISchemaInterface {
|
||||||
|
discovery, err := f.clientGetter.ToDiscoveryClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
f.getter.Do(func() {
|
||||||
|
f.openAPIGetter = openapi.NewOpenAPIGetter(discovery)
|
||||||
|
})
|
||||||
|
|
||||||
|
return f.openAPIGetter
|
||||||
}
|
}
|
||||||
|
@ -19,47 +19,64 @@ package openapi
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
)
|
)
|
||||||
|
|
||||||
// synchronizedOpenAPIGetter fetches the openapi schema once and then caches it in memory
|
// CachedOpenAPIGetter fetches the openapi schema once and then caches it in memory
|
||||||
type synchronizedOpenAPIGetter struct {
|
type CachedOpenAPIGetter struct {
|
||||||
|
openAPIClient discovery.OpenAPISchemaInterface
|
||||||
|
|
||||||
// Cached results
|
// Cached results
|
||||||
sync.Once
|
sync.Once
|
||||||
openAPISchema Resources
|
openAPISchema *openapi_v2.Document
|
||||||
err error
|
err error
|
||||||
|
|
||||||
openAPIClient discovery.OpenAPISchemaInterface
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Getter = &synchronizedOpenAPIGetter{}
|
var _ discovery.OpenAPISchemaInterface = &CachedOpenAPIGetter{}
|
||||||
|
|
||||||
// Getter is an interface for fetching openapi specs and parsing them into an Resources struct
|
|
||||||
type Getter interface {
|
|
||||||
// OpenAPIData returns the parsed OpenAPIData
|
|
||||||
Get() (Resources, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOpenAPIGetter returns an object to return OpenAPIDatas which reads
|
// NewOpenAPIGetter returns an object to return OpenAPIDatas which reads
|
||||||
// from a server, and then stores in memory for subsequent invocations
|
// from a server, and then stores in memory for subsequent invocations
|
||||||
func NewOpenAPIGetter(openAPIClient discovery.OpenAPISchemaInterface) Getter {
|
func NewOpenAPIGetter(openAPIClient discovery.OpenAPISchemaInterface) *CachedOpenAPIGetter {
|
||||||
return &synchronizedOpenAPIGetter{
|
return &CachedOpenAPIGetter{
|
||||||
openAPIClient: openAPIClient,
|
openAPIClient: openAPIClient,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources implements Getter
|
// OpenAPISchema implements OpenAPISchemaInterface.
|
||||||
func (g *synchronizedOpenAPIGetter) Get() (Resources, error) {
|
func (g *CachedOpenAPIGetter) OpenAPISchema() (*openapi_v2.Document, error) {
|
||||||
g.Do(func() {
|
g.Do(func() {
|
||||||
s, err := g.openAPIClient.OpenAPISchema()
|
g.openAPISchema, g.err = g.openAPIClient.OpenAPISchema()
|
||||||
if err != nil {
|
|
||||||
g.err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
g.openAPISchema, g.err = NewOpenAPIData(s)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Return the save result
|
// Return the saved result.
|
||||||
return g.openAPISchema, g.err
|
return g.openAPISchema, g.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CachedOpenAPIParser struct {
|
||||||
|
openAPIClient discovery.OpenAPISchemaInterface
|
||||||
|
|
||||||
|
// Cached results
|
||||||
|
sync.Once
|
||||||
|
openAPIResources Resources
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOpenAPIParser(openAPIClient discovery.OpenAPISchemaInterface) *CachedOpenAPIParser {
|
||||||
|
return &CachedOpenAPIParser{
|
||||||
|
openAPIClient: openAPIClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CachedOpenAPIParser) Parse() (Resources, error) {
|
||||||
|
p.Do(func() {
|
||||||
|
oapi, err := p.openAPIClient.OpenAPISchema()
|
||||||
|
if err != nil {
|
||||||
|
p.err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.openAPIResources, p.err = NewOpenAPIData(oapi)
|
||||||
|
})
|
||||||
|
|
||||||
|
return p.openAPIResources, p.err
|
||||||
|
}
|
||||||
|
@ -40,12 +40,12 @@ func (f *FakeCounter) OpenAPISchema() (*openapi_v2.Document, error) {
|
|||||||
|
|
||||||
var _ = Describe("Getting the Resources", func() {
|
var _ = Describe("Getting the Resources", func() {
|
||||||
var client FakeCounter
|
var client FakeCounter
|
||||||
var instance openapi.Getter
|
var instance *openapi.CachedOpenAPIParser
|
||||||
var expectedData openapi.Resources
|
var expectedData openapi.Resources
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
client = FakeCounter{}
|
client = FakeCounter{}
|
||||||
instance = openapi.NewOpenAPIGetter(&client)
|
instance = openapi.NewOpenAPIParser(openapi.NewOpenAPIGetter(&client))
|
||||||
var err error
|
var err error
|
||||||
expectedData, err = openapi.NewOpenAPIData(nil)
|
expectedData, err = openapi.NewOpenAPIData(nil)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
@ -55,12 +55,12 @@ var _ = Describe("Getting the Resources", func() {
|
|||||||
It("should return the same data for multiple calls", func() {
|
It("should return the same data for multiple calls", func() {
|
||||||
Expect(client.Calls).To(Equal(0))
|
Expect(client.Calls).To(Equal(0))
|
||||||
|
|
||||||
result, err := instance.Get()
|
result, err := instance.Parse()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(result).To(Equal(expectedData))
|
Expect(result).To(Equal(expectedData))
|
||||||
Expect(client.Calls).To(Equal(1))
|
Expect(client.Calls).To(Equal(1))
|
||||||
|
|
||||||
result, err = instance.Get()
|
result, err = instance.Parse()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(result).To(Equal(expectedData))
|
Expect(result).To(Equal(expectedData))
|
||||||
// No additional client calls expected
|
// No additional client calls expected
|
||||||
@ -73,11 +73,11 @@ var _ = Describe("Getting the Resources", func() {
|
|||||||
Expect(client.Calls).To(Equal(0))
|
Expect(client.Calls).To(Equal(0))
|
||||||
|
|
||||||
client.Err = fmt.Errorf("expected error")
|
client.Err = fmt.Errorf("expected error")
|
||||||
_, err := instance.Get()
|
_, err := instance.Parse()
|
||||||
Expect(err).To(Equal(client.Err))
|
Expect(err).To(Equal(client.Err))
|
||||||
Expect(client.Calls).To(Equal(1))
|
Expect(client.Calls).To(Equal(1))
|
||||||
|
|
||||||
_, err = instance.Get()
|
_, err = instance.Parse()
|
||||||
Expect(err).To(Equal(client.Err))
|
Expect(err).To(Equal(client.Err))
|
||||||
// No additional client calls expected
|
// No additional client calls expected
|
||||||
Expect(client.Calls).To(Equal(1))
|
Expect(client.Calls).To(Equal(1))
|
||||||
|
Loading…
Reference in New Issue
Block a user