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_with_completion=()
|
||||||
flags_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+=("--help")
|
||||||
flags+=("-h")
|
flags+=("-h")
|
||||||
flags+=("--selector=")
|
flags+=("--selector=")
|
||||||
|
|
|
@ -34,6 +34,10 @@ namespaces (ns) or secrets.
|
||||||
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
.PP
|
||||||
|
\fB\-f\fP, \fB\-\-filename\fP=[]
|
||||||
|
Filename, directory, or URL to a file containing the resource to describe
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-h\fP, \fB\-\-help\fP=false
|
\fB\-h\fP, \fB\-\-help\fP=false
|
||||||
help for describe
|
help for describe
|
||||||
|
@ -152,6 +156,9 @@ $ kubectl describe nodes kubernetes\-minion\-emt8.c.myproject.internal
|
||||||
// Describe a pod
|
// Describe a pod
|
||||||
$ kubectl describe pods/nginx
|
$ kubectl describe pods/nginx
|
||||||
|
|
||||||
|
// Describe a pod using the data in pod.json.
|
||||||
|
$ kubectl describe \-f pod.json
|
||||||
|
|
||||||
// Describe pods by label name=myLabel
|
// Describe pods by label name=myLabel
|
||||||
$ kubectl describe po \-l name=myLabel
|
$ kubectl describe po \-l name=myLabel
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ kubectl api-versions
|
||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [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 -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_api-versions.md?pixel)]()
|
[![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.
|
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
|
### Examples
|
||||||
|
@ -66,6 +66,9 @@ $ kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal
|
||||||
// Describe a pod
|
// Describe a pod
|
||||||
$ kubectl describe pods/nginx
|
$ kubectl describe pods/nginx
|
||||||
|
|
||||||
|
// Describe a pod using the data in pod.json.
|
||||||
|
$ kubectl describe -f pod.json
|
||||||
|
|
||||||
// Describe pods by label name=myLabel
|
// Describe pods by label name=myLabel
|
||||||
$ kubectl describe po -l name=myLabel
|
$ kubectl describe po -l name=myLabel
|
||||||
|
|
||||||
|
@ -77,6 +80,7 @@ $ kubectl describe pods frontend
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
|
-f, --filename=[]: Filename, directory, or URL to a file containing the resource to describe
|
||||||
-h, --help[=false]: help for describe
|
-h, --help[=false]: help for describe
|
||||||
-l, --selector="": Selector (label query) to filter on
|
-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
|
* [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 -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_describe.md?pixel)]()
|
[![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"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
"k8s.io/kubernetes/pkg/util/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -52,6 +53,9 @@ $ kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal
|
||||||
// Describe a pod
|
// Describe a pod
|
||||||
$ kubectl describe pods/nginx
|
$ kubectl describe pods/nginx
|
||||||
|
|
||||||
|
// Describe a pod using the data in pod.json.
|
||||||
|
$ kubectl describe -f pod.json
|
||||||
|
|
||||||
// Describe pods by label name=myLabel
|
// Describe pods by label name=myLabel
|
||||||
$ kubectl describe po -l 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 {
|
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
cmd := &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",
|
Short: "Show details of a specific resource or group of resources",
|
||||||
Long: describe_long,
|
Long: describe_long,
|
||||||
Example: describe_example,
|
Example: describe_example,
|
||||||
|
@ -72,18 +76,20 @@ func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
},
|
},
|
||||||
ValidArgs: kubectl.DescribableResources(),
|
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")
|
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||||
selector := cmdutil.GetFlagString(cmd, "selector")
|
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||||
cmdNamespace, _, err := f.DefaultNamespace()
|
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
filenames := cmdutil.GetFlagStringSlice(cmd, "filename")
|
||||||
if len(args) == 0 {
|
if len(args) == 0 && len(filenames) == 0 {
|
||||||
fmt.Fprint(out, "You must specify the type of resource to describe. ", valid_resources)
|
fmt.Fprint(out, "You must specify the type of resource to describe. ", valid_resources)
|
||||||
return cmdutil.UsageError(cmd, "Required resource not specified.")
|
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()).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||||
ContinueOnError().
|
ContinueOnError().
|
||||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||||
|
FilenameParam(enforceNamespace, filenames...).
|
||||||
SelectorParam(selector).
|
SelectorParam(selector).
|
||||||
ResourceTypeOrNameArgs(false, args...).
|
ResourceTypeOrNameArgs(false, args...).
|
||||||
Flatten().
|
Flatten().
|
||||||
|
@ -100,41 +107,49 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mapping, err := r.ResourceMapping()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
describer, err := f.Describer(mapping)
|
allErrs := []error{}
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
infos, err := r.Infos()
|
infos, err := r.Infos()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if apierrors.IsNotFound(err) && len(args) == 2 {
|
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 {
|
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)
|
s, err := describer.Describe(info.Namespace, info.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
allErrs = append(allErrs, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
fmt.Fprintf(out, "%s\n\n", s)
|
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()).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||||
NamespaceParam(namespace).DefaultNamespace().
|
NamespaceParam(namespace).DefaultNamespace().
|
||||||
ResourceTypeOrNameArgs(true, rsrc).
|
ResourceTypeOrNameArgs(true, rsrc).
|
||||||
SingleResourceType().
|
SingleResourceType().
|
||||||
Flatten().
|
Flatten().
|
||||||
Do()
|
Do()
|
||||||
|
mapping, err := r.ResourceMapping()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
describer, err := f.Describer(mapping)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
infos, err := r.Infos()
|
infos, err := r.Infos()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -48,3 +48,36 @@ func TestDescribeUnknownSchemaObject(t *testing.T) {
|
||||||
t.Errorf("unexpected output: %s", buf.String())
|
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