Skip to content

Commit fffca53

Browse files
Merge pull request #20550 from juanvallejo/jvallejo/fix-debug-panic
Fix debug panic
2 parents 62c3948 + 0e8193e commit fffca53

File tree

6 files changed

+123
-16
lines changed

6 files changed

+123
-16
lines changed

pkg/oc/cli/admin/diagnostics/diagnostics/cluster/app_create/app.go

+46-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ import (
55
"time"
66

77
corev1 "k8s.io/api/core/v1"
8+
"k8s.io/apimachinery/pkg/api/errors"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/apimachinery/pkg/runtime/schema"
911
"k8s.io/apimachinery/pkg/util/intstr"
12+
"k8s.io/apimachinery/pkg/watch"
13+
api "k8s.io/kubernetes/pkg/apis/core"
1014
"k8s.io/kubernetes/pkg/kubectl"
1115

1216
appsv1 "github.com/openshift/api/apps/v1"
@@ -100,7 +104,7 @@ This may be a transient error. Check the master API logs for anomalies near this
100104
}
101105
defer stopWatcher(watcher)
102106
for event := range watcher.ResultChan() {
103-
running, err := kubectl.PodContainerRunning(d.appName)(event)
107+
running, err := podContainerRunning(d.appName)(event)
104108
if err != nil {
105109
d.out.Error("DCluAC009", err, fmt.Sprintf(`
106110
%s: Error while watching for app pod to deploy:
@@ -124,3 +128,44 @@ There are many reasons why this can occur; for example:
124128
`, now(), d.deployTimeout))
125129
return false
126130
}
131+
132+
// podContainerRunning returns false until the named container has ContainerStatus running (at least once),
133+
// and will return an error if the pod is deleted, runs to completion, or the container pod is not available.
134+
func podContainerRunning(containerName string) watch.ConditionFunc {
135+
return func(event watch.Event) (bool, error) {
136+
switch event.Type {
137+
case watch.Deleted:
138+
return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "")
139+
}
140+
switch t := event.Object.(type) {
141+
case *api.Pod:
142+
switch t.Status.Phase {
143+
case api.PodRunning, api.PodPending:
144+
case api.PodFailed, api.PodSucceeded:
145+
return false, kubectl.ErrPodCompleted
146+
default:
147+
return false, nil
148+
}
149+
for _, s := range t.Status.ContainerStatuses {
150+
if s.Name != containerName {
151+
continue
152+
}
153+
if s.State.Terminated != nil {
154+
return false, kubectl.ErrContainerTerminated
155+
}
156+
return s.State.Running != nil, nil
157+
}
158+
for _, s := range t.Status.InitContainerStatuses {
159+
if s.Name != containerName {
160+
continue
161+
}
162+
if s.State.Terminated != nil {
163+
return false, kubectl.ErrContainerTerminated
164+
}
165+
return s.State.Running != nil, nil
166+
}
167+
return false, nil
168+
}
169+
return false, nil
170+
}
171+
}

pkg/oc/cli/debug/debug.go

+11-6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import (
4646
appsutil "github.com/openshift/origin/pkg/apps/util"
4747
imageapi "github.com/openshift/origin/pkg/image/apis/image"
4848
imageutil "github.com/openshift/origin/pkg/image/util"
49+
conditions "github.com/openshift/origin/pkg/oc/lib/conditions"
4950
generateapp "github.com/openshift/origin/pkg/oc/lib/newapp/app"
5051
utilenv "github.com/openshift/origin/pkg/oc/util/env"
5152
)
@@ -103,8 +104,9 @@ type DebugOptions struct {
103104
AppsClient appsv1client.AppsV1Interface
104105
ImageClient imagev1client.ImageV1Interface
105106

106-
Printer printers.ResourcePrinter
107-
LogsForObject polymorphichelpers.LogsForObjectFunc
107+
Printer printers.ResourcePrinter
108+
LogsForObject polymorphichelpers.LogsForObjectFunc
109+
RESTClientGetter genericclioptions.RESTClientGetter
108110

109111
NoStdin bool
110112
ForceTTY bool
@@ -211,6 +213,7 @@ func (o *DebugOptions) Complete(cmd *cobra.Command, f kcmdutil.Factory, args []s
211213
return kcmdutil.UsageErrorf(cmd, "all resources must be specified before environment changes: %s", strings.Join(args, " "))
212214
}
213215
o.Resources = resources
216+
o.RESTClientGetter = f
214217

215218
switch {
216219
case o.ForceTTY && o.NoStdin:
@@ -432,7 +435,7 @@ func (o *DebugOptions) RunDebug() error {
432435
}
433436
fmt.Fprintf(o.ErrOut, "Waiting for pod to start ...\n")
434437

435-
switch containerRunningEvent, err := watch.Until(o.Timeout, w, kubectl.PodContainerRunning(o.Attach.ContainerName)); {
438+
switch containerRunningEvent, err := watch.Until(o.Timeout, w, conditions.PodContainerRunning(o.Attach.ContainerName)); {
436439
// api didn't error right away but the pod wasn't even created
437440
case kapierrors.IsNotFound(err):
438441
msg := fmt.Sprintf("unable to create the debug pod %q", pod.Name)
@@ -444,12 +447,14 @@ func (o *DebugOptions) RunDebug() error {
444447
case err == kubectl.ErrPodCompleted, err == kubectl.ErrContainerTerminated, !o.Attach.Stdin:
445448
return kcmd.LogsOptions{
446449
Object: pod,
447-
Options: &kapi.PodLogOptions{
450+
Options: &corev1.PodLogOptions{
448451
Container: o.Attach.ContainerName,
449452
Follow: true,
450453
},
451-
IOStreams: o.IOStreams,
452-
LogsForObject: o.LogsForObject,
454+
RESTClientGetter: o.RESTClientGetter,
455+
ConsumeRequestFn: kcmd.DefaultConsumeRequestFn,
456+
IOStreams: o.IOStreams,
457+
LogsForObject: o.LogsForObject,
453458
}.RunLogs()
454459
case err != nil:
455460
return err

pkg/oc/cli/newapp/newapp.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,11 @@ type ObjectGeneratorOptions struct {
162162
}
163163

164164
type AppOptions struct {
165-
genericclioptions.IOStreams
166165
*ObjectGeneratorOptions
166+
167+
RESTClientGetter genericclioptions.RESTClientGetter
168+
169+
genericclioptions.IOStreams
167170
}
168171

169172
type versionedPrintObj struct {
@@ -368,6 +371,8 @@ func NewCmdNewApplication(name, baseName string, f kcmdutil.Factory, streams gen
368371

369372
// Complete sets any default behavior for the command
370373
func (o *AppOptions) Complete(baseName, commandName string, f kcmdutil.Factory, c *cobra.Command, args []string) error {
374+
o.RESTClientGetter = f
375+
371376
cmdutil.WarnAboutCommaSeparation(o.ErrOut, o.ObjectGeneratorOptions.Config.TemplateParameters, "--param")
372377
err := o.ObjectGeneratorOptions.Complete(baseName, commandName, f, c, args)
373378
if err != nil {
@@ -526,7 +531,7 @@ func (o *AppOptions) RunNewApp() error {
526531
}
527532
switch {
528533
case len(installing) == 1:
529-
return followInstallation(config, installing[0], o.LogsForObject)
534+
return followInstallation(config, o.RESTClientGetter, installing[0], o.LogsForObject)
530535
case len(installing) > 1:
531536
for i := range installing {
532537
fmt.Fprintf(out, "%sTrack installation of %s with '%s logs %s'.\n", indent, installing[i].Name, o.BaseName, installing[i].Name)
@@ -570,7 +575,7 @@ func getServices(items []runtime.Object) []*corev1.Service {
570575
return svc
571576
}
572577

573-
func followInstallation(config *newcmd.AppConfig, pod *corev1.Pod, logsForObjectFn polymorphichelpers.LogsForObjectFunc) error {
578+
func followInstallation(config *newcmd.AppConfig, clientGetter genericclioptions.RESTClientGetter, pod *corev1.Pod, logsForObjectFn polymorphichelpers.LogsForObjectFunc) error {
574579
fmt.Fprintf(config.Out, "--> Installing ...\n")
575580

576581
// we cannot retrieve logs until the pod is out of pending
@@ -583,12 +588,14 @@ func followInstallation(config *newcmd.AppConfig, pod *corev1.Pod, logsForObject
583588
opts := &kcmd.LogsOptions{
584589
Namespace: pod.Namespace,
585590
ResourceArg: pod.Name,
586-
Options: &kapi.PodLogOptions{
591+
Options: &corev1.PodLogOptions{
587592
Follow: true,
588593
Container: pod.Spec.Containers[0].Name,
589594
},
590-
LogsForObject: logsForObjectFn,
591-
IOStreams: genericclioptions.IOStreams{Out: config.Out},
595+
RESTClientGetter: clientGetter,
596+
ConsumeRequestFn: kcmd.DefaultConsumeRequestFn,
597+
LogsForObject: logsForObjectFn,
598+
IOStreams: genericclioptions.IOStreams{Out: config.Out},
592599
}
593600
logErr := opts.RunLogs()
594601

pkg/oc/lib/conditions/conditions.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package conditions
2+
3+
import (
4+
corev1 "k8s.io/api/core/v1"
5+
"k8s.io/apimachinery/pkg/api/errors"
6+
"k8s.io/apimachinery/pkg/runtime/schema"
7+
"k8s.io/apimachinery/pkg/watch"
8+
"k8s.io/kubernetes/pkg/kubectl"
9+
)
10+
11+
// PodContainerRunning returns false until the named container has ContainerStatus running (at least once),
12+
// and will return an error if the pod is deleted, runs to completion, or the container pod is not available.
13+
func PodContainerRunning(containerName string) watch.ConditionFunc {
14+
return func(event watch.Event) (bool, error) {
15+
switch event.Type {
16+
case watch.Deleted:
17+
return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "")
18+
}
19+
switch t := event.Object.(type) {
20+
case *corev1.Pod:
21+
switch t.Status.Phase {
22+
case corev1.PodRunning, corev1.PodPending:
23+
case corev1.PodFailed, corev1.PodSucceeded:
24+
return false, kubectl.ErrPodCompleted
25+
default:
26+
return false, nil
27+
}
28+
for _, s := range t.Status.ContainerStatuses {
29+
if s.Name != containerName {
30+
continue
31+
}
32+
if s.State.Terminated != nil {
33+
return false, kubectl.ErrContainerTerminated
34+
}
35+
return s.State.Running != nil, nil
36+
}
37+
for _, s := range t.Status.InitContainerStatuses {
38+
if s.Name != containerName {
39+
continue
40+
}
41+
if s.State.Terminated != nil {
42+
return false, kubectl.ErrContainerTerminated
43+
}
44+
return s.State.Running != nil, nil
45+
}
46+
return false, nil
47+
}
48+
return false, nil
49+
}
50+
}

vendor/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/k8s.io/kubernetes/pkg/kubectl/cmd/run.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)