k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/util/output/output.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package output 18 19 import ( 20 "fmt" 21 "io" 22 "strings" 23 24 "github.com/spf13/cobra" 25 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/cli-runtime/pkg/genericclioptions" 28 "k8s.io/cli-runtime/pkg/printers" 29 ) 30 31 const ( 32 // TextOutput describes the plain text output 33 TextOutput = "text" 34 35 // JSONOutput describes the JSON output 36 JSONOutput = "json" 37 38 // YAMLOutput describes the YAML output 39 YAMLOutput = "yaml" 40 ) 41 42 // TextPrintFlags is an interface to handle custom text output 43 type TextPrintFlags interface { 44 ToPrinter(outputFormat string) (Printer, error) 45 } 46 47 // PrintFlags composes common printer flag structs 48 // used across kubeadm commands, and provides a method 49 // of retrieving a known printer based on flag values provided. 50 type PrintFlags struct { 51 // JSONYamlPrintFlags provides default flags necessary for json/yaml printing. 52 JSONYamlPrintFlags *genericclioptions.JSONYamlPrintFlags 53 // KubeTemplatePrintFlags composes print flags that provide both a JSONPath and a go-template printer. 54 KubeTemplatePrintFlags *genericclioptions.KubeTemplatePrintFlags 55 // TextPrintFlags provides default flags necessary for kubeadm text printing. 56 TextPrintFlags TextPrintFlags 57 // TypeSetterPrinter is an implementation of ResourcePrinter that wraps another printer with types set on the objects 58 TypeSetterPrinter *printers.TypeSetterPrinter 59 // OutputFormat contains currently set output format 60 OutputFormat *string 61 } 62 63 // AllowedFormats returns a list of allowed output formats 64 func (pf *PrintFlags) AllowedFormats() []string { 65 ret := []string{TextOutput} 66 ret = append(ret, pf.JSONYamlPrintFlags.AllowedFormats()...) 67 ret = append(ret, pf.KubeTemplatePrintFlags.AllowedFormats()...) 68 69 return ret 70 } 71 72 // ToPrinter receives an outputFormat and returns a printer capable of 73 // handling format printing. 74 // Returns error if the specified outputFormat does not match supported formats. 75 func (pf *PrintFlags) ToPrinter() (Printer, error) { 76 outputFormat := "" 77 if pf.OutputFormat != nil { 78 outputFormat = *pf.OutputFormat 79 } 80 81 if pf.TextPrintFlags != nil { 82 if p, err := pf.TextPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { 83 return p, err 84 } 85 } 86 87 if pf.JSONYamlPrintFlags != nil { 88 if p, err := pf.JSONYamlPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { 89 return NewResourcePrinterWrapper(pf.TypeSetterPrinter.WrapToPrinter(p, err)) 90 } 91 } 92 93 if pf.KubeTemplatePrintFlags != nil { 94 if p, err := pf.KubeTemplatePrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { 95 return NewResourcePrinterWrapper(pf.TypeSetterPrinter.WrapToPrinter(p, err)) 96 } 97 } 98 99 return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: pf.OutputFormat, AllowedFormats: pf.AllowedFormats()} 100 } 101 102 // AddFlags receives a *cobra.Command reference and binds 103 // flags related to Kubeadm printing to it 104 func (pf *PrintFlags) AddFlags(cmd *cobra.Command) { 105 pf.JSONYamlPrintFlags.AddFlags(cmd) 106 pf.KubeTemplatePrintFlags.AddFlags(cmd) 107 cmd.Flags().StringVarP(pf.OutputFormat, "output", "o", *pf.OutputFormat, fmt.Sprintf("Output format. One of: %s.", strings.Join(pf.AllowedFormats(), "|"))) 108 cmd.Flags().StringVarP(pf.OutputFormat, "experimental-output", "", *pf.OutputFormat, fmt.Sprintf("Output format. One of: %s.", strings.Join(pf.AllowedFormats(), "|"))) 109 _ = cmd.Flags().MarkDeprecated("experimental-output", "please use --output instead.") 110 } 111 112 // WithDefaultOutput sets a default output format if one is not provided through a flag value 113 func (pf *PrintFlags) WithDefaultOutput(outputFormat string) *PrintFlags { 114 pf.OutputFormat = &outputFormat 115 return pf 116 } 117 118 // WithTypeSetter sets a wrapper than will surround the returned printer with a printer to type resources 119 func (pf *PrintFlags) WithTypeSetter(scheme *runtime.Scheme) *PrintFlags { 120 pf.TypeSetterPrinter = printers.NewTypeSetter(scheme) 121 return pf 122 } 123 124 // NewOutputFlags creates new KubeadmOutputFlags 125 func NewOutputFlags(textPrintFlags TextPrintFlags) *PrintFlags { 126 outputFormat := "" 127 128 pf := &PrintFlags{ 129 OutputFormat: &outputFormat, 130 131 JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(), 132 KubeTemplatePrintFlags: genericclioptions.NewKubeTemplatePrintFlags(), 133 TextPrintFlags: textPrintFlags, 134 } 135 136 // disable deprecated --template option 137 pf.KubeTemplatePrintFlags.TemplateArgument = nil 138 139 return pf 140 } 141 142 // Printer is a common printing interface in Kubeadm 143 type Printer interface { 144 PrintObj(obj runtime.Object, writer io.Writer) error 145 Fprintf(writer io.Writer, format string, args ...interface{}) (n int, err error) 146 Fprintln(writer io.Writer, args ...interface{}) (n int, err error) 147 Printf(format string, args ...interface{}) (n int, err error) 148 Println(args ...interface{}) (n int, err error) 149 } 150 151 // TextPrinter implements Printer interface for generic text output 152 type TextPrinter struct { 153 } 154 155 // PrintObj is an implementation of ResourcePrinter.PrintObj that prints object 156 func (tp *TextPrinter) PrintObj(obj runtime.Object, writer io.Writer) error { 157 _, err := fmt.Fprintf(writer, "%+v\n", obj) 158 return err 159 } 160 161 // Fprintf is a wrapper around fmt.Fprintf 162 func (tp *TextPrinter) Fprintf(writer io.Writer, format string, args ...interface{}) (n int, err error) { 163 return fmt.Fprintf(writer, format, args...) 164 } 165 166 // Fprintln is a wrapper around fmt.Fprintln 167 func (tp *TextPrinter) Fprintln(writer io.Writer, args ...interface{}) (n int, err error) { 168 return fmt.Fprintln(writer, args...) 169 } 170 171 // Printf is a wrapper around fmt.Printf 172 func (tp *TextPrinter) Printf(format string, args ...interface{}) (n int, err error) { 173 return fmt.Printf(format, args...) 174 } 175 176 // Println is a wrapper around fmt.Printf 177 func (tp *TextPrinter) Println(args ...interface{}) (n int, err error) { 178 return fmt.Println(args...) 179 } 180 181 // ResourcePrinterWrapper wraps ResourcePrinter and implements Printer interface 182 type ResourcePrinterWrapper struct { 183 Printer printers.ResourcePrinter 184 } 185 186 // NewResourcePrinterWrapper creates new ResourcePrinter object 187 func NewResourcePrinterWrapper(resourcePrinter printers.ResourcePrinter, err error) (Printer, error) { 188 if err != nil { 189 return nil, err 190 } 191 return &ResourcePrinterWrapper{Printer: resourcePrinter}, nil 192 } 193 194 // PrintObj is an implementation of ResourcePrinter.PrintObj that calls underlying printer API 195 func (rpw *ResourcePrinterWrapper) PrintObj(obj runtime.Object, writer io.Writer) error { 196 return rpw.Printer.PrintObj(obj, writer) 197 } 198 199 // Fprintf is an empty method to satisfy Printer interface 200 // and silent info printing for structured output 201 // This method is usually redefined for the text output 202 func (rpw *ResourcePrinterWrapper) Fprintf(writer io.Writer, format string, args ...interface{}) (n int, err error) { 203 return 0, nil 204 } 205 206 // Fprintln is an empty method to satisfy the Printer interface 207 // and silent info printing for structured output 208 // This method is usually redefined for the text output 209 func (rpw *ResourcePrinterWrapper) Fprintln(writer io.Writer, args ...interface{}) (n int, err error) { 210 return 0, nil 211 } 212 213 // Printf is an empty method to satisfy Printer interface 214 // and silent info printing for structured output 215 // This method is usually redefined for the text output 216 func (rpw *ResourcePrinterWrapper) Printf(format string, args ...interface{}) (n int, err error) { 217 return 0, nil 218 } 219 220 // Println is an empty method to satisfy Printer interface 221 // and silent info printing for structured output 222 // This method is usually redefined for the text output 223 func (rpw *ResourcePrinterWrapper) Println(args ...interface{}) (n int, err error) { 224 return 0, nil 225 }