diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug.go b/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug.go index 4f5d66de9f1..24f740ec2a6 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug.go @@ -121,6 +121,7 @@ type DebugOptions struct { TargetContainer string TTY bool + attachChanged bool deprecatedInvocation bool shareProcessedChanged bool @@ -223,7 +224,8 @@ func (o *DebugOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st return err } - // Share processes + // Record flags that the user explicitly changed from their defaults + o.attachChanged = cmd.Flags().Changed("attach") o.shareProcessedChanged = cmd.Flags().Changed("share-processes") return nil @@ -231,6 +233,11 @@ func (o *DebugOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st // Validate checks that the provided debug options are specified. func (o *DebugOptions) Validate(cmd *cobra.Command) error { + // Attach + if o.Attach && o.attachChanged && len(o.Image) == 0 && len(o.Container) == 0 { + return fmt.Errorf("you must specify --container or create a new container using --image in order to attach.") + } + // CopyTo if len(o.CopyTo) > 0 { if len(o.Image) == 0 && len(o.SetImages) == 0 && len(o.Args) == 0 { @@ -332,7 +339,7 @@ func (o *DebugOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error { return visitErr } - if o.Attach { + if o.Attach && len(containerName) > 0 { opts := &attach.AttachOptions{ StreamOptions: exec.StreamOptions{ IOStreams: o.IOStreams, @@ -552,18 +559,22 @@ func (o *DebugOptions) generatePodCopyWithDebugContainer(pod *corev1.Pod) (*core } } - containerByName := containerNameToRef(copied) - name := o.Container - if len(name) == 0 { - name = o.computeDebugContainerName(copied) - } + name, containerByName := o.Container, containerNameToRef(copied) c, ok := containerByName[name] if !ok { // Adding a new debug container if len(o.Image) == 0 { + if len(o.SetImages) > 0 { + // This was a --set-image only invocation + return copied, "", nil + } return nil, "", fmt.Errorf("you must specify image when creating new container") } + + if len(name) == 0 { + name = o.computeDebugContainerName(copied) + } c = &corev1.Container{ Name: name, TerminationMessagePolicy: corev1.TerminationMessageReadFile, diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug_test.go b/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug_test.go index d2024c74c9d..84b26cad8a2 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug_test.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug_test.go @@ -868,7 +868,6 @@ func TestGeneratePodCopyWithDebugContainer(t *testing.T) { name: "Change image for all containers with set-image", opts: &DebugOptions{ CopyTo: "myapp-copy", - Container: "app", SetImages: map[string]string{"*": "busybox"}, }, havePod: &corev1.Pod{ @@ -898,7 +897,6 @@ func TestGeneratePodCopyWithDebugContainer(t *testing.T) { name: "Change image for multiple containers with set-image", opts: &DebugOptions{ CopyTo: "myapp-copy", - Container: "app", SetImages: map[string]string{"*": "busybox", "app": "app-debugger"}, }, havePod: &corev1.Pod{ @@ -1361,6 +1359,19 @@ func TestCompleteAndValidate(t *testing.T) { TargetNames: []string{"mypod"}, }, }, + { + name: "Pod copy: explicit attach", + args: "mypod --image=busybox --copy-to=my-debugger --attach -- sleep 1d", + wantOpts: &DebugOptions{ + Args: []string{"sleep", "1d"}, + Attach: true, + CopyTo: "my-debugger", + Image: "busybox", + Namespace: "default", + ShareProcesses: true, + TargetNames: []string{"mypod"}, + }, + }, { name: "Pod copy: replace single image of existing container", args: "mypod --image=busybox --container=my-container --copy-to=my-debugger", @@ -1443,6 +1454,11 @@ func TestCompleteAndValidate(t *testing.T) { args: "mypod --set-image=*=SUPERGOODIMAGE#1!!!! --copy-to=my-debugger", wantError: true, }, + { + name: "Pod copy: specifying attach without existing or newly created container", + args: "mypod --set-image=*=busybox --copy-to=my-debugger --attach", + wantError: true, + }, { name: "Node: interactive session minimal args", args: "node/mynode -it --image=busybox",