React to moves

This commit is contained in:
Maciej Szulik 2018-10-05 14:38:38 +02:00
parent 33adf367f9
commit 55d5df8a36
No known key found for this signature in database
GPG Key ID: F15E55D276FA84C4
50 changed files with 929 additions and 1010 deletions

View File

@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
@ -420,7 +421,7 @@ func TestAnnotateErrors(t *testing.T) {
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
iostreams, _, bufOut, bufErr := genericclioptions.NewTestIOStreams() iostreams, _, bufOut, bufErr := genericclioptions.NewTestIOStreams()
cmd := NewCmdAnnotate("kubectl", tf, iostreams) cmd := NewCmdAnnotate("kubectl", tf, iostreams)
@ -449,7 +450,7 @@ func TestAnnotateErrors(t *testing.T) {
} }
func TestAnnotateObject(t *testing.T) { func TestAnnotateObject(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -458,13 +459,13 @@ func TestAnnotateObject(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -472,7 +473,7 @@ func TestAnnotateObject(t *testing.T) {
case "PATCH": case "PATCH":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -483,7 +484,7 @@ func TestAnnotateObject(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdAnnotate("kubectl", tf, iostreams) cmd := NewCmdAnnotate("kubectl", tf, iostreams)
@ -502,7 +503,7 @@ func TestAnnotateObject(t *testing.T) {
} }
func TestAnnotateObjectFromFile(t *testing.T) { func TestAnnotateObjectFromFile(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -511,13 +512,13 @@ func TestAnnotateObjectFromFile(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -525,7 +526,7 @@ func TestAnnotateObjectFromFile(t *testing.T) {
case "PATCH": case "PATCH":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -536,13 +537,13 @@ func TestAnnotateObjectFromFile(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdAnnotate("kubectl", tf, iostreams) cmd := NewCmdAnnotate("kubectl", tf, iostreams)
cmd.SetOutput(bufOut) cmd.SetOutput(bufOut)
options := NewAnnotateOptions(iostreams) options := NewAnnotateOptions(iostreams)
options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} options.Filenames = []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}
args := []string{"a=b", "c-"} args := []string{"a=b", "c-"}
if err := options.Complete(tf, cmd, args); err != nil { if err := options.Complete(tf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -561,19 +562,19 @@ func TestAnnotateLocal(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
return nil, nil return nil, nil
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
iostreams, _, _, _ := genericclioptions.NewTestIOStreams() iostreams, _, _, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdAnnotate("kubectl", tf, iostreams) cmd := NewCmdAnnotate("kubectl", tf, iostreams)
options := NewAnnotateOptions(iostreams) options := NewAnnotateOptions(iostreams)
options.local = true options.local = true
options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} options.Filenames = []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}
args := []string{"a=b"} args := []string{"a=b"}
if err := options.Complete(tf, cmd, args); err != nil { if err := options.Complete(tf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -587,7 +588,7 @@ func TestAnnotateLocal(t *testing.T) {
} }
func TestAnnotateMultipleObjects(t *testing.T) { func TestAnnotateMultipleObjects(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -595,13 +596,13 @@ func TestAnnotateMultipleObjects(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -609,9 +610,9 @@ func TestAnnotateMultipleObjects(t *testing.T) {
case "PATCH": case "PATCH":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
case "/namespaces/test/pods/bar": case "/namespaces/test/pods/bar":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[1])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[1])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -622,7 +623,7 @@ func TestAnnotateMultipleObjects(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
iostreams, _, _, _ := genericclioptions.NewTestIOStreams() iostreams, _, _, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdAnnotate("kubectl", tf, iostreams) cmd := NewCmdAnnotate("kubectl", tf, iostreams)

View File

@ -45,6 +45,7 @@ import (
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
oapi "k8s.io/kube-openapi/pkg/util/proto" oapi "k8s.io/kube-openapi/pkg/util/proto"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/delete"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
@ -60,8 +61,8 @@ type ApplyOptions struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
ToPrinter func(string) (printers.ResourcePrinter, error) ToPrinter func(string) (printers.ResourcePrinter, error)
DeleteFlags *DeleteFlags DeleteFlags *delete.DeleteFlags
DeleteOptions *DeleteOptions DeleteOptions *delete.DeleteOptions
Selector string Selector string
DryRun bool DryRun bool
@ -126,7 +127,7 @@ var (
func NewApplyOptions(ioStreams genericclioptions.IOStreams) *ApplyOptions { func NewApplyOptions(ioStreams genericclioptions.IOStreams) *ApplyOptions {
return &ApplyOptions{ return &ApplyOptions{
RecordFlags: genericclioptions.NewRecordFlags(), RecordFlags: genericclioptions.NewRecordFlags(),
DeleteFlags: NewDeleteFlags("that contains the configuration to apply"), DeleteFlags: delete.NewDeleteFlags("that contains the configuration to apply"),
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
Overwrite: true, Overwrite: true,
@ -403,21 +404,21 @@ func (o *ApplyOptions) Run() error {
} }
helper := resource.NewHelper(info.Client, info.Mapping) helper := resource.NewHelper(info.Client, info.Mapping)
patcher := &patcher{ patcher := &Patcher{
mapping: info.Mapping, Mapping: info.Mapping,
helper: helper, Helper: helper,
dynamicClient: o.DynamicClient, DynamicClient: o.DynamicClient,
overwrite: o.Overwrite, Overwrite: o.Overwrite,
backOff: clockwork.NewRealClock(), BackOff: clockwork.NewRealClock(),
force: o.DeleteOptions.ForceDeletion, Force: o.DeleteOptions.ForceDeletion,
cascade: o.DeleteOptions.Cascade, Cascade: o.DeleteOptions.Cascade,
timeout: o.DeleteOptions.Timeout, Timeout: o.DeleteOptions.Timeout,
gracePeriod: o.DeleteOptions.GracePeriod, GracePeriod: o.DeleteOptions.GracePeriod,
serverDryRun: o.ServerDryRun, ServerDryRun: o.ServerDryRun,
openapiSchema: openapiSchema, OpenapiSchema: openapiSchema,
} }
patchBytes, patchedObject, err := patcher.patch(info.Object, modified, info.Source, info.Namespace, info.Name, o.ErrOut) patchBytes, patchedObject, err := patcher.Patch(info.Object, modified, info.Source, info.Namespace, info.Name, o.ErrOut)
if err != nil { if err != nil {
return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patchBytes, info), info.Source, err) return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patchBytes, info), info.Source, err)
} }
@ -662,28 +663,28 @@ func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Inte
return c.Resource(mapping.Resource).Namespace(namespace).Delete(name, options) return c.Resource(mapping.Resource).Namespace(namespace).Delete(name, options)
} }
func (p *patcher) delete(namespace, name string) error { func (p *Patcher) delete(namespace, name string) error {
return runDelete(namespace, name, p.mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.serverDryRun) return runDelete(namespace, name, p.Mapping, p.DynamicClient, p.Cascade, p.GracePeriod, p.ServerDryRun)
} }
type patcher struct { type Patcher struct {
mapping *meta.RESTMapping Mapping *meta.RESTMapping
helper *resource.Helper Helper *resource.Helper
dynamicClient dynamic.Interface DynamicClient dynamic.Interface
overwrite bool Overwrite bool
backOff clockwork.Clock BackOff clockwork.Clock
force bool Force bool
cascade bool Cascade bool
timeout time.Duration Timeout time.Duration
gracePeriod int GracePeriod int
serverDryRun bool ServerDryRun bool
openapiSchema openapi.Resources OpenapiSchema openapi.Resources
} }
func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, namespace, name string, errOut io.Writer) ([]byte, runtime.Object, error) { func (p *Patcher) patchSimple(obj runtime.Object, modified []byte, source, namespace, name string, errOut io.Writer) ([]byte, runtime.Object, error) {
// Serialize the current configuration of the object from the server. // Serialize the current configuration of the object from the server.
current, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) current, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
if err != nil { if err != nil {
@ -704,7 +705,7 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names
// Create the versioned struct from the type defined in the restmapping // Create the versioned struct from the type defined in the restmapping
// (which is the API version we'll be submitting the patch to) // (which is the API version we'll be submitting the patch to)
versionedObject, err := scheme.Scheme.New(p.mapping.GroupVersionKind) versionedObject, err := scheme.Scheme.New(p.Mapping.GroupVersionKind)
switch { switch {
case runtime.IsNotRegisteredError(err): case runtime.IsNotRegisteredError(err):
// fall back to generic JSON merge patch // fall back to generic JSON merge patch
@ -719,17 +720,17 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names
return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err) return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err)
} }
case err != nil: case err != nil:
return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf("getting instance of versioned object for %v:", p.mapping.GroupVersionKind), source, err) return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf("getting instance of versioned object for %v:", p.Mapping.GroupVersionKind), source, err)
case err == nil: case err == nil:
// Compute a three way strategic merge patch to send to server. // Compute a three way strategic merge patch to send to server.
patchType = types.StrategicMergePatchType patchType = types.StrategicMergePatchType
// Try to use openapi first if the openapi spec is available and can successfully calculate the patch. // Try to use openapi first if the openapi spec is available and can successfully calculate the patch.
// Otherwise, fall back to baked-in types. // Otherwise, fall back to baked-in types.
if p.openapiSchema != nil { if p.OpenapiSchema != nil {
if schema = p.openapiSchema.LookupResource(p.mapping.GroupVersionKind); schema != nil { if schema = p.OpenapiSchema.LookupResource(p.Mapping.GroupVersionKind); schema != nil {
lookupPatchMeta = strategicpatch.PatchMetaFromOpenAPI{Schema: schema} lookupPatchMeta = strategicpatch.PatchMetaFromOpenAPI{Schema: schema}
if openapiPatch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, p.overwrite); err != nil { if openapiPatch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, p.Overwrite); err != nil {
fmt.Fprintf(errOut, "warning: error calculating patch from openapi spec: %v\n", err) fmt.Fprintf(errOut, "warning: error calculating patch from openapi spec: %v\n", err)
} else { } else {
patchType = types.StrategicMergePatchType patchType = types.StrategicMergePatchType
@ -743,7 +744,7 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names
if err != nil { if err != nil {
return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err) return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err)
} }
patch, err = strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, p.overwrite) patch, err = strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, p.Overwrite)
if err != nil { if err != nil {
return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err) return nil, nil, cmdutil.AddSourceToErr(fmt.Sprintf(createPatchErrFormat, original, modified, current), source, err)
} }
@ -755,40 +756,40 @@ func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, names
} }
options := metav1.UpdateOptions{} options := metav1.UpdateOptions{}
if p.serverDryRun { if p.ServerDryRun {
options.DryRun = []string{metav1.DryRunAll} options.DryRun = []string{metav1.DryRunAll}
} }
patchedObj, err := p.helper.Patch(namespace, name, patchType, patch, &options) patchedObj, err := p.Helper.Patch(namespace, name, patchType, patch, &options)
return patch, patchedObj, err return patch, patchedObj, err
} }
func (p *patcher) patch(current runtime.Object, modified []byte, source, namespace, name string, errOut io.Writer) ([]byte, runtime.Object, error) { func (p *Patcher) Patch(current runtime.Object, modified []byte, source, namespace, name string, errOut io.Writer) ([]byte, runtime.Object, error) {
var getErr error var getErr error
patchBytes, patchObject, err := p.patchSimple(current, modified, source, namespace, name, errOut) patchBytes, patchObject, err := p.patchSimple(current, modified, source, namespace, name, errOut)
for i := 1; i <= maxPatchRetry && errors.IsConflict(err); i++ { for i := 1; i <= maxPatchRetry && errors.IsConflict(err); i++ {
if i > triesBeforeBackOff { if i > triesBeforeBackOff {
p.backOff.Sleep(backOffPeriod) p.BackOff.Sleep(backOffPeriod)
} }
current, getErr = p.helper.Get(namespace, name, false) current, getErr = p.Helper.Get(namespace, name, false)
if getErr != nil { if getErr != nil {
return nil, nil, getErr return nil, nil, getErr
} }
patchBytes, patchObject, err = p.patchSimple(current, modified, source, namespace, name, errOut) patchBytes, patchObject, err = p.patchSimple(current, modified, source, namespace, name, errOut)
} }
if err != nil && (errors.IsConflict(err) || errors.IsInvalid(err)) && p.force { if err != nil && (errors.IsConflict(err) || errors.IsInvalid(err)) && p.Force {
patchBytes, patchObject, err = p.deleteAndCreate(current, modified, namespace, name) patchBytes, patchObject, err = p.deleteAndCreate(current, modified, namespace, name)
} }
return patchBytes, patchObject, err return patchBytes, patchObject, err
} }
func (p *patcher) deleteAndCreate(original runtime.Object, modified []byte, namespace, name string) ([]byte, runtime.Object, error) { func (p *Patcher) deleteAndCreate(original runtime.Object, modified []byte, namespace, name string) ([]byte, runtime.Object, error) {
if err := p.delete(namespace, name); err != nil { if err := p.delete(namespace, name); err != nil {
return modified, nil, err return modified, nil, err
} }
// TODO: use wait // TODO: use wait
if err := wait.PollImmediate(1*time.Second, p.timeout, func() (bool, error) { if err := wait.PollImmediate(1*time.Second, p.Timeout, func() (bool, error) {
if _, err := p.helper.Get(namespace, name, false); !errors.IsNotFound(err) { if _, err := p.Helper.Get(namespace, name, false); !errors.IsNotFound(err) {
return false, err return false, err
} }
return true, nil return true, nil
@ -800,14 +801,14 @@ func (p *patcher) deleteAndCreate(original runtime.Object, modified []byte, name
return modified, nil, err return modified, nil, err
} }
options := metav1.CreateOptions{} options := metav1.CreateOptions{}
if p.serverDryRun { if p.ServerDryRun {
options.DryRun = []string{metav1.DryRunAll} options.DryRun = []string{metav1.DryRunAll}
} }
createdObject, err := p.helper.Create(namespace, true, versionedObject, &options) createdObject, err := p.Helper.Create(namespace, true, versionedObject, &options)
if err != nil { if err != nil {
// restore the original object if we fail to create the new one // restore the original object if we fail to create the new one
// but still propagate and advertise error to user // but still propagate and advertise error to user
recreated, recreateErr := p.helper.Create(namespace, true, original, &options) recreated, recreateErr := p.Helper.Create(namespace, true, original, &options)
if recreateErr != nil { if recreateErr != nil {
err = fmt.Errorf("An error occurred force-replacing the existing object with the newly provided one:\n\n%v.\n\nAdditionally, an error occurred attempting to restore the original object:\n\n%v\n", err, recreateErr) err = fmt.Errorf("An error occurred force-replacing the existing object with the newly provided one:\n\n%v.\n\nAdditionally, an error occurred attempting to restore the original object:\n\n%v\n", err, recreateErr)
} else { } else {

View File

@ -40,6 +40,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
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/genericclioptions/resource"
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"
@ -84,21 +85,21 @@ func validateApplyArgs(cmd *cobra.Command, args []string) error {
} }
const ( const (
filenameCM = "../../../test/fixtures/pkg/kubectl/cmd/apply/cm.yaml" filenameCM = "../../../../test/fixtures/pkg/kubectl/cmd/apply/cm.yaml"
filenameRC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc.yaml" filenameRC = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc.yaml"
filenameRCArgs = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-args.yaml" filenameRCArgs = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc-args.yaml"
filenameRCLastAppliedArgs = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-lastapplied-args.yaml" filenameRCLastAppliedArgs = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc-lastapplied-args.yaml"
filenameRCNoAnnotation = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-no-annotation.yaml" filenameRCNoAnnotation = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc-no-annotation.yaml"
filenameRCLASTAPPLIED = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-lastapplied.yaml" filenameRCLASTAPPLIED = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc-lastapplied.yaml"
filenameSVC = "../../../test/fixtures/pkg/kubectl/cmd/apply/service.yaml" filenameSVC = "../../../../test/fixtures/pkg/kubectl/cmd/apply/service.yaml"
filenameRCSVC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-service.yaml" filenameRCSVC = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc-service.yaml"
filenameNoExistRC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-noexist.yaml" filenameNoExistRC = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc-noexist.yaml"
filenameRCPatchTest = "../../../test/fixtures/pkg/kubectl/cmd/apply/patch.json" filenameRCPatchTest = "../../../../test/fixtures/pkg/kubectl/cmd/apply/patch.json"
dirName = "../../../test/fixtures/pkg/kubectl/cmd/apply/testdir" dirName = "../../../../test/fixtures/pkg/kubectl/cmd/apply/testdir"
filenameRCJSON = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc.json" filenameRCJSON = "../../../../test/fixtures/pkg/kubectl/cmd/apply/rc.json"
filenameWidgetClientside = "../../../test/fixtures/pkg/kubectl/cmd/apply/widget-clientside.yaml" filenameWidgetClientside = "../../../../test/fixtures/pkg/kubectl/cmd/apply/widget-clientside.yaml"
filenameWidgetServerside = "../../../test/fixtures/pkg/kubectl/cmd/apply/widget-serverside.yaml" filenameWidgetServerside = "../../../../test/fixtures/pkg/kubectl/cmd/apply/widget-serverside.yaml"
) )
func readConfigMapList(t *testing.T, filename string) []byte { func readConfigMapList(t *testing.T, filename string) []byte {
@ -267,7 +268,7 @@ func walkMapPath(t *testing.T, start map[string]interface{}, path []string) map[
} }
func TestRunApplyPrintsValidObjectList(t *testing.T) { func TestRunApplyPrintsValidObjectList(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
cmBytes := readConfigMapList(t, filenameCM) cmBytes := readConfigMapList(t, filenameCM)
pathCM := "/namespaces/test/configmaps" pathCM := "/namespaces/test/configmaps"
@ -275,22 +276,22 @@ func TestRunApplyPrintsValidObjectList(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case strings.HasPrefix(p, pathCM) && m != "GET": case strings.HasPrefix(p, pathCM) && m != "GET":
pod := ioutil.NopCloser(bytes.NewReader(cmBytes)) pod := ioutil.NopCloser(bytes.NewReader(cmBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: pod}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: pod}, nil
case strings.HasPrefix(p, pathCM) && m != "PATCH": case strings.HasPrefix(p, pathCM) && m != "PATCH":
pod := ioutil.NopCloser(bytes.NewReader(cmBytes)) pod := ioutil.NopCloser(bytes.NewReader(cmBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: pod}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: pod}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -395,26 +396,26 @@ func TestRunApplyViewLastApplied(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"}, GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes)) bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == "/namespaces/test/replicationcontrollers" && m == "GET": case p == "/namespaces/test/replicationcontrollers" && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes)) bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == "/namespaces/test/replicationcontrollers/no-match" && m == "GET": case p == "/namespaces/test/replicationcontrollers/no-match" && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &corev1.Pod{})}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Pod{})}, nil
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
cmdutil.BehaviorOnFatal(func(str string, code int) { cmdutil.BehaviorOnFatal(func(str string, code int) {
if str != test.expectedErr { if str != test.expectedErr {
@ -443,7 +444,7 @@ func TestRunApplyViewLastApplied(t *testing.T) {
} }
func TestApplyObjectWithoutAnnotation(t *testing.T) { func TestApplyObjectWithoutAnnotation(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
nameRC, rcBytes := readReplicationController(t, filenameRC) nameRC, rcBytes := readReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
@ -451,22 +452,22 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(rcBytes)) bodyRC := ioutil.NopCloser(bytes.NewReader(rcBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "PATCH": case p == pathRC && m == "PATCH":
bodyRC := ioutil.NopCloser(bytes.NewReader(rcBytes)) bodyRC := ioutil.NopCloser(bytes.NewReader(rcBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -486,7 +487,7 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) {
} }
func TestApplyObject(t *testing.T) { func TestApplyObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
@ -496,16 +497,16 @@ func TestApplyObject(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "PATCH": case p == pathRC && m == "PATCH":
validatePatchApplication(t, req) validatePatchApplication(t, req)
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -513,7 +514,7 @@ func TestApplyObject(t *testing.T) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -534,7 +535,7 @@ func TestApplyObject(t *testing.T) {
} }
func TestApplyObjectOutput(t *testing.T) { func TestApplyObjectOutput(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
@ -560,16 +561,16 @@ func TestApplyObjectOutput(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "PATCH": case p == pathRC && m == "PATCH":
validatePatchApplication(t, req) validatePatchApplication(t, req)
bodyRC := ioutil.NopCloser(bytes.NewReader(postPatchData)) bodyRC := ioutil.NopCloser(bytes.NewReader(postPatchData))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -577,7 +578,7 @@ func TestApplyObjectOutput(t *testing.T) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -599,7 +600,7 @@ func TestApplyObjectOutput(t *testing.T) {
} }
func TestApplyRetry(t *testing.T) { func TestApplyRetry(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
@ -612,25 +613,25 @@ func TestApplyRetry(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
getCount++ getCount++
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "PATCH": case p == pathRC && m == "PATCH":
if firstPatch { if firstPatch {
firstPatch = false firstPatch = false
statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first."))
bodyBytes, _ := json.Marshal(statusErr) bodyBytes, _ := json.Marshal(statusErr)
bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes))
return &http.Response{StatusCode: http.StatusConflict, Header: defaultHeader(), Body: bodyErr}, nil return &http.Response{StatusCode: http.StatusConflict, Header: cmdtesting.DefaultHeader(), Body: bodyErr}, nil
} }
retry = true retry = true
validatePatchApplication(t, req) validatePatchApplication(t, req)
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -638,7 +639,7 @@ func TestApplyRetry(t *testing.T) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -671,23 +672,23 @@ func TestApplyNonExistObject(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil
case p == pathNameRC && m == "GET": case p == pathNameRC && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil
case p == pathRC && m == "POST": case p == pathRC && m == "POST":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -703,7 +704,7 @@ func TestApplyNonExistObject(t *testing.T) {
} }
func TestApplyEmptyPatch(t *testing.T) { func TestApplyEmptyPatch(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
nameRC, _ := readAndAnnotateReplicationController(t, filenameRC) nameRC, _ := readAndAnnotateReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers" pathRC := "/namespaces/test/replicationcontrollers"
pathNameRC := pathRC + "/" + nameRC pathNameRC := pathRC + "/" + nameRC
@ -717,29 +718,29 @@ func TestApplyEmptyPatch(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"}, GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil
case p == pathNameRC && m == "GET": case p == pathNameRC && m == "GET":
if body == nil { if body == nil {
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil
} }
bodyRC := ioutil.NopCloser(bytes.NewReader(body)) bodyRC := ioutil.NopCloser(bytes.NewReader(body))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "POST": case p == pathRC && m == "POST":
body, _ = ioutil.ReadAll(req.Body) body, _ = ioutil.ReadAll(req.Body)
verifyPost = true verifyPost = true
bodyRC := ioutil.NopCloser(bytes.NewReader(body)) bodyRC := ioutil.NopCloser(bytes.NewReader(body))
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
// 1. apply non exist object // 1. apply non exist object
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -789,23 +790,23 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathRC && m == "PATCH": case p == pathRC && m == "PATCH":
validatePatchApplication(t, req) validatePatchApplication(t, req)
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == pathSVC && m == "GET": case p == pathSVC && m == "GET":
bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodySVC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodySVC}, nil
case p == pathSVC && m == "PATCH": case p == pathSVC && m == "PATCH":
validatePatchApplication(t, req) validatePatchApplication(t, req)
bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodySVC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodySVC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -813,7 +814,7 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -844,8 +845,8 @@ func testApplyMultipleObjects(t *testing.T, asList bool) {
} }
const ( const (
filenameDeployObjServerside = "../../../test/fixtures/pkg/kubectl/cmd/apply/deploy-serverside.yaml" filenameDeployObjServerside = "../../../../test/fixtures/pkg/kubectl/cmd/apply/deploy-serverside.yaml"
filenameDeployObjClientside = "../../../test/fixtures/pkg/kubectl/cmd/apply/deploy-clientside.yaml" filenameDeployObjClientside = "../../../../test/fixtures/pkg/kubectl/cmd/apply/deploy-clientside.yaml"
) )
func readDeploymentFromFile(t *testing.T, file string) []byte { func readDeploymentFromFile(t *testing.T, file string) []byte {
@ -862,7 +863,7 @@ func readDeploymentFromFile(t *testing.T, file string) []byte {
} }
func TestApplyNULLPreservation(t *testing.T) { func TestApplyNULLPreservation(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
deploymentName := "nginx-deployment" deploymentName := "nginx-deployment"
deploymentPath := "/namespaces/test/deployments/" + deploymentName deploymentPath := "/namespaces/test/deployments/" + deploymentName
@ -875,12 +876,12 @@ func TestApplyNULLPreservation(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == deploymentPath && m == "GET": case p == deploymentPath && m == "GET":
body := ioutil.NopCloser(bytes.NewReader(deploymentBytes)) body := ioutil.NopCloser(bytes.NewReader(deploymentBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == deploymentPath && m == "PATCH": case p == deploymentPath && m == "PATCH":
patch, err := ioutil.ReadAll(req.Body) patch, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
@ -905,7 +906,7 @@ func TestApplyNULLPreservation(t *testing.T) {
// is ignoring the actual return object. // is ignoring the actual return object.
// TODO: Make this match actual server behavior by returning the patched object. // TODO: Make this match actual server behavior by returning the patched object.
body := ioutil.NopCloser(bytes.NewReader(deploymentBytes)) body := ioutil.NopCloser(bytes.NewReader(deploymentBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -913,7 +914,7 @@ func TestApplyNULLPreservation(t *testing.T) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -938,7 +939,7 @@ func TestApplyNULLPreservation(t *testing.T) {
// TestUnstructuredApply checks apply operations on an unstructured object // TestUnstructuredApply checks apply operations on an unstructured object
func TestUnstructuredApply(t *testing.T) { func TestUnstructuredApply(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
name, curr := readAndAnnotateUnstructured(t, filenameWidgetClientside) name, curr := readAndAnnotateUnstructured(t, filenameWidgetClientside)
path := "/namespaces/test/widgets/" + name path := "/namespaces/test/widgets/" + name
@ -950,14 +951,14 @@ func TestUnstructuredApply(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == path && m == "GET": case p == path && m == "GET":
body := ioutil.NopCloser(bytes.NewReader(curr)) body := ioutil.NopCloser(bytes.NewReader(curr))
return &http.Response{ return &http.Response{
StatusCode: 200, StatusCode: 200,
Header: defaultHeader(), Header: cmdtesting.DefaultHeader(),
Body: body}, nil Body: body}, nil
case p == path && m == "PATCH": case p == path && m == "PATCH":
contentType := req.Header.Get("Content-Type") contentType := req.Header.Get("Content-Type")
@ -970,7 +971,7 @@ func TestUnstructuredApply(t *testing.T) {
body := ioutil.NopCloser(bytes.NewReader(curr)) body := ioutil.NopCloser(bytes.NewReader(curr))
return &http.Response{ return &http.Response{
StatusCode: 200, StatusCode: 200,
Header: defaultHeader(), Header: cmdtesting.DefaultHeader(),
Body: body}, nil Body: body}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
@ -979,7 +980,7 @@ func TestUnstructuredApply(t *testing.T) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -1003,7 +1004,7 @@ func TestUnstructuredApply(t *testing.T) {
// TestUnstructuredIdempotentApply checks repeated apply operation on an unstructured object // TestUnstructuredIdempotentApply checks repeated apply operation on an unstructured object
func TestUnstructuredIdempotentApply(t *testing.T) { func TestUnstructuredIdempotentApply(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
serversideObject := readUnstructuredFromFile(t, filenameWidgetServerside) serversideObject := readUnstructuredFromFile(t, filenameWidgetServerside)
serversideData, err := runtime.Encode(unstructured.JSONFallbackEncoder{Encoder: codec}, serversideObject) serversideData, err := runtime.Encode(unstructured.JSONFallbackEncoder{Encoder: codec}, serversideObject)
@ -1018,14 +1019,14 @@ func TestUnstructuredIdempotentApply(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == path && m == "GET": case p == path && m == "GET":
body := ioutil.NopCloser(bytes.NewReader(serversideData)) body := ioutil.NopCloser(bytes.NewReader(serversideData))
return &http.Response{ return &http.Response{
StatusCode: 200, StatusCode: 200,
Header: defaultHeader(), Header: cmdtesting.DefaultHeader(),
Body: body}, nil Body: body}, nil
case p == path && m == "PATCH": case p == path && m == "PATCH":
// In idempotent updates, kubectl will resolve to an empty patch and not send anything to the server // In idempotent updates, kubectl will resolve to an empty patch and not send anything to the server
@ -1044,7 +1045,7 @@ func TestUnstructuredIdempotentApply(t *testing.T) {
}), }),
} }
tf.OpenAPISchemaFunc = fn tf.OpenAPISchemaFunc = fn
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdApply("kubectl", tf, ioStreams) cmd := NewCmdApply("kubectl", tf, ioStreams)
@ -1064,7 +1065,7 @@ func TestUnstructuredIdempotentApply(t *testing.T) {
} }
func TestRunApplySetLastApplied(t *testing.T) { func TestRunApplySetLastApplied(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
@ -1120,30 +1121,30 @@ func TestRunApplySetLastApplied(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"}, GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == pathRC && m == "GET": case p == pathRC && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == noAnnotationPath && m == "GET": case p == noAnnotationPath && m == "GET":
bodyRC := ioutil.NopCloser(bytes.NewReader(noAnnotationRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(noAnnotationRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == noExistPath && m == "GET": case p == noExistPath && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &corev1.Pod{})}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Pod{})}, nil
case p == pathRC && m == "PATCH": case p == pathRC && m == "PATCH":
checkPatchString(t, req) checkPatchString(t, req)
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
cmdutil.BehaviorOnFatal(func(str string, code int) { cmdutil.BehaviorOnFatal(func(str string, code int) {
if str != test.expectedErr { if str != test.expectedErr {
@ -1189,7 +1190,7 @@ func checkPatchString(t *testing.T, req *http.Request) {
} }
func TestForceApply(t *testing.T) { func TestForceApply(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC)
pathRC := "/namespaces/test/replicationcontrollers/" + nameRC pathRC := "/namespaces/test/replicationcontrollers/" + nameRC
@ -1211,21 +1212,21 @@ func TestForceApply(t *testing.T) {
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case strings.HasSuffix(p, pathRC) && m == "GET": case strings.HasSuffix(p, pathRC) && m == "GET":
if deleted { if deleted {
counts["getNotFound"]++ counts["getNotFound"]++
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil
} }
counts["getOk"]++ counts["getOk"]++
var bodyRC io.ReadCloser var bodyRC io.ReadCloser
if isScaledDownToZero { if isScaledDownToZero {
rcObj := readReplicationControllerFromFile(t, filenameRC) rcObj := readReplicationControllerFromFile(t, filenameRC)
rcObj.Spec.Replicas = int32ptr(0) rcObj.Spec.Replicas = cmdtesting.Int32ptr(0)
rcBytes, err := runtime.Encode(codec, rcObj) rcBytes, err := runtime.Encode(codec, rcObj)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -1234,7 +1235,7 @@ func TestForceApply(t *testing.T) {
} else { } else {
bodyRC = ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC = ioutil.NopCloser(bytes.NewReader(currentRC))
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case strings.HasSuffix(p, pathRCList) && m == "GET": case strings.HasSuffix(p, pathRCList) && m == "GET":
counts["getList"]++ counts["getList"]++
rcObj := readUnstructuredFromFile(t, filenameRC) rcObj := readUnstructuredFromFile(t, filenameRC)
@ -1250,14 +1251,14 @@ func TestForceApply(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
bodyRCList := ioutil.NopCloser(bytes.NewReader(listBytes)) bodyRCList := ioutil.NopCloser(bytes.NewReader(listBytes))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRCList}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRCList}, nil
case strings.HasSuffix(p, pathRC) && m == "PATCH": case strings.HasSuffix(p, pathRC) && m == "PATCH":
counts["patch"]++ counts["patch"]++
if counts["patch"] <= 6 { if counts["patch"] <= 6 {
statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first."))
bodyBytes, _ := json.Marshal(statusErr) bodyBytes, _ := json.Marshal(statusErr)
bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes))
return &http.Response{StatusCode: http.StatusConflict, Header: defaultHeader(), Body: bodyErr}, nil return &http.Response{StatusCode: http.StatusConflict, Header: cmdtesting.DefaultHeader(), Body: bodyErr}, nil
} }
t.Fatalf("unexpected request: %#v after %v tries\n%#v", req.URL, counts["patch"], req) t.Fatalf("unexpected request: %#v after %v tries\n%#v", req.URL, counts["patch"], req)
return nil, nil return nil, nil
@ -1265,13 +1266,13 @@ func TestForceApply(t *testing.T) {
counts["put"]++ counts["put"]++
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
isScaledDownToZero = true isScaledDownToZero = true
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
case strings.HasSuffix(p, pathRCList) && m == "POST": case strings.HasSuffix(p, pathRCList) && m == "POST":
counts["post"]++ counts["post"]++
deleted = false deleted = false
isScaledDownToZero = false isScaledDownToZero = false
bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC))
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: bodyRC}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -31,6 +31,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/genericclioptions/resource"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/tools/remotecommand"
"k8s.io/kubernetes/pkg/kubectl/cmd/exec"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
@ -62,7 +63,7 @@ const (
// AttachOptions declare the arguments accepted by the Exec command // AttachOptions declare the arguments accepted by the Exec command
type AttachOptions struct { type AttachOptions struct {
StreamOptions exec.StreamOptions
// whether to disable use of standard error when streaming output from tty // whether to disable use of standard error when streaming output from tty
DisableStderr bool DisableStderr bool
@ -85,11 +86,11 @@ type AttachOptions struct {
func NewAttachOptions(streams genericclioptions.IOStreams) *AttachOptions { func NewAttachOptions(streams genericclioptions.IOStreams) *AttachOptions {
return &AttachOptions{ return &AttachOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
IOStreams: streams, IOStreams: streams,
}, },
Attach: &DefaultRemoteAttach{}, Attach: &DefaultRemoteAttach{},
AttachFunc: defaultAttachFunc, AttachFunc: DefaultAttachFunc,
} }
} }
@ -119,7 +120,7 @@ type RemoteAttach interface {
Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool, terminalSizeQueue remotecommand.TerminalSizeQueue) error
} }
func defaultAttachFunc(o *AttachOptions, containerToAttach *corev1.Container, raw bool, sizeQueue remotecommand.TerminalSizeQueue) func() error { func DefaultAttachFunc(o *AttachOptions, containerToAttach *corev1.Container, raw bool, sizeQueue remotecommand.TerminalSizeQueue) func() error {
return func() error { return func() error {
restClient, err := restclient.RESTClientFor(o.Config) restClient, err := restclient.RESTClientFor(o.Config)
if err != nil { if err != nil {
@ -262,7 +263,7 @@ func (o *AttachOptions) Run() error {
} }
// ensure we can recover the terminal while attached // ensure we can recover the terminal while attached
t := o.setupTTY() t := o.SetupTTY()
var sizeQueue remotecommand.TerminalSizeQueue var sizeQueue remotecommand.TerminalSizeQueue
if t.Raw { if t.Raw {

View File

@ -33,6 +33,7 @@ import (
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/tools/remotecommand"
"k8s.io/kubernetes/pkg/kubectl/cmd/exec"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
@ -87,7 +88,7 @@ func TestPodAndContainerAttach(t *testing.T) {
}, },
{ {
name: "container in flag", name: "container in flag",
options: &AttachOptions{StreamOptions: StreamOptions{ContainerName: "bar"}, GetPodTimeout: 10000000}, options: &AttachOptions{StreamOptions: exec.StreamOptions{ContainerName: "bar"}, GetPodTimeout: 10000000},
args: []string{"foo"}, args: []string{"foo"},
expectedPodName: "foo", expectedPodName: "foo",
expectedContainerName: "bar", expectedContainerName: "bar",
@ -95,7 +96,7 @@ func TestPodAndContainerAttach(t *testing.T) {
}, },
{ {
name: "init container in flag", name: "init container in flag",
options: &AttachOptions{StreamOptions: StreamOptions{ContainerName: "initfoo"}, GetPodTimeout: 30}, options: &AttachOptions{StreamOptions: exec.StreamOptions{ContainerName: "initfoo"}, GetPodTimeout: 30},
args: []string{"foo"}, args: []string{"foo"},
expectedPodName: "foo", expectedPodName: "foo",
expectedContainerName: "initfoo", expectedContainerName: "initfoo",
@ -103,7 +104,7 @@ func TestPodAndContainerAttach(t *testing.T) {
}, },
{ {
name: "non-existing container", name: "non-existing container",
options: &AttachOptions{StreamOptions: StreamOptions{ContainerName: "wrong"}, GetPodTimeout: 10}, options: &AttachOptions{StreamOptions: exec.StreamOptions{ContainerName: "wrong"}, GetPodTimeout: 10},
args: []string{"foo"}, args: []string{"foo"},
expectedPodName: "foo", expectedPodName: "foo",
expectError: "container not found", expectError: "container not found",
@ -238,11 +239,11 @@ func TestAttach(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == test.podPath && m == "GET": case p == test.podPath && m == "GET":
body := objBody(codec, test.pod) body := cmdtesting.ObjBody(codec, test.pod)
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == test.fetchPodPath && m == "GET": case p == test.fetchPodPath && m == "GET":
body := objBody(codec, test.pod) body := cmdtesting.ObjBody(codec, test.pod)
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")
@ -256,7 +257,7 @@ func TestAttach(t *testing.T) {
remoteAttach.err = fmt.Errorf("attach error") remoteAttach.err = fmt.Errorf("attach error")
} }
options := &AttachOptions{ options := &AttachOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
ContainerName: test.container, ContainerName: test.container,
IOStreams: genericclioptions.NewTestIOStreamsDiscard(), IOStreams: genericclioptions.NewTestIOStreamsDiscard(),
}, },
@ -340,11 +341,11 @@ func TestAttachWarnings(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == test.podPath && m == "GET": case p == test.podPath && m == "GET":
body := objBody(codec, test.pod) body := cmdtesting.ObjBody(codec, test.pod)
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == test.fetchPodPath && m == "GET": case p == test.fetchPodPath && m == "GET":
body := objBody(codec, test.pod) body := cmdtesting.ObjBody(codec, test.pod)
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")
@ -354,7 +355,7 @@ func TestAttachWarnings(t *testing.T) {
tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: scheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: scheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}}
options := &AttachOptions{ options := &AttachOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
Stdin: test.stdin, Stdin: test.stdin,
TTY: test.tty, TTY: test.tty,
ContainerName: test.container, ContainerName: test.container,

View File

@ -38,6 +38,11 @@ import (
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
const (
defaultPodLogsTimeout = 20 * time.Second
timeout = 5 * time.Minute
)
type ClusterInfoDumpOptions struct { type ClusterInfoDumpOptions struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
PrintObj printers.ResourcePrinterFunc PrintObj printers.ResourcePrinterFunc

View File

@ -28,17 +28,48 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
utilflag "k8s.io/apiserver/pkg/util/flag" utilflag "k8s.io/apiserver/pkg/util/flag"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/pkg/kubectl/cmd/annotate"
"k8s.io/kubernetes/pkg/kubectl/cmd/apiresources"
"k8s.io/kubernetes/pkg/kubectl/cmd/apply"
"k8s.io/kubernetes/pkg/kubectl/cmd/attach"
"k8s.io/kubernetes/pkg/kubectl/cmd/auth" "k8s.io/kubernetes/pkg/kubectl/cmd/auth"
"k8s.io/kubernetes/pkg/kubectl/cmd/autoscale"
"k8s.io/kubernetes/pkg/kubectl/cmd/certificates"
"k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo"
"k8s.io/kubernetes/pkg/kubectl/cmd/completion"
cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config" cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
"k8s.io/kubernetes/pkg/kubectl/cmd/convert"
"k8s.io/kubernetes/pkg/kubectl/cmd/cp"
"k8s.io/kubernetes/pkg/kubectl/cmd/create" "k8s.io/kubernetes/pkg/kubectl/cmd/create"
"k8s.io/kubernetes/pkg/kubectl/cmd/delete"
"k8s.io/kubernetes/pkg/kubectl/cmd/describe"
"k8s.io/kubernetes/pkg/kubectl/cmd/diff"
"k8s.io/kubernetes/pkg/kubectl/cmd/drain"
"k8s.io/kubernetes/pkg/kubectl/cmd/edit"
cmdexec "k8s.io/kubernetes/pkg/kubectl/cmd/exec"
"k8s.io/kubernetes/pkg/kubectl/cmd/explain"
"k8s.io/kubernetes/pkg/kubectl/cmd/expose"
"k8s.io/kubernetes/pkg/kubectl/cmd/get" "k8s.io/kubernetes/pkg/kubectl/cmd/get"
"k8s.io/kubernetes/pkg/kubectl/cmd/label"
"k8s.io/kubernetes/pkg/kubectl/cmd/logs"
"k8s.io/kubernetes/pkg/kubectl/cmd/options"
"k8s.io/kubernetes/pkg/kubectl/cmd/patch"
"k8s.io/kubernetes/pkg/kubectl/cmd/plugin"
"k8s.io/kubernetes/pkg/kubectl/cmd/portforward"
"k8s.io/kubernetes/pkg/kubectl/cmd/proxy"
"k8s.io/kubernetes/pkg/kubectl/cmd/replace"
"k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate"
"k8s.io/kubernetes/pkg/kubectl/cmd/rollout" "k8s.io/kubernetes/pkg/kubectl/cmd/rollout"
"k8s.io/kubernetes/pkg/kubectl/cmd/run"
"k8s.io/kubernetes/pkg/kubectl/cmd/scale"
"k8s.io/kubernetes/pkg/kubectl/cmd/set" "k8s.io/kubernetes/pkg/kubectl/cmd/set"
"k8s.io/kubernetes/pkg/kubectl/cmd/taint"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
"k8s.io/kubernetes/pkg/kubectl/cmd/top"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/version"
"k8s.io/kubernetes/pkg/kubectl/cmd/wait" "k8s.io/kubernetes/pkg/kubectl/cmd/wait"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
@ -416,72 +447,72 @@ func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
Message: "Basic Commands (Beginner):", Message: "Basic Commands (Beginner):",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
create.NewCmdCreate(f, ioStreams), create.NewCmdCreate(f, ioStreams),
NewCmdExposeService(f, ioStreams), expose.NewCmdExposeService(f, ioStreams),
NewCmdRun(f, ioStreams), run.NewCmdRun(f, ioStreams),
set.NewCmdSet(f, ioStreams), set.NewCmdSet(f, ioStreams),
deprecatedAlias("run-container", NewCmdRun(f, ioStreams)), deprecatedAlias("run-container", run.NewCmdRun(f, ioStreams)),
}, },
}, },
{ {
Message: "Basic Commands (Intermediate):", Message: "Basic Commands (Intermediate):",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
NewCmdExplain("kubectl", f, ioStreams), explain.NewCmdExplain("kubectl", f, ioStreams),
get.NewCmdGet("kubectl", f, ioStreams), get.NewCmdGet("kubectl", f, ioStreams),
NewCmdEdit(f, ioStreams), edit.NewCmdEdit(f, ioStreams),
NewCmdDelete(f, ioStreams), delete.NewCmdDelete(f, ioStreams),
}, },
}, },
{ {
Message: "Deploy Commands:", Message: "Deploy Commands:",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
rollout.NewCmdRollout(f, ioStreams), rollout.NewCmdRollout(f, ioStreams),
NewCmdRollingUpdate(f, ioStreams), rollingupdate.NewCmdRollingUpdate(f, ioStreams),
NewCmdScale(f, ioStreams), scale.NewCmdScale(f, ioStreams),
NewCmdAutoscale(f, ioStreams), autoscale.NewCmdAutoscale(f, ioStreams),
}, },
}, },
{ {
Message: "Cluster Management Commands:", Message: "Cluster Management Commands:",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
NewCmdCertificate(f, ioStreams), certificates.NewCmdCertificate(f, ioStreams),
NewCmdClusterInfo(f, ioStreams), clusterinfo.NewCmdClusterInfo(f, ioStreams),
NewCmdTop(f, ioStreams), top.NewCmdTop(f, ioStreams),
NewCmdCordon(f, ioStreams), drain.NewCmdCordon(f, ioStreams),
NewCmdUncordon(f, ioStreams), drain.NewCmdUncordon(f, ioStreams),
NewCmdDrain(f, ioStreams), drain.NewCmdDrain(f, ioStreams),
NewCmdTaint(f, ioStreams), taint.NewCmdTaint(f, ioStreams),
}, },
}, },
{ {
Message: "Troubleshooting and Debugging Commands:", Message: "Troubleshooting and Debugging Commands:",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
NewCmdDescribe("kubectl", f, ioStreams), describe.NewCmdDescribe("kubectl", f, ioStreams),
NewCmdLogs(f, ioStreams), logs.NewCmdLogs(f, ioStreams),
NewCmdAttach(f, ioStreams), attach.NewCmdAttach(f, ioStreams),
NewCmdExec(f, ioStreams), cmdexec.NewCmdExec(f, ioStreams),
NewCmdPortForward(f, ioStreams), portforward.NewCmdPortForward(f, ioStreams),
NewCmdProxy(f, ioStreams), proxy.NewCmdProxy(f, ioStreams),
NewCmdCp(f, ioStreams), cp.NewCmdCp(f, ioStreams),
auth.NewCmdAuth(f, ioStreams), auth.NewCmdAuth(f, ioStreams),
}, },
}, },
{ {
Message: "Advanced Commands:", Message: "Advanced Commands:",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
NewCmdDiff(f, ioStreams), diff.NewCmdDiff(f, ioStreams),
NewCmdApply("kubectl", f, ioStreams), apply.NewCmdApply("kubectl", f, ioStreams),
NewCmdPatch(f, ioStreams), patch.NewCmdPatch(f, ioStreams),
NewCmdReplace(f, ioStreams), replace.NewCmdReplace(f, ioStreams),
wait.NewCmdWait(f, ioStreams), wait.NewCmdWait(f, ioStreams),
NewCmdConvert(f, ioStreams), convert.NewCmdConvert(f, ioStreams),
}, },
}, },
{ {
Message: "Settings Commands:", Message: "Settings Commands:",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
NewCmdLabel(f, ioStreams), label.NewCmdLabel(f, ioStreams),
NewCmdAnnotate("kubectl", f, ioStreams), annotate.NewCmdAnnotate("kubectl", f, ioStreams),
NewCmdCompletion(ioStreams.Out, ""), completion.NewCmdCompletion(ioStreams.Out, ""),
}, },
}, },
} }
@ -511,11 +542,11 @@ func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
cmds.AddCommand(alpha) cmds.AddCommand(alpha)
cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), ioStreams)) cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), ioStreams))
cmds.AddCommand(NewCmdPlugin(f, ioStreams)) cmds.AddCommand(plugin.NewCmdPlugin(f, ioStreams))
cmds.AddCommand(NewCmdVersion(f, ioStreams)) cmds.AddCommand(version.NewCmdVersion(f, ioStreams))
cmds.AddCommand(NewCmdApiVersions(f, ioStreams)) cmds.AddCommand(apiresources.NewCmdApiVersions(f, ioStreams))
cmds.AddCommand(NewCmdApiResources(f, ioStreams)) cmds.AddCommand(apiresources.NewCmdApiResources(f, ioStreams))
cmds.AddCommand(NewCmdOptions(ioStreams.Out)) cmds.AddCommand(options.NewCmdOptions(ioStreams.Out))
return cmds return cmds
} }
@ -524,10 +555,6 @@ func runHelp(cmd *cobra.Command, args []string) {
cmd.Help() cmd.Help()
} }
func printDeprecationWarning(errOut io.Writer, command, alias string) {
fmt.Fprintf(errOut, "%s is DEPRECATED and will be removed in a future version. Use %s instead.\n", alias, command)
}
// deprecatedAlias is intended to be used to create a "wrapper" command around // deprecatedAlias is intended to be used to create a "wrapper" command around
// an existing command. The wrapper works the same but prints a deprecation // an existing command. The wrapper works the same but prints a deprecation
// message before running. This command is identical functionality. // message before running. This command is identical functionality.
@ -542,5 +569,3 @@ func deprecatedAlias(deprecatedVersion string, cmd *cobra.Command) *cobra.Comman
cmd.Hidden = true cmd.Hidden = true
return cmd return cmd
} }
var metadataAccessor = meta.NewAccessor()

View File

@ -18,127 +18,19 @@ package cmd
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"reflect" "reflect"
stdstrings "strings" "strings"
"testing" "testing"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
restclient "k8s.io/client-go/rest"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme"
) )
func initTestErrorHandler(t *testing.T) {
cmdutil.BehaviorOnFatal(func(str string, code int) {
t.Errorf("Error running command (exit code %d): %s", code, str)
})
}
func defaultHeader() http.Header {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return header
}
func defaultClientConfig() *restclient.Config {
return &restclient.Config{
APIPath: "/api",
ContentConfig: restclient.ContentConfig{
NegotiatedSerializer: scheme.Codecs,
ContentType: runtime.ContentTypeJSON,
GroupVersion: &corev1.SchemeGroupVersion,
},
}
}
func testData() (*corev1.PodList, *corev1.ServiceList, *corev1.ReplicationControllerList) {
grace := int64(30)
enableServiceLinks := corev1.DefaultEnableServiceLinks
pods := &corev1.PodList{
ListMeta: metav1.ListMeta{
ResourceVersion: "15",
},
Items: []corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
EnableServiceLinks: &enableServiceLinks,
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
EnableServiceLinks: &enableServiceLinks,
},
},
},
}
svc := &corev1.ServiceList{
ListMeta: metav1.ListMeta{
ResourceVersion: "16",
},
Items: []corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"},
Spec: corev1.ServiceSpec{
SessionAffinity: "None",
Type: corev1.ServiceTypeClusterIP,
},
},
},
}
rc := &corev1.ReplicationControllerList{
ListMeta: metav1.ListMeta{
ResourceVersion: "17",
},
Items: []corev1.ReplicationController{
{
ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"},
Spec: corev1.ReplicationControllerSpec{
Replicas: int32ptr(1),
},
},
},
}
return pods, svc, rc
}
func int32ptr(val int) *int32 {
t := int32(val)
return &t
}
func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
}
func bytesBody(bodyBytes []byte) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader(bodyBytes))
}
func stringBody(body string) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(body)))
}
func TestNormalizationFuncGlobalExistence(t *testing.T) { func TestNormalizationFuncGlobalExistence(t *testing.T) {
// This test can be safely deleted when we will not support multiple flag formats // This test can be safely deleted when we will not support multiple flag formats
root := NewKubectlCommand(os.Stdin, os.Stdout, os.Stderr) root := NewKubectlCommand(os.Stdin, os.Stdout, os.Stderr)
@ -165,14 +57,6 @@ func TestNormalizationFuncGlobalExistence(t *testing.T) {
} }
} }
func genResponseWithJsonEncodedBody(bodyStruct interface{}) (*http.Response, error) {
jsonBytes, err := json.Marshal(bodyStruct)
if err != nil {
return nil, err
}
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bytesBody(jsonBytes)}, nil
}
func Test_deprecatedAlias(t *testing.T) { func Test_deprecatedAlias(t *testing.T) {
var correctCommandCalled bool var correctCommandCalled bool
makeCobraCommand := func() *cobra.Command { makeCobraCommand := func() *cobra.Command {
@ -190,7 +74,7 @@ func Test_deprecatedAlias(t *testing.T) {
if len(alias.Deprecated) == 0 { if len(alias.Deprecated) == 0 {
t.Error("deprecatedAlias should always have a non-empty .Deprecated") t.Error("deprecatedAlias should always have a non-empty .Deprecated")
} }
if !stdstrings.Contains(alias.Deprecated, "print") { if !strings.Contains(alias.Deprecated, "print") {
t.Error("deprecatedAlias should give the name of the new function in its .Deprecated field") t.Error("deprecatedAlias should give the name of the new function in its .Deprecated field")
} }
if !alias.Hidden { if !alias.Hidden {
@ -210,7 +94,7 @@ func Test_deprecatedAlias(t *testing.T) {
alias.SetOutput(buffer) alias.SetOutput(buffer)
alias.Execute() alias.Execute()
str := buffer.String() str := buffer.String()
if !stdstrings.Contains(str, "deprecated") || !stdstrings.Contains(str, "print") { if !strings.Contains(str, "deprecated") || !strings.Contains(str, "print") {
t.Errorf("deprecation warning %q does not include enough information", str) t.Errorf("deprecation warning %q does not include enough information", str)
} }
@ -240,7 +124,7 @@ func TestKubectlCommandHandlesPlugins(t *testing.T) {
{ {
name: "test that a plugin executable is found based on command args", name: "test that a plugin executable is found based on command args",
args: []string{"kubectl", "foo", "--bar"}, args: []string{"kubectl", "foo", "--bar"},
expectPlugin: "testdata/plugin/kubectl-foo", expectPlugin: "plugin/testdata/kubectl-foo",
expectPluginArgs: []string{"foo", "--bar"}, expectPluginArgs: []string{"foo", "--bar"},
}, },
{ {
@ -252,7 +136,7 @@ func TestKubectlCommandHandlesPlugins(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
pluginsHandler := &testPluginHandler{ pluginsHandler := &testPluginHandler{
pluginsDirectory: "testdata/plugin", pluginsDirectory: "plugin/testdata",
} }
_, in, out, errOut := genericclioptions.NewTestIOStreams() _, in, out, errOut := genericclioptions.NewTestIOStreams()

View File

@ -43,7 +43,7 @@ func TestConvertObject(t *testing.T) {
testcases := []testcase{ testcases := []testcase{
{ {
name: "apps deployment to extensions deployment", name: "apps deployment to extensions deployment",
file: "../../../test/fixtures/pkg/kubectl/cmd/convert/appsdeployment.yaml", file: "../../../../test/fixtures/pkg/kubectl/cmd/convert/appsdeployment.yaml",
outputVersion: "extensions/v1beta1", outputVersion: "extensions/v1beta1",
fields: []checkField{ fields: []checkField{
{ {
@ -53,7 +53,7 @@ func TestConvertObject(t *testing.T) {
}, },
{ {
name: "extensions deployment to apps deployment", name: "extensions deployment to apps deployment",
file: "../../../test/fixtures/pkg/kubectl/cmd/convert/extensionsdeployment.yaml", file: "../../../../test/fixtures/pkg/kubectl/cmd/convert/extensionsdeployment.yaml",
outputVersion: "apps/v1beta2", outputVersion: "apps/v1beta2",
fields: []checkField{ fields: []checkField{
{ {
@ -63,7 +63,7 @@ func TestConvertObject(t *testing.T) {
}, },
{ {
name: "v1 HPA to v2beta1 HPA", name: "v1 HPA to v2beta1 HPA",
file: "../../../test/fixtures/pkg/kubectl/cmd/convert/v1HPA.yaml", file: "../../../../test/fixtures/pkg/kubectl/cmd/convert/v1HPA.yaml",
outputVersion: "autoscaling/v2beta1", outputVersion: "autoscaling/v2beta1",
fields: []checkField{ fields: []checkField{
{ {
@ -79,7 +79,7 @@ func TestConvertObject(t *testing.T) {
}, },
{ {
name: "v2beta1 HPA to v1 HPA", name: "v2beta1 HPA to v1 HPA",
file: "../../../test/fixtures/pkg/kubectl/cmd/convert/v2beta1HPA.yaml", file: "../../../../test/fixtures/pkg/kubectl/cmd/convert/v2beta1HPA.yaml",
outputVersion: "autoscaling/v1", outputVersion: "autoscaling/v1",
fields: []checkField{ fields: []checkField{
{ {

View File

@ -30,6 +30,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/kubectl/cmd/exec"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
@ -197,8 +198,8 @@ func (o *CopyOptions) Run(args []string) error {
// pod. If the destination path does not exist or is _not_ a // pod. If the destination path does not exist or is _not_ a
// directory, an error is returned with the exit code received. // directory, an error is returned with the exit code received.
func (o *CopyOptions) checkDestinationIsDir(dest fileSpec) error { func (o *CopyOptions) checkDestinationIsDir(dest fileSpec) error {
options := &ExecOptions{ options := &exec.ExecOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
IOStreams: genericclioptions.IOStreams{ IOStreams: genericclioptions.IOStreams{
Out: bytes.NewBuffer([]byte{}), Out: bytes.NewBuffer([]byte{}),
ErrOut: bytes.NewBuffer([]byte{}), ErrOut: bytes.NewBuffer([]byte{}),
@ -209,7 +210,7 @@ func (o *CopyOptions) checkDestinationIsDir(dest fileSpec) error {
}, },
Command: []string{"test", "-d", dest.File}, Command: []string{"test", "-d", dest.File},
Executor: &DefaultRemoteExecutor{}, Executor: &exec.DefaultRemoteExecutor{},
} }
return o.execute(options) return o.execute(options)
@ -245,8 +246,8 @@ func (o *CopyOptions) copyToPod(src, dest fileSpec) error {
cmdArr = append(cmdArr, "-C", destDir) cmdArr = append(cmdArr, "-C", destDir)
} }
options := &ExecOptions{ options := &exec.ExecOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
IOStreams: genericclioptions.IOStreams{ IOStreams: genericclioptions.IOStreams{
In: reader, In: reader,
Out: o.Out, Out: o.Out,
@ -259,7 +260,7 @@ func (o *CopyOptions) copyToPod(src, dest fileSpec) error {
}, },
Command: cmdArr, Command: cmdArr,
Executor: &DefaultRemoteExecutor{}, Executor: &exec.DefaultRemoteExecutor{},
} }
return o.execute(options) return o.execute(options)
} }
@ -270,8 +271,8 @@ func (o *CopyOptions) copyFromPod(src, dest fileSpec) error {
} }
reader, outStream := io.Pipe() reader, outStream := io.Pipe()
options := &ExecOptions{ options := &exec.ExecOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
IOStreams: genericclioptions.IOStreams{ IOStreams: genericclioptions.IOStreams{
In: nil, In: nil,
Out: outStream, Out: outStream,
@ -284,7 +285,7 @@ func (o *CopyOptions) copyFromPod(src, dest fileSpec) error {
// TODO: Improve error messages by first testing if 'tar' is present in the container? // TODO: Improve error messages by first testing if 'tar' is present in the container?
Command: []string{"tar", "cf", "-", src.File}, Command: []string{"tar", "cf", "-", src.File},
Executor: &DefaultRemoteExecutor{}, Executor: &exec.DefaultRemoteExecutor{},
} }
go func() { go func() {
@ -460,7 +461,7 @@ func getPrefix(file string) string {
return strings.TrimLeft(file, "/") return strings.TrimLeft(file, "/")
} }
func (o *CopyOptions) execute(options *ExecOptions) error { func (o *CopyOptions) execute(options *exec.ExecOptions) error {
if len(options.Namespace) == 0 { if len(options.Namespace) == 0 {
options.Namespace = o.Namespace options.Namespace = o.Namespace
} }

View File

@ -527,11 +527,11 @@ func TestCopyToPod(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
responsePod := &v1.Pod{} responsePod := &v1.Pod{}
return &http.Response{StatusCode: http.StatusNotFound, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, responsePod))))}, nil return &http.Response{StatusCode: http.StatusNotFound, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, responsePod))))}, nil
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() ioStreams, _, _, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdCp(tf, ioStreams) cmd := NewCmdCp(tf, ioStreams)

View File

@ -24,9 +24,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
@ -39,7 +37,7 @@ func TestCreateClusterRole(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.Client = &fake.RESTClient{} tf.Client = &fake.RESTClient{}
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
tests := map[string]struct { tests := map[string]struct {
verbs string verbs string
@ -514,14 +512,3 @@ func TestClusterRoleValidate(t *testing.T) {
}) })
} }
} }
func defaultClientConfig() *restclient.Config {
return &restclient.Config{
APIPath: "/api",
ContentConfig: restclient.ContentConfig{
NegotiatedSerializer: scheme.Codecs,
ContentType: runtime.ContentTypeJSON,
GroupVersion: &schema.GroupVersion{Version: "v1"},
},
}
}

View File

@ -101,7 +101,7 @@ func TestCreateClusterRoleBinding(t *testing.T) {
responseBinding := &rbac.ClusterRoleBinding{} responseBinding := &rbac.ClusterRoleBinding{}
responseBinding.Name = "fake-binding" responseBinding.Name = "fake-binding"
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseBinding))))}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseBinding))))}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -145,9 +145,3 @@ func (c *ClusterRoleBindingRESTClient) Post() *restclient.Request {
} }
return restclient.NewRequest(c, "POST", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0) return restclient.NewRequest(c, "POST", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0)
} }
func defaultHeader() http.Header {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return header
}

View File

@ -17,14 +17,10 @@ limitations under the License.
package create package create
import ( import (
"bytes"
"io"
"io/ioutil"
"net/http" "net/http"
"testing" "testing"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
@ -47,7 +43,7 @@ func TestCreateConfigMap(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/configmaps" && m == "POST": case p == "/namespaces/test/configmaps" && m == "POST":
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, configMap)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, configMap)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -63,7 +59,3 @@ func TestCreateConfigMap(t *testing.T) {
t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String())
} }
} }
func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
}

View File

@ -43,7 +43,7 @@ func TestCreateNamespace(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces" && m == "POST": case p == "/namespaces" && m == "POST":
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, namespaceObject)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, namespaceObject)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -38,7 +38,7 @@ func TestCreateRole(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.Client = &fake.RESTClient{} tf.Client = &fake.RESTClient{}
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
tests := map[string]struct { tests := map[string]struct {
verbs string verbs string
@ -358,7 +358,7 @@ func TestComplete(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.Client = &fake.RESTClient{} tf.Client = &fake.RESTClient{}
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
defaultTestResources := "pods,deployments.extensions" defaultTestResources := "pods,deployments.extensions"

View File

@ -103,7 +103,7 @@ func TestCreateRoleBinding(t *testing.T) {
responseBinding := &rbac.RoleBinding{} responseBinding := &rbac.RoleBinding{}
responseBinding.Name = "fake-binding" responseBinding.Name = "fake-binding"
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseBinding))))}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseBinding))))}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -48,7 +48,7 @@ func TestCreateSecretGeneric(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/secrets" && m == "POST": case p == "/namespaces/test/secrets" && m == "POST":
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, secretObject)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, secretObject)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -80,7 +80,7 @@ func TestCreateSecretDockerRegistry(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/secrets" && m == "POST": case p == "/namespaces/test/secrets" && m == "POST":
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, secretObject)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, secretObject)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -43,7 +43,7 @@ func TestCreateService(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services" && m == "POST": case p == "/namespaces/test/services" && m == "POST":
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, service)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, service)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -76,7 +76,7 @@ func TestCreateServiceNodePort(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services" && m == http.MethodPost: case p == "/namespaces/test/services" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, service)}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, service)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -109,7 +109,7 @@ func TestCreateServiceExternalName(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services" && m == http.MethodPost: case p == "/namespaces/test/services" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, service)}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, service)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -43,7 +43,7 @@ func TestCreateServiceAccount(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/serviceaccounts" && m == "POST": case p == "/namespaces/test/serviceaccounts" && m == "POST":
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, serviceAccountObject)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, serviceAccountObject)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -20,19 +20,16 @@ import (
"net/http" "net/http"
"testing" "testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
func TestExtraArgsFail(t *testing.T) { func TestExtraArgsFail(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
f := cmdtesting.NewTestFactory() f := cmdtesting.NewTestFactory()
defer f.Cleanup() defer f.Cleanup()
@ -45,8 +42,8 @@ func TestExtraArgsFail(t *testing.T) {
} }
func TestCreateObject(t *testing.T) { func TestCreateObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
rc.Items[0].Name = "redis-master-controller" rc.Items[0].Name = "redis-master-controller"
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
@ -56,11 +53,11 @@ func TestCreateObject(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"}, GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -81,8 +78,8 @@ func TestCreateObject(t *testing.T) {
} }
func TestCreateMultipleObject(t *testing.T) { func TestCreateMultipleObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, svc, rc := testData() _, svc, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -91,13 +88,13 @@ func TestCreateMultipleObject(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"}, GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services" && m == http.MethodPost: case p == "/namespaces/test/services" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -119,8 +116,8 @@ func TestCreateMultipleObject(t *testing.T) {
} }
func TestCreateDirectory(t *testing.T) { func TestCreateDirectory(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
rc.Items[0].Name = "name" rc.Items[0].Name = "name"
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
@ -130,11 +127,11 @@ func TestCreateDirectory(t *testing.T) {
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"}, GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -152,69 +149,3 @@ func TestCreateDirectory(t *testing.T) {
t.Errorf("unexpected output: %s", buf.String()) t.Errorf("unexpected output: %s", buf.String())
} }
} }
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer
func initTestErrorHandler(t *testing.T) {
cmdutil.BehaviorOnFatal(func(str string, code int) {
t.Errorf("Error running command (exit code %d): %s", code, str)
})
}
func testData() (*corev1.PodList, *corev1.ServiceList, *corev1.ReplicationControllerList) {
grace := int64(30)
pods := &corev1.PodList{
ListMeta: metav1.ListMeta{
ResourceVersion: "15",
},
Items: []corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
},
},
},
}
svc := &corev1.ServiceList{
ListMeta: metav1.ListMeta{
ResourceVersion: "16",
},
Items: []corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"},
Spec: corev1.ServiceSpec{
SessionAffinity: "None",
Type: corev1.ServiceTypeClusterIP,
},
},
},
}
one := int32(1)
rc := &corev1.ReplicationControllerList{
ListMeta: metav1.ListMeta{
ResourceVersion: "17",
},
Items: []corev1.ReplicationController{
{
ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"},
Spec: corev1.ReplicationControllerSpec{
Replicas: &one,
},
},
},
}
return pods, svc, rc
}

View File

@ -36,8 +36,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer
func fakecmd() *cobra.Command { func fakecmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])",
@ -48,8 +46,8 @@ func fakecmd() *cobra.Command {
} }
func TestDeleteObjectByTuple(t *testing.T) { func TestDeleteObjectByTuple(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -57,17 +55,17 @@ func TestDeleteObjectByTuple(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
// replication controller with cascade off // replication controller with cascade off
case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
// secret with cascade on, but no client-side reaper // secret with cascade on, but no client-side reaper
case p == "/namespaces/test/secrets/mysecret" && m == "DELETE": case p == "/namespaces/test/secrets/mysecret" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
// Ensures no GET is performed when deleting by name // Ensures no GET is performed when deleting by name
@ -113,8 +111,8 @@ func hasExpectedPropagationPolicy(body io.ReadCloser, policy *metav1.DeletionPro
// Tests that DeleteOptions.OrphanDependents is appropriately set while deleting objects. // Tests that DeleteOptions.OrphanDependents is appropriately set while deleting objects.
func TestOrphanDependentsInDeleteObject(t *testing.T) { func TestOrphanDependentsInDeleteObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -123,13 +121,13 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) {
var policy *metav1.DeletionPropagation var policy *metav1.DeletionPropagation
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m, b := req.URL.Path, req.Method, req.Body; { switch p, m, b := req.URL.Path, req.Method, req.Body; {
case p == "/namespaces/test/secrets/mysecret" && m == "DELETE" && hasExpectedPropagationPolicy(b, policy): case p == "/namespaces/test/secrets/mysecret" && m == "DELETE" && hasExpectedPropagationPolicy(b, policy):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
return nil, nil return nil, nil
} }
@ -163,9 +161,9 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) {
} }
func TestDeleteNamedObject(t *testing.T) { func TestDeleteNamedObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -173,17 +171,17 @@ func TestDeleteNamedObject(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
// replication controller with cascade off // replication controller with cascade off
case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
// secret with cascade on, but no client-side reaper // secret with cascade on, but no client-side reaper
case p == "/namespaces/test/secrets/mysecret" && m == "DELETE": case p == "/namespaces/test/secrets/mysecret" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
// Ensures no GET is performed when deleting by name // Ensures no GET is performed when deleting by name
@ -216,8 +214,8 @@ func TestDeleteNamedObject(t *testing.T) {
} }
func TestDeleteObject(t *testing.T) { func TestDeleteObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -225,11 +223,11 @@ func TestDeleteObject(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -239,7 +237,7 @@ func TestDeleteObject(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdDelete(tf, streams) cmd := NewCmdDelete(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Flags().Set("cascade", "false") cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
@ -251,8 +249,8 @@ func TestDeleteObject(t *testing.T) {
} }
func TestDeleteObjectGraceZero(t *testing.T) { func TestDeleteObjectGraceZero(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
count := 0 count := 0
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
@ -261,7 +259,7 @@ func TestDeleteObjectGraceZero(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
t.Logf("got request %s %s", req.Method, req.URL.Path) t.Logf("got request %s %s", req.Method, req.URL.Path)
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
@ -269,14 +267,14 @@ func TestDeleteObjectGraceZero(t *testing.T) {
count++ count++
switch count { switch count {
case 1, 2, 3: case 1, 2, 3:
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &metav1.Status{})}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &metav1.Status{})}, nil
} }
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
case p == "/namespaces/test/pods/nginx" && m == "DELETE": case p == "/namespaces/test/pods/nginx" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -300,16 +298,16 @@ func TestDeleteObjectGraceZero(t *testing.T) {
} }
func TestDeleteObjectNotFound(t *testing.T) { func TestDeleteObjectNotFound(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("")}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -319,7 +317,7 @@ func TestDeleteObjectNotFound(t *testing.T) {
options := &DeleteOptions{ options := &DeleteOptions{
FilenameOptions: resource.FilenameOptions{ FilenameOptions: resource.FilenameOptions{
Filenames: []string{"../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml"}, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml"},
}, },
GracePeriod: -1, GracePeriod: -1,
Cascade: false, Cascade: false,
@ -337,16 +335,16 @@ func TestDeleteObjectNotFound(t *testing.T) {
} }
func TestDeleteObjectIgnoreNotFound(t *testing.T) { func TestDeleteObjectIgnoreNotFound(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("")}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -356,7 +354,7 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdDelete(tf, streams) cmd := NewCmdDelete(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Flags().Set("cascade", "false") cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("ignore-not-found", "true") cmd.Flags().Set("ignore-not-found", "true")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
@ -368,8 +366,8 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) {
} }
func TestDeleteAllNotFound(t *testing.T) { func TestDeleteAllNotFound(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
// Add an item to the list which will result in a 404 on delete // Add an item to the list which will result in a 404 on delete
svc.Items = append(svc.Items, corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}) svc.Items = append(svc.Items, corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
notFoundError := &errors.NewNotFound(corev1.Resource("services"), "foo").ErrStatus notFoundError := &errors.NewNotFound(corev1.Resource("services"), "foo").ErrStatus
@ -380,15 +378,15 @@ func TestDeleteAllNotFound(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services" && m == "GET": case p == "/namespaces/test/services" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
case p == "/namespaces/test/services/foo" && m == "DELETE": case p == "/namespaces/test/services/foo" && m == "DELETE":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, notFoundError)}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, notFoundError)}, nil
case p == "/namespaces/test/services/baz" && m == "DELETE": case p == "/namespaces/test/services/baz" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -417,8 +415,8 @@ func TestDeleteAllNotFound(t *testing.T) {
} }
func TestDeleteAllIgnoreNotFound(t *testing.T) { func TestDeleteAllIgnoreNotFound(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -430,15 +428,15 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) {
notFoundError := &errors.NewNotFound(corev1.Resource("services"), "foo").ErrStatus notFoundError := &errors.NewNotFound(corev1.Resource("services"), "foo").ErrStatus
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services" && m == "GET": case p == "/namespaces/test/services" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
case p == "/namespaces/test/services/foo" && m == "DELETE": case p == "/namespaces/test/services/foo" && m == "DELETE":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, notFoundError)}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, notFoundError)}, nil
case p == "/namespaces/test/services/baz" && m == "DELETE": case p == "/namespaces/test/services/baz" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -459,8 +457,8 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) {
} }
func TestDeleteMultipleObject(t *testing.T) { func TestDeleteMultipleObject(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, svc, rc := testData() _, svc, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -468,13 +466,13 @@ func TestDeleteMultipleObject(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/services/frontend" && m == "DELETE": case p == "/namespaces/test/services/frontend" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -484,8 +482,8 @@ func TestDeleteMultipleObject(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdDelete(tf, streams) cmd := NewCmdDelete(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml")
cmd.Flags().Set("cascade", "false") cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
@ -496,8 +494,8 @@ func TestDeleteMultipleObject(t *testing.T) {
} }
func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -505,13 +503,13 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("")}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
case p == "/namespaces/test/services/frontend" && m == "DELETE": case p == "/namespaces/test/services/frontend" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -522,7 +520,7 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
options := &DeleteOptions{ options := &DeleteOptions{
FilenameOptions: resource.FilenameOptions{ FilenameOptions: resource.FilenameOptions{
Filenames: []string{"../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml"}, Filenames: []string{"../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml", "../../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml"},
}, },
GracePeriod: -1, GracePeriod: -1,
Cascade: false, Cascade: false,
@ -544,25 +542,25 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
} }
func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, svc, rc := testData() _, svc, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/baz" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/baz" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/replicationcontrollers/foo" && m == "DELETE": case p == "/namespaces/test/replicationcontrollers/foo" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/services/baz" && m == "DELETE": case p == "/namespaces/test/services/baz" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
case p == "/namespaces/test/services/foo" && m == "DELETE": case p == "/namespaces/test/services/foo" && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
// Ensures no GET is performed when deleting by name // Ensures no GET is performed when deleting by name
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
@ -583,8 +581,8 @@ func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) {
} }
func TestDeleteDirectory(t *testing.T) { func TestDeleteDirectory(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -592,11 +590,11 @@ func TestDeleteDirectory(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == "DELETE": case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -606,7 +604,7 @@ func TestDeleteDirectory(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdDelete(tf, streams) cmd := NewCmdDelete(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy")
cmd.Flags().Set("cascade", "false") cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
@ -617,8 +615,8 @@ func TestDeleteDirectory(t *testing.T) {
} }
func TestDeleteMultipleSelector(t *testing.T) { func TestDeleteMultipleSelector(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
pods, svc, _ := testData() pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -626,23 +624,23 @@ func TestDeleteMultipleSelector(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/pods" && m == "GET": case p == "/namespaces/test/pods" && m == "GET":
if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case p == "/namespaces/test/services" && m == "GET": case p == "/namespaces/test/services" && m == "GET":
if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
case strings.HasPrefix(p, "/namespaces/test/pods/") && m == "DELETE": case strings.HasPrefix(p, "/namespaces/test/pods/") && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
case strings.HasPrefix(p, "/namespaces/test/services/") && m == "DELETE": case strings.HasPrefix(p, "/namespaces/test/services/") && m == "DELETE":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -663,7 +661,7 @@ func TestDeleteMultipleSelector(t *testing.T) {
} }
func TestResourceErrors(t *testing.T) { func TestResourceErrors(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
testCases := map[string]struct { testCases := map[string]struct {
args []string args []string
errFn func(error) bool errFn func(error) bool
@ -691,7 +689,7 @@ func TestResourceErrors(t *testing.T) {
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
options := &DeleteOptions{ options := &DeleteOptions{

View File

@ -24,6 +24,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/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
@ -45,8 +46,8 @@ func TestDescribeUnknownSchemaObject(t *testing.T) {
_, _, codec := cmdtesting.NewExternalScheme() _, _, codec := cmdtesting.NewExternalScheme()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", "foo"))}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, cmdtesting.NewInternalType("", "", "foo"))},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -77,8 +78,8 @@ func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) {
_, _, codec := cmdtesting.NewExternalScheme() _, _, codec := cmdtesting.NewExternalScheme()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalNamespacedType("", "", "foo", "non-default"))}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, cmdtesting.NewInternalNamespacedType("", "", "foo", "non-default"))},
} }
tf.WithNamespace("non-default") tf.WithNamespace("non-default")
@ -104,17 +105,17 @@ func TestDescribeObject(t *testing.T) {
}() }()
cmdutil.DescriberFn = d.describerFor cmdutil.DescriberFn = d.describerFor
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "GET": case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -125,7 +126,7 @@ func TestDescribeObject(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdDescribe("kubectl", tf, streams) cmd := NewCmdDescribe("kubectl", tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
if d.Name != "redis-master" || d.Namespace != "test" { if d.Name != "redis-master" || d.Namespace != "test" {
@ -145,14 +146,14 @@ func TestDescribeListObjects(t *testing.T) {
}() }()
cmdutil.DescriberFn = d.describerFor cmdutil.DescriberFn = d.describerFor
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -172,14 +173,14 @@ func TestDescribeObjectShowEvents(t *testing.T) {
}() }()
cmdutil.DescriberFn = d.describerFor cmdutil.DescriberFn = d.describerFor
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
} }
cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard()) cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard())
@ -198,14 +199,14 @@ func TestDescribeObjectSkipEvents(t *testing.T) {
}() }()
cmdutil.DescriberFn = d.describerFor cmdutil.DescriberFn = d.describerFor
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
} }
cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard()) cmd := NewCmdDescribe("kubectl", tf, genericclioptions.NewTestIOStreamsDiscard())

View File

@ -34,6 +34,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/apply"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
@ -259,16 +260,16 @@ func (obj InfoObject) Merged() (runtime.Object, error) {
// This is using the patcher from apply, to keep the same behavior. // This is using the patcher from apply, to keep the same behavior.
// We plan on replacing this with server-side apply when it becomes available. // We plan on replacing this with server-side apply when it becomes available.
patcher := &patcher{ patcher := &apply.Patcher{
mapping: obj.Info.Mapping, Mapping: obj.Info.Mapping,
helper: resource.NewHelper(obj.Info.Client, obj.Info.Mapping), Helper: resource.NewHelper(obj.Info.Client, obj.Info.Mapping),
overwrite: true, Overwrite: true,
backOff: clockwork.NewRealClock(), BackOff: clockwork.NewRealClock(),
serverDryRun: true, ServerDryRun: true,
openapiSchema: obj.OpenAPI, OpenapiSchema: obj.OpenAPI,
} }
_, result, err := patcher.patch(obj.Info.Object, modified, obj.Info.Source, obj.Info.Namespace, obj.Info.Name, nil) _, result, err := patcher.Patch(obj.Info.Object, modified, obj.Info.Source, obj.Info.Namespace, obj.Info.Name, nil)
return result, err return result, err
} }

View File

@ -161,9 +161,9 @@ func TestCordon(t *testing.T) {
m := &MyReq{req} m := &MyReq{req}
switch { switch {
case m.isFor("GET", "/nodes/node"): case m.isFor("GET", "/nodes/node"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, test.node)}, nil
case m.isFor("GET", "/nodes/bar"): case m.isFor("GET", "/nodes/bar"):
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("nope")}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("nope")}, nil
case m.isFor("PATCH", "/nodes/node"): case m.isFor("PATCH", "/nodes/node"):
data, err := ioutil.ReadAll(req.Body) data, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
@ -185,14 +185,14 @@ func TestCordon(t *testing.T) {
t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec.Unschedulable, new_node.Spec.Unschedulable) t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec.Unschedulable, new_node.Spec.Unschedulable)
} }
updated = true updated = true
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil
default: default:
t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() ioStreams, _, _, _ := genericclioptions.NewTestIOStreams()
cmd := test.cmd(tf, ioStreams) cmd := test.cmd(tf, ioStreams)
@ -719,7 +719,7 @@ func TestDrain(t *testing.T) {
apiVersions := metav1.APIVersions{ apiVersions := metav1.APIVersions{
Versions: []string{"v1"}, Versions: []string{"v1"},
} }
return genResponseWithJsonEncodedBody(apiVersions) return cmdtesting.GenResponseWithJsonEncodedBody(apiVersions)
case req.Method == "GET" && req.URL.Path == "/apis": case req.Method == "GET" && req.URL.Path == "/apis":
groupList := metav1.APIGroupList{ groupList := metav1.APIGroupList{
Groups: []metav1.APIGroup{ Groups: []metav1.APIGroup{
@ -731,7 +731,7 @@ func TestDrain(t *testing.T) {
}, },
}, },
} }
return genResponseWithJsonEncodedBody(groupList) return cmdtesting.GenResponseWithJsonEncodedBody(groupList)
case req.Method == "GET" && req.URL.Path == "/api/v1": case req.Method == "GET" && req.URL.Path == "/api/v1":
resourceList := metav1.APIResourceList{ resourceList := metav1.APIResourceList{
GroupVersion: "v1", GroupVersion: "v1",
@ -744,21 +744,21 @@ func TestDrain(t *testing.T) {
}, },
} }
} }
return genResponseWithJsonEncodedBody(resourceList) return cmdtesting.GenResponseWithJsonEncodedBody(resourceList)
case m.isFor("GET", "/nodes/node"): case m.isFor("GET", "/nodes/node"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, test.node)}, nil
case m.isFor("GET", "/namespaces/default/replicationcontrollers/rc"): case m.isFor("GET", "/namespaces/default/replicationcontrollers/rc"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &test.rcs[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &test.rcs[0])}, nil
case m.isFor("GET", "/namespaces/default/daemonsets/ds"): case m.isFor("GET", "/namespaces/default/daemonsets/ds"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &ds)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &ds)}, nil
case m.isFor("GET", "/namespaces/default/daemonsets/missing-ds"): case m.isFor("GET", "/namespaces/default/daemonsets/missing-ds"):
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &extensionsv1beta1.DaemonSet{})}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DaemonSet{})}, nil
case m.isFor("GET", "/namespaces/default/jobs/job"): case m.isFor("GET", "/namespaces/default/jobs/job"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &job)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &job)}, nil
case m.isFor("GET", "/namespaces/default/replicasets/rs"): case m.isFor("GET", "/namespaces/default/replicasets/rs"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &test.replicaSets[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &test.replicaSets[0])}, nil
case m.isFor("GET", "/namespaces/default/pods/bar"): case m.isFor("GET", "/namespaces/default/pods/bar"):
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &corev1.Pod{})}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Pod{})}, nil
case m.isFor("GET", "/pods"): case m.isFor("GET", "/pods"):
values, err := url.ParseQuery(req.URL.RawQuery) values, err := url.ParseQuery(req.URL.RawQuery)
if err != nil { if err != nil {
@ -769,9 +769,9 @@ func TestDrain(t *testing.T) {
if !reflect.DeepEqual(get_params, values) { if !reflect.DeepEqual(get_params, values) {
t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, get_params, values) t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, get_params, values)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.PodList{Items: test.pods})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.PodList{Items: test.pods})}, nil
case m.isFor("GET", "/replicationcontrollers"): case m.isFor("GET", "/replicationcontrollers"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.ReplicationControllerList{Items: test.rcs})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationControllerList{Items: test.rcs})}, nil
case m.isFor("PATCH", "/nodes/node"): case m.isFor("PATCH", "/nodes/node"):
data, err := ioutil.ReadAll(req.Body) data, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
@ -792,20 +792,20 @@ func TestDrain(t *testing.T) {
if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) {
t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec) t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil
case m.isFor("DELETE", "/namespaces/default/pods/bar"): case m.isFor("DELETE", "/namespaces/default/pods/bar"):
deleted = true deleted = true
return &http.Response{StatusCode: 204, Header: defaultHeader(), Body: objBody(codec, &test.pods[0])}, nil return &http.Response{StatusCode: 204, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &test.pods[0])}, nil
case m.isFor("POST", "/namespaces/default/pods/bar/eviction"): case m.isFor("POST", "/namespaces/default/pods/bar/eviction"):
evicted = true evicted = true
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, &policyv1beta1.Eviction{})}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &policyv1beta1.Eviction{})}, nil
default: default:
t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, _, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, _, errBuf := genericclioptions.NewTestIOStreams()
cmd := NewCmdDrain(tf, ioStreams) cmd := NewCmdDrain(tf, ioStreams)

View File

@ -38,6 +38,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/kubectl/cmd/apply"
"k8s.io/kubernetes/pkg/kubectl/cmd/create" "k8s.io/kubernetes/pkg/kubectl/cmd/create"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
@ -102,13 +103,13 @@ func TestEdit(t *testing.T) {
} }
} }
inputFile := filepath.Join("testdata/edit", "testcase-"+name, step.Input) inputFile := filepath.Join("testdata", "testcase-"+name, step.Input)
expectedInput, err := ioutil.ReadFile(inputFile) expectedInput, err := ioutil.ReadFile(inputFile)
if err != nil { if err != nil {
t.Fatalf("%s, step %d: %v", name, i, err) t.Fatalf("%s, step %d: %v", name, i, err)
} }
outputFile := filepath.Join("testdata/edit", "testcase-"+name, step.Output) outputFile := filepath.Join("testdata", "testcase-"+name, step.Output)
resultingOutput, err := ioutil.ReadFile(outputFile) resultingOutput, err := ioutil.ReadFile(outputFile)
if err != nil { if err != nil {
t.Fatalf("%s, step %d: %v", name, i, err) t.Fatalf("%s, step %d: %v", name, i, err)
@ -150,7 +151,7 @@ func TestEdit(t *testing.T) {
t.Logf("If the change in input is expected, rerun tests with %s=true to update input fixtures", updateEnvVar) t.Logf("If the change in input is expected, rerun tests with %s=true to update input fixtures", updateEnvVar)
} }
} }
return &http.Response{StatusCode: step.ResponseStatusCode, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(resultingOutput))}, nil return &http.Response{StatusCode: step.ResponseStatusCode, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader(resultingOutput))}, nil
} }
} }
@ -169,15 +170,15 @@ func TestEdit(t *testing.T) {
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
os.Setenv("KUBE_EDITOR", "testdata/edit/test_editor.sh") os.Setenv("KUBE_EDITOR", "testdata/test_editor.sh")
os.Setenv("KUBE_EDITOR_CALLBACK", server.URL+"/callback") os.Setenv("KUBE_EDITOR_CALLBACK", server.URL+"/callback")
testcases := sets.NewString() testcases := sets.NewString()
filepath.Walk("testdata/edit", func(path string, info os.FileInfo, err error) error { filepath.Walk("testdata", func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
if path == "testdata/edit" { if path == "testdata" {
return nil return nil
} }
name := filepath.Base(path) name := filepath.Base(path)
@ -199,7 +200,7 @@ func TestEdit(t *testing.T) {
i = 0 i = 0
name = testcaseName name = testcaseName
testcase = EditTestCase{} testcase = EditTestCase{}
testcaseDir := filepath.Join("testdata", "edit", "testcase-"+name) testcaseDir := filepath.Join("testdata", "testcase-"+name)
testcaseData, err := ioutil.ReadFile(filepath.Join(testcaseDir, "test.yaml")) testcaseData, err := ioutil.ReadFile(filepath.Join(testcaseDir, "test.yaml"))
if err != nil { if err != nil {
t.Fatalf("%s: %v", name, err) t.Fatalf("%s: %v", name, err)
@ -220,12 +221,12 @@ func TestEdit(t *testing.T) {
} }
return &fake.RESTClient{ return &fake.RESTClient{
VersionedAPIPath: versionedAPIPath, VersionedAPIPath: versionedAPIPath,
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(reqResp), Client: fake.CreateHTTPClient(reqResp),
}, nil }, nil
} }
tf.WithNamespace(testcase.Namespace) tf.WithNamespace(testcase.Namespace)
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams()
var cmd *cobra.Command var cmd *cobra.Command
@ -236,7 +237,7 @@ func TestEdit(t *testing.T) {
cmd = create.NewCmdCreate(tf, ioStreams) cmd = create.NewCmdCreate(tf, ioStreams)
cmd.Flags().Set("edit", "true") cmd.Flags().Set("edit", "true")
case "edit-last-applied": case "edit-last-applied":
cmd = NewCmdApplyEditLastApplied(tf, ioStreams) cmd = apply.NewCmdApplyEditLastApplied(tf, ioStreams)
default: default:
t.Fatalf("%s: unexpected mode %s", name, testcase.Mode) t.Fatalf("%s: unexpected mode %s", name, testcase.Mode)
} }

View File

@ -212,7 +212,7 @@ func (p *ExecOptions) Validate() error {
return nil return nil
} }
func (o *StreamOptions) setupTTY() term.TTY { func (o *StreamOptions) SetupTTY() term.TTY {
t := term.TTY{ t := term.TTY{
Parent: o.InterruptParent, Parent: o.InterruptParent,
Out: o.Out, Out: o.Out,
@ -288,7 +288,7 @@ func (p *ExecOptions) Run() error {
} }
// ensure we can recover the terminal while attached // ensure we can recover the terminal while attached
t := p.setupTTY() t := p.SetupTTY()
var sizeQueue remotecommand.TerminalSizeQueue var sizeQueue remotecommand.TerminalSizeQueue
if t.Raw { if t.Raw {

View File

@ -140,7 +140,7 @@ func TestPodAndContainer(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
cmd := &cobra.Command{} cmd := &cobra.Command{}
options := test.p options := test.p
@ -202,15 +202,15 @@ func TestExec(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == test.podPath && m == "GET": case p == test.podPath && m == "GET":
body := objBody(codec, test.pod) body := cmdtesting.ObjBody(codec, test.pod)
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ex := &fakeRemoteExecutor{} ex := &fakeRemoteExecutor{}
if test.execErr { if test.execErr {
ex.execErr = fmt.Errorf("exec error") ex.execErr = fmt.Errorf("exec error")
@ -280,7 +280,7 @@ func TestSetupTTY(t *testing.T) {
TTY: true, TTY: true,
} }
tty := o.setupTTY() tty := o.SetupTTY()
if o.In != nil { if o.In != nil {
t.Errorf("don't attach stdin: o.In should be nil") t.Errorf("don't attach stdin: o.In should be nil")
@ -304,7 +304,7 @@ func TestSetupTTY(t *testing.T) {
o.In = &bytes.Buffer{} o.In = &bytes.Buffer{}
o.TTY = false o.TTY = false
tty = o.setupTTY() tty = o.SetupTTY()
if o.In == nil { if o.In == nil {
t.Errorf("attach stdin, no TTY: o.In should not be nil") t.Errorf("attach stdin, no TTY: o.In should not be nil")
@ -328,7 +328,7 @@ func TestSetupTTY(t *testing.T) {
o.ErrOut = stderr o.ErrOut = stderr
o.TTY = true o.TTY = true
tty = o.setupTTY() tty = o.SetupTTY()
if o.In == nil { if o.In == nil {
t.Errorf("attach stdin, TTY, not a terminal: o.In should not be nil") t.Errorf("attach stdin, TTY, not a terminal: o.In should not be nil")
@ -363,7 +363,7 @@ func TestSetupTTY(t *testing.T) {
return true return true
} }
tty = o.setupTTY() tty = o.SetupTTY()
if o.In != overrideStdin { if o.In != overrideStdin {
t.Errorf("attach stdin, TTY, is a terminal: o.In should equal overrideStdin") t.Errorf("attach stdin, TTY, is a terminal: o.In should equal overrideStdin")

View File

@ -306,7 +306,7 @@ func TestRunExposeService(t *testing.T) {
Selector: map[string]string{"app": "go"}, Selector: map[string]string{"app": "go"},
}, },
}, },
flags: map[string]string{"filename": "../../../test/e2e/testing-manifests/guestbook/redis-master-service.yaml", "selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "dry-run": "true"}, flags: map[string]string{"filename": "../../../../test/e2e/testing-manifests/guestbook/redis-master-service.yaml", "selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "dry-run": "true"},
output: &corev1.Service{ output: &corev1.Service{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Labels: map[string]string{"svc": "test"}}, ObjectMeta: metav1.ObjectMeta{Name: "foo", Labels: map[string]string{"svc": "test"}},
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
@ -610,7 +610,7 @@ func TestRunExposeService(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == test.calls[m] && m == "GET": case p == test.calls[m] && m == "GET":
return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.input)}, nil return &http.Response{StatusCode: test.status, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, test.input)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -49,109 +49,17 @@ import (
restclientwatch "k8s.io/client-go/rest/watch" restclientwatch "k8s.io/client-go/rest/watch"
"k8s.io/kube-openapi/pkg/util/proto" "k8s.io/kube-openapi/pkg/util/proto"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
var openapiSchemaPath = filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json") var (
openapiSchemaPath = filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json")
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer grace = int64(30)
enableServiceLinks = corev1.DefaultEnableServiceLinks
var grace = int64(30) )
var enableServiceLinks = corev1.DefaultEnableServiceLinks
func defaultHeader() http.Header {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return header
}
func defaultClientConfig() *restclient.Config {
return &restclient.Config{
APIPath: "/api",
ContentConfig: restclient.ContentConfig{
NegotiatedSerializer: scheme.Codecs,
ContentType: runtime.ContentTypeJSON,
GroupVersion: &corev1.SchemeGroupVersion,
},
}
}
func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
}
func stringBody(body string) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(body)))
}
func initTestErrorHandler(t *testing.T) {
cmdutil.BehaviorOnFatal(func(str string, code int) {
t.Errorf("Error running command (exit code %d): %s", code, str)
})
}
func testData() (*corev1.PodList, *corev1.ServiceList, *corev1.ReplicationControllerList) {
pods := &corev1.PodList{
ListMeta: metav1.ListMeta{
ResourceVersion: "15",
},
Items: []corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
EnableServiceLinks: &enableServiceLinks,
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
EnableServiceLinks: &enableServiceLinks,
},
},
},
}
svc := &corev1.ServiceList{
ListMeta: metav1.ListMeta{
ResourceVersion: "16",
},
Items: []corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"},
Spec: corev1.ServiceSpec{
SessionAffinity: "None",
Type: corev1.ServiceTypeClusterIP,
},
},
},
}
one := int32(1)
rc := &corev1.ReplicationControllerList{
ListMeta: metav1.ListMeta{
ResourceVersion: "17",
},
Items: []corev1.ReplicationController{
{
ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"},
Spec: corev1.ReplicationControllerSpec{
Replicas: &one,
},
},
},
}
return pods, svc, rc
}
func testComponentStatusData() *corev1.ComponentStatusList { func testComponentStatusData() *corev1.ComponentStatusList {
good := corev1.ComponentStatus{ good := corev1.ComponentStatus{
@ -195,13 +103,13 @@ func TestGetUnknownSchemaObject(t *testing.T) {
} }
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{ Resp: &http.Response{
StatusCode: 200, Header: defaultHeader(), StatusCode: 200, Header: cmdtesting.DefaultHeader(),
Body: objBody(codec, obj), Body: cmdtesting.ObjBody(codec, obj),
}, },
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet("kubectl", tf, streams) cmd := NewCmdGet("kubectl", tf, streams)
@ -241,10 +149,10 @@ func TestGetSchemaObject(t *testing.T) {
t.Logf("%v", string(runtime.EncodeOrDie(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}))) t.Logf("%v", string(runtime.EncodeOrDie(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})))
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})},
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet("kubectl", tf, streams) cmd := NewCmdGet("kubectl", tf, streams)
@ -256,7 +164,7 @@ func TestGetSchemaObject(t *testing.T) {
} }
func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -266,8 +174,8 @@ func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) {
// for Pod type. // for Pod type.
tf.OpenAPISchemaFunc = testOpenAPISchemaData tf.OpenAPISchemaFunc = testOpenAPISchemaData
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -312,15 +220,15 @@ func testOpenAPISchemaData() (openapi.Resources, error) {
} }
func TestGetObjects(t *testing.T) { func TestGetObjects(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -337,15 +245,15 @@ foo 0/0 0 <unknown>
} }
func TestGetObjectsShowKind(t *testing.T) { func TestGetObjectsShowKind(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -363,36 +271,36 @@ pod/foo 0/0 0 <unknown>
} }
func TestGetMultipleResourceTypesShowKinds(t *testing.T) { func TestGetMultipleResourceTypesShowKinds(t *testing.T) {
pods, svcs, _ := testData() pods, svcs, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/pods" && m == "GET": case p == "/namespaces/test/pods" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case p == "/namespaces/test/replicationcontrollers" && m == "GET": case p == "/namespaces/test/replicationcontrollers" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.ReplicationControllerList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationControllerList{})}, nil
case p == "/namespaces/test/services" && m == "GET": case p == "/namespaces/test/services" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svcs)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svcs)}, nil
case p == "/namespaces/test/statefulsets" && m == "GET": case p == "/namespaces/test/statefulsets" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &appsv1.StatefulSetList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.StatefulSetList{})}, nil
case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET": case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &autoscalingv1.HorizontalPodAutoscalerList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &autoscalingv1.HorizontalPodAutoscalerList{})}, nil
case p == "/namespaces/test/jobs" && m == "GET": case p == "/namespaces/test/jobs" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &batchv1.JobList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1.JobList{})}, nil
case p == "/namespaces/test/cronjobs" && m == "GET": case p == "/namespaces/test/cronjobs" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &batchv1beta1.CronJobList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1beta1.CronJobList{})}, nil
case p == "/namespaces/test/daemonsets" && m == "GET": case p == "/namespaces/test/daemonsets" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &appsv1.DaemonSetList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.DaemonSetList{})}, nil
case p == "/namespaces/test/deployments" && m == "GET": case p == "/namespaces/test/deployments" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &extensionsv1beta1.DeploymentList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DeploymentList{})}, nil
case p == "/namespaces/test/replicasets" && m == "GET": case p == "/namespaces/test/replicasets" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &extensionsv1beta1.ReplicaSetList{})}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.ReplicaSetList{})}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
@ -418,15 +326,15 @@ service/baz ClusterIP <none> <none> <none> <unknown>
} }
func TestGetObjectsShowLabels(t *testing.T) { func TestGetObjectsShowLabels(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -444,7 +352,7 @@ foo 0/0 0 <unknown> <none>
} }
func TestGetObjectIgnoreNotFound(t *testing.T) { func TestGetObjectIgnoreNotFound(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
ns := &corev1.NamespaceList{ ns := &corev1.NamespaceList{
ListMeta: metav1.ListMeta{ ListMeta: metav1.ListMeta{
@ -463,13 +371,13 @@ func TestGetObjectIgnoreNotFound(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/pods/nonexistentpod" && m == "GET": case p == "/namespaces/test/pods/nonexistentpod" && m == "GET":
return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("")}, nil return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
case p == "/api/v1/namespaces/test" && m == "GET": case p == "/api/v1/namespaces/test" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &ns.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &ns.Items[0])}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -533,8 +441,8 @@ func TestGetSortedObjects(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
} }
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &corev1.SchemeGroupVersion}} tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &corev1.SchemeGroupVersion}}
@ -737,15 +645,15 @@ func TestRuntimeSorter(t *testing.T) {
} }
func TestGetObjectsIdentifiedByFile(t *testing.T) { func TestGetObjectsIdentifiedByFile(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -763,15 +671,15 @@ foo 0/0 0 <unknown>
} }
func TestGetListObjects(t *testing.T) { func TestGetListObjects(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -796,8 +704,8 @@ func TestGetListComponentStatus(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, statuses)}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, statuses)},
} }
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -816,7 +724,7 @@ serverunknown Unhealthy fizzbuzz error
} }
func TestGetMixedGenericObjects(t *testing.T) { func TestGetMixedGenericObjects(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
// ensure that a runtime.Object without // ensure that a runtime.Object without
// an ObjectMeta field is handled properly // an ObjectMeta field is handled properly
@ -836,18 +744,18 @@ func TestGetMixedGenericObjects(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, structuredObj)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, structuredObj)}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet("kubectl", tf, streams) cmd := NewCmdGet("kubectl", tf, streams)
@ -878,20 +786,20 @@ func TestGetMixedGenericObjects(t *testing.T) {
} }
func TestGetMultipleTypeObjects(t *testing.T) { func TestGetMultipleTypeObjects(t *testing.T) {
pods, svc, _ := testData() pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services": case "/namespaces/test/services":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -916,27 +824,27 @@ service/baz ClusterIP <none> <none> <none> <unknown>
} }
func TestGetMultipleTypeObjectsAsList(t *testing.T) { func TestGetMultipleTypeObjectsAsList(t *testing.T) {
pods, svc, _ := testData() pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services": case "/namespaces/test/services":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet("kubectl", tf, streams) cmd := NewCmdGet("kubectl", tf, streams)
@ -1017,23 +925,23 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
} }
func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) {
pods, svc, _ := testData() pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
} }
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services": case "/namespaces/test/services":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -1060,23 +968,23 @@ service/baz ClusterIP <none> <none> <none> <unknown>
} }
func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) {
pods, svc, _ := testData() pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" { if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
} }
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services": case "/namespaces/test/services":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -1103,7 +1011,7 @@ service/baz ClusterIP <none> <none> <none> <unknown>
} }
func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
node := &corev1.Node{ node := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "foo", Name: "foo",
@ -1115,13 +1023,13 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/nodes/foo": case "/nodes/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, node)}, nil
case "/namespaces/test/services/bar": case "/namespaces/test/services/bar":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -1265,7 +1173,7 @@ func TestWatchLabelSelector(t *testing.T) {
}, },
} }
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" { if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
@ -1273,9 +1181,9 @@ func TestWatchLabelSelector(t *testing.T) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" { if req.URL.Query().Get("watch") == "true" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -1316,7 +1224,7 @@ func TestWatchFieldSelector(t *testing.T) {
}, },
} }
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" { if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
@ -1324,9 +1232,9 @@ func TestWatchFieldSelector(t *testing.T) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" { if req.URL.Query().Get("watch") == "true" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -1361,14 +1269,14 @@ func TestWatchResource(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
case "/namespaces/test/pods": case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" { if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
} }
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -1404,14 +1312,14 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
case "/namespaces/test/replicationcontrollers": case "/namespaces/test/replicationcontrollers":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" { if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
} }
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -1448,14 +1356,14 @@ func TestWatchOnlyResource(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods[1])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
case "/namespaces/test/pods": case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" { if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[1:])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
} }
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil
@ -1496,14 +1404,14 @@ func TestWatchOnlyList(t *testing.T) {
}, },
} }
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" { if req.URL.Query().Get("watch") == "true" {
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
default: default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req) t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil return nil, nil

View File

@ -27,6 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
@ -324,7 +325,7 @@ func TestLabelErrors(t *testing.T) {
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, _, _ := genericclioptions.NewTestIOStreams() ioStreams, _, _, _ := genericclioptions.NewTestIOStreams()
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
@ -354,20 +355,20 @@ func TestLabelErrors(t *testing.T) {
} }
func TestLabelForResourceFromFile(t *testing.T) { func TestLabelForResourceFromFile(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -375,7 +376,7 @@ func TestLabelForResourceFromFile(t *testing.T) {
case "PATCH": case "PATCH":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/replicationcontrollers/cassandra": case "/namespaces/test/replicationcontrollers/cassandra":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -386,12 +387,12 @@ func TestLabelForResourceFromFile(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdLabel(tf, ioStreams) cmd := NewCmdLabel(tf, ioStreams)
opts := NewLabelOptions(ioStreams) opts := NewLabelOptions(ioStreams)
opts.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} opts.Filenames = []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}
err := opts.Complete(tf, cmd, []string{"a=b"}) err := opts.Complete(tf, cmd, []string{"a=b"})
if err == nil { if err == nil {
err = opts.Validate() err = opts.Validate()
@ -412,18 +413,18 @@ func TestLabelLocal(t *testing.T) {
defer tf.Cleanup() defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
return nil, nil return nil, nil
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdLabel(tf, ioStreams) cmd := NewCmdLabel(tf, ioStreams)
opts := NewLabelOptions(ioStreams) opts := NewLabelOptions(ioStreams)
opts.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} opts.Filenames = []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}
opts.local = true opts.local = true
err := opts.Complete(tf, cmd, []string{"a=b"}) err := opts.Complete(tf, cmd, []string{"a=b"})
if err == nil { if err == nil {
@ -441,20 +442,20 @@ func TestLabelLocal(t *testing.T) {
} }
func TestLabelMultipleObjects(t *testing.T) { func TestLabelMultipleObjects(t *testing.T) {
pods, _, _ := testData() pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.Method { switch req.Method {
case "GET": case "GET":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods": case "/namespaces/test/pods":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -462,9 +463,9 @@ func TestLabelMultipleObjects(t *testing.T) {
case "PATCH": case "PATCH":
switch req.URL.Path { switch req.URL.Path {
case "/namespaces/test/pods/foo": case "/namespaces/test/pods/foo":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])}, nil
case "/namespaces/test/pods/bar": case "/namespaces/test/pods/bar":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[1])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[1])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -475,7 +476,7 @@ func TestLabelMultipleObjects(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
opts := NewLabelOptions(ioStreams) opts := NewLabelOptions(ioStreams)

View File

@ -75,6 +75,10 @@ var (
logsUsageErrStr = fmt.Sprintf("expected '%s'.\nPOD or TYPE/NAME is a required argument for the logs command", logsUsageStr) logsUsageErrStr = fmt.Sprintf("expected '%s'.\nPOD or TYPE/NAME is a required argument for the logs command", logsUsageStr)
) )
const (
defaultPodLogsTimeout = 20 * time.Second
)
type LogsOptions struct { type LogsOptions struct {
Namespace string Namespace string
ResourceArg string ResourceArg string
@ -126,7 +130,7 @@ func NewCmdLogs(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C
Example: logsExample, Example: logsExample,
PreRun: func(cmd *cobra.Command, args []string) { PreRun: func(cmd *cobra.Command, args []string) {
if len(os.Args) > 1 && os.Args[1] == "log" { if len(os.Args) > 1 && os.Args[1] == "log" {
printDeprecationWarning(o.ErrOut, "logs", "log") fmt.Fprintf(o.ErrOut, "%s is DEPRECATED and will be removed in a future version. Use %s instead.\n", "log", "logs")
} }
}, },
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {

View File

@ -22,13 +22,14 @@ import (
"testing" "testing"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
func TestPatchObject(t *testing.T) { func TestPatchObject(t *testing.T) {
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -36,7 +37,7 @@ func TestPatchObject(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"):
@ -47,7 +48,7 @@ func TestPatchObject(t *testing.T) {
if m == "PATCH" { if m == "PATCH" {
obj.Spec.Type = "NodePort" obj.Spec.Type = "NodePort"
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &obj)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &obj)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -69,7 +70,7 @@ func TestPatchObject(t *testing.T) {
} }
func TestPatchObjectFromFile(t *testing.T) { func TestPatchObjectFromFile(t *testing.T) {
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -77,11 +78,11 @@ func TestPatchObjectFromFile(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -94,7 +95,7 @@ func TestPatchObjectFromFile(t *testing.T) {
cmd.Flags().Set("namespace", "test") cmd.Flags().Set("namespace", "test")
cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
// uses the name from the response // uses the name from the response
@ -104,7 +105,7 @@ func TestPatchObjectFromFile(t *testing.T) {
} }
func TestPatchNoop(t *testing.T) { func TestPatchNoop(t *testing.T) {
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
getObject := &svc.Items[0] getObject := &svc.Items[0]
patchObject := &svc.Items[0] patchObject := &svc.Items[0]
@ -114,13 +115,13 @@ func TestPatchNoop(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services/frontend" && m == "PATCH": case p == "/namespaces/test/services/frontend" && m == "PATCH":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, patchObject)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, patchObject)}, nil
case p == "/namespaces/test/services/frontend" && m == "GET": case p == "/namespaces/test/services/frontend" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, getObject)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, getObject)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -147,7 +148,7 @@ func TestPatchNoop(t *testing.T) {
} }
func TestPatchObjectFromFileOutput(t *testing.T) { func TestPatchObjectFromFileOutput(t *testing.T) {
_, svc, _ := testData() _, svc, _ := cmdtesting.TestData()
svcCopy := svc.Items[0].DeepCopy() svcCopy := svc.Items[0].DeepCopy()
if svcCopy.Labels == nil { if svcCopy.Labels == nil {
@ -161,13 +162,13 @@ func TestPatchObjectFromFileOutput(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/services/frontend" && m == "GET": case p == "/namespaces/test/services/frontend" && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
case p == "/namespaces/test/services/frontend" && m == "PATCH": case p == "/namespaces/test/services/frontend" && m == "PATCH":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svcCopy)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svcCopy)}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -180,7 +181,7 @@ func TestPatchObjectFromFileOutput(t *testing.T) {
cmd.Flags().Set("namespace", "test") cmd.Flags().Set("namespace", "test")
cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`)
cmd.Flags().Set("output", "yaml") cmd.Flags().Set("output", "yaml")
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
t.Log(buf.String()) t.Log(buf.String())

View File

@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
@ -85,15 +86,15 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == test.podPath && m == "GET": case p == test.podPath && m == "GET":
body := objBody(codec, test.pod) body := cmdtesting.ObjBody(codec, test.pod)
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
ff := &fakePortForwarder{} ff := &fakePortForwarder{}
if test.pfErr { if test.pfErr {
ff.pfErr = fmt.Errorf("pf error") ff.pfErr = fmt.Errorf("pf error")
@ -354,3 +355,21 @@ func TestTranslateServicePortToTargetPort(t *testing.T) {
} }
} }
} }
func execPod() *corev1.Pod {
return &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
Containers: []corev1.Container{
{
Name: "bar",
},
},
},
Status: corev1.PodStatus{
Phase: corev1.PodRunning,
},
}
}

View File

@ -33,6 +33,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/delete"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
@ -67,10 +68,10 @@ var (
type ReplaceOptions struct { type ReplaceOptions struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
DeleteFlags *DeleteFlags
RecordFlags *genericclioptions.RecordFlags RecordFlags *genericclioptions.RecordFlags
DeleteOptions *DeleteOptions DeleteFlags *delete.DeleteFlags
DeleteOptions *delete.DeleteOptions
PrintObj func(obj runtime.Object) error PrintObj func(obj runtime.Object) error
@ -92,7 +93,7 @@ type ReplaceOptions struct {
func NewReplaceOptions(streams genericclioptions.IOStreams) *ReplaceOptions { func NewReplaceOptions(streams genericclioptions.IOStreams) *ReplaceOptions {
return &ReplaceOptions{ return &ReplaceOptions{
PrintFlags: genericclioptions.NewPrintFlags("replaced"), PrintFlags: genericclioptions.NewPrintFlags("replaced"),
DeleteFlags: NewDeleteFlags("to use to replace the resource."), DeleteFlags: delete.NewDeleteFlags("to use to replace the resource."),
IOStreams: streams, IOStreams: streams,
} }

View File

@ -23,13 +23,14 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
func TestReplaceObject(t *testing.T) { func TestReplaceObject(t *testing.T) {
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -37,24 +38,24 @@ func TestReplaceObject(t *testing.T) {
deleted := false deleted := false
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api/v1/namespaces/test" && m == http.MethodGet: case p == "/api/v1/namespaces/test" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete: case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete:
deleted = true deleted = true
fallthrough fallthrough
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut: case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet: case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet:
statusCode := http.StatusOK statusCode := http.StatusOK
if deleted { if deleted {
statusCode = http.StatusNotFound statusCode = http.StatusNotFound
} }
return &http.Response{StatusCode: statusCode, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -64,7 +65,7 @@ func TestReplaceObject(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdReplace(tf, streams) cmd := NewCmdReplace(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
@ -85,7 +86,7 @@ func TestReplaceObject(t *testing.T) {
} }
func TestReplaceMultipleObject(t *testing.T) { func TestReplaceMultipleObject(t *testing.T) {
_, svc, rc := testData() _, svc, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -94,37 +95,37 @@ func TestReplaceMultipleObject(t *testing.T) {
redisMasterDeleted := false redisMasterDeleted := false
frontendDeleted := false frontendDeleted := false
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api/v1/namespaces/test" && m == http.MethodGet: case p == "/api/v1/namespaces/test" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete: case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete:
redisMasterDeleted = true redisMasterDeleted = true
fallthrough fallthrough
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut: case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet: case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet:
statusCode := http.StatusOK statusCode := http.StatusOK
if redisMasterDeleted { if redisMasterDeleted {
statusCode = http.StatusNotFound statusCode = http.StatusNotFound
} }
return &http.Response{StatusCode: statusCode, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case p == "/namespaces/test/services/frontend" && m == http.MethodDelete: case p == "/namespaces/test/services/frontend" && m == http.MethodDelete:
frontendDeleted = true frontendDeleted = true
fallthrough fallthrough
case p == "/namespaces/test/services/frontend" && m == http.MethodPut: case p == "/namespaces/test/services/frontend" && m == http.MethodPut:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
case p == "/namespaces/test/services/frontend" && m == http.MethodGet: case p == "/namespaces/test/services/frontend" && m == http.MethodGet:
statusCode := http.StatusOK statusCode := http.StatusOK
if frontendDeleted { if frontendDeleted {
statusCode = http.StatusNotFound statusCode = http.StatusNotFound
} }
return &http.Response{StatusCode: statusCode, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
case p == "/namespaces/test/services" && m == http.MethodPost: case p == "/namespaces/test/services" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -134,8 +135,8 @@ func TestReplaceMultipleObject(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdReplace(tf, streams) cmd := NewCmdReplace(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/frontend-service.yaml")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
@ -155,7 +156,7 @@ func TestReplaceMultipleObject(t *testing.T) {
} }
func TestReplaceDirectory(t *testing.T) { func TestReplaceDirectory(t *testing.T) {
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
@ -163,25 +164,25 @@ func TestReplaceDirectory(t *testing.T) {
created := map[string]bool{} created := map[string]bool{}
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api/v1/namespaces/test" && m == http.MethodGet: case p == "/api/v1/namespaces/test" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodPut: case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodPut:
created[p] = true created[p] = true
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodGet: case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodGet:
statusCode := http.StatusNotFound statusCode := http.StatusNotFound
if created[p] { if created[p] {
statusCode = http.StatusOK statusCode = http.StatusOK
} }
return &http.Response{StatusCode: statusCode, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodDelete: case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodDelete:
delete(created, p) delete(created, p)
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers") && m == http.MethodPost: case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers") && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -191,7 +192,7 @@ func TestReplaceDirectory(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdReplace(tf, streams) cmd := NewCmdReplace(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy")
cmd.Flags().Set("namespace", "test") cmd.Flags().Set("namespace", "test")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{}) cmd.Run(cmd, []string{})
@ -212,22 +213,22 @@ func TestReplaceDirectory(t *testing.T) {
} }
func TestForceReplaceObjectNotFound(t *testing.T) { func TestForceReplaceObjectNotFound(t *testing.T) {
_, _, rc := testData() _, _, rc := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test") tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup() defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{ tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer, NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api/v1/namespaces/test" && m == http.MethodGet: case p == "/api/v1/namespaces/test" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, &corev1.Namespace{})}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == http.MethodGet || m == http.MethodDelete): case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == http.MethodGet || m == http.MethodDelete):
return &http.Response{StatusCode: http.StatusNotFound, Header: defaultHeader(), Body: stringBody("")}, nil return &http.Response{StatusCode: http.StatusNotFound, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost: case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
return &http.Response{StatusCode: http.StatusCreated, Header: defaultHeader(), Body: objBody(codec, &rc.Items[0])}, nil return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -237,7 +238,7 @@ func TestForceReplaceObjectNotFound(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdReplace(tf, streams) cmd := NewCmdReplace(tf, streams)
cmd.Flags().Set("filename", "../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml")
cmd.Flags().Set("force", "true") cmd.Flags().Set("force", "true")
cmd.Flags().Set("cascade", "false") cmd.Flags().Set("cascade", "false")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")

View File

@ -72,10 +72,10 @@ var (
kubectl rolling-update frontend-v1 frontend-v2 --rollback`)) kubectl rolling-update frontend-v1 frontend-v2 --rollback`))
) )
var ( const (
updatePeriod, _ = time.ParseDuration("1m0s") updatePeriod = 1 * time.Minute
timeout, _ = time.ParseDuration("5m0s") timeout = 5 * time.Minute
pollInterval, _ = time.ParseDuration("3s") pollInterval = 3 * time.Second
) )
type RollingUpdateOptions struct { type RollingUpdateOptions struct {

View File

@ -53,7 +53,7 @@ func TestRolloutPause(t *testing.T) {
responseDeployment := &extensionsv1beta1.Deployment{} responseDeployment := &extensionsv1beta1.Deployment{}
responseDeployment.Name = deploymentName responseDeployment.Name = deploymentName
body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseDeployment)))) body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, responseDeployment))))
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil return nil, nil
@ -113,9 +113,3 @@ func (c *RolloutPauseRESTClient) Patch(pt types.PatchType) *restclient.Request {
} }
return restclient.NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0) return restclient.NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, c.VersionedAPIPath, config, serializers, nil, nil, 0)
} }
func defaultHeader() http.Header {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return header
}

View File

@ -39,6 +39,10 @@ import (
corev1client "k8s.io/client-go/kubernetes/typed/core/v1" corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
watchtools "k8s.io/client-go/tools/watch" watchtools "k8s.io/client-go/tools/watch"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/attach"
"k8s.io/kubernetes/pkg/kubectl/cmd/delete"
"k8s.io/kubernetes/pkg/kubectl/cmd/exec"
"k8s.io/kubernetes/pkg/kubectl/cmd/logs"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
@ -92,16 +96,23 @@ var (
kubectl run pi --schedule="0/5 * * * ?" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'`)) kubectl run pi --schedule="0/5 * * * ?" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'`))
) )
const (
defaultPodAttachTimeout = 60 * time.Second
)
var metadataAccessor = meta.NewAccessor()
type RunObject struct { type RunObject struct {
Object runtime.Object Object runtime.Object
Mapping *meta.RESTMapping Mapping *meta.RESTMapping
} }
type RunOptions struct { type RunOptions struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
DeleteFlags *DeleteFlags RecordFlags *genericclioptions.RecordFlags
DeleteOptions *DeleteOptions
RecordFlags *genericclioptions.RecordFlags DeleteFlags *delete.DeleteFlags
DeleteOptions *delete.DeleteOptions
DryRun bool DryRun bool
@ -128,7 +139,7 @@ type RunOptions struct {
func NewRunOptions(streams genericclioptions.IOStreams) *RunOptions { func NewRunOptions(streams genericclioptions.IOStreams) *RunOptions {
return &RunOptions{ return &RunOptions{
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme), PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
DeleteFlags: NewDeleteFlags("to use to replace the resource."), DeleteFlags: delete.NewDeleteFlags("to use to replace the resource."),
RecordFlags: genericclioptions.NewRecordFlags(), RecordFlags: genericclioptions.NewRecordFlags(),
Recorder: genericclioptions.NoopRecorder{}, Recorder: genericclioptions.NoopRecorder{},
@ -369,8 +380,8 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e
defer o.removeCreatedObjects(f, createdObjects) defer o.removeCreatedObjects(f, createdObjects)
} }
opts := &AttachOptions{ opts := &attach.AttachOptions{
StreamOptions: StreamOptions{ StreamOptions: exec.StreamOptions{
IOStreams: o.IOStreams, IOStreams: o.IOStreams,
Stdin: o.Interactive, Stdin: o.Interactive,
TTY: o.TTY, TTY: o.TTY,
@ -379,14 +390,14 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e
GetPodTimeout: timeout, GetPodTimeout: timeout,
CommandName: cmd.Parent().CommandPath() + " attach", CommandName: cmd.Parent().CommandPath() + " attach",
Attach: &DefaultRemoteAttach{}, Attach: &attach.DefaultRemoteAttach{},
} }
config, err := f.ToRESTConfig() config, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
opts.Config = config opts.Config = config
opts.AttachFunc = defaultAttachFunc opts.AttachFunc = attach.DefaultAttachFunc
clientset, err := kubernetes.NewForConfig(config) clientset, err := kubernetes.NewForConfig(config)
if err != nil { if err != nil {
@ -504,7 +515,7 @@ func waitForPod(podClient corev1client.PodsGetter, ns, name string, exitConditio
return result, err return result, err
} }
func handleAttachPod(f cmdutil.Factory, podClient corev1client.PodsGetter, ns, name string, opts *AttachOptions) error { func handleAttachPod(f cmdutil.Factory, podClient corev1client.PodsGetter, ns, name string, opts *attach.AttachOptions) error {
pod, err := waitForPod(podClient, ns, name, kubectl.PodRunningAndReady) pod, err := waitForPod(podClient, ns, name, kubectl.PodRunningAndReady)
if err != nil && err != kubectl.ErrPodCompleted { if err != nil && err != kubectl.ErrPodCompleted {
return err return err
@ -519,7 +530,7 @@ func handleAttachPod(f cmdutil.Factory, podClient corev1client.PodsGetter, ns, n
opts.Namespace = ns opts.Namespace = ns
if opts.AttachFunc == nil { if opts.AttachFunc == nil {
opts.AttachFunc = defaultAttachFunc opts.AttachFunc = attach.DefaultAttachFunc
} }
if err := opts.Run(); err != nil { if err := opts.Run(); err != nil {
@ -530,7 +541,7 @@ func handleAttachPod(f cmdutil.Factory, podClient corev1client.PodsGetter, ns, n
} }
// logOpts logs output from opts to the pods log. // logOpts logs output from opts to the pods log.
func logOpts(restClientGetter genericclioptions.RESTClientGetter, pod *corev1.Pod, opts *AttachOptions) error { func logOpts(restClientGetter genericclioptions.RESTClientGetter, pod *corev1.Pod, opts *attach.AttachOptions) error {
ctrName, err := opts.GetContainerName(pod) ctrName, err := opts.GetContainerName(pod)
if err != nil { if err != nil {
return err return err
@ -541,7 +552,7 @@ func logOpts(restClientGetter genericclioptions.RESTClientGetter, pod *corev1.Po
return err return err
} }
for _, request := range requests { for _, request := range requests {
if err := DefaultConsumeRequest(request, opts.Out); err != nil { if err := logs.DefaultConsumeRequest(request, opts.Out); err != nil {
return err return err
} }
} }

View File

@ -36,6 +36,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/kubectl/cmd/delete"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
@ -174,7 +175,7 @@ func TestRunArgsFollowDashRules(t *testing.T) {
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if req.URL.Path == "/namespaces/test/replicationcontrollers" { if req.URL.Path == "/namespaces/test/replicationcontrollers" {
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, rc)}, nil return &http.Response{StatusCode: 201, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, rc)}, nil
} }
return &http.Response{ return &http.Response{
StatusCode: http.StatusOK, StatusCode: http.StatusOK,
@ -196,7 +197,7 @@ func TestRunArgsFollowDashRules(t *testing.T) {
return return
} }
deleteFlags := NewDeleteFlags("to use to replace the resource.") deleteFlags := delete.NewDeleteFlags("to use to replace the resource.")
opts := &RunOptions{ opts := &RunOptions{
PrintFlags: printFlags, PrintFlags: printFlags,
DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()), DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()),
@ -328,7 +329,7 @@ func TestGenerateService(t *testing.T) {
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
ns := scheme.Codecs ns := scheme.Codecs
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
GroupVersion: corev1.SchemeGroupVersion, GroupVersion: corev1.SchemeGroupVersion,
NegotiatedSerializer: ns, NegotiatedSerializer: ns,
@ -336,7 +337,7 @@ func TestGenerateService(t *testing.T) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case test.expectPOST && m == "POST" && p == "/namespaces/test/services": case test.expectPOST && m == "POST" && p == "/namespaces/test/services":
sawPOST = true sawPOST = true
body := objBody(codec, &test.service) body := cmdtesting.ObjBody(codec, &test.service)
data, err := ioutil.ReadAll(req.Body) data, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -352,7 +353,7 @@ func TestGenerateService(t *testing.T) {
if !apiequality.Semantic.DeepEqual(&test.service, svc) { if !apiequality.Semantic.DeepEqual(&test.service, svc) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc) t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")
@ -368,7 +369,7 @@ func TestGenerateService(t *testing.T) {
} }
ioStreams, _, buff, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buff, _ := genericclioptions.NewTestIOStreams()
deleteFlags := NewDeleteFlags("to use to replace the resource.") deleteFlags := delete.NewDeleteFlags("to use to replace the resource.")
opts := &RunOptions{ opts := &RunOptions{
PrintFlags: printFlags, PrintFlags: printFlags,
DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()), DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()),
@ -506,9 +507,9 @@ func TestRunValidations(t *testing.T) {
_, _, codec := cmdtesting.NewExternalScheme() _, _, codec := cmdtesting.NewExternalScheme()
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
NegotiatedSerializer: scheme.Codecs, NegotiatedSerializer: scheme.Codecs,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", ""))}, Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, cmdtesting.NewInternalType("", "", ""))},
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, _, bufErr := genericclioptions.NewTestIOStreams() streams, _, _, bufErr := genericclioptions.NewTestIOStreams()
cmdutil.BehaviorOnFatal(func(str string, code int) { cmdutil.BehaviorOnFatal(func(str string, code int) {

View File

@ -64,6 +64,10 @@ var (
kubectl scale --replicas=3 statefulset/web`)) kubectl scale --replicas=3 statefulset/web`))
) )
const (
timeout = 5 * time.Minute
)
type ScaleOptions struct { type ScaleOptions struct {
FilenameOptions resource.FilenameOptions FilenameOptions resource.FilenameOptions
RecordFlags *genericclioptions.RecordFlags RecordFlags *genericclioptions.RecordFlags

View File

@ -452,7 +452,7 @@ func TestSetEnvRemote(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == input.path && m == http.MethodGet: case p == input.path && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
case p == input.path && m == http.MethodPatch: case p == input.path && m == http.MethodPatch:
stream, err := req.GetBody() stream, err := req.GetBody()
if err != nil { if err != nil {
@ -463,7 +463,7 @@ func TestSetEnvRemote(t *testing.T) {
return nil, err return nil, err
} }
assert.Contains(t, string(bytes), `"value":`+`"`+"prod"+`"`, fmt.Sprintf("env not updated for %#v", input.object)) assert.Contains(t, string(bytes), `"value":`+`"`+"prod"+`"`, fmt.Sprintf("env not updated for %#v", input.object))
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")
@ -587,11 +587,11 @@ func TestSetEnvFromResource(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/namespaces/test/configmaps/testconfigmap" && m == http.MethodGet: case p == "/namespaces/test/configmaps/testconfigmap" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockConfigMap)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(mockConfigMap)}, nil
case p == "/namespaces/test/secrets/testsecret" && m == http.MethodGet: case p == "/namespaces/test/secrets/testsecret" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockSecret)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(mockSecret)}, nil
case p == "/namespaces/test/deployments/nginx" && m == http.MethodGet: case p == "/namespaces/test/deployments/nginx" && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockDeployment)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(mockDeployment)}, nil
case p == "/namespaces/test/deployments/nginx" && m == http.MethodPatch: case p == "/namespaces/test/deployments/nginx" && m == http.MethodPatch:
stream, err := req.GetBody() stream, err := req.GetBody()
if err != nil { if err != nil {
@ -607,7 +607,7 @@ func TestSetEnvFromResource(t *testing.T) {
for _, exclude := range input.assertExcludes { for _, exclude := range input.assertExcludes {
assert.NotContains(t, string(bytes), exclude) assert.NotContains(t, string(bytes), exclude)
} }
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(mockDeployment)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(mockDeployment)}, nil
default: default:
t.Errorf("%s: unexpected request: %#v\n%#v", input.name, req.URL, req) t.Errorf("%s: unexpected request: %#v\n%#v", input.name, req.URL, req)
return nil, nil return nil, nil

View File

@ -535,7 +535,7 @@ func TestSetImageRemote(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == input.path && m == http.MethodGet: case p == input.path && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
case p == input.path && m == http.MethodPatch: case p == input.path && m == http.MethodPatch:
stream, err := req.GetBody() stream, err := req.GetBody()
if err != nil { if err != nil {
@ -546,7 +546,7 @@ func TestSetImageRemote(t *testing.T) {
return nil, err return nil, err
} }
assert.Contains(t, string(bytes), `"image":`+`"`+"thingy"+`"`, fmt.Sprintf("image not updated for %#v", input.object)) assert.Contains(t, string(bytes), `"image":`+`"`+"thingy"+`"`, fmt.Sprintf("image not updated for %#v", input.object))
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")

View File

@ -475,7 +475,7 @@ func TestSetResourcesRemote(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == input.path && m == http.MethodGet: case p == input.path && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
case p == input.path && m == http.MethodPatch: case p == input.path && m == http.MethodPatch:
stream, err := req.GetBody() stream, err := req.GetBody()
if err != nil { if err != nil {
@ -486,7 +486,7 @@ func TestSetResourcesRemote(t *testing.T) {
return nil, err return nil, err
} }
assert.Contains(t, string(bytes), "200m", fmt.Sprintf("resources not updated for %#v", input.object)) assert.Contains(t, string(bytes), "200m", fmt.Sprintf("resources not updated for %#v", input.object))
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", "resources", req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", "resources", req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")

View File

@ -17,7 +17,6 @@ limitations under the License.
package set package set
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -327,7 +326,7 @@ func TestSetServiceAccountRemote(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == input.path && m == http.MethodGet: case p == input.path && m == http.MethodGet:
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
case p == input.path && m == http.MethodPatch: case p == input.path && m == http.MethodPatch:
stream, err := req.GetBody() stream, err := req.GetBody()
if err != nil { if err != nil {
@ -338,7 +337,7 @@ func TestSetServiceAccountRemote(t *testing.T) {
return nil, err return nil, err
} }
assert.Contains(t, string(bytes), `"serviceAccountName":`+`"`+serviceAccount+`"`, fmt.Sprintf("serviceaccount not updated for %#v", input.object)) assert.Contains(t, string(bytes), `"serviceAccountName":`+`"`+serviceAccount+`"`, fmt.Sprintf("serviceaccount not updated for %#v", input.object))
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(input.object)}, nil return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
default: default:
t.Errorf("%s: unexpected request: %s %#v\n%#v", "serviceaccount", req.Method, req.URL, req) t.Errorf("%s: unexpected request: %s %#v\n%#v", "serviceaccount", req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request") return nil, fmt.Errorf("unexpected request")
@ -403,15 +402,5 @@ func TestServiceAccountValidation(t *testing.T) {
} }
func objBody(obj runtime.Object) io.ReadCloser { func objBody(obj runtime.Object) io.ReadCloser {
return bytesBody([]byte(runtime.EncodeOrDie(scheme.DefaultJSONEncoder(), obj))) return cmdtesting.BytesBody([]byte(runtime.EncodeOrDie(scheme.DefaultJSONEncoder(), obj)))
}
func defaultHeader() http.Header {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return header
}
func bytesBody(bodyBytes []byte) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader(bodyBytes))
} }

View File

@ -20,6 +20,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"reflect" "reflect"
"strings"
"testing" "testing"
"time" "time"
@ -251,9 +252,9 @@ func TestTaint(t *testing.T) {
m := &MyReq{req} m := &MyReq{req}
switch { switch {
case m.isFor("GET", "/nodes"): case m.isFor("GET", "/nodes"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, oldNode)}, nil
case m.isFor("GET", "/nodes/node-name"): case m.isFor("GET", "/nodes/node-name"):
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, oldNode)}, nil
case m.isFor("PATCH", "/nodes/node-name"): case m.isFor("PATCH", "/nodes/node-name"):
tainted = true tainted = true
data, err := ioutil.ReadAll(req.Body) data, err := ioutil.ReadAll(req.Body)
@ -279,7 +280,7 @@ func TestTaint(t *testing.T) {
if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) {
t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil
case m.isFor("PUT", "/nodes/node-name"): case m.isFor("PUT", "/nodes/node-name"):
tainted = true tainted = true
data, err := ioutil.ReadAll(req.Body) data, err := ioutil.ReadAll(req.Body)
@ -293,14 +294,14 @@ func TestTaint(t *testing.T) {
if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) {
t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, new_node)}, nil
default: default:
t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
cmd := NewCmdTaint(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd := NewCmdTaint(tf, genericclioptions.NewTestIOStreamsDiscard())
@ -386,3 +387,16 @@ func TestValidateFlags(t *testing.T) {
} }
} }
} }
type MyReq struct {
Request *http.Request
}
func (m *MyReq) isFor(method string, path string) bool {
req := m.Request
return method == req.Method && (req.URL.Path == path ||
req.URL.Path == strings.Join([]string{"/api/v1", path}, "") ||
req.URL.Path == strings.Join([]string{"/apis/extensions/v1beta1", path}, "") ||
req.URL.Path == strings.Join([]string{"/apis/batch/v1", path}, ""))
}

View File

@ -0,0 +1,146 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
restclient "k8s.io/client-go/rest"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme"
)
var (
grace = int64(30)
enableServiceLinks = corev1.DefaultEnableServiceLinks
)
func DefaultHeader() http.Header {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return header
}
func DefaultClientConfig() *restclient.Config {
return &restclient.Config{
APIPath: "/api",
ContentConfig: restclient.ContentConfig{
NegotiatedSerializer: scheme.Codecs,
ContentType: runtime.ContentTypeJSON,
GroupVersion: &corev1.SchemeGroupVersion,
},
}
}
func ObjBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
}
func BytesBody(bodyBytes []byte) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader(bodyBytes))
}
func StringBody(body string) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(body)))
}
func TestData() (*corev1.PodList, *corev1.ServiceList, *corev1.ReplicationControllerList) {
pods := &corev1.PodList{
ListMeta: metav1.ListMeta{
ResourceVersion: "15",
},
Items: []corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
EnableServiceLinks: &enableServiceLinks,
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
DNSPolicy: corev1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace,
SecurityContext: &corev1.PodSecurityContext{},
EnableServiceLinks: &enableServiceLinks,
},
},
},
}
svc := &corev1.ServiceList{
ListMeta: metav1.ListMeta{
ResourceVersion: "16",
},
Items: []corev1.Service{
{
ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"},
Spec: corev1.ServiceSpec{
SessionAffinity: "None",
Type: corev1.ServiceTypeClusterIP,
},
},
},
}
one := int32(1)
rc := &corev1.ReplicationControllerList{
ListMeta: metav1.ListMeta{
ResourceVersion: "17",
},
Items: []corev1.ReplicationController{
{
ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"},
Spec: corev1.ReplicationControllerSpec{
Replicas: &one,
},
},
},
}
return pods, svc, rc
}
func GenResponseWithJsonEncodedBody(bodyStruct interface{}) (*http.Response, error) {
jsonBytes, err := json.Marshal(bodyStruct)
if err != nil {
return nil, err
}
return &http.Response{StatusCode: 200, Header: DefaultHeader(), Body: BytesBody(jsonBytes)}, nil
}
func InitTestErrorHandler(t *testing.T) {
cmdutil.BehaviorOnFatal(func(str string, code int) {
t.Errorf("Error running command (exit code %d): %s", code, str)
})
}
func Int32ptr(val int) *int32 {
t := int32(val)
return &t
}

View File

@ -44,7 +44,7 @@ const (
) )
func TestTopNodeAllMetrics(t *testing.T) { func TestTopNodeAllMetrics(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
metrics, nodes := testNodeV1alpha1MetricsData() metrics, nodes := testNodeV1alpha1MetricsData()
expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion)
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
@ -60,24 +60,24 @@ func TestTopNodeAllMetrics(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
case p == expectedMetricsPath && m == "GET": case p == expectedMetricsPath && m == "GET":
body, err := marshallBody(metrics) body, err := marshallBody(metrics)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, nodes)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, nodes)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedMetricsPath) t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedMetricsPath)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopNode(tf, nil, streams) cmd := NewCmdTopNode(tf, nil, streams)
@ -100,7 +100,7 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) {
customBaseHeapsterServiceAddress := "/api/v1/namespaces/custom-namespace/services/https:custom-heapster-service:/proxy" customBaseHeapsterServiceAddress := "/api/v1/namespaces/custom-namespace/services/https:custom-heapster-service:/proxy"
customBaseMetricsAddress := customBaseHeapsterServiceAddress + "/apis/metrics" customBaseMetricsAddress := customBaseHeapsterServiceAddress + "/apis/metrics"
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
metrics, nodes := testNodeV1alpha1MetricsData() metrics, nodes := testNodeV1alpha1MetricsData()
expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsApiVersion) expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsApiVersion)
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
@ -116,24 +116,24 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
case p == expectedMetricsPath && m == "GET": case p == expectedMetricsPath && m == "GET":
body, err := marshallBody(metrics) body, err := marshallBody(metrics)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, nodes)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, nodes)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedMetricsPath) t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedMetricsPath)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
opts := &TopNodeOptions{ opts := &TopNodeOptions{
@ -157,7 +157,7 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) {
} }
func TestTopNodeWithNameMetrics(t *testing.T) { func TestTopNodeWithNameMetrics(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
metrics, nodes := testNodeV1alpha1MetricsData() metrics, nodes := testNodeV1alpha1MetricsData()
expectedMetrics := metrics.Items[0] expectedMetrics := metrics.Items[0]
expectedNode := nodes.Items[0] expectedNode := nodes.Items[0]
@ -179,24 +179,24 @@ func TestTopNodeWithNameMetrics(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
case p == expectedPath && m == "GET": case p == expectedPath && m == "GET":
body, err := marshallBody(expectedMetrics) body, err := marshallBody(expectedMetrics)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNode)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &expectedNode)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath) t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopNode(tf, nil, streams) cmd := NewCmdTopNode(tf, nil, streams)
@ -215,7 +215,7 @@ func TestTopNodeWithNameMetrics(t *testing.T) {
} }
func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
metrics, nodes := testNodeV1alpha1MetricsData() metrics, nodes := testNodeV1alpha1MetricsData()
expectedMetrics := metricsv1alpha1api.NodeMetricsList{ expectedMetrics := metricsv1alpha1api.NodeMetricsList{
ListMeta: metrics.ListMeta, ListMeta: metrics.ListMeta,
@ -245,24 +245,24 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
case p == expectedPath && m == "GET" && q == expectedQuery: case p == expectedPath && m == "GET" && q == expectedQuery:
body, err := marshallBody(expectedMetrics) body, err := marshallBody(expectedMetrics)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNodes)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &expectedNodes)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath) t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
return nil, nil return nil, nil
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopNode(tf, nil, streams) cmd := NewCmdTopNode(tf, nil, streams)
@ -284,7 +284,7 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
} }
func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) { func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
expectedMetrics, nodes := testNodeV1beta1MetricsData() expectedMetrics, nodes := testNodeV1beta1MetricsData()
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
@ -299,11 +299,11 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, nodes)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, nodes)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL) t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL)
return nil, nil return nil, nil
@ -314,7 +314,7 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) {
fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) {
return true, expectedMetrics, nil return true, expectedMetrics, nil
}) })
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopNode(tf, nil, streams) cmd := NewCmdTopNode(tf, nil, streams)
@ -345,7 +345,7 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) {
} }
func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) { func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
metrics, nodes := testNodeV1beta1MetricsData() metrics, nodes := testNodeV1beta1MetricsData()
expectedMetrics := metrics.Items[0] expectedMetrics := metrics.Items[0]
expectedNode := nodes.Items[0] expectedNode := nodes.Items[0]
@ -366,11 +366,11 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; { switch p, m := req.URL.Path, req.Method; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNode)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &expectedNode)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL) t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL)
return nil, nil return nil, nil
@ -381,7 +381,7 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) {
fakemetricsClientset.AddReactor("get", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { fakemetricsClientset.AddReactor("get", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) {
return true, &expectedMetrics, nil return true, &expectedMetrics, nil
}) })
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopNode(tf, nil, streams) cmd := NewCmdTopNode(tf, nil, streams)
@ -415,7 +415,7 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) {
} }
func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) { func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
metrics, nodes := testNodeV1beta1MetricsData() metrics, nodes := testNodeV1beta1MetricsData()
expectedMetrics := &metricsv1beta1api.NodeMetricsList{ expectedMetrics := &metricsv1beta1api.NodeMetricsList{
ListMeta: metrics.ListMeta, ListMeta: metrics.ListMeta,
@ -443,11 +443,11 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m, _ := req.URL.Path, req.Method, req.URL.RawQuery; { switch p, m, _ := req.URL.Path, req.Method, req.URL.RawQuery; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
case p == expectedNodePath && m == "GET": case p == expectedNodePath && m == "GET":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNodes)}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &expectedNodes)}, nil
default: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL) t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL)
return nil, nil return nil, nil
@ -459,7 +459,7 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) {
fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) { fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) {
return true, expectedMetrics, nil return true, expectedMetrics, nil
}) })
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopNode(tf, nil, streams) cmd := NewCmdTopNode(tf, nil, streams)

View File

@ -142,7 +142,7 @@ func TestTopPod(t *testing.T) {
containers: true, containers: true,
}, },
} }
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
for _, testCase := range testCases { for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {
t.Logf("Running test case: %s", testCase.name) t.Logf("Running test case: %s", testCase.name)
@ -183,15 +183,15 @@ func TestTopPod(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery): case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery):
body, err := marshallBody(response) body, err := marshallBody(response)
if err != nil { if err != nil {
t.Errorf("%s: unexpected error: %v", testCase.name, err) t.Errorf("%s: unexpected error: %v", testCase.name, err)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v", t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v",
testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery) testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery)
@ -199,7 +199,7 @@ func TestTopPod(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopPod(tf, nil, streams) cmd := NewCmdTopPod(tf, nil, streams)
@ -284,7 +284,7 @@ func TestTopPodWithMetricsServer(t *testing.T) {
containers: true, containers: true,
}, },
} }
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
for _, testCase := range testCases { for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {
metricsList := testV1beta1PodMetricsData() metricsList := testV1beta1PodMetricsData()
@ -330,9 +330,9 @@ func TestTopPodWithMetricsServer(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p := req.URL.Path; { switch p := req.URL.Path; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
default: default:
t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v", t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v",
testCase.name, req, req.URL) testCase.name, req, req.URL)
@ -340,7 +340,7 @@ func TestTopPodWithMetricsServer(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdTopPod(tf, nil, streams) cmd := NewCmdTopPod(tf, nil, streams)
@ -487,7 +487,7 @@ func TestTopPodCustomDefaults(t *testing.T) {
containers: true, containers: true,
}, },
} }
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
for _, testCase := range testCases { for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {
t.Logf("Running test case: %s", testCase.name) t.Logf("Running test case: %s", testCase.name)
@ -528,15 +528,15 @@ func TestTopPodCustomDefaults(t *testing.T) {
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; {
case p == "/api": case p == "/api":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
case p == "/apis": case p == "/apis":
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery): case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery):
body, err := marshallBody(response) body, err := marshallBody(response)
if err != nil { if err != nil {
t.Errorf("%s: unexpected error: %v", testCase.name, err) t.Errorf("%s: unexpected error: %v", testCase.name, err)
} }
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body}, nil
default: default:
t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v", t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v",
testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery) testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery)
@ -544,7 +544,7 @@ func TestTopPodCustomDefaults(t *testing.T) {
} }
}), }),
} }
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
opts := &TopPodOptions{ opts := &TopPodOptions{

View File

@ -42,7 +42,7 @@ const (
) )
func TestTopSubcommandsExist(t *testing.T) { func TestTopSubcommandsExist(t *testing.T) {
initTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
f := cmdtesting.NewTestFactory() f := cmdtesting.NewTestFactory()
defer f.Cleanup() defer f.Cleanup()