...

Source file src/k8s.io/cli-runtime/pkg/genericclioptions/template_flags.go

Documentation: k8s.io/cli-runtime/pkg/genericclioptions

     1  /*
     2  Copyright 2018 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 genericclioptions
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"sort"
    23  	"strings"
    24  
    25  	"github.com/spf13/cobra"
    26  
    27  	"k8s.io/cli-runtime/pkg/printers"
    28  )
    29  
    30  // templates are logically optional for specifying a format.
    31  // this allows a user to specify a template format value
    32  // as --output=go-template=
    33  var templateFormats = map[string]bool{
    34  	"template":         true,
    35  	"go-template":      true,
    36  	"go-template-file": true,
    37  	"templatefile":     true,
    38  }
    39  
    40  // GoTemplatePrintFlags provides default flags necessary for template printing.
    41  // Given the following flag values, a printer can be requested that knows
    42  // how to handle printing based on these values.
    43  type GoTemplatePrintFlags struct {
    44  	// indicates if it is OK to ignore missing keys for rendering
    45  	// an output template.
    46  	AllowMissingKeys *bool
    47  	TemplateArgument *string
    48  }
    49  
    50  // AllowedFormats returns slice of string of allowed GoTemplatePrint printing format
    51  func (f *GoTemplatePrintFlags) AllowedFormats() []string {
    52  	formats := make([]string, 0, len(templateFormats))
    53  	for format := range templateFormats {
    54  		formats = append(formats, format)
    55  	}
    56  	sort.Strings(formats)
    57  	return formats
    58  }
    59  
    60  // ToPrinter receives an templateFormat and returns a printer capable of
    61  // handling --template format printing.
    62  // Returns false if the specified templateFormat does not match a template format.
    63  func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) {
    64  	if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 {
    65  		return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat}
    66  	}
    67  
    68  	templateValue := ""
    69  
    70  	if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 {
    71  		for format := range templateFormats {
    72  			format = format + "="
    73  			if strings.HasPrefix(templateFormat, format) {
    74  				templateValue = templateFormat[len(format):]
    75  				templateFormat = format[:len(format)-1]
    76  				break
    77  			}
    78  		}
    79  	} else {
    80  		templateValue = *f.TemplateArgument
    81  	}
    82  
    83  	if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat {
    84  		return nil, NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()}
    85  	}
    86  
    87  	if len(templateValue) == 0 {
    88  		return nil, fmt.Errorf("template format specified but no template given")
    89  	}
    90  
    91  	if templateFormat == "templatefile" || templateFormat == "go-template-file" {
    92  		data, err := os.ReadFile(templateValue)
    93  		if err != nil {
    94  			return nil, fmt.Errorf("error reading --template %s, %v", templateValue, err)
    95  		}
    96  
    97  		templateValue = string(data)
    98  	}
    99  
   100  	p, err := printers.NewGoTemplatePrinter([]byte(templateValue))
   101  	if err != nil {
   102  		return nil, fmt.Errorf("error parsing template %s, %v", templateValue, err)
   103  	}
   104  
   105  	allowMissingKeys := true
   106  	if f.AllowMissingKeys != nil {
   107  		allowMissingKeys = *f.AllowMissingKeys
   108  	}
   109  
   110  	p.AllowMissingKeys(allowMissingKeys)
   111  	return p, nil
   112  }
   113  
   114  // AddFlags receives a *cobra.Command reference and binds
   115  // flags related to template printing to it
   116  func (f *GoTemplatePrintFlags) AddFlags(c *cobra.Command) {
   117  	if f.TemplateArgument != nil {
   118  		c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].")
   119  		c.MarkFlagFilename("template")
   120  	}
   121  	if f.AllowMissingKeys != nil {
   122  		c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.")
   123  	}
   124  }
   125  
   126  // NewGoTemplatePrintFlags returns flags associated with
   127  // --template printing, with default values set.
   128  func NewGoTemplatePrintFlags() *GoTemplatePrintFlags {
   129  	allowMissingKeysPtr := true
   130  	templateValuePtr := ""
   131  
   132  	return &GoTemplatePrintFlags{
   133  		TemplateArgument: &templateValuePtr,
   134  		AllowMissingKeys: &allowMissingKeysPtr,
   135  	}
   136  }
   137  

View as plain text