2014-10-06 01:24:19 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
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-11-01 22:44:03 +00:00
"fmt"
2014-10-06 01:24:19 +00:00
"io"
2016-05-20 17:49:56 +00:00
"github.com/renstrom/dedent"
2015-08-10 11:02:14 +00:00
"github.com/spf13/cobra"
2015-10-13 18:36:22 +00:00
"k8s.io/kubernetes/pkg/api/meta"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
2015-10-20 05:44:48 +00:00
"k8s.io/kubernetes/pkg/runtime"
2016-04-14 22:00:40 +00:00
utilerrors "k8s.io/kubernetes/pkg/util/errors"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/watch"
2014-10-06 01:24:19 +00:00
)
2015-08-14 18:46:43 +00:00
// GetOptions 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 GetOptions 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 (
get_long = dedent . Dedent ( `
Display one or many resources .
2014-10-06 01:24:19 +00:00
2016-05-20 17:49:56 +00:00
` ) + kubectl.PossibleResourceTypes + dedent.Dedent( `
2014-10-06 01:24:19 +00:00
2016-05-20 17:49:56 +00:00
By specifying the output as ' template ' and providing a Go template as the value
of the -- template flag , you can filter the attributes of the fetched resource ( s ) . ` )
get_example = dedent . Dedent ( `
# List all pods in ps output format .
kubectl get pods
2014-10-06 01:24:19 +00:00
2016-05-20 17:49:56 +00:00
# List all pods in ps output format with more information ( such as node name ) .
kubectl get pods - o wide
2015-06-29 18:36:06 +00:00
2016-05-20 17:49:56 +00:00
# List a single replication controller with specified NAME in ps output format .
kubectl get replicationcontroller web
2014-10-06 01:24:19 +00:00
2016-05-20 17:49:56 +00:00
# List a single pod in JSON output format .
kubectl get - o json pod web - pod - 13 je7
2014-12-31 00:42:55 +00:00
2016-05-20 17:49:56 +00:00
# List a pod identified by type and name specified in "pod.yaml" in JSON output format .
kubectl get - f pod . yaml - o json
2015-08-10 11:02:14 +00:00
2016-05-20 17:49:56 +00:00
# Return only the phase value of the specified pod .
kubectl get - o template pod / web - pod - 13 je7 -- template = { { . status . phase } }
2015-02-03 17:59:21 +00:00
2016-05-20 17:49:56 +00:00
# List all replication controllers and services together in ps output format .
kubectl get rc , services
2015-03-25 05:01:07 +00:00
2016-05-20 17:49:56 +00:00
# List one or more resources by their type and names .
kubectl get rc / web service / frontend pods / web - pod - 13 je7 ` )
2015-02-20 21:28:43 +00:00
)
2015-02-03 17:59:21 +00:00
2015-02-20 21:28:43 +00:00
// NewCmdGet creates a command object for the generic "get" action, which
// retrieves one or more resources from a server.
2015-04-07 18:21:25 +00:00
func NewCmdGet ( f * cmdutil . Factory , out io . Writer ) * cobra . Command {
2015-08-14 18:46:43 +00:00
options := & GetOptions { }
2015-03-17 17:01:57 +00:00
2015-09-02 22:38:40 +00:00
// retrieve a list of handled resources from printer as valid args
2016-03-20 18:14:25 +00:00
validArgs , argAliases := [ ] string { } , [ ] string { }
2016-02-04 07:08:44 +00:00
p , err := f . Printer ( nil , false , false , false , false , false , false , [ ] string { } )
2015-09-02 22:38:40 +00:00
cmdutil . CheckErr ( err )
if p != nil {
validArgs = p . HandledResources ( )
2016-03-20 18:14:25 +00:00
argAliases = kubectl . ResourceAliases ( validArgs )
2015-09-02 22:38:40 +00:00
}
2015-02-20 21:28:43 +00:00
cmd := & cobra . Command {
2015-08-21 13:09:41 +00:00
Use : "get [(-o|--output=)json|yaml|wide|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE [NAME | -l label] | TYPE/NAME ...) [flags]" ,
2015-02-20 21:28:43 +00:00
Short : "Display one or many resources" ,
Long : get_long ,
Example : get_example ,
2014-10-06 01:24:19 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2015-08-14 18:46:43 +00:00
err := RunGet ( f , out , cmd , args , options )
2015-04-07 18:21:25 +00:00
cmdutil . CheckErr ( err )
2014-12-31 00:42:55 +00:00
} ,
2016-05-05 00:18:52 +00:00
SuggestFor : [ ] string { "list" , "ps" } ,
2016-03-20 18:14:25 +00:00
ValidArgs : validArgs ,
ArgAliases : argAliases ,
2014-12-31 00:42:55 +00:00
}
2015-04-07 18:21:25 +00:00
cmdutil . AddPrinterFlags ( cmd )
2014-12-31 00:42:55 +00:00
cmd . Flags ( ) . StringP ( "selector" , "l" , "" , "Selector (label query) to filter on" )
cmd . Flags ( ) . BoolP ( "watch" , "w" , false , "After listing/getting the requested object, watch for changes." )
2015-01-18 07:32:34 +00:00
cmd . Flags ( ) . Bool ( "watch-only" , false , "Watch for changes to the requested object(s), without listing/getting first." )
2016-06-29 22:02:08 +00:00
cmd . Flags ( ) . Bool ( "show-kind" , false , "If present, list the resource type for the requested object(s)." )
2015-05-12 11:14:31 +00:00
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." )
2015-08-05 14:21:47 +00:00
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..." )
2015-12-02 20:20:10 +00:00
cmd . Flags ( ) . Bool ( "export" , false , "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information." )
2015-08-10 11:02:14 +00:00
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
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 )
2016-03-10 01:27:19 +00:00
cmdutil . AddInclude3rdPartyFlags ( cmd )
2014-12-31 00:42:55 +00:00
return cmd
}
2014-10-27 19:56:34 +00:00
2014-12-31 00:42:55 +00:00
// RunGet implements the generic Get command
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
2015-08-14 18:46:43 +00:00
func RunGet ( f * cmdutil . Factory , out io . Writer , cmd * cobra . Command , args [ ] string , options * GetOptions ) error {
2015-04-07 18:21:25 +00:00
selector := cmdutil . GetFlagString ( cmd , "selector" )
2015-05-12 11:14:31 +00:00
allNamespaces := cmdutil . GetFlagBool ( cmd , "all-namespaces" )
2016-06-29 22:02:08 +00:00
allKinds := cmdutil . GetFlagBool ( cmd , "show-kind" )
2016-03-10 01:27:19 +00:00
mapper , typer := f . Object ( cmdutil . GetIncludeThirdPartyAPIs ( cmd ) )
2014-12-31 00:42:55 +00:00
2015-08-10 11:02:14 +00:00
cmdNamespace , enforceNamespace , err := f . DefaultNamespace ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2015-01-02 18:08:37 +00:00
2016-02-08 07:47:20 +00:00
if allNamespaces {
enforceNamespace = false
}
2015-08-14 18:46:43 +00:00
if len ( args ) == 0 && len ( options . Filenames ) == 0 {
2015-12-09 10:31:35 +00:00
fmt . Fprint ( out , "You must specify the type of resource to get. " , valid_resources )
2015-07-07 03:14:28 +00:00
return cmdutil . UsageError ( cmd , "Required resource not specified." )
2015-06-09 22:04:56 +00:00
}
2015-12-03 19:32:22 +00:00
// always show resources when getting by name or filename
argsHasNames , err := resource . HasNames ( args )
if err != nil {
return err
}
if len ( options . Filenames ) > 0 || argsHasNames {
cmd . Flag ( "show-all" ) . Value . Set ( "true" )
}
2015-12-02 20:20:10 +00:00
export := cmdutil . GetFlagBool ( cmd , "export" )
2015-12-03 19:32:22 +00:00
2014-12-31 00:42:55 +00:00
// handle watch separately since we cannot watch multiple resource types
2015-04-07 18:21:25 +00:00
isWatch , isWatchOnly := cmdutil . GetFlagBool ( cmd , "watch" ) , cmdutil . GetFlagBool ( cmd , "watch-only" )
2014-12-31 00:42:55 +00:00
if isWatch || isWatchOnly {
2015-12-21 05:37:49 +00:00
r := resource . NewBuilder ( mapper , typer , resource . ClientMapperFunc ( f . ClientForMapping ) , f . Decoder ( true ) ) .
2015-05-12 11:14:31 +00:00
NamespaceParam ( cmdNamespace ) . DefaultNamespace ( ) . AllNamespaces ( allNamespaces ) .
2016-03-28 19:44:21 +00:00
FilenameParam ( enforceNamespace , options . Recursive , options . Filenames ... ) .
2014-12-31 00:42:55 +00:00
SelectorParam ( selector ) .
2015-12-02 20:20:10 +00:00
ExportParam ( export ) .
2015-02-12 14:59:58 +00:00
ResourceTypeOrNameArgs ( true , args ... ) .
2014-12-31 00:42:55 +00:00
SingleResourceType ( ) .
2015-08-10 11:02:14 +00:00
Latest ( ) .
2014-12-31 00:42:55 +00:00
Do ( )
2015-09-09 10:02:22 +00:00
err := r . Err ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2015-08-10 11:02:14 +00:00
infos , err := r . Infos ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2015-08-10 11:02:14 +00:00
if len ( infos ) != 1 {
2015-10-14 22:06:06 +00:00
return fmt . Errorf ( "watch is only supported on individual resources and resource collections - %d resources were found" , len ( infos ) )
2015-08-10 11:02:14 +00:00
}
info := infos [ 0 ]
mapping := info . ResourceMapping ( )
2015-05-12 11:14:31 +00:00
printer , err := f . PrinterForMapping ( cmd , mapping , allNamespaces )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-12-31 00:42:55 +00:00
obj , err := r . Object ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-12-31 00:42:55 +00:00
rv , err := mapping . MetadataAccessor . ResourceVersion ( obj )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-12-31 00:42:55 +00:00
// print the current object
if ! isWatchOnly {
if err := printer . PrintObj ( obj , out ) ; err != nil {
2015-03-09 22:08:16 +00:00
return fmt . Errorf ( "unable to output the provided object: %v" , err )
2014-12-31 00:42:55 +00:00
}
}
2014-10-27 19:56:34 +00:00
2014-12-31 00:42:55 +00:00
// print watched changes
w , err := r . Watch ( rv )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-10-27 19:56:34 +00:00
2014-12-31 00:42:55 +00:00
kubectl . WatchLoop ( w , func ( e watch . Event ) error {
return printer . PrintObj ( e . Object , out )
} )
2015-03-09 22:08:16 +00:00
return nil
2014-12-31 00:42:55 +00:00
}
2014-10-27 19:56:34 +00:00
2016-04-14 22:00:40 +00:00
r := resource . NewBuilder ( mapper , typer , resource . ClientMapperFunc ( f . ClientForMapping ) , f . Decoder ( true ) ) .
2015-05-12 11:14:31 +00:00
NamespaceParam ( cmdNamespace ) . DefaultNamespace ( ) . AllNamespaces ( allNamespaces ) .
2016-03-28 19:44:21 +00:00
FilenameParam ( enforceNamespace , options . Recursive , options . Filenames ... ) .
2014-12-31 00:42:55 +00:00
SelectorParam ( selector ) .
2015-12-02 20:20:10 +00:00
ExportParam ( export ) .
2015-02-12 14:59:58 +00:00
ResourceTypeOrNameArgs ( true , args ... ) .
2015-03-25 05:01:07 +00:00
ContinueOnError ( ) .
2016-04-14 22:00:40 +00:00
Latest ( ) .
Flatten ( ) .
Do ( )
err = r . Err ( )
if err != nil {
return err
}
2015-04-07 18:21:25 +00:00
printer , generic , err := cmdutil . PrinterForCommand ( cmd )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-11-01 22:44:03 +00:00
2016-04-14 22:00:40 +00:00
if generic {
clientConfig , err := f . ClientConfig ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-11-18 18:04:10 +00:00
2016-06-02 06:57:43 +00:00
allErrs := [ ] error { }
2016-04-14 22:00:40 +00:00
singular := false
2016-06-02 06:57:43 +00:00
infos , err := r . IntoSingular ( & singular ) . Infos ( )
if err != nil {
2016-06-30 15:23:48 +00:00
if singular {
return err
}
2016-06-02 06:57:43 +00:00
allErrs = append ( allErrs , err )
}
2016-04-14 22:00:40 +00:00
2015-04-16 23:21:13 +00:00
// the outermost object will be converted to the output-version, but inner
// objects can use their mappings
2015-12-01 16:52:11 +00:00
version , err := cmdutil . OutputVersion ( cmd , clientConfig . GroupVersion )
if err != nil {
return err
}
2016-06-02 06:57:43 +00:00
2016-05-01 00:43:30 +00:00
obj , err := resource . AsVersionedObject ( infos , ! singular , version , f . JSONEncoder ( ) )
2015-04-16 23:21:13 +00:00
if err != nil {
return err
2015-03-04 03:18:15 +00:00
}
2016-06-02 06:57:43 +00:00
if err := printer . PrintObj ( obj , out ) ; err != nil {
allErrs = append ( allErrs , err )
}
return utilerrors . NewAggregate ( allErrs )
}
allErrs := [ ] error { }
infos , err := r . Infos ( )
if err != nil {
allErrs = append ( allErrs , err )
2014-12-31 00:42:55 +00:00
}
2014-11-12 01:31:13 +00:00
2015-10-20 05:44:48 +00:00
objs := make ( [ ] runtime . Object , len ( infos ) )
for ix := range infos {
objs [ ix ] = infos [ ix ] . Object
}
sorting , err := cmd . Flags ( ) . GetString ( "sort-by" )
var sorter * kubectl . RuntimeSort
2016-01-13 17:11:46 +00:00
if err == nil && len ( sorting ) > 0 && len ( objs ) > 1 {
2016-02-29 22:17:48 +00:00
clientConfig , err := f . ClientConfig ( )
if err != nil {
return err
}
version , err := cmdutil . OutputVersion ( cmd , clientConfig . GroupVersion )
if err != nil {
return err
}
for ix := range infos {
2016-05-01 00:43:30 +00:00
objs [ ix ] , err = infos [ ix ] . Mapping . ConvertToVersion ( infos [ ix ] . Object , version )
2016-02-29 22:17:48 +00:00
if err != nil {
2016-04-14 22:00:40 +00:00
allErrs = append ( allErrs , err )
continue
2016-02-29 22:17:48 +00:00
}
}
2015-12-21 05:37:49 +00:00
// TODO: questionable
if sorter , err = kubectl . SortObjects ( f . Decoder ( true ) , objs , sorting ) ; err != nil {
2015-10-20 05:44:48 +00:00
return err
}
}
2014-12-31 00:42:55 +00:00
// use the default printer for each object
2015-10-13 18:36:22 +00:00
printer = nil
var lastMapping * meta . RESTMapping
2016-06-29 22:02:08 +00:00
var withKind bool = allKinds
2015-10-14 01:48:06 +00:00
w := kubectl . GetNewTabWriter ( out )
2015-10-13 18:36:22 +00:00
defer w . Flush ( )
2015-10-20 05:44:48 +00:00
2016-06-29 22:02:08 +00:00
// determine if printing multiple kinds of
// objects and enforce "show-kinds" flag if so
for ix := range objs {
var mapping * meta . RESTMapping
if sorter != nil {
mapping = infos [ sorter . OriginalPosition ( ix ) ] . Mapping
} else {
mapping = infos [ ix ] . Mapping
}
// display "kind" column only if we have mixed resources
if lastMapping != nil && mapping . Resource != lastMapping . Resource {
withKind = true
}
lastMapping = mapping
}
lastMapping = nil
2015-10-20 05:44:48 +00:00
for ix := range objs {
var mapping * meta . RESTMapping
2016-02-29 22:17:48 +00:00
var original runtime . Object
2015-10-20 05:44:48 +00:00
if sorter != nil {
mapping = infos [ sorter . OriginalPosition ( ix ) ] . Mapping
2016-02-29 22:17:48 +00:00
original = infos [ sorter . OriginalPosition ( ix ) ] . Object
2015-10-20 05:44:48 +00:00
} else {
mapping = infos [ ix ] . Mapping
2016-02-29 22:17:48 +00:00
original = infos [ ix ] . Object
2015-06-15 02:48:56 +00:00
}
2015-10-20 05:44:48 +00:00
if printer == nil || lastMapping == nil || mapping == nil || mapping . Resource != lastMapping . Resource {
printer , err = f . PrinterForMapping ( cmd , mapping , allNamespaces )
2015-10-13 18:36:22 +00:00
if err != nil {
2016-04-14 22:00:40 +00:00
allErrs = append ( allErrs , err )
continue
2015-10-13 18:36:22 +00:00
}
2015-10-20 05:44:48 +00:00
lastMapping = mapping
2015-10-13 18:36:22 +00:00
}
2016-06-29 22:02:08 +00:00
if resourcePrinter , found := printer . ( * kubectl . HumanReadablePrinter ) ; found {
resourceName := mapping . Resource
if alias , ok := kubectl . ResourceShortFormFor ( mapping . Resource ) ; ok {
resourceName = alias
} else if resourceName == "" {
resourceName = "none"
}
resourcePrinter . Options . WithKind = withKind
resourcePrinter . Options . KindName = resourceName
2016-02-29 22:17:48 +00:00
if err := printer . PrintObj ( original , w ) ; err != nil {
2016-04-14 22:00:40 +00:00
allErrs = append ( allErrs , err )
2015-10-20 05:44:48 +00:00
}
2015-11-09 05:42:52 +00:00
continue
2015-10-20 05:44:48 +00:00
}
2016-02-29 22:17:48 +00:00
if err := printer . PrintObj ( original , w ) ; err != nil {
2016-04-14 22:00:40 +00:00
allErrs = append ( allErrs , err )
continue
2014-12-31 00:42:55 +00:00
}
2015-10-20 05:44:48 +00:00
}
2016-06-02 06:57:43 +00:00
return utilerrors . NewAggregate ( allErrs )
2014-12-31 00:42:55 +00:00
}