From bf3dfaf99942eab20fac1570ca0146d32cb93b57 Mon Sep 17 00:00:00 2001 From: Kiyoshi Muranaka Date: Mon, 7 Sep 2020 02:43:21 +0900 Subject: [PATCH] Fix index out of range panic for kubectl alpha debug Fix containerNameToRef func to get init containers and ephemeral containers properly. Set EphemeralContainers in generatePodCopyWithDebugContainer func to nil which means dropping ephemeral containers from a copy of pod so that it can be created successfully, otherwise it is rejected by the API server. --- .../src/k8s.io/kubectl/pkg/cmd/debug/debug.go | 6 +- .../kubectl/pkg/cmd/debug/debug_test.go | 172 ++++++++++++++++++ 2 files changed, 176 insertions(+), 2 deletions(-) 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 0c9ec32ca55..6a6fe892d4e 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/debug/debug.go @@ -485,6 +485,8 @@ func (o *DebugOptions) generatePodCopyWithDebugContainer(pod *corev1.Pod) (*core }, Spec: *pod.Spec.DeepCopy(), } + // set EphemeralContainers to nil so that the copy of pod can be created + copied.Spec.EphemeralContainers = nil // change ShareProcessNamespace configuration only when commanded explicitly if o.shareProcessedChanged { copied.Spec.ShareProcessNamespace = pointer.BoolPtr(o.ShareProcesses) @@ -544,11 +546,11 @@ func containerNameToRef(pod *corev1.Pod) map[string]*corev1.Container { names[ref.Name] = ref } for i := range pod.Spec.InitContainers { - ref := &pod.Spec.Containers[i] + ref := &pod.Spec.InitContainers[i] names[ref.Name] = ref } for i := range pod.Spec.EphemeralContainers { - ref := &pod.Spec.Containers[i] + ref := (*corev1.Container)(&pod.Spec.EphemeralContainers[i].EphemeralContainerCommon) names[ref.Name] = ref } return names 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 de224cc398f..3e060920289 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 @@ -153,6 +153,74 @@ func TestGenerateDebugContainer(t *testing.T) { }, }, }, + { + name: "pod with init containers", + opts: &DebugOptions{ + Image: "busybox", + PullPolicy: corev1.PullIfNotPresent, + }, + pod: &corev1.Pod{ + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-1", + }, + { + Name: "init-container-2", + }, + }, + Containers: []corev1.Container{ + { + Name: "debugger", + }, + }, + }, + }, + expected: &corev1.EphemeralContainer{ + EphemeralContainerCommon: corev1.EphemeralContainerCommon{ + Name: "debugger-1", + Image: "busybox", + ImagePullPolicy: "IfNotPresent", + TerminationMessagePolicy: "File", + }, + }, + }, + { + name: "pod with ephemeral containers", + opts: &DebugOptions{ + Image: "busybox", + PullPolicy: corev1.PullIfNotPresent, + }, + pod: &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "debugger", + }, + }, + EphemeralContainers: []corev1.EphemeralContainer{ + { + EphemeralContainerCommon: corev1.EphemeralContainerCommon{ + Name: "ephemeral-container-1", + }, + }, + { + EphemeralContainerCommon: corev1.EphemeralContainerCommon{ + Name: "ephemeral-container-2", + }, + }, + }, + }, + }, + expected: &corev1.EphemeralContainer{ + EphemeralContainerCommon: corev1.EphemeralContainerCommon{ + Name: "debugger-1", + Image: "busybox", + ImagePullPolicy: "IfNotPresent", + TerminationMessagePolicy: "File", + }, + }, + }, } { t.Run(tc.name, func(t *testing.T) { tc.opts.IOStreams = genericclioptions.NewTestIOStreamsDiscard() @@ -590,6 +658,110 @@ func TestGeneratePodCopyWithDebugContainer(t *testing.T) { }, }, }, + { + name: "pod with init containers", + opts: &DebugOptions{ + CopyTo: "debugger", + Image: "busybox", + PullPolicy: corev1.PullIfNotPresent, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "target", + }, + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-1", + }, + { + Name: "init-container-2", + }, + }, + Containers: []corev1.Container{ + { + Name: "debugger-1", + }, + }, + }, + }, + expected: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "debugger", + }, + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-1", + }, + { + Name: "init-container-2", + }, + }, + Containers: []corev1.Container{ + { + Name: "debugger-1", + }, + { + Name: "debugger-2", + Image: "busybox", + ImagePullPolicy: corev1.PullIfNotPresent, + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + }, + }, + }, + }, + }, + { + name: "pod with ephemeral containers", + opts: &DebugOptions{ + CopyTo: "debugger", + Image: "busybox", + PullPolicy: corev1.PullIfNotPresent, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "target", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "debugger-1", + }, + }, + EphemeralContainers: []corev1.EphemeralContainer{ + { + EphemeralContainerCommon: corev1.EphemeralContainerCommon{ + Name: "ephemeral-container-1", + }, + }, + { + EphemeralContainerCommon: corev1.EphemeralContainerCommon{ + Name: "ephemeral-container-2", + }, + }, + }, + }, + }, + expected: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "debugger", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "debugger-1", + }, + { + Name: "debugger-2", + Image: "busybox", + ImagePullPolicy: corev1.PullIfNotPresent, + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + }, + }, + }, + }, + }, { name: "shared process namespace", opts: &DebugOptions{