1/*
2Copyright 2018 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package get
18
19import (
20	"fmt"
21	"os"
22	"strings"
23
24	"github.com/spf13/cobra"
25
26	"k8s.io/cli-runtime/pkg/genericclioptions"
27	"k8s.io/cli-runtime/pkg/printers"
28	"k8s.io/kubectl/pkg/scheme"
29)
30
31var columnsFormats = map[string]bool{
32	"custom-columns-file": true,
33	"custom-columns":      true,
34}
35
36// CustomColumnsPrintFlags provides default flags necessary for printing
37// custom resource columns from an inline-template or file.
38type CustomColumnsPrintFlags struct {
39	NoHeaders        bool
40	TemplateArgument string
41}
42
43func (f *CustomColumnsPrintFlags) AllowedFormats() []string {
44	formats := make([]string, 0, len(columnsFormats))
45	for format := range columnsFormats {
46		formats = append(formats, format)
47	}
48	return formats
49}
50
51// ToPrinter receives an templateFormat and returns a printer capable of
52// handling custom-column printing.
53// Returns false if the specified templateFormat does not match a supported format.
54// Supported format types can be found in pkg/printers/printers.go
55func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) {
56	if len(templateFormat) == 0 {
57		return nil, genericclioptions.NoCompatiblePrinterError{}
58	}
59
60	templateValue := ""
61
62	if len(f.TemplateArgument) == 0 {
63		for format := range columnsFormats {
64			format = format + "="
65			if strings.HasPrefix(templateFormat, format) {
66				templateValue = templateFormat[len(format):]
67				templateFormat = format[:len(format)-1]
68				break
69			}
70		}
71	} else {
72		templateValue = f.TemplateArgument
73	}
74
75	if _, supportedFormat := columnsFormats[templateFormat]; !supportedFormat {
76		return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()}
77	}
78
79	if len(templateValue) == 0 {
80		return nil, fmt.Errorf("custom-columns format specified but no custom columns given")
81	}
82
83	// UniversalDecoder call must specify parameter versions; otherwise it will decode to internal versions.
84	decoder := scheme.Codecs.UniversalDecoder(scheme.Scheme.PrioritizedVersionsAllGroups()...)
85
86	if templateFormat == "custom-columns-file" {
87		file, err := os.Open(templateValue)
88		if err != nil {
89			return nil, fmt.Errorf("error reading template %s, %v\n", templateValue, err)
90		}
91		defer file.Close()
92		p, err := NewCustomColumnsPrinterFromTemplate(file, decoder)
93		return p, err
94	}
95
96	return NewCustomColumnsPrinterFromSpec(templateValue, decoder, f.NoHeaders)
97}
98
99// AddFlags receives a *cobra.Command reference and binds
100// flags related to custom-columns printing
101func (f *CustomColumnsPrintFlags) AddFlags(c *cobra.Command) {}
102
103// NewCustomColumnsPrintFlags returns flags associated with
104// custom-column printing, with default values set.
105// NoHeaders and TemplateArgument should be set by callers.
106func NewCustomColumnsPrintFlags() *CustomColumnsPrintFlags {
107	return &CustomColumnsPrintFlags{
108		NoHeaders:        false,
109		TemplateArgument: "",
110	}
111}
112