Change:
When attaching to an ephemeral container, prints a message suggesting that the container can be reattached after it exists. This is not true because an ephemeral container is never restarted. This cosmetic issue should be resolved for
/assign /sig node /triage accepted /priority important-longterm

Discussion:
"fmt" "io" "net/url" <ins> "strings" </ins> "time" "github.com/spf13/cobra"

return err } <del> 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 runningn", o.CommandName, o.Pod.Name, containerToAttach.Name) </del> <ins> if msg := o.reattachMessage(containerToAttach.Name, t.Raw); msg != "" { fmt.Fprintln(o.Out, msg) </ins> } return nil }

} return c.Name, nil } <ins> // 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) } </ins>

pod.Annotations[podcmd.DefaultContainerAnnotationName] = name return pod } <ins> 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) } }) } } </ins>

TTY:       o.TTY, Quiet:     o.Quiet, }, <del> // TODO(verb): kubectl prints an incorrect "Session ended" message for debug containers. </del> CommandName: cmd.Parent().CommandPath() + " attach", Attach: &attach.DefaultRemoteAttach{},