2014-10-06 01:24:19 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors All rights reserved.
|
2014-10-06 01:24:19 +00:00
|
|
|
|
|
|
|
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 (
|
2014-10-27 19:56:34 +00:00
|
|
|
"fmt"
|
2014-10-06 01:24:19 +00:00
|
|
|
"io"
|
2015-04-29 23:47:10 +00:00
|
|
|
"strings"
|
2014-10-06 01:24:19 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
"github.com/renstrom/dedent"
|
2014-10-06 01:24:19 +00:00
|
|
|
"github.com/spf13/cobra"
|
2015-04-08 13:34:07 +00:00
|
|
|
|
2015-08-05 22:03:47 +00:00
|
|
|
apierrors "k8s.io/kubernetes/pkg/api/errors"
|
|
|
|
"k8s.io/kubernetes/pkg/api/meta"
|
|
|
|
"k8s.io/kubernetes/pkg/kubectl"
|
|
|
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
|
|
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
|
|
|
"k8s.io/kubernetes/pkg/runtime"
|
2015-10-14 05:18:37 +00:00
|
|
|
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
2014-10-06 01:24:19 +00:00
|
|
|
)
|
|
|
|
|
2015-08-14 18:46:43 +00:00
|
|
|
// DescribeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
|
|
|
|
// referencing the cmd.Flags()
|
|
|
|
type DescribeOptions struct {
|
|
|
|
Filenames []string
|
2016-03-28 19:44:21 +00:00
|
|
|
Recursive bool
|
2015-08-14 18:46:43 +00:00
|
|
|
}
|
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
var (
|
|
|
|
describe_long = dedent.Dedent(`
|
|
|
|
Show details of a specific resource or group of resources.
|
|
|
|
This command joins many API calls together to form a detailed description of a
|
|
|
|
given resource or group of resources.
|
2014-10-06 01:24:19 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
$ kubectl describe TYPE NAME_PREFIX
|
2015-07-07 23:57:37 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
will first check for an exact match on TYPE and NAME_PREFIX. If no such resource
|
|
|
|
exists, it will output details for every resource that has a name prefixed with NAME_PREFIX.
|
2015-07-07 23:57:37 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
`) +
|
|
|
|
kubectl.PossibleResourceTypes
|
2015-07-07 03:14:28 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
describe_example = dedent.Dedent(`
|
|
|
|
# Describe a node
|
|
|
|
kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal
|
2015-04-23 21:21:13 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
# Describe a pod
|
|
|
|
kubectl describe pods/nginx
|
2015-06-12 07:08:28 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
# Describe a pod identified by type and name in "pod.json"
|
|
|
|
kubectl describe -f pod.json
|
2015-07-07 07:31:08 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
# Describe all pods
|
|
|
|
kubectl describe pods
|
2015-08-04 07:12:29 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
# Describe pods by label name=myLabel
|
|
|
|
kubectl describe po -l name=myLabel
|
2015-07-07 23:57:37 +00:00
|
|
|
|
2016-05-20 17:49:56 +00:00
|
|
|
# Describe all pods managed by the 'frontend' replication controller (rc-created pods
|
|
|
|
# get the name of the rc as a prefix in the pod the name).
|
|
|
|
kubectl describe pods frontend`)
|
2015-07-07 23:57:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
2015-08-14 18:46:43 +00:00
|
|
|
options := &DescribeOptions{}
|
2016-04-20 17:27:32 +00:00
|
|
|
describerSettings := &kubectl.DescriberSettings{}
|
2015-08-14 18:46:43 +00:00
|
|
|
|
2016-03-20 18:14:25 +00:00
|
|
|
validArgs := kubectl.DescribableResources()
|
|
|
|
argAliases := kubectl.ResourceAliases(validArgs)
|
|
|
|
|
2015-07-07 23:57:37 +00:00
|
|
|
cmd := &cobra.Command{
|
2015-07-07 07:31:08 +00:00
|
|
|
Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)",
|
2015-07-07 23:57:37 +00:00
|
|
|
Short: "Show details of a specific resource or group of resources",
|
|
|
|
Long: describe_long,
|
|
|
|
Example: describe_example,
|
2014-10-06 01:24:19 +00:00
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
2016-04-20 17:27:32 +00:00
|
|
|
err := RunDescribe(f, out, cmd, args, options, describerSettings)
|
2015-04-07 18:21:25 +00:00
|
|
|
cmdutil.CheckErr(err)
|
2015-03-09 22:08:16 +00:00
|
|
|
},
|
2016-03-20 18:14:25 +00:00
|
|
|
ValidArgs: validArgs,
|
|
|
|
ArgAliases: argAliases,
|
2015-03-09 22:08:16 +00:00
|
|
|
}
|
2015-07-07 07:31:08 +00:00
|
|
|
usage := "Filename, directory, or URL to a file containing the resource to describe"
|
2015-08-14 18:46:43 +00:00
|
|
|
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
2016-03-28 19:44:21 +00:00
|
|
|
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
|
2015-06-12 07:08:28 +00:00
|
|
|
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
2016-04-20 17:27:32 +00:00
|
|
|
cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.")
|
2016-03-10 01:27:19 +00:00
|
|
|
cmdutil.AddInclude3rdPartyFlags(cmd)
|
2015-03-09 22:08:16 +00:00
|
|
|
return cmd
|
|
|
|
}
|
2015-01-02 18:08:37 +00:00
|
|
|
|
2016-04-20 17:27:32 +00:00
|
|
|
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions, describerSettings *kubectl.DescriberSettings) error {
|
2015-06-12 07:08:28 +00:00
|
|
|
selector := cmdutil.GetFlagString(cmd, "selector")
|
2015-07-07 07:31:08 +00:00
|
|
|
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
2015-03-09 22:08:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-08-14 18:46:43 +00:00
|
|
|
if len(args) == 0 && len(options.Filenames) == 0 {
|
2015-07-07 03:14:28 +00:00
|
|
|
fmt.Fprint(out, "You must specify the type of resource to describe. ", valid_resources)
|
|
|
|
return cmdutil.UsageError(cmd, "Required resource not specified.")
|
|
|
|
}
|
|
|
|
|
2016-03-10 01:27:19 +00:00
|
|
|
mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
|
2015-12-21 05:37:49 +00:00
|
|
|
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
2015-04-08 13:34:07 +00:00
|
|
|
ContinueOnError().
|
|
|
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
2016-03-28 19:44:21 +00:00
|
|
|
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
|
2015-06-12 07:08:28 +00:00
|
|
|
SelectorParam(selector).
|
2015-08-04 07:12:29 +00:00
|
|
|
ResourceTypeOrNameArgs(true, args...).
|
2015-04-08 13:34:07 +00:00
|
|
|
Flatten().
|
|
|
|
Do()
|
|
|
|
err = r.Err()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-10-27 19:56:34 +00:00
|
|
|
|
2015-07-07 07:31:08 +00:00
|
|
|
allErrs := []error{}
|
2015-04-08 13:34:07 +00:00
|
|
|
infos, err := r.Infos()
|
|
|
|
if err != nil {
|
2015-07-07 03:14:28 +00:00
|
|
|
if apierrors.IsNotFound(err) && len(args) == 2 {
|
2016-04-20 17:27:32 +00:00
|
|
|
return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], describerSettings, out, err)
|
2015-04-29 23:47:10 +00:00
|
|
|
}
|
2015-07-07 07:31:08 +00:00
|
|
|
allErrs = append(allErrs, err)
|
2015-04-08 13:34:07 +00:00
|
|
|
}
|
2015-03-09 22:08:16 +00:00
|
|
|
|
2015-06-12 07:08:28 +00:00
|
|
|
for _, info := range infos {
|
2015-07-07 07:31:08 +00:00
|
|
|
mapping := info.ResourceMapping()
|
|
|
|
describer, err := f.Describer(mapping)
|
|
|
|
if err != nil {
|
|
|
|
allErrs = append(allErrs, err)
|
|
|
|
continue
|
|
|
|
}
|
2016-04-20 17:27:32 +00:00
|
|
|
s, err := describer.Describe(info.Namespace, info.Name, *describerSettings)
|
2015-06-12 07:08:28 +00:00
|
|
|
if err != nil {
|
2015-07-07 07:31:08 +00:00
|
|
|
allErrs = append(allErrs, err)
|
|
|
|
continue
|
2015-06-12 07:08:28 +00:00
|
|
|
}
|
|
|
|
fmt.Fprintf(out, "%s\n\n", s)
|
2015-03-09 22:08:16 +00:00
|
|
|
}
|
2015-06-12 07:08:28 +00:00
|
|
|
|
2015-10-14 05:18:37 +00:00
|
|
|
return utilerrors.NewAggregate(allErrs)
|
2014-10-06 01:24:19 +00:00
|
|
|
}
|
2015-04-29 23:47:10 +00:00
|
|
|
|
2016-04-20 17:27:32 +00:00
|
|
|
func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper, f *cmdutil.Factory, namespace, rsrc, prefix string, describerSettings *kubectl.DescriberSettings, out io.Writer, originalError error) error {
|
2015-12-21 05:37:49 +00:00
|
|
|
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
2015-04-29 23:47:10 +00:00
|
|
|
NamespaceParam(namespace).DefaultNamespace().
|
|
|
|
ResourceTypeOrNameArgs(true, rsrc).
|
|
|
|
SingleResourceType().
|
|
|
|
Flatten().
|
|
|
|
Do()
|
2015-07-07 07:31:08 +00:00
|
|
|
mapping, err := r.ResourceMapping()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
describer, err := f.Describer(mapping)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-04-29 23:47:10 +00:00
|
|
|
infos, err := r.Infos()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-06-30 06:12:58 +00:00
|
|
|
isFound := false
|
2015-04-29 23:47:10 +00:00
|
|
|
for ix := range infos {
|
|
|
|
info := infos[ix]
|
|
|
|
if strings.HasPrefix(info.Name, prefix) {
|
2015-06-30 06:12:58 +00:00
|
|
|
isFound = true
|
2016-04-20 17:27:32 +00:00
|
|
|
s, err := describer.Describe(info.Namespace, info.Name, *describerSettings)
|
2015-04-29 23:47:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
fmt.Fprintf(out, "%s\n", s)
|
|
|
|
}
|
|
|
|
}
|
2015-06-30 06:12:58 +00:00
|
|
|
if !isFound {
|
2015-07-03 07:28:05 +00:00
|
|
|
return originalError
|
2015-06-30 06:12:58 +00:00
|
|
|
}
|
2015-04-29 23:47:10 +00:00
|
|
|
return nil
|
|
|
|
}
|