mirror of https://github.com/k3s-io/k3s
Prompt the user to select a container if they don't provide one
and we can't infer it.pull/6/head
parent
74c0dd179e
commit
eefaafc214
|
@ -24,6 +24,7 @@ $ kubectl log -f 123456-7890 ruby-container
|
|||
|
||||
```
|
||||
-f, --follow=false: Specify if the logs should be streamed.
|
||||
--interactive=true: If true, prompt the user for input when required. Default true.
|
||||
```
|
||||
|
||||
### Options inherrited from parent commands
|
||||
|
|
|
@ -21,6 +21,10 @@ Print the logs for a container in a pod. If the pod has only one container, the
|
|||
\fB\-f\fP, \fB\-\-follow\fP=false
|
||||
Specify if the logs should be streamed.
|
||||
|
||||
.PP
|
||||
\fB\-\-interactive\fP=true
|
||||
If true, prompt the user for input when required. Default true.
|
||||
|
||||
|
||||
.SH OPTIONS INHERITED FROM PARENT COMMANDS
|
||||
.PP
|
||||
|
|
|
@ -17,10 +17,14 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
libutil "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -32,6 +36,28 @@ $ kubectl log 123456-7890 ruby-container
|
|||
$ kubectl log -f 123456-7890 ruby-container`
|
||||
)
|
||||
|
||||
func selectContainer(pod *api.Pod, in io.Reader, out io.Writer) string {
|
||||
fmt.Fprintf(out, "Please select a container:\n")
|
||||
options := libutil.StringSet{}
|
||||
for ix := range pod.Spec.Containers {
|
||||
fmt.Fprintf(out, "[%d] %s\n", ix+1, pod.Spec.Containers[ix].Name)
|
||||
options.Insert(pod.Spec.Containers[ix].Name)
|
||||
}
|
||||
for {
|
||||
var input string
|
||||
fmt.Fprintf(out, "> ")
|
||||
fmt.Fscanln(in, &input)
|
||||
if options.Has(input) {
|
||||
return input
|
||||
}
|
||||
ix, err := strconv.Atoi(input)
|
||||
if err == nil && ix > 0 && ix <= len(pod.Spec.Containers) {
|
||||
return pod.Spec.Containers[ix-1].Name
|
||||
}
|
||||
fmt.Fprintf(out, "Invalid input: %s", input)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "log [-f] <pod> [<container>]",
|
||||
|
@ -60,11 +86,15 @@ func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
|||
var container string
|
||||
if len(args) == 1 {
|
||||
if len(pod.Spec.Containers) != 1 {
|
||||
usageError(cmd, "<container> is required for pods with multiple containers")
|
||||
if !util.GetFlagBool(cmd, "interactive") {
|
||||
usageError(cmd, "<container> is required for pods with multiple containers")
|
||||
} else {
|
||||
container = selectContainer(pod, os.Stdin, out)
|
||||
}
|
||||
} else {
|
||||
// Get logs for the only container in the pod
|
||||
container = pod.Spec.Containers[0].Name
|
||||
}
|
||||
|
||||
// Get logs for the only container in the pod
|
||||
container = pod.Spec.Containers[0].Name
|
||||
} else {
|
||||
container = args[1]
|
||||
}
|
||||
|
@ -89,5 +119,6 @@ func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
|||
},
|
||||
}
|
||||
cmd.Flags().BoolP("follow", "f", false, "Specify if the logs should be streamed.")
|
||||
cmd.Flags().Bool("interactive", true, "If true, prompt the user for input when required. Default true.")
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestSelectContainer(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
pod api.Pod
|
||||
expectedContainer string
|
||||
}{
|
||||
{
|
||||
input: "1\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
{
|
||||
input: "foo\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
{
|
||||
input: "foo\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
{
|
||||
input: "2\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
{
|
||||
input: "-1\n2\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
{
|
||||
input: "3\n2\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
{
|
||||
input: "baz\n2\n",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedContainer: "foo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var buff bytes.Buffer
|
||||
container := selectContainer(&test.pod, bytes.NewBufferString(test.input), &buff)
|
||||
if container != test.expectedContainer {
|
||||
t.Errorf("unexpected output: %s for input: %s", container, test.input)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue