Merge pull request #12511 from feihujiang/kubectlGetAcceptFileNameParam

Kubectl get command accepts a filename param
This commit is contained in:
Brendan Burns 2015-08-14 14:21:56 -07:00
commit eed655a6e6
5 changed files with 103 additions and 9 deletions

View File

@ -230,6 +230,12 @@ _kubectl_get()
flags_completion=()
flags+=("--all-namespaces")
flags+=("--filename=")
flags_with_completion+=("--filename")
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
two_word_flags+=("-f")
flags_with_completion+=("-f")
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--help")
flags+=("-h")
flags+=("--label-columns=")

View File

@ -31,6 +31,10 @@ of the \-\-template flag, you can filter the attributes of the fetched resource(
\fB\-\-all\-namespaces\fP=false
If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with \-\-namespace.
.PP
\fB\-f\fP, \fB\-\-filename\fP=[]
Filename, directory, or URL to a file identifying the resource to get from a server.
.PP
\fB\-h\fP, \fB\-\-help\fP=false
help for get
@ -188,6 +192,9 @@ $ kubectl get replicationcontroller web
# List a single pod in JSON output format.
$ kubectl get \-o json pod web\-pod\-13je7
# List a pod identified by type and name specified in "pod.yaml" in JSON output format.
$ kubectl get \-f pod.yaml \-o json
# Return only the phase value of the specified pod.
$ kubectl get \-o template web\-pod\-13je7 \-\-template={{.status.phase}} \-\-api\-version=v1

View File

@ -67,6 +67,9 @@ $ kubectl get replicationcontroller web
# List a single pod in JSON output format.
$ kubectl get -o json pod web-pod-13je7
# List a pod identified by type and name specified in "pod.yaml" in JSON output format.
$ kubectl get -f pod.yaml -o json
# Return only the phase value of the specified pod.
$ kubectl get -o template web-pod-13je7 --template={{.status.phase}} --api-version=v1
@ -81,6 +84,7 @@ $ kubectl get rc/web service/frontend pods/web-pod-13je7
```
--all-namespaces[=false]: If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.
-f, --filename=[]: Filename, directory, or URL to a file identifying the resource to get from a server.
-h, --help[=false]: help for get
-L, --label-columns=[]: Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag statements like -L label1 -L label2...
--no-headers[=false]: When using the default output, don't print headers.
@ -126,7 +130,7 @@ $ kubectl get rc/web service/frontend pods/web-pod-13je7
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra at 2015-08-12 23:41:01.301023165 +0000 UTC
###### Auto generated by spf13/cobra at 2015-08-13 06:12:05.386038784 +0000 UTC
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_get.md?pixel)]()

View File

@ -20,12 +20,11 @@ import (
"fmt"
"io"
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/watch"
"github.com/spf13/cobra"
)
const (
@ -50,6 +49,9 @@ $ kubectl get replicationcontroller web
# List a single pod in JSON output format.
$ kubectl get -o json pod web-pod-13je7
# List a pod identified by type and name specified in "pod.yaml" in JSON output format.
$ kubectl get -f pod.yaml -o json
# Return only the phase value of the specified pod.
$ kubectl get -o template web-pod-13je7 --template={{.status.phase}} --api-version=v1
@ -83,6 +85,8 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.")
cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
cmd.Flags().StringSliceP("label-columns", "L", []string{}, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag statements like -L label1 -L label2...")
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, usage)
return cmd
}
@ -93,12 +97,14 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces")
mapper, typer := f.Object()
cmdNamespace, _, err := f.DefaultNamespace()
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
return err
}
if len(args) == 0 {
filenames := cmdutil.GetFlagStringSlice(cmd, "filename")
if len(args) == 0 && len(filenames) == 0 {
fmt.Fprint(out, "You must specify the type of resource to get. ", valid_resources, ` * componentstatuses (aka 'cs')
* endpoints (aka 'ep')
`)
@ -110,19 +116,24 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
if isWatch || isWatchOnly {
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
FilenameParam(enforceNamespace, filenames...).
SelectorParam(selector).
ResourceTypeOrNameArgs(true, args...).
SingleResourceType().
Latest().
Do()
if err != nil {
return err
}
mapping, err := r.ResourceMapping()
infos, err := r.Infos()
if err != nil {
return err
}
if len(infos) != 1 {
return fmt.Errorf("watch is only supported on a single resource - %d resources were found", len(infos))
}
info := infos[0]
mapping := info.ResourceMapping()
printer, err := f.PrinterForMapping(cmd, mapping, allNamespaces)
if err != nil {
return err
@ -132,7 +143,6 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
if err != nil {
return err
}
rv, err := mapping.MetadataAccessor.ResourceVersion(obj)
if err != nil {
return err
@ -159,6 +169,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
FilenameParam(enforceNamespace, filenames...).
SelectorParam(selector).
ResourceTypeOrNameArgs(true, args...).
ContinueOnError().

View File

@ -275,6 +275,33 @@ func TestGetObjects(t *testing.T) {
}
}
func TestGetObjectsIdentifiedByFile(t *testing.T) {
pods, _, _ := testData()
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
tf.Client = &client.FakeRESTClient{
Codec: codec,
Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])},
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd.SetOutput(buf)
cmd.Flags().Set("filename", "../../../examples/cassandra/cassandra.yaml")
cmd.Run(cmd, []string{})
expected := []runtime.Object{&pods.Items[0]}
actual := tf.Printer.(*testPrinter).Objects
if !reflect.DeepEqual(expected, actual) {
t.Errorf("unexpected object: %#v", actual)
}
if len(buf.String()) == 0 {
t.Errorf("unexpected empty output")
}
}
func TestGetListObjects(t *testing.T) {
pods, _, _ := testData()
@ -635,6 +662,45 @@ func TestWatchResource(t *testing.T) {
}
}
func TestWatchResourceIdentifiedByFile(t *testing.T) {
pods, events := watchTestData()
f, tf, codec := NewAPIFactory()
tf.Printer = &testPrinter{}
tf.Client = &client.FakeRESTClient{
Codec: codec,
Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods/cassandra":
return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil
case "/watch/namespaces/test/pods/cassandra":
return &http.Response{StatusCode: 200, Body: watchBody(codec, events)}, nil
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch", "true")
cmd.Flags().Set("filename", "../../../examples/cassandra/cassandra.yaml")
cmd.Run(cmd, []string{})
expected := []runtime.Object{&pods[0], events[0].Object, events[1].Object}
actual := tf.Printer.(*testPrinter).Objects
if !reflect.DeepEqual(expected, actual) {
t.Errorf("expected object: %#v unexpected object: %#v", expected, actual)
}
if len(buf.String()) == 0 {
t.Errorf("unexpected empty output")
}
}
func TestWatchOnlyResource(t *testing.T) {
pods, events := watchTestData()