From a8eb62c8afccaf4de4e508748a06ac4b521326ce Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 16 Nov 2019 19:17:00 -0500 Subject: [PATCH 1/5] debug: Allow the object to be targeted at another namespace When using `oc debug istag/foo:bar` it is not uncommon to want to create the debug pod in another namespace. Make that possible by adding `--to-namespace` which overrides the pod namespace. --- contrib/completions/bash/oc | 3 +++ contrib/completions/zsh/oc | 3 +++ pkg/cli/debug/debug.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/contrib/completions/bash/oc b/contrib/completions/bash/oc index 31c3005db7..3538ed3b40 100644 --- a/contrib/completions/bash/oc +++ b/contrib/completions/bash/oc @@ -11876,6 +11876,9 @@ _oc_debug() flags_with_completion+=("--template") flags_completion+=("_filedir") local_nonpersistent_flags+=("--template=") + flags+=("--to-namespace=") + two_word_flags+=("--to-namespace") + local_nonpersistent_flags+=("--to-namespace=") flags+=("--tty") flags+=("-t") local_nonpersistent_flags+=("--tty") diff --git a/contrib/completions/zsh/oc b/contrib/completions/zsh/oc index 34a85da05a..26b756f708 100644 --- a/contrib/completions/zsh/oc +++ b/contrib/completions/zsh/oc @@ -12018,6 +12018,9 @@ _oc_debug() flags_with_completion+=("--template") flags_completion+=("_filedir") local_nonpersistent_flags+=("--template=") + flags+=("--to-namespace=") + two_word_flags+=("--to-namespace") + local_nonpersistent_flags+=("--to-namespace=") flags+=("--tty") flags+=("-t") local_nonpersistent_flags+=("--tty") diff --git a/pkg/cli/debug/debug.go b/pkg/cli/debug/debug.go index b862c88251..8b48b709d8 100644 --- a/pkg/cli/debug/debug.go +++ b/pkg/cli/debug/debug.go @@ -141,6 +141,7 @@ type DebugOptions struct { DryRun bool FullCmdName string Image string + ToNamespace string // IsNode is set after we see the object we're debugging. We use it to be able to print pertinent advice. IsNode bool @@ -204,6 +205,7 @@ func NewCmdDebug(fullName string, f kcmdutil.Factory, streams genericclioptions. cmd.Flags().BoolVar(&o.AsRoot, "as-root", o.AsRoot, "If true, try to run the container as the root user") cmd.Flags().Int64Var(&o.AsUser, "as-user", o.AsUser, "Try to run the container as a specific user UID (note: admins may limit your ability to use this flag)") cmd.Flags().StringVar(&o.Image, "image", o.Image, "Override the image used by the targeted container.") + cmd.Flags().StringVar(&o.ToNamespace, "to-namespace", o.ToNamespace, "Override the namespace to create the pod into (instead of using --namespace).") o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) @@ -362,6 +364,9 @@ func (o *DebugOptions) RunDebug() error { if len(ns) == 0 { ns = o.Namespace } + if len(o.ToNamespace) > 0 { + ns = o.ToNamespace + } pod.Name, pod.Namespace = fmt.Sprintf("%s-debug", generateapp.MakeSimpleName(infos[0].Name)), ns o.Attach.Pod = pod From e78b64c93d8cbd276e0f67e79001fde98c61de71 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 16 Nov 2019 19:18:43 -0500 Subject: [PATCH 2/5] debug: Clear initContainers when --one-container The implication of --one-container is that we only want a single container. --- pkg/cli/debug/debug.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/cli/debug/debug.go b/pkg/cli/debug/debug.go index 8b48b709d8..23661f3272 100644 --- a/pkg/cli/debug/debug.go +++ b/pkg/cli/debug/debug.go @@ -670,6 +670,7 @@ func (o *DebugOptions) transformPodForDebug(annotations map[string]string) (*cor } if o.OneContainer { + pod.Spec.InitContainers = nil pod.Spec.Containers = []corev1.Container{*container} } From 2aa5641d3ef79d4372e6cf49a3df2b23d03c3543 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 16 Nov 2019 19:19:22 -0500 Subject: [PATCH 3/5] debug: Print init containers in the list of suggested container names We only printed the regular container names. --- pkg/cli/debug/debug.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/cli/debug/debug.go b/pkg/cli/debug/debug.go index 23661f3272..e8c450ea78 100644 --- a/pkg/cli/debug/debug.go +++ b/pkg/cli/debug/debug.go @@ -731,14 +731,14 @@ func (o *DebugOptions) createPod(pod *corev1.Pod) (*corev1.Pod, error) { } func containerForName(pod *corev1.Pod, name string) *corev1.Container { - for i, c := range pod.Spec.Containers { + for i, c := range pod.Spec.InitContainers { if c.Name == name { - return &pod.Spec.Containers[i] + return &pod.Spec.InitContainers[i] } } - for i, c := range pod.Spec.InitContainers { + for i, c := range pod.Spec.Containers { if c.Name == name { - return &pod.Spec.InitContainers[i] + return &pod.Spec.Containers[i] } } return nil @@ -746,6 +746,9 @@ func containerForName(pod *corev1.Pod, name string) *corev1.Container { func containerNames(pod *corev1.Pod) []string { var names []string + for _, c := range pod.Spec.InitContainers { + names = append(names, c.Name) + } for _, c := range pod.Spec.Containers { names = append(names, c.Name) } From 175c7479b9966833c7c3e8789ec0f255edda25ab Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 16 Nov 2019 19:28:37 -0500 Subject: [PATCH 4/5] debug: When debugging an init container, don't clear it immediately If a user specifies an init container, we have to preserve it even if `--keep-init-containers=false` is set. In that case, we strip all other init containers. --- pkg/cli/debug/debug.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/pkg/cli/debug/debug.go b/pkg/cli/debug/debug.go index e8c450ea78..e70c01d4db 100644 --- a/pkg/cli/debug/debug.go +++ b/pkg/cli/debug/debug.go @@ -601,10 +601,6 @@ func (o *DebugOptions) getContainerImageCommand(pod *corev1.Pod, container *core func (o *DebugOptions) transformPodForDebug(annotations map[string]string) (*corev1.Pod, []string) { pod := o.Attach.Pod - if !o.KeepInitContainers { - pod.Spec.InitContainers = nil - } - // reset the container container := containerForName(pod, o.Attach.ContainerName) @@ -669,9 +665,18 @@ func (o *DebugOptions) transformPodForDebug(annotations map[string]string) (*cor container.SecurityContext.RunAsNonRoot = nil } - if o.OneContainer { + switch { + case o.OneContainer: pod.Spec.InitContainers = nil pod.Spec.Containers = []corev1.Container{*container} + case o.KeepInitContainers: + // there is nothing we need to do + case isInitContainer(pod, o.Attach.ContainerName): + // keep only the init container we are debugging + pod.Spec.InitContainers = []corev1.Container{*container} + default: + // clear all init containers + pod.Spec.InitContainers = nil } // reset the pod @@ -744,6 +749,15 @@ func containerForName(pod *corev1.Pod, name string) *corev1.Container { return nil } +func isInitContainer(pod *corev1.Pod, name string) bool { + for _, c := range pod.Spec.InitContainers { + if c.Name == name { + return true + } + } + return false +} + func containerNames(pod *corev1.Pod) []string { var names []string for _, c := range pod.Spec.InitContainers { From 9a9ced545ff948d78b7255f0df1adb36bc0f4660 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 16 Nov 2019 19:39:27 -0500 Subject: [PATCH 5/5] debug: Clear host ports when debugging a pod If there is a host port set, clear it. If this is a host network pod, clear all ports. This allows us to debug a pod on the same node for daemonsets that declare host network or host pods. --- pkg/cli/debug/debug.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pkg/cli/debug/debug.go b/pkg/cli/debug/debug.go index e70c01d4db..b208d6ca7c 100644 --- a/pkg/cli/debug/debug.go +++ b/pkg/cli/debug/debug.go @@ -679,6 +679,8 @@ func (o *DebugOptions) transformPodForDebug(annotations map[string]string) (*cor pod.Spec.InitContainers = nil } + clearHostPorts(pod) + // reset the pod if pod.Annotations == nil || !o.KeepAnnotations { pod.Annotations = make(map[string]string) @@ -769,6 +771,31 @@ func containerNames(pod *corev1.Pod) []string { return names } +func clearHostPorts(pod *corev1.Pod) { + for i := range pod.Spec.InitContainers { + if pod.Spec.HostNetwork { + pod.Spec.InitContainers[i].Ports = nil + continue + } + for j := range pod.Spec.InitContainers[i].Ports { + if pod.Spec.InitContainers[i].Ports[j].HostPort > 0 { + pod.Spec.InitContainers[i].Ports[j].HostPort = 0 + } + } + } + for i := range pod.Spec.Containers { + if pod.Spec.HostNetwork { + pod.Spec.Containers[i].Ports = nil + continue + } + for j := range pod.Spec.Containers[i].Ports { + if pod.Spec.Containers[i].Ports[j].HostPort > 0 { + pod.Spec.Containers[i].Ports[j].HostPort = 0 + } + } + } +} + func (o *DebugOptions) approximatePodTemplateForObject(object runtime.Object) (*corev1.PodTemplateSpec, error) { switch t := object.(type) { case *corev1.Node: