...

Source file src/k8s.io/cli-runtime/pkg/genericclioptions/jsonpath_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=jsonpath=
    33  var jsonFormats = map[string]bool{
    34  	"jsonpath":         true,
    35  	"jsonpath-file":    true,
    36  	"jsonpath-as-json": true,
    37  }
    38  
    39  // JSONPathPrintFlags provides default flags necessary for template printing.
    40  // Given the following flag values, a printer can be requested that knows
    41  // how to handle printing based on these values.
    42  type JSONPathPrintFlags struct {
    43  	// indicates if it is OK to ignore missing keys for rendering
    44  	// an output template.
    45  	AllowMissingKeys *bool
    46  	TemplateArgument *string
    47  }
    48  
    49  // AllowedFormats returns slice of string of allowed JSONPath printing format
    50  func (f *JSONPathPrintFlags) AllowedFormats() []string {
    51  	formats := make([]string, 0, len(jsonFormats))
    52  	for format := range jsonFormats {
    53  		formats = append(formats, format)
    54  	}
    55  	sort.Strings(formats)
    56  	return formats
    57  }
    58  
    59  // ToPrinter receives an templateFormat and returns a printer capable of
    60  // handling --template format printing.
    61  // Returns false if the specified templateFormat does not match a template format.
    62  func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) {
    63  	if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 {
    64  		return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat}
    65  	}
    66  
    67  	templateValue := ""
    68  
    69  	if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 {
    70  		for format := range jsonFormats {
    71  			format = format + "="
    72  			if strings.HasPrefix(templateFormat, format) {
    73  				templateValue = templateFormat[len(format):]
    74  				templateFormat = format[:len(format)-1]
    75  				break
    76  			}
    77  		}
    78  	} else {
    79  		templateValue = *f.TemplateArgument
    80  	}
    81  
    82  	if _, supportedFormat := jsonFormats[templateFormat]; !supportedFormat {
    83  		return nil, NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()}
    84  	}
    85  
    86  	if len(templateValue) == 0 {
    87  		return nil, fmt.Errorf("template format specified but no template given")
    88  	}
    89  
    90  	if templateFormat == "jsonpath-file" {
    91  		data, err := os.ReadFile(templateValue)
    92  		if err != nil {
    93  			return nil, fmt.Errorf("error reading --template %s, %v", templateValue, err)
    94  		}
    95  
    96  		templateValue = string(data)
    97  	}
    98  
    99  	p, err := printers.NewJSONPathPrinter(templateValue)
   100  	if err != nil {
   101  		return nil, fmt.Errorf("error parsing jsonpath %s, %v", templateValue, err)
   102  	}
   103  
   104  	allowMissingKeys := true
   105  	if f.AllowMissingKeys != nil {
   106  		allowMissingKeys = *f.AllowMissingKeys
   107  	}
   108  
   109  	p.AllowMissingKeys(allowMissingKeys)
   110  
   111  	if templateFormat == "jsonpath-as-json" {
   112  		p.EnableJSONOutput(true)
   113  	}
   114  
   115  	return p, nil
   116  }
   117  
   118  // AddFlags receives a *cobra.Command reference and binds
   119  // flags related to template printing to it
   120  func (f *JSONPathPrintFlags) AddFlags(c *cobra.Command) {
   121  	if f.TemplateArgument != nil {
   122  		c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when --output=jsonpath, --output=jsonpath-file.")
   123  		c.MarkFlagFilename("template")
   124  	}
   125  	if f.AllowMissingKeys != nil {
   126  		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.")
   127  	}
   128  }
   129  
   130  // NewJSONPathPrintFlags returns flags associated with
   131  // --template printing, with default values set.
   132  func NewJSONPathPrintFlags(templateValue string, allowMissingKeys bool) *JSONPathPrintFlags {
   133  	return &JSONPathPrintFlags{
   134  		TemplateArgument: &templateValue,
   135  		AllowMissingKeys: &allowMissingKeys,
   136  	}
   137  }
   138  

View as plain text