Skip to content

Commit d9e7f25

Browse files
authored
Merge pull request kubernetes#110668 from brianpursley/k-108630
Remove unused flags from kubectl run
2 parents f4abde9 + 25e713b commit d9e7f25

File tree

2 files changed

+208
-17
lines changed

2 files changed

+208
-17
lines changed

staging/src/k8s.io/kubectl/pkg/cmd/run/run.go

+18-17
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636
"k8s.io/apimachinery/pkg/watch"
3737
"k8s.io/cli-runtime/pkg/genericclioptions"
3838
"k8s.io/cli-runtime/pkg/resource"
39-
"k8s.io/client-go/kubernetes"
4039
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
4140
"k8s.io/client-go/tools/cache"
4241
watchtools "k8s.io/client-go/tools/watch"
@@ -94,6 +93,8 @@ const (
9493

9594
var metadataAccessor = meta.NewAccessor()
9695

96+
var attachFunc = attach.DefaultAttachFunc
97+
9798
type RunObject struct {
9899
Object runtime.Object
99100
Mapping *meta.RESTMapping
@@ -105,7 +106,6 @@ type RunOptions struct {
105106
PrintFlags *genericclioptions.PrintFlags
106107
RecordFlags *genericclioptions.RecordFlags
107108

108-
DeleteFlags *cmddelete.DeleteFlags
109109
DeleteOptions *cmddelete.DeleteOptions
110110

111111
DryRunStrategy cmdutil.DryRunStrategy
@@ -135,7 +135,6 @@ type RunOptions struct {
135135
func NewRunOptions(streams genericclioptions.IOStreams) *RunOptions {
136136
return &RunOptions{
137137
PrintFlags: genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
138-
DeleteFlags: cmddelete.NewDeleteFlags("to use to replace the resource."),
139138
RecordFlags: genericclioptions.NewRecordFlags(),
140139

141140
Recorder: genericclioptions.NoopRecorder{},
@@ -159,7 +158,6 @@ func NewCmdRun(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Co
159158
},
160159
}
161160

162-
o.DeleteFlags.AddFlags(cmd)
163161
o.PrintFlags.AddFlags(cmd)
164162
o.RecordFlags.AddFlags(cmd)
165163

@@ -226,18 +224,17 @@ func (o *RunOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
226224
return printer.PrintObj(obj, o.Out)
227225
}
228226

229-
deleteOpts, err := o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams)
230-
if err != nil {
231-
return err
227+
o.DeleteOptions = &cmddelete.DeleteOptions{
228+
CascadingStrategy: metav1.DeletePropagationBackground,
229+
DynamicClient: dynamicClient,
230+
GracePeriod: -1,
231+
IgnoreNotFound: true,
232+
IOStreams: o.IOStreams,
233+
Quiet: o.Quiet,
234+
Timeout: time.Duration(0),
235+
WaitForDeletion: false,
232236
}
233237

234-
deleteOpts.IgnoreNotFound = true
235-
deleteOpts.WaitForDeletion = false
236-
deleteOpts.GracePeriod = -1
237-
deleteOpts.Quiet = o.Quiet
238-
239-
o.DeleteOptions = deleteOpts
240-
241238
return nil
242239
}
243240

@@ -325,7 +322,11 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e
325322

326323
if o.Attach {
327324
if remove {
328-
defer o.removeCreatedObjects(f, createdObjects)
325+
defer func() {
326+
if err := o.removeCreatedObjects(f, createdObjects); err != nil {
327+
fmt.Fprintf(o.ErrOut, "Delete failed: %v\n", err)
328+
}
329+
}()
329330
}
330331

331332
opts := &attach.AttachOptions{
@@ -345,9 +346,9 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e
345346
return err
346347
}
347348
opts.Config = config
348-
opts.AttachFunc = attach.DefaultAttachFunc
349+
opts.AttachFunc = attachFunc
349350

350-
clientset, err := kubernetes.NewForConfig(config)
351+
clientset, err := f.KubernetesClientSet()
351352
if err != nil {
352353
return err
353354
}

staging/src/k8s.io/kubectl/pkg/cmd/run/run_test.go

+190
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@ import (
3333
apiequality "k8s.io/apimachinery/pkg/api/equality"
3434
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3535
"k8s.io/apimachinery/pkg/runtime"
36+
"k8s.io/apimachinery/pkg/runtime/schema"
3637
"k8s.io/apimachinery/pkg/util/intstr"
3738
"k8s.io/cli-runtime/pkg/genericclioptions"
3839
restclient "k8s.io/client-go/rest"
3940
"k8s.io/client-go/rest/fake"
41+
"k8s.io/client-go/tools/remotecommand"
42+
"k8s.io/kubectl/pkg/cmd/attach"
4043
"k8s.io/kubectl/pkg/cmd/delete"
4144
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
4245
cmdutil "k8s.io/kubectl/pkg/cmd/util"
@@ -640,6 +643,193 @@ func TestExpose(t *testing.T) {
640643
}
641644
}
642645

646+
func TestRunAttach(t *testing.T) {
647+
tests := []struct {
648+
name string
649+
rm bool
650+
quiet bool
651+
deleteErrorMessage string
652+
expectedDeleteCount int
653+
expectedOut string
654+
expectedErrOut string
655+
}{
656+
{
657+
name: "test attach",
658+
rm: false,
659+
quiet: false,
660+
expectedDeleteCount: 0,
661+
expectedOut: "",
662+
expectedErrOut: "If you don't see a command prompt, try pressing enter.\n",
663+
},
664+
{
665+
name: "test attach with quiet",
666+
rm: false,
667+
quiet: true,
668+
expectedDeleteCount: 0,
669+
expectedOut: "",
670+
expectedErrOut: "",
671+
},
672+
{
673+
name: "test attach with rm",
674+
rm: true,
675+
quiet: false,
676+
expectedDeleteCount: 1,
677+
expectedOut: "pod \"foo\" deleted\n",
678+
expectedErrOut: "If you don't see a command prompt, try pressing enter.\n",
679+
},
680+
{
681+
name: "test attach with rm should not print message if quiet is specified",
682+
rm: true,
683+
quiet: true,
684+
expectedDeleteCount: 1,
685+
expectedOut: "",
686+
expectedErrOut: "",
687+
},
688+
{
689+
name: "error should be displayed if delete fails",
690+
rm: true,
691+
quiet: false,
692+
deleteErrorMessage: "delete error message",
693+
expectedDeleteCount: 1,
694+
expectedOut: "",
695+
expectedErrOut: "If you don't see a command prompt, try pressing enter.\nDelete failed: delete error message\n",
696+
},
697+
}
698+
699+
fakePod := &corev1.Pod{
700+
TypeMeta: metav1.TypeMeta{
701+
APIVersion: "v1",
702+
Kind: "Pod",
703+
},
704+
ObjectMeta: metav1.ObjectMeta{
705+
Name: "foo",
706+
Namespace: "default",
707+
},
708+
Spec: corev1.PodSpec{
709+
Containers: []corev1.Container{
710+
{
711+
Name: "bar",
712+
},
713+
},
714+
},
715+
Status: corev1.PodStatus{
716+
Phase: corev1.PodRunning,
717+
Conditions: []corev1.PodCondition{
718+
{
719+
Type: corev1.PodReady,
720+
Status: corev1.ConditionTrue,
721+
},
722+
},
723+
},
724+
}
725+
726+
for _, test := range tests {
727+
t.Run(test.name, func(tt *testing.T) {
728+
postCount := 0
729+
attachCount := 0
730+
deleteCount := 0
731+
732+
attachFunc = func(o *attach.AttachOptions, containerToAttach *corev1.Container, raw bool, sizeQueue remotecommand.TerminalSizeQueue) func() error {
733+
if containerToAttach.Name != "bar" {
734+
tt.Fatalf("expected attach to container name \"bar\", but got %q", containerToAttach.Name)
735+
}
736+
return func() error {
737+
attachCount++
738+
return nil
739+
}
740+
}
741+
742+
tf := cmdtesting.NewTestFactory().WithNamespace("test")
743+
defer tf.Cleanup()
744+
745+
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
746+
ns := scheme.Codecs.WithoutConversion()
747+
tf.Client = &fake.RESTClient{
748+
GroupVersion: schema.GroupVersion{Version: ""},
749+
NegotiatedSerializer: ns,
750+
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
751+
switch p, m := req.URL.Path, req.Method; {
752+
case m == "POST" && p == "/namespaces/test/pods":
753+
postCount++
754+
body := cmdtesting.ObjBody(codec, fakePod)
755+
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
756+
case m == "GET" && p == "/api/v1/namespaces/default/pods":
757+
event := &metav1.WatchEvent{
758+
Type: "ADDED",
759+
Object: runtime.RawExtension{Object: fakePod},
760+
}
761+
body := cmdtesting.ObjBody(codec, event)
762+
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
763+
case m == "GET" && p == "/namespaces/default/pods/foo":
764+
body := cmdtesting.ObjBody(codec, fakePod)
765+
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
766+
case m == "DELETE" && p == "/namespaces/default/pods/foo":
767+
deleteCount++
768+
if test.deleteErrorMessage != "" {
769+
body := cmdtesting.ObjBody(codec, &metav1.Status{
770+
Status: metav1.StatusFailure,
771+
Message: test.deleteErrorMessage,
772+
})
773+
return &http.Response{StatusCode: http.StatusInternalServerError, Header: cmdtesting.DefaultHeader(), Body: body}, nil
774+
} else {
775+
body := cmdtesting.ObjBody(codec, fakePod)
776+
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
777+
}
778+
default:
779+
tt.Errorf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
780+
return nil, fmt.Errorf("unexpected request")
781+
}
782+
}),
783+
}
784+
785+
tf.ClientConfigVal = &restclient.Config{
786+
ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}, NegotiatedSerializer: ns},
787+
}
788+
789+
streams, _, bufOut, bufErr := genericclioptions.NewTestIOStreams()
790+
cmdutil.BehaviorOnFatal(func(str string, code int) {
791+
bufErr.Write([]byte(str))
792+
})
793+
794+
cmd := NewCmdRun(tf, streams)
795+
cmd.Flags().Set("image", "test-image")
796+
cmd.Flags().Set("attach", "true")
797+
if test.rm {
798+
cmd.Flags().Set("rm", "true")
799+
}
800+
if test.quiet {
801+
cmd.Flags().Set("quiet", "true")
802+
}
803+
804+
parentCmd := cobra.Command{}
805+
parentCmd.AddCommand(cmd)
806+
807+
cmd.Run(cmd, []string{"test-pod"})
808+
809+
if postCount != 1 {
810+
tt.Fatalf("expected 1 post request, but got %d", postCount)
811+
}
812+
813+
if attachCount != 1 {
814+
tt.Fatalf("expected 1 attach call, but got %d", attachCount)
815+
}
816+
817+
if deleteCount != test.expectedDeleteCount {
818+
tt.Fatalf("expected %d delete requests, but got %d", test.expectedDeleteCount, deleteCount)
819+
}
820+
821+
if bufErr.String() != test.expectedErrOut {
822+
tt.Fatalf("unexpected error. got: %q, expected: %q", bufErr.String(), test.expectedErrOut)
823+
}
824+
825+
if bufOut.String() != test.expectedOut {
826+
tt.Fatalf("unexpected output. got: %q, expected: %q", bufOut.String(), test.expectedOut)
827+
}
828+
})
829+
830+
}
831+
}
832+
643833
func TestRunOverride(t *testing.T) {
644834
tests := []struct {
645835
name string

0 commit comments

Comments
 (0)