mirror of https://github.com/k3s-io/k3s
Kubectl describe command accepts a filename param
parent
d04fce045e
commit
2ca200f087
|
@ -275,6 +275,12 @@ _kubectl_describe()
|
|||
flags_with_completion=()
|
||||
flags_completion=()
|
||||
|
||||
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+=("--selector=")
|
||||
|
|
|
@ -34,6 +34,10 @@ namespaces (ns) or secrets.
|
|||
|
||||
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
\fB\-f\fP, \fB\-\-filename\fP=[]
|
||||
Filename, directory, or URL to a file containing the resource to describe
|
||||
|
||||
.PP
|
||||
\fB\-h\fP, \fB\-\-help\fP=false
|
||||
help for describe
|
||||
|
@ -152,6 +156,9 @@ $ kubectl describe nodes kubernetes\-minion\-emt8.c.myproject.internal
|
|||
// Describe a pod
|
||||
$ kubectl describe pods/nginx
|
||||
|
||||
// Describe a pod using the data in pod.json.
|
||||
$ kubectl describe \-f pod.json
|
||||
|
||||
// Describe pods by label name=myLabel
|
||||
$ kubectl describe po \-l name=myLabel
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ kubectl api-versions
|
|||
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-08-05 23:27:50.890645232 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-08-07 07:32:08.138043968 +0000 UTC
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_api-versions.md?pixel)]()
|
||||
|
|
|
@ -54,7 +54,7 @@ persistentvolumes (pv), persistentvolumeclaims (pvc), resourcequotas (quota),
|
|||
namespaces (ns) or secrets.
|
||||
|
||||
```
|
||||
kubectl describe (TYPE [(NAME_PREFIX | -l label] | TYPE/NAME)
|
||||
kubectl describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
@ -66,6 +66,9 @@ $ kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal
|
|||
// Describe a pod
|
||||
$ kubectl describe pods/nginx
|
||||
|
||||
// Describe a pod using the data in pod.json.
|
||||
$ kubectl describe -f pod.json
|
||||
|
||||
// Describe pods by label name=myLabel
|
||||
$ kubectl describe po -l name=myLabel
|
||||
|
||||
|
@ -77,6 +80,7 @@ $ kubectl describe pods frontend
|
|||
### Options
|
||||
|
||||
```
|
||||
-f, --filename=[]: Filename, directory, or URL to a file containing the resource to describe
|
||||
-h, --help[=false]: help for describe
|
||||
-l, --selector="": Selector (label query) to filter on
|
||||
```
|
||||
|
@ -114,7 +118,7 @@ $ kubectl describe pods frontend
|
|||
|
||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||
|
||||
###### Auto generated by spf13/cobra at 2015-08-05 23:27:50.885301316 +0000 UTC
|
||||
###### Auto generated by spf13/cobra at 2015-08-07 07:32:08.128980687 +0000 UTC
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_describe.md?pixel)]()
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -52,6 +53,9 @@ $ kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal
|
|||
// Describe a pod
|
||||
$ kubectl describe pods/nginx
|
||||
|
||||
// Describe a pod using the data in pod.json.
|
||||
$ kubectl describe -f pod.json
|
||||
|
||||
// Describe pods by label name=myLabel
|
||||
$ kubectl describe po -l name=myLabel
|
||||
|
||||
|
@ -62,7 +66,7 @@ $ kubectl describe pods frontend`
|
|||
|
||||
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "describe (TYPE [(NAME_PREFIX | -l label] | TYPE/NAME)",
|
||||
Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)",
|
||||
Short: "Show details of a specific resource or group of resources",
|
||||
Long: describe_long,
|
||||
Example: describe_example,
|
||||
|
@ -72,18 +76,20 @@ func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||
},
|
||||
ValidArgs: kubectl.DescribableResources(),
|
||||
}
|
||||
usage := "Filename, directory, or URL to a file containing the resource to describe"
|
||||
kubectl.AddJsonFilenameFlag(cmd, usage)
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||
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 describe. ", valid_resources)
|
||||
return cmdutil.UsageError(cmd, "Required resource not specified.")
|
||||
}
|
||||
|
@ -92,6 +98,7 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
|
|||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, filenames...).
|
||||
SelectorParam(selector).
|
||||
ResourceTypeOrNameArgs(false, args...).
|
||||
Flatten().
|
||||
|
@ -100,41 +107,49 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mapping, err := r.ResourceMapping()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
describer, err := f.Describer(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allErrs := []error{}
|
||||
infos, err := r.Infos()
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) && len(args) == 2 {
|
||||
return DescribeMatchingResources(mapper, typer, describer, f, cmdNamespace, args[0], args[1], out, err)
|
||||
return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], out, err)
|
||||
}
|
||||
return err
|
||||
allErrs = append(allErrs, err)
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
mapping := info.ResourceMapping()
|
||||
describer, err := f.Describer(mapping)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, err)
|
||||
continue
|
||||
}
|
||||
s, err := describer.Describe(info.Namespace, info.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
allErrs = append(allErrs, err)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(out, "%s\n\n", s)
|
||||
}
|
||||
|
||||
return nil
|
||||
return errors.NewAggregate(allErrs)
|
||||
}
|
||||
|
||||
func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper, describer kubectl.Describer, f *cmdutil.Factory, namespace, rsrc, prefix string, out io.Writer, originalError error) error {
|
||||
func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper, f *cmdutil.Factory, namespace, rsrc, prefix string, out io.Writer, originalError error) error {
|
||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
ResourceTypeOrNameArgs(true, rsrc).
|
||||
SingleResourceType().
|
||||
Flatten().
|
||||
Do()
|
||||
mapping, err := r.ResourceMapping()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
describer, err := f.Describer(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
infos, err := r.Infos()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -48,3 +48,36 @@ func TestDescribeUnknownSchemaObject(t *testing.T) {
|
|||
t.Errorf("unexpected output: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDescribeObject(t *testing.T) {
|
||||
_, _, rc := testData()
|
||||
f, tf, codec := NewAPIFactory()
|
||||
d := &testDescriber{Output: "test output"}
|
||||
tf.Describer = d
|
||||
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 == "/namespaces/test/replicationcontrollers/redis-master" && m == "GET":
|
||||
return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
|
||||
return nil, nil
|
||||
}
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := NewCmdDescribe(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.yaml")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
if d.Name != "redis-master" || d.Namespace != "test" {
|
||||
t.Errorf("unexpected describer: %#v", d)
|
||||
}
|
||||
|
||||
if buf.String() != fmt.Sprintf("%s\n\n", d.Output) {
|
||||
t.Errorf("unexpected output: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue