From f8f45df5784eb0dd1e251284cfcd93470f6d2bd4 Mon Sep 17 00:00:00 2001 From: deads2k Date: Tue, 16 Feb 2016 15:21:35 -0500 Subject: [PATCH] make kubectl logs work for replication controllers --- pkg/kubectl/cmd/util/factory.go | 53 ++++++++++++++++++++++++++++----- test/e2e/kubectl.go | 9 +++++- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 974c0348ffb..2e2258b0d96 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -380,6 +380,42 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { return nil, errors.New("provided options object is not a PodLogOptions") } return c.Pods(t.Namespace).GetLogs(t.Name, opts), nil + + case *api.ReplicationController: + opts, ok := options.(*api.PodLogOptions) + if !ok { + return nil, errors.New("provided options object is not a PodLogOptions") + } + selector := labels.SelectorFromSet(t.Spec.Selector) + pod, numPods, err := GetFirstPod(c, t.Namespace, selector) + if err != nil { + return nil, err + } + if numPods > 1 { + fmt.Fprintf(os.Stderr, "Found %v pods, using pod/%v\n", numPods, pod.Name) + } + + return c.Pods(pod.Namespace).GetLogs(pod.Name, opts), nil + + case *extensions.ReplicaSet: + opts, ok := options.(*api.PodLogOptions) + if !ok { + return nil, errors.New("provided options object is not a PodLogOptions") + } + selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector) + if err != nil { + return nil, fmt.Errorf("invalid label selector: %v", err) + } + pod, numPods, err := GetFirstPod(c, t.Namespace, selector) + if err != nil { + return nil, err + } + if numPods > 1 { + fmt.Fprintf(os.Stderr, "Found %v pods, using pod/%v\n", numPods, pod.Name) + } + + return c.Pods(pod.Namespace).GetLogs(pod.Name, opts), nil + default: gvk, err := api.Scheme.ObjectKind(object) if err != nil { @@ -527,19 +563,22 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { switch t := object.(type) { case *api.ReplicationController: selector := labels.SelectorFromSet(t.Spec.Selector) - return GetFirstPod(client, t.Namespace, selector) + pod, _, err := GetFirstPod(client, t.Namespace, selector) + return pod, err case *extensions.Deployment: selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector) if err != nil { return nil, fmt.Errorf("invalid label selector: %v", err) } - return GetFirstPod(client, t.Namespace, selector) + pod, _, err := GetFirstPod(client, t.Namespace, selector) + return pod, err case *extensions.Job: selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector) if err != nil { return nil, fmt.Errorf("invalid label selector: %v", err) } - return GetFirstPod(client, t.Namespace, selector) + pod, _, err := GetFirstPod(client, t.Namespace, selector) + return pod, err case *api.Pod: return t, nil default: @@ -556,21 +595,21 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { } } -// GetFirstPod returns the first pod of an object from its namespace and selector -func GetFirstPod(client *client.Client, namespace string, selector labels.Selector) (*api.Pod, error) { +// GetFirstPod returns the first pod of an object from its namespace and selector and the number of matching pods +func GetFirstPod(client *client.Client, namespace string, selector labels.Selector) (*api.Pod, int, error) { var pods *api.PodList for pods == nil || len(pods.Items) == 0 { var err error options := api.ListOptions{LabelSelector: selector} if pods, err = client.Pods(namespace).List(options); err != nil { - return nil, err + return nil, 0, err } if len(pods.Items) == 0 { time.Sleep(2 * time.Second) } } pod := &pods.Items[0] - return pod, nil + return pod, len(pods.Items), nil } // Command will stringify and return all environment arguments ie. a command run by a client diff --git a/test/e2e/kubectl.go b/test/e2e/kubectl.go index 5fc9c7cec42..f764faed629 100644 --- a/test/e2e/kubectl.go +++ b/test/e2e/kubectl.go @@ -464,7 +464,7 @@ var _ = Describe("Kubectl client", func() { withStdinData("abcd1234\n"). execOrDie() Expect(runOutput).ToNot(ContainSubstring("stdin closed")) - runTestPod, err := util.GetFirstPod(c, ns, labels.SelectorFromSet(map[string]string{"run": "run-test-3"})) + runTestPod, _, err := util.GetFirstPod(c, ns, labels.SelectorFromSet(map[string]string{"run": "run-test-3"})) if err != nil { os.Exit(1) } @@ -898,6 +898,13 @@ var _ = Describe("Kubectl client", func() { runKubectlOrDie("get", "pods", "-L", "run", nsFlag) Failf("Failed creating 1 pod with expected image %s. Number of pods = %v", nginxImage, len(pods)) } + + By("confirm that you can get logs from an rc") + _, err = runKubectl("logs", "rc/"+rcName, nsFlag) + // a non-nil error is fine as long as we actually found a pod. + if err != nil && !strings.Contains(err.Error(), " in pod ") { + Failf("Failed getting logs by rc %s: %v", rcName, err) + } }) })