Merge pull request #111185 from verb/111027-kubectl-reattach

Fix incorrect message when attaching to ephemeral containers

Kubernetes-commit: c464ee889e126a675c5ed4a0fa7c20034cb69628
This commit is contained in:
Kubernetes Publisher 2022-07-21 12:59:35 -07:00
commit 0052fe6991
3 changed files with 88 additions and 3 deletions

View File

@ -20,6 +20,7 @@ import (
"fmt"
"io"
"net/url"
"strings"
"time"
"github.com/spf13/cobra"
@ -286,8 +287,8 @@ func (o *AttachOptions) Run() error {
return err
}
if !o.Quiet && o.Stdin && t.Raw && o.Pod.Spec.RestartPolicy == corev1.RestartPolicyAlways {
fmt.Fprintf(o.Out, "Session ended, resume using '%s %s -c %s -i -t' command when the pod is running\n", o.CommandName, o.Pod.Name, containerToAttach.Name)
if msg := o.reattachMessage(containerToAttach.Name, t.Raw); msg != "" {
fmt.Fprintln(o.Out, msg)
}
return nil
}
@ -317,3 +318,15 @@ func (o *AttachOptions) GetContainerName(pod *corev1.Pod) (string, error) {
}
return c.Name, nil
}
// reattachMessage returns a message to print after attach has completed, or
// the empty string if no message should be printed.
func (o *AttachOptions) reattachMessage(containerName string, rawTTY bool) string {
if o.Quiet || !o.Stdin || !rawTTY || o.Pod.Spec.RestartPolicy != corev1.RestartPolicyAlways {
return ""
}
if _, path := podcmd.FindContainerByName(o.Pod, containerName); strings.HasPrefix(path, "spec.ephemeralContainers") {
return fmt.Sprintf("Session ended, the ephemeral container will not be restarted but may be reattached using '%s %s -c %s -i -t' if it is still running", o.CommandName, o.Pod.Name, containerName)
}
return fmt.Sprintf("Session ended, resume using '%s %s -c %s -i -t' command when the pod is running", o.CommandName, o.Pod.Name, containerName)
}

View File

@ -484,3 +484,76 @@ func setDefaultContainer(pod *corev1.Pod, name string) *corev1.Pod {
pod.Annotations[podcmd.DefaultContainerAnnotationName] = name
return pod
}
func TestReattachMessage(t *testing.T) {
tests := []struct {
name string
pod *corev1.Pod
rawTTY, stdin bool
container string
expected string
}{
{
name: "normal interactive session",
pod: attachPod(),
container: "bar",
rawTTY: true,
stdin: true,
expected: "Session ended, resume using",
},
{
name: "no stdin",
pod: attachPod(),
container: "bar",
rawTTY: true,
stdin: false,
expected: "",
},
{
name: "not connected to a real TTY",
pod: attachPod(),
container: "bar",
rawTTY: false,
stdin: true,
expected: "",
},
{
name: "no restarts",
pod: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{{Name: "bar"}},
},
Status: corev1.PodStatus{Phase: corev1.PodRunning},
},
container: "bar",
rawTTY: true,
stdin: true,
expected: "",
},
{
name: "ephemeral container",
pod: attachPod(),
container: "debugger",
rawTTY: true,
stdin: true,
expected: "Session ended, the ephemeral container will not be restarted",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
options := &AttachOptions{
StreamOptions: exec.StreamOptions{
Stdin: test.stdin,
},
Pod: test.pod,
}
if msg := options.reattachMessage(test.container, test.rawTTY); test.expected == "" && msg != "" {
t.Errorf("reattachMessage(%v, %v) = %q, want empty string", test.container, test.rawTTY, msg)
} else if !strings.Contains(msg, test.expected) {
t.Errorf("reattachMessage(%v, %v) = %q, want string containing %q", test.container, test.rawTTY, msg, test.expected)
}
})
}
}

View File

@ -364,7 +364,6 @@ func (o *DebugOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
TTY: o.TTY,
Quiet: o.Quiet,
},
// TODO(verb): kubectl prints an incorrect "Session ended" message for debug containers.
CommandName: cmd.Parent().CommandPath() + " attach",
Attach: &attach.DefaultRemoteAttach{},