6
6
)
7
7
8
8
// RenderTemplates returns an []string to render the templates
9
+ //
10
+ // Deprecated: this should be removed when we remove APIServer.Args.
9
11
func RenderTemplates (argTemplates []string , data interface {}) (args []string , err error ) {
10
12
var t * template.Template
11
13
@@ -27,3 +29,216 @@ func RenderTemplates(argTemplates []string, data interface{}) (args []string, er
27
29
28
30
return
29
31
}
32
+
33
+ // EmptyArguments constructs an empty set of flags with no defaults.
34
+ func EmptyArguments () * Arguments {
35
+ return & Arguments {
36
+ values : make (map [string ]Arg ),
37
+ }
38
+ }
39
+
40
+ // Arguments are structured, overridable arguments.
41
+ // Each Arguments object contains some set of default arguments, which may
42
+ // be appended to, or overridden.
43
+ //
44
+ // When ready, you can serialize them to pass to exec.Command and friends using
45
+ // AsStrings.
46
+ //
47
+ // All flag-setting methods return the *same* instance of Arguments so that you
48
+ // can chain calls.
49
+ type Arguments struct {
50
+ // values contains the user-set values for the arguments.
51
+ // `values[key] = dontPass` means "don't pass this flag"
52
+ // `values[key] = passAsName` means "pass this flag without args like --key`
53
+ // `values[key] = []string{a, b, c}` means "--key=a --key=b --key=c`
54
+ // any values not explicitly set here will be copied from defaults on final rendering.
55
+ values map [string ]Arg
56
+ }
57
+
58
+ // Arg is an argument that has one or more values,
59
+ // and optionally falls back to default values.
60
+ type Arg interface {
61
+ // Append adds new values to this argument, returning
62
+ // a new instance contain the new value. The intermediate
63
+ // argument should generally be assumed to be consumed.
64
+ Append (vals ... string ) Arg
65
+ // Get returns the full set of values, optionally including
66
+ // the passed in defaults. If it returns nil, this will be
67
+ // skipped. If it returns a non-nil empty slice, it'll be
68
+ // assumed that the argument should be passed as name-only.
69
+ Get (defaults []string ) []string
70
+ }
71
+
72
+ type userArg []string
73
+
74
+ func (a userArg ) Append (vals ... string ) Arg {
75
+ return userArg (append (a , vals ... ))
76
+ }
77
+ func (a userArg ) Get (_ []string ) []string {
78
+ return []string (a )
79
+ }
80
+
81
+ type defaultedArg []string
82
+
83
+ func (a defaultedArg ) Append (vals ... string ) Arg {
84
+ return defaultedArg (append (a , vals ... ))
85
+ }
86
+ func (a defaultedArg ) Get (defaults []string ) []string {
87
+ res := append ([]string (nil ), defaults ... )
88
+ return append (res , a ... )
89
+ }
90
+
91
+ type dontPassArg struct {}
92
+
93
+ func (a dontPassArg ) Append (vals ... string ) Arg {
94
+ return userArg (vals )
95
+ }
96
+ func (dontPassArg ) Get (_ []string ) []string {
97
+ return nil
98
+ }
99
+
100
+ type passAsNameArg struct {}
101
+
102
+ func (a passAsNameArg ) Append (_ ... string ) Arg {
103
+ return passAsNameArg {}
104
+ }
105
+ func (passAsNameArg ) Get (_ []string ) []string {
106
+ return []string {}
107
+ }
108
+
109
+ var (
110
+ // DontPass indicates that the given argument will not actually be
111
+ // rendered.
112
+ DontPass Arg = dontPassArg {}
113
+ // PassAsName indicates that the given flag will be passed as `--key`
114
+ // without any value.
115
+ PassAsName Arg = passAsNameArg {}
116
+ )
117
+
118
+ // AsStrings serializes this set of arguments to a slice of strings appropriate
119
+ // for passing to exec.Command and friends, making use of the given defaults
120
+ // as indicated for each particular argument.
121
+ //
122
+ // - Any flag in defaults that's not in Arguments will be present in the output
123
+ // - Any flag that's present in Arguments will be passed the corresponding
124
+ // defaults to do with as it will (ignore, append-to, suppress, etc).
125
+ func (a * Arguments ) AsStrings (defaults map [string ][]string ) []string {
126
+ // sort for deterministic ordering
127
+ keysInOrder := make ([]string , 0 , len (defaults )+ len (a .values ))
128
+ for key := range defaults {
129
+ if _ , userSet := a .values [key ]; userSet {
130
+ continue
131
+ }
132
+ keysInOrder = append (keysInOrder , key )
133
+ }
134
+ for key := range a .values {
135
+ keysInOrder = append (keysInOrder , key )
136
+ }
137
+ sort .Strings (keysInOrder )
138
+
139
+ var res []string
140
+ for _ , key := range keysInOrder {
141
+ vals := a .Get (key ).Get (defaults [key ])
142
+ switch {
143
+ case vals == nil : // don't pass
144
+ continue
145
+ case len (vals ) == 0 : // pass as name
146
+ res = append (res , "--" + key )
147
+ default :
148
+ for _ , val := range vals {
149
+ res = append (res , "--" + key + "=" + val )
150
+ }
151
+ }
152
+ }
153
+
154
+ return res
155
+ }
156
+
157
+ // Get returns the value of the given flag. If nil,
158
+ // it will not be passed in AsString, otherwise:
159
+ //
160
+ // len == 0 --> `--key`, len > 0 --> `--key=val1 --key=val2 ...`
161
+ func (a * Arguments ) Get (key string ) Arg {
162
+ if vals , ok := a .values [key ]; ok {
163
+ return vals
164
+ }
165
+ return defaultedArg (nil )
166
+ }
167
+
168
+ // Enable configures the given key to be passed as a "name-only" flag,
169
+ // like, `--key`.
170
+ func (a * Arguments ) Enable (key string ) * Arguments {
171
+ a .values [key ] = PassAsName
172
+ return a
173
+ }
174
+
175
+ // Disable prevents this flag from be passed.
176
+ func (a * Arguments ) Disable (key string ) * Arguments {
177
+ a .values [key ] = DontPass
178
+ return a
179
+ }
180
+
181
+ // Append adds additional values to this flag. If this flag has
182
+ // yet to be set, initial values will include defaults. If you want
183
+ // to intentionally ignore defaults/start from scratch, call AppendNoDefaults.
184
+ //
185
+ // Multiple values will look like `--key=value1 --key=value2 ...`.
186
+ func (a * Arguments ) Append (key string , values ... string ) * Arguments {
187
+ vals , present := a .values [key ]
188
+ if ! present {
189
+ vals = defaultedArg {}
190
+ }
191
+ a .values [key ] = vals .Append (values ... )
192
+ return a
193
+ }
194
+
195
+ // AppendNoDefaults adds additional values to this flag. However,
196
+ // unlike Append, it will *not* copy values from defaults.
197
+ func (a * Arguments ) AppendNoDefaults (key string , values ... string ) * Arguments {
198
+ vals , present := a .values [key ]
199
+ if ! present {
200
+ vals = userArg {}
201
+ }
202
+ a .values [key ] = vals .Append (values ... )
203
+ return a
204
+ }
205
+
206
+ // Set resets the given flag to the specified values, ignoring any existing
207
+ // values or defaults.
208
+ func (a * Arguments ) Set (key string , values ... string ) * Arguments {
209
+ a .values [key ] = userArg (values )
210
+ return a
211
+ }
212
+
213
+ // SetRaw sets the given flag to the given Arg value directly. Use this if
214
+ // you need to do some complicated deferred logic or something.
215
+ //
216
+ // Otherwise behaves like Set.
217
+ func (a * Arguments ) SetRaw (key string , val Arg ) * Arguments {
218
+ a .values [key ] = val
219
+ return a
220
+ }
221
+
222
+ // FuncArg is a basic implementation of Arg that can be used for custom argument logic,
223
+ // like pulling values out of APIServer, or dynamically calculating values just before
224
+ // launch.
225
+ //
226
+ // The given function will be mapped directly to Arg#Get, and will generally be
227
+ // used in conjunction with SetRaw. For example, to set `--some-flag` to the
228
+ // API server's CertDir, you could do:
229
+ //
230
+ // server.Configure().SetRaw("--some-flag", FuncArg(func(defaults []string) []string {
231
+ // return []string{server.CertDir}
232
+ // }))
233
+ //
234
+ // FuncArg ignores Appends; if you need to support appending values too, consider implementing
235
+ // Arg directly.
236
+ type FuncArg func ([]string ) []string
237
+
238
+ // Append is a no-op for FuncArg, and just returns itself.
239
+ func (a FuncArg ) Append (vals ... string ) Arg { return a }
240
+
241
+ // Get delegates functionality to the FuncArg function itself.
242
+ func (a FuncArg ) Get (defaults []string ) []string {
243
+ return a (defaults )
244
+ }
0 commit comments