1
16
17 package generate
18
19 import (
20 "fmt"
21 "reflect"
22 "strconv"
23 "strings"
24
25 "github.com/spf13/cobra"
26 "github.com/spf13/pflag"
27
28 "k8s.io/apimachinery/pkg/runtime"
29 utilerrors "k8s.io/apimachinery/pkg/util/errors"
30 )
31
32
33 type GeneratorFunc func(cmdName string) map[string]Generator
34
35
36
37 type GeneratorParam struct {
38 Name string
39 Required bool
40 }
41
42
43
44
45 type Generator interface {
46
47 Generate(params map[string]interface{}) (runtime.Object, error)
48
49 ParamNames() []GeneratorParam
50 }
51
52
53 type StructuredGenerator interface {
54
55 StructuredGenerate() (runtime.Object, error)
56 }
57
58 func IsZero(i interface{}) bool {
59 if i == nil {
60 return true
61 }
62 return reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface())
63 }
64
65
66 func ValidateParams(paramSpec []GeneratorParam, params map[string]interface{}) error {
67 allErrs := []error{}
68 for ix := range paramSpec {
69 if paramSpec[ix].Required {
70 value, found := params[paramSpec[ix].Name]
71 if !found || IsZero(value) {
72 allErrs = append(allErrs, fmt.Errorf("Parameter: %s is required", paramSpec[ix].Name))
73 }
74 }
75 }
76 return utilerrors.NewAggregate(allErrs)
77 }
78
79
80 func AnnotateFlags(cmd *cobra.Command, generators map[string]Generator) {
81
82 for name, generator := range generators {
83 generatorParams := map[string]struct{}{}
84 for _, param := range generator.ParamNames() {
85 generatorParams[param.Name] = struct{}{}
86 }
87
88 cmd.Flags().VisitAll(func(flag *pflag.Flag) {
89 if _, found := generatorParams[flag.Name]; !found {
90
91
92 return
93 }
94 if flag.Annotations == nil {
95 flag.Annotations = map[string][]string{}
96 }
97 if annotations := flag.Annotations["generator"]; annotations == nil {
98 flag.Annotations["generator"] = []string{}
99 }
100 flag.Annotations["generator"] = append(flag.Annotations["generator"], name)
101 })
102 }
103 }
104
105
106 func EnsureFlagsValid(cmd *cobra.Command, generators map[string]Generator, generatorInUse string) error {
107 AnnotateFlags(cmd, generators)
108
109 allErrs := []error{}
110 cmd.Flags().VisitAll(func(flag *pflag.Flag) {
111
112 if !flag.Changed {
113 return
114 }
115
116 if annotations := flag.Annotations["generator"]; len(annotations) > 0 {
117 annotationMap := map[string]struct{}{}
118 for _, ann := range annotations {
119 annotationMap[ann] = struct{}{}
120 }
121
122
123 if _, found := annotationMap[generatorInUse]; !found {
124 allErrs = append(allErrs, fmt.Errorf("cannot use --%s with --generator=%s", flag.Name, generatorInUse))
125 }
126 }
127 })
128 return utilerrors.NewAggregate(allErrs)
129 }
130
131
132 func MakeParams(cmd *cobra.Command, params []GeneratorParam) map[string]interface{} {
133 result := map[string]interface{}{}
134 for ix := range params {
135 f := cmd.Flags().Lookup(params[ix].Name)
136 if f != nil {
137 result[params[ix].Name] = f.Value.String()
138 }
139 }
140 return result
141 }
142
143 func MakeProtocols(protocols map[string]string) string {
144 out := []string{}
145 for key, value := range protocols {
146 out = append(out, fmt.Sprintf("%s/%s", key, value))
147 }
148 return strings.Join(out, ",")
149 }
150
151 func ParseProtocols(protocols interface{}) (map[string]string, error) {
152 protocolsString, isString := protocols.(string)
153 if !isString {
154 return nil, fmt.Errorf("expected string, found %v", protocols)
155 }
156 if len(protocolsString) == 0 {
157 return nil, fmt.Errorf("no protocols passed")
158 }
159 portProtocolMap := map[string]string{}
160 protocolsSlice := strings.Split(protocolsString, ",")
161 for ix := range protocolsSlice {
162 portProtocol := strings.Split(protocolsSlice[ix], "/")
163 if len(portProtocol) != 2 {
164 return nil, fmt.Errorf("unexpected port protocol mapping: %s", protocolsSlice[ix])
165 }
166 if len(portProtocol[0]) == 0 {
167 return nil, fmt.Errorf("unexpected empty port")
168 }
169 if len(portProtocol[1]) == 0 {
170 return nil, fmt.Errorf("unexpected empty protocol")
171 }
172 portProtocolMap[portProtocol[0]] = portProtocol[1]
173 }
174 return portProtocolMap, nil
175 }
176
177
178 func ParseLabels(labelSpec interface{}) (map[string]string, error) {
179 labelString, isString := labelSpec.(string)
180 if !isString {
181 return nil, fmt.Errorf("expected string, found %v", labelSpec)
182 }
183 if len(labelString) == 0 {
184 return nil, fmt.Errorf("no label spec passed")
185 }
186 labels := map[string]string{}
187 labelSpecs := strings.Split(labelString, ",")
188 for ix := range labelSpecs {
189 labelSpec := strings.Split(labelSpecs[ix], "=")
190 if len(labelSpec) != 2 {
191 return nil, fmt.Errorf("unexpected label spec: %s", labelSpecs[ix])
192 }
193 if len(labelSpec[0]) == 0 {
194 return nil, fmt.Errorf("unexpected empty label key")
195 }
196 labels[labelSpec[0]] = labelSpec[1]
197 }
198 return labels, nil
199 }
200
201 func GetBool(params map[string]string, key string, defValue bool) (bool, error) {
202 if val, found := params[key]; !found {
203 return defValue, nil
204 } else {
205 return strconv.ParseBool(val)
206 }
207 }
208
View as plain text