get_flags.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. Copyright 2018 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package get
  14. import (
  15. "strings"
  16. "github.com/spf13/cobra"
  17. "k8s.io/apimachinery/pkg/api/meta"
  18. "k8s.io/apimachinery/pkg/runtime/schema"
  19. "k8s.io/cli-runtime/pkg/genericclioptions"
  20. "k8s.io/cli-runtime/pkg/printers"
  21. "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
  22. )
  23. // PrintFlags composes common printer flag structs
  24. // used in the Get command.
  25. type PrintFlags struct {
  26. JSONYamlPrintFlags *genericclioptions.JSONYamlPrintFlags
  27. NamePrintFlags *genericclioptions.NamePrintFlags
  28. CustomColumnsFlags *CustomColumnsPrintFlags
  29. HumanReadableFlags *HumanPrintFlags
  30. TemplateFlags *genericclioptions.KubeTemplatePrintFlags
  31. NoHeaders *bool
  32. OutputFormat *string
  33. }
  34. // SetKind sets the Kind option of humanreadable flags
  35. func (f *PrintFlags) SetKind(kind schema.GroupKind) {
  36. f.HumanReadableFlags.SetKind(kind)
  37. }
  38. // EnsureWithNamespace ensures that humanreadable flags return
  39. // a printer capable of printing with a "namespace" column.
  40. func (f *PrintFlags) EnsureWithNamespace() error {
  41. return f.HumanReadableFlags.EnsureWithNamespace()
  42. }
  43. // EnsureWithKind ensures that humanreadable flags return
  44. // a printer capable of including resource kinds.
  45. func (f *PrintFlags) EnsureWithKind() error {
  46. return f.HumanReadableFlags.EnsureWithKind()
  47. }
  48. // Copy returns a copy of PrintFlags for mutation
  49. func (f *PrintFlags) Copy() PrintFlags {
  50. printFlags := *f
  51. return printFlags
  52. }
  53. // AllowedFormats is the list of formats in which data can be displayed
  54. func (f *PrintFlags) AllowedFormats() []string {
  55. formats := f.JSONYamlPrintFlags.AllowedFormats()
  56. formats = append(formats, f.NamePrintFlags.AllowedFormats()...)
  57. formats = append(formats, f.TemplateFlags.AllowedFormats()...)
  58. formats = append(formats, f.CustomColumnsFlags.AllowedFormats()...)
  59. formats = append(formats, f.HumanReadableFlags.AllowedFormats()...)
  60. return formats
  61. }
  62. // UseOpenAPIColumns modifies the output format, as well as the
  63. // "allowMissingKeys" option for template printers, to values
  64. // defined in the OpenAPI schema of a resource.
  65. func (f *PrintFlags) UseOpenAPIColumns(api openapi.Resources, mapping *meta.RESTMapping) error {
  66. // Found openapi metadata for this resource
  67. schema := api.LookupResource(mapping.GroupVersionKind)
  68. if schema == nil {
  69. // Schema not found, return empty columns
  70. return nil
  71. }
  72. columns, found := openapi.GetPrintColumns(schema.GetExtensions())
  73. if !found {
  74. // Extension not found, return empty columns
  75. return nil
  76. }
  77. parts := strings.SplitN(columns, "=", 2)
  78. if len(parts) < 2 {
  79. return nil
  80. }
  81. allowMissingKeys := true
  82. f.OutputFormat = &parts[0]
  83. f.TemplateFlags.TemplateArgument = &parts[1]
  84. f.TemplateFlags.AllowMissingKeys = &allowMissingKeys
  85. return nil
  86. }
  87. // ToPrinter attempts to find a composed set of PrintFlags suitable for
  88. // returning a printer based on current flag values.
  89. func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) {
  90. outputFormat := ""
  91. if f.OutputFormat != nil {
  92. outputFormat = *f.OutputFormat
  93. }
  94. noHeaders := false
  95. if f.NoHeaders != nil {
  96. noHeaders = *f.NoHeaders
  97. }
  98. f.HumanReadableFlags.NoHeaders = noHeaders
  99. f.CustomColumnsFlags.NoHeaders = noHeaders
  100. // for "get.go" we want to support a --template argument given, even when no --output format is provided
  101. if f.TemplateFlags.TemplateArgument != nil && len(*f.TemplateFlags.TemplateArgument) > 0 && len(outputFormat) == 0 {
  102. outputFormat = "go-template"
  103. }
  104. if p, err := f.TemplateFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
  105. return p, err
  106. }
  107. if f.TemplateFlags.TemplateArgument != nil {
  108. f.CustomColumnsFlags.TemplateArgument = *f.TemplateFlags.TemplateArgument
  109. }
  110. if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
  111. return p, err
  112. }
  113. if p, err := f.HumanReadableFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
  114. return p, err
  115. }
  116. if p, err := f.CustomColumnsFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
  117. return p, err
  118. }
  119. if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) {
  120. return p, err
  121. }
  122. return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()}
  123. }
  124. // AddFlags receives a *cobra.Command reference and binds
  125. // flags related to humanreadable and template printing.
  126. func (f *PrintFlags) AddFlags(cmd *cobra.Command) {
  127. f.JSONYamlPrintFlags.AddFlags(cmd)
  128. f.NamePrintFlags.AddFlags(cmd)
  129. f.TemplateFlags.AddFlags(cmd)
  130. f.HumanReadableFlags.AddFlags(cmd)
  131. f.CustomColumnsFlags.AddFlags(cmd)
  132. if f.OutputFormat != nil {
  133. cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].")
  134. }
  135. if f.NoHeaders != nil {
  136. cmd.Flags().BoolVar(f.NoHeaders, "no-headers", *f.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).")
  137. }
  138. }
  139. // NewGetPrintFlags returns flags associated with humanreadable,
  140. // template, and "name" printing, with default values set.
  141. func NewGetPrintFlags() *PrintFlags {
  142. outputFormat := ""
  143. noHeaders := false
  144. return &PrintFlags{
  145. OutputFormat: &outputFormat,
  146. NoHeaders: &noHeaders,
  147. JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(),
  148. NamePrintFlags: genericclioptions.NewNamePrintFlags(""),
  149. TemplateFlags: genericclioptions.NewKubeTemplatePrintFlags(),
  150. HumanReadableFlags: NewHumanPrintFlags(),
  151. CustomColumnsFlags: NewCustomColumnsPrintFlags(),
  152. }
  153. }