From 556faa45900512e3727e7641108889909c9b448f Mon Sep 17 00:00:00 2001 From: Cesar Wong Date: Thu, 23 Apr 2015 14:11:42 -0400 Subject: [PATCH] Switch kubelet log command to use pod log subresource --- pkg/kubectl/cmd/log.go | 11 +++-- pkg/kubectl/cmd/log_test.go | 86 +++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/pkg/kubectl/cmd/log.go b/pkg/kubectl/cmd/log.go index 1c55c028bd..869a4e3457 100644 --- a/pkg/kubectl/cmd/log.go +++ b/pkg/kubectl/cmd/log.go @@ -57,6 +57,7 @@ func selectContainer(pod *api.Pod, in io.Reader, out io.Writer) string { } } +// NewCmdLog creates a new pod log command func NewCmdLog(f *cmdutil.Factory, out io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "log [-f] POD [CONTAINER]", @@ -73,6 +74,7 @@ func NewCmdLog(f *cmdutil.Factory, out io.Writer) *cobra.Command { return cmd } +// RunLog retrieves a pod log func RunLog(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 { return cmdutil.UsageError(cmd, "POD is required for log") @@ -114,11 +116,12 @@ func RunLog(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string } readCloser, err := client.RESTClient.Get(). - Prefix("proxy"). - Resource("nodes"). - Name(pod.Spec.Host). - Suffix("containerLogs", namespace, podID, container). + Namespace(namespace). + Name(podID). + Resource("pods"). + SubResource("log"). Param("follow", strconv.FormatBool(follow)). + Param("container", container). Stream() if err != nil { return err diff --git a/pkg/kubectl/cmd/log_test.go b/pkg/kubectl/cmd/log_test.go index fcd93191a8..eaa45cd7e6 100644 --- a/pkg/kubectl/cmd/log_test.go +++ b/pkg/kubectl/cmd/log_test.go @@ -18,9 +18,12 @@ package cmd import ( "bytes" + "io/ioutil" + "net/http" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client" ) func TestSelectContainer(t *testing.T) { @@ -145,3 +148,86 @@ func TestSelectContainer(t *testing.T) { } } } + +func TestLog(t *testing.T) { + + tests := []struct { + name, version, podPath, logPath, container string + nsInQuery bool + pod *api.Pod + }{ + { + name: "v1beta1 - pod log", + version: "v1beta1", + podPath: "/api/v1beta1/pods/foo", + logPath: "/api/v1beta1/pods/foo/log", + nsInQuery: true, + pod: testPod(), + }, + { + name: "v1beta3 - pod log", + version: "v1beta3", + podPath: "/api/v1beta3/namespaces/test/pods/foo", + logPath: "/api/v1beta3/namespaces/test/pods/foo/log", + nsInQuery: false, + pod: testPod(), + }, + } + for _, test := range tests { + logContent := "test log content" + f, tf, codec := NewAPIFactory() + tf.Client = &client.FakeRESTClient{ + Codec: codec, + Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.podPath && m == "GET": + if test.nsInQuery { + if ns := req.URL.Query().Get("namespace"); ns != "test" { + t.Errorf("%s: did not get expected namespace: %s\n", test.name, ns) + } + } + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Body: body}, nil + case p == test.logPath && m == "GET": + if test.nsInQuery { + if ns := req.URL.Query().Get("namespace"); ns != "test" { + t.Errorf("%s: did not get expected namespace: %s\n", test.name, ns) + } + } + body := ioutil.NopCloser(bytes.NewBufferString(logContent)) + return &http.Response{StatusCode: 200, Body: body}, nil + default: + // Ensures no GET is performed when deleting by name + t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) + return nil, nil + } + }), + } + tf.Namespace = "test" + tf.ClientConfig = &client.Config{Version: test.version} + buf := bytes.NewBuffer([]byte{}) + + cmd := NewCmdLog(f, buf) + cmd.Flags().Set("namespace", "test") + cmd.Run(cmd, []string{"foo"}) + + if buf.String() != logContent { + t.Errorf("%s: did not get expected log content. Got: %s", test.name, buf.String()) + } + } +} + +func testPod() *api.Pod { + return &api.Pod{ + ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicyAlways, + DNSPolicy: api.DNSClusterFirst, + Containers: []api.Container{ + { + Name: "bar", + }, + }, + }, + } +}