@@ -89,7 +89,7 @@ func (sc *ServicesCmd) ListServicesCmd() *cobra.Command {
89
89
return err
90
90
}
91
91
92
- params := & instanceCreateParams {}
92
+ params := & InstanceCreateParams {}
93
93
if err := json .Unmarshal (clusterServicePlan .Spec .ServiceInstanceCreateParameterSchema .Raw , & params ); err != nil {
94
94
return err
95
95
}
@@ -124,7 +124,7 @@ func findServiceClassByName(scClient versioned.Interface, name string) (*v1beta1
124
124
return nil , err
125
125
}
126
126
if mobileServices == nil || len (mobileServices .Items ) == 0 {
127
- return nil , errors .New ("failed to find and service classes for " + name )
127
+ return nil , errors .New ("failed to find serviceclass with name: " + name )
128
128
}
129
129
130
130
for _ , item := range mobileServices .Items {
@@ -137,11 +137,12 @@ func findServiceClassByName(scClient versioned.Interface, name string) (*v1beta1
137
137
return & item , nil
138
138
}
139
139
}
140
- return nil , nil
140
+ return nil , errors . New ( "failed to find serviceclass with name: " + name )
141
141
142
142
}
143
143
144
144
func findServicePlanByNameAndClass (scClient versioned.Interface , planName , serviceClassName string ) (* v1beta1.ClusterServicePlan , error ) {
145
+
145
146
plans , err := scClient .ServicecatalogV1beta1 ().ClusterServicePlans ().List (metav1.ListOptions {})
146
147
if err != nil {
147
148
return nil , err
@@ -152,10 +153,31 @@ func findServicePlanByNameAndClass(scClient versioned.Interface, planName, servi
152
153
}
153
154
}
154
155
155
- return nil , nil
156
+ return nil , errors .New ("failed to find serviceplan with associated with the serviceclass " + serviceClassName )
157
+ }
158
+
159
+ func requiredParam (instParams InstanceCreateParams , key string ) bool {
160
+ for _ , r := range instParams .Required {
161
+ if r == key {
162
+ return true
163
+ }
164
+ }
165
+ return false
166
+ }
167
+
168
+ func parseParams (keyVals []string ) (map [string ]string , error ) {
169
+ params := map [string ]string {}
170
+ for _ , p := range keyVals {
171
+ kv := strings .Split (p , "=" )
172
+ if len (kv ) != 2 {
173
+ return nil , NewIncorrectParameterFormat ("key value pairs are needed failed to find one: " + p )
174
+ }
175
+ params [strings .TrimSpace (kv [0 ])] = kv [1 ]
176
+ }
177
+ return params , nil
156
178
}
157
179
158
- type instanceCreateParams struct {
180
+ type InstanceCreateParams struct {
159
181
AdditionalProperties bool `json:"additionalProperties"`
160
182
Properties map [string ]map [string ]interface {} `json:"properties"`
161
183
Required []string `json:"required"`
@@ -166,10 +188,16 @@ func (sc *ServicesCmd) CreateServiceInstanceCmd() *cobra.Command {
166
188
cmd := & cobra.Command {
167
189
Use : "serviceinstance <serviceName>" ,
168
190
Short : `create a running instance of the given service` ,
191
+ Long : `Create service instance, allows you to provison an availble service to your namespace.
192
+ To see which services are available, first list them using the "get services" command from this tool.
193
+ Once you have selected a service, take note of its name then run:
194
+
195
+ create serviceinstance <selectedService>` ,
169
196
RunE : func (cmd * cobra.Command , args []string ) error {
170
197
if len (args ) != 1 {
171
198
return errors .New ("expected the name of a service to provision" )
172
199
}
200
+ // find our serviceclass and plan
173
201
serviceName := args [0 ]
174
202
175
203
ns , err := currentNamespace (cmd .Flags ())
@@ -178,47 +206,66 @@ func (sc *ServicesCmd) CreateServiceInstanceCmd() *cobra.Command {
178
206
}
179
207
180
208
clusterServiceClass , err := findServiceClassByName (sc .scClient , serviceName )
181
- if err != nil || clusterServiceClass == nil {
182
- msg := "failed to find a service class associated with that name "
183
- if err != nil {
184
- msg += err .Error ()
185
- }
186
- return errors .New (msg )
209
+ if err != nil {
210
+ return errors .WithStack (err )
187
211
}
188
212
clusterServicePlan , err := findServicePlanByNameAndClass (sc .scClient , "default" , clusterServiceClass .Name )
189
213
if err != nil {
190
- return err
214
+ return errors . WithStack ( err )
191
215
}
192
-
193
- if clusterServicePlan == nil {
194
- return errors .New ("failed to find service plan with name default for service " + serviceName )
216
+ // handle the params
217
+ params , err := cmd .Flags ().GetStringArray ("params" )
218
+ if err != nil {
219
+ return errors .WithStack (err )
195
220
}
196
-
197
- params := & instanceCreateParams {}
198
-
199
- if err := json .Unmarshal (clusterServicePlan .Spec .ServiceInstanceCreateParameterSchema .Raw , params ); err != nil {
200
- return err
221
+ parsedParams , err := parseParams (params )
222
+ if err != nil {
223
+ return errors .WithStack (err )
224
+ }
225
+ instParams := & InstanceCreateParams {}
226
+ if err := json .Unmarshal (clusterServicePlan .Spec .ServiceInstanceCreateParameterSchema .Raw , instParams ); err != nil {
227
+ return errors .WithStack (err )
201
228
}
202
- scanner := bufio .NewScanner (os .Stdin )
203
- for k , v := range params .Properties {
204
- fmt .Printf ("Set value for %v, default value: %v" , k , v ["default" ])
205
- scanner .Scan ()
206
- //
207
- val := scanner .Text ()
208
- if val == "" {
209
- val = v ["default" ].(string )
229
+
230
+ if len (parsedParams ) > 0 {
231
+ for k , v := range instParams .Properties {
232
+ defaultVal := v ["default" ]
233
+ if pVal , ok := parsedParams [k ]; ! ok && requiredParam (* instParams , k ) || requiredParam (* instParams , k ) && pVal == "" {
234
+ if defaultVal != nil {
235
+ //use default
236
+ v ["value" ] = defaultVal
237
+ continue
238
+ }
239
+ return errors .New (fmt .Sprintf ("missing required parameter %s" , k ))
240
+ }
241
+ v ["value" ] = parsedParams [k ]
242
+ instParams .Properties [k ] = v
243
+ }
244
+ } else {
245
+
246
+ scanner := bufio .NewScanner (os .Stdin )
247
+ for k , v := range instParams .Properties {
248
+ questionFormat := "Set value for %s [default value: %s required: %v]"
249
+
250
+ fmt .Println (fmt .Sprintf (questionFormat , k , v ["default" ], requiredParam (* instParams , k )))
251
+ scanner .Scan ()
252
+ //
253
+ val := scanner .Text ()
254
+ if val == "" {
255
+ val = v ["default" ].(string )
256
+ }
257
+ v ["value" ] = val
258
+ instParams .Properties [k ] = v
259
+ fmt .Println ("set value for " + k + " to : " + val )
210
260
}
211
- v ["value" ] = val
212
- params .Properties [k ] = v
213
- fmt .Println ("set value for " + k + " to : " + val )
214
261
}
215
262
216
263
validServiceName := clusterServiceClass .Spec .ExternalName
217
264
sid := uuid .NewV4 ().String ()
218
265
extMeta := clusterServiceClass .Spec .ExternalMetadata .Raw
219
266
var extServiceClass ExternalServiceMetaData
220
267
if err := json .Unmarshal (extMeta , & extServiceClass ); err != nil {
221
- return err
268
+ return errors . WithStack ( err )
222
269
}
223
270
224
271
si := v1beta1.ServiceInstance {
@@ -251,7 +298,7 @@ func (sc *ServicesCmd) CreateServiceInstanceCmd() *cobra.Command {
251
298
},
252
299
}
253
300
if _ , err := sc .scClient .ServicecatalogV1beta1 ().ServiceInstances (ns ).Create (& si ); err != nil {
254
- return err
301
+ return errors . WithStack ( err )
255
302
}
256
303
257
304
pSecret := v1.Secret {
@@ -262,38 +309,45 @@ func (sc *ServicesCmd) CreateServiceInstanceCmd() *cobra.Command {
262
309
pSecret .Data = map [string ][]byte {}
263
310
parameters := map [string ]string {}
264
311
265
- for k , v := range params .Properties {
266
- parameters [k ] = v ["value" ].(string )
312
+ for k , v := range instParams .Properties {
313
+ if v , ok := v ["value" ]; ok && v != nil {
314
+ parameters [k ] = v .(string )
315
+ }
267
316
}
268
317
secretData , err := json .Marshal (parameters )
269
318
if err != nil {
270
- return err
319
+ return errors . WithStack ( err )
271
320
}
272
321
pSecret .Data ["parameters" ] = secretData
273
322
if _ , err := sc .k8Client .CoreV1 ().Secrets (ns ).Create (& pSecret ); err != nil {
274
- return err
323
+ return errors . WithStack ( err )
275
324
}
325
+
276
326
noWait , err := cmd .PersistentFlags ().GetBool ("no-wait" )
277
327
if err != nil {
278
- return err
328
+ return errors . WithStack ( err )
279
329
}
280
330
if noWait {
281
331
return nil
282
332
}
283
333
w , err := sc .scClient .ServicecatalogV1beta1 ().ServiceInstances (ns ).Watch (metav1.ListOptions {LabelSelector : "id=" + sid })
284
334
if err != nil {
285
- return err
335
+ return errors . WithStack ( err )
286
336
}
287
337
for u := range w .ResultChan () {
338
+ o := u .Object .(* v1beta1.ServiceInstance )
288
339
switch u .Type {
340
+ case watch .Error :
341
+ w .Stop ()
342
+ return errors .New ("unexpected error watching ServiceInstance " + err .Error ())
289
343
case watch .Modified :
290
- o := u . Object .( * v1beta1. ServiceInstance )
344
+
291
345
lastOp := o .Status .LastOperation
292
346
if nil != lastOp {
293
- // fmt.Println("last operation " + *lastOp)
347
+ fmt .Println ("last operation: " + * lastOp )
294
348
}
295
349
for _ , c := range o .Status .Conditions {
296
- fmt .Println (c .Message )
350
+ fmt .Println ("status: " + c .Message )
297
351
if c .Type == "Ready" && c .Status == "True" {
298
352
w .Stop ()
299
353
}
@@ -305,6 +359,7 @@ func (sc *ServicesCmd) CreateServiceInstanceCmd() *cobra.Command {
305
359
},
306
360
}
307
361
cmd .PersistentFlags ().Bool ("no-wait" , false , "--no-wait will cause the command to exit immediately instead of waiting for the service to be provisioned" )
362
+ cmd .PersistentFlags ().StringArrayP ("params" , "p" , []string {}, "set the parameters needed by the template: -p PARAM1=val -p PARAM2=val2" )
308
363
return cmd
309
364
}
310
365
0 commit comments