From 39fd13dd152d89d91a4a95b721e9d3659fa9d01b 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 0c9ec32ca5502..6a6fe892d4ed6 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 de224cc398ff8..3e0609202896c 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{