morpheus-cli 3.3.1.4 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/api_client.rb +28 -0
  3. data/lib/morpheus/api/instance_types_interface.rb +12 -10
  4. data/lib/morpheus/api/instances_interface.rb +4 -0
  5. data/lib/morpheus/api/library_container_scripts_interface.rb +49 -0
  6. data/lib/morpheus/api/library_container_templates_interface.rb +49 -0
  7. data/lib/morpheus/api/library_container_types_interface.rb +65 -0
  8. data/lib/morpheus/api/library_container_upgrades_interface.rb +66 -0
  9. data/lib/morpheus/api/library_instance_types_interface.rb +59 -0
  10. data/lib/morpheus/api/library_layouts_interface.rb +65 -0
  11. data/lib/morpheus/api/servers_interface.rb +4 -0
  12. data/lib/morpheus/api/user_sources_interface.rb +120 -0
  13. data/lib/morpheus/api/virtual_images_interface.rb +7 -0
  14. data/lib/morpheus/cli.rb +12 -1
  15. data/lib/morpheus/cli/accounts.rb +35 -9
  16. data/lib/morpheus/cli/cli_command.rb +82 -2
  17. data/lib/morpheus/cli/curl_command.rb +1 -1
  18. data/lib/morpheus/cli/echo_command.rb +1 -1
  19. data/lib/morpheus/cli/hosts.rb +40 -14
  20. data/lib/morpheus/cli/instance_types.rb +106 -64
  21. data/lib/morpheus/cli/instances.rb +39 -15
  22. data/lib/morpheus/cli/library.rb +1 -1184
  23. data/lib/morpheus/cli/library_container_scripts_command.rb +437 -0
  24. data/lib/morpheus/cli/library_container_templates_command.rb +397 -0
  25. data/lib/morpheus/cli/library_container_types_command.rb +653 -0
  26. data/lib/morpheus/cli/library_instance_types_command.rb +491 -0
  27. data/lib/morpheus/cli/library_layouts_command.rb +650 -0
  28. data/lib/morpheus/cli/library_option_lists_command.rb +476 -0
  29. data/lib/morpheus/cli/library_option_types_command.rb +549 -0
  30. data/lib/morpheus/cli/library_upgrades_command.rb +604 -0
  31. data/lib/morpheus/cli/mixins/library_helper.rb +123 -0
  32. data/lib/morpheus/cli/mixins/print_helper.rb +21 -22
  33. data/lib/morpheus/cli/mixins/provisioning_helper.rb +56 -11
  34. data/lib/morpheus/cli/network_services_command.rb +1 -1
  35. data/lib/morpheus/cli/option_types.rb +12 -2
  36. data/lib/morpheus/cli/power_scheduling_command.rb +1 -1
  37. data/lib/morpheus/cli/shell.rb +120 -22
  38. data/lib/morpheus/cli/sleep_command.rb +45 -0
  39. data/lib/morpheus/cli/user_sources_command.rb +963 -0
  40. data/lib/morpheus/cli/users.rb +33 -2
  41. data/lib/morpheus/cli/version.rb +1 -1
  42. data/lib/morpheus/cli/version_command.rb +1 -1
  43. data/lib/morpheus/cli/virtual_images.rb +93 -39
  44. data/lib/morpheus/formatters.rb +37 -27
  45. data/lib/morpheus/terminal.rb +1 -1
  46. metadata +20 -2
@@ -0,0 +1,653 @@
1
+ require 'io/console'
2
+ require 'optparse'
3
+ require 'filesize'
4
+ require 'morpheus/cli/cli_command'
5
+ require 'morpheus/cli/mixins/library_helper'
6
+
7
+ class Morpheus::Cli::LibraryContainerTypesCommand
8
+ include Morpheus::Cli::CliCommand
9
+ include Morpheus::Cli::LibraryHelper
10
+
11
+ set_command_name :'library-node-types'
12
+
13
+ register_subcommands :list, :get, :add, :update, :remove
14
+
15
+ def initialize()
16
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
17
+ end
18
+
19
+ def connect(opts)
20
+ @api_client = establish_remote_appliance_connection(opts)
21
+ @library_container_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).library_container_types
22
+ @library_layouts_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).library_layouts
23
+ #@library_instance_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).library_instance_types
24
+ @provision_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).provision_types
25
+ @option_types_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).option_types
26
+ #@option_type_lists_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).option_type_lists
27
+ end
28
+
29
+ def handle(args)
30
+ handle_subcommand(args)
31
+ end
32
+
33
+ def list(args)
34
+ options = {}
35
+ params = {}
36
+ layout_id = nil
37
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
38
+ opts.banner = subcommand_usage()
39
+ opts.on('--layout ID', String, "Filter by Layout") do |val|
40
+ layout_id = val
41
+ end
42
+ opts.on('--technology VALUE', String, "Filter by technology") do |val|
43
+ params['provisionType'] = val
44
+ end
45
+ opts.on('--category VALUE', String, "Filter by category") do |val|
46
+ params['category'] = val
47
+ end
48
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
49
+ opts.footer = "List node types."
50
+ end
51
+ optparse.parse!(args)
52
+ if args.count > 0
53
+ print_error Morpheus::Terminal.angry_prompt
54
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
55
+ return 1
56
+ end
57
+ connect(options)
58
+ begin
59
+ # construct payload
60
+ params.merge!(parse_list_options(options))
61
+ # dry run?
62
+ if options[:dry_run]
63
+ print_dry_run @library_container_types_interface.dry.list(layout_id, params)
64
+ return
65
+ end
66
+ # do it
67
+ json_response = @library_container_types_interface.list(layout_id, params)
68
+ if options[:include_fields]
69
+ json_response = {"containerTypes" => filter_data(json_response["containerTypes"], options[:include_fields]) }
70
+ end
71
+ # print and/or return result
72
+ # return 0 if options[:quiet]
73
+ if options[:json]
74
+ puts as_json(json_response, options)
75
+ return 0
76
+ elsif options[:csv]
77
+ puts records_as_csv(json_response['containerTypes'], options)
78
+ return 0
79
+ elsif options[:yaml]
80
+ puts as_yaml(json_response, options)
81
+ return 0
82
+ end
83
+ container_types = json_response['containerTypes']
84
+ title = "Morpheus Library - Node Types"
85
+ subtitles = []
86
+ if layout_id
87
+ subtitles << "Layout: #{layout_id}".strip
88
+ end
89
+ subtitles += parse_list_subtitles(options)
90
+ print_h1 title, subtitles
91
+ if container_types.empty?
92
+ print cyan,"No node types found.",reset,"\n"
93
+ else
94
+ print_container_types_table(container_types, options)
95
+ print_results_pagination(json_response, {:label => "node type", :n_label => "node types"})
96
+ end
97
+ print reset,"\n"
98
+ rescue RestClient::Exception => e
99
+ print_rest_exception(e, options)
100
+ return 1
101
+ end
102
+ end
103
+
104
+ def get(args)
105
+ options = {}
106
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
107
+ opts.banner = subcommand_usage("[name]")
108
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
109
+ opts.footer = "Display node type details." + "\n" +
110
+ "[name] is required. This is the name or id of a node type."
111
+ end
112
+ optparse.parse!(args)
113
+ if args.count < 1
114
+ puts optparse
115
+ return 1
116
+ end
117
+ connect(options)
118
+ id_list = parse_id_list(args)
119
+ return run_command_for_each_arg(id_list) do |arg|
120
+ _get(arg, options)
121
+ end
122
+ end
123
+
124
+ def _get(id, options)
125
+ layout_id = nil
126
+ begin
127
+ if options[:dry_run]
128
+ if arg.to_s =~ /\A\d{1,}\Z/
129
+ print_dry_run @library_container_types_interface.dry.get(layout_id, arg.to_i)
130
+ else
131
+ print_dry_run @library_container_types_interface.dry.list(layout_id, {name:arg})
132
+ end
133
+ return
134
+ end
135
+ container_type = find_container_type_by_name_or_id(layout_id, id)
136
+ if container_type.nil?
137
+ return 1
138
+ end
139
+ # skip redundant request
140
+ #json_response = @library_container_types_interface.get(layout_id, container_type['id'])
141
+ json_response = {'containerType' => container_type}
142
+ #container_type = json_response['containerType']
143
+ if options[:include_fields]
144
+ json_response = {"containerType" => filter_data(json_response["containerType"], options[:include_fields]) }
145
+ end
146
+ if options[:json]
147
+ puts as_json(json_response, options)
148
+ return 0
149
+ elsif options[:yaml]
150
+ puts as_yaml(json_response, options)
151
+ return 0
152
+ elsif options[:csv]
153
+ puts records_as_csv([json_response['containerType']], options)
154
+ return 0
155
+ end
156
+
157
+ print_h1 "Node Type Details"
158
+ print cyan
159
+ description_cols = {
160
+ "ID" => lambda {|it| it['id'] },
161
+ "Name" => lambda {|it| it['name'] },
162
+ "Short Name" => lambda {|it| it['shortName'] },
163
+ "Version" => lambda {|it| it['containerVersion'] },
164
+ "Technology" => lambda {|it| format_container_type_technology(it) },
165
+ "Category" => lambda {|it| it['category'] },
166
+ "Virtual Image" => lambda {|it|
167
+ it['virtualImage'] ? it['virtualImage']['name'] : ''
168
+ },
169
+ # "Category" => lambda {|it| it['category'].to_s.capitalize },
170
+ # # "Logo" => lambda {|it| it['logo'].to_s },
171
+ # "Visiblity" => lambda {|it| it['visibility'].to_s.capitalize },
172
+ # "Environment Prefix" => lambda {|it| it['environmentPrefix'] },
173
+ # "Enable Settings" => lambda {|it| format_boolean it['hasSettings'] },
174
+ # "Enable Scaling" => lambda {|it| format_boolean it['hasAutoScale'] },
175
+ # "Supports Deployments" => lambda {|it| format_boolean it['hasDeployment'] },
176
+ # "Featured" => lambda {|it| format_boolean it['featured'] },
177
+ # "Owner" => lambda {|it| it['account'] ? it['account']['name'] : '' },
178
+ # "Active" => lambda {|it| format_boolean it['active'] },
179
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
180
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
181
+ }
182
+ print_description_list(description_cols, container_type)
183
+
184
+
185
+ evars = container_type['environmentVariables']
186
+ if evars && evars.size > 0
187
+ print_h2 "Environment Variables"
188
+ evar_columns = [
189
+ {"NAME" => lambda {|it| it['name'] } },
190
+ {"VALUE" => lambda {|it| it['defaultValue'] } },
191
+ {"TYPE" => lambda {|it| it['valueType'].to_s.capitalize } },
192
+ {"EXPORT" => lambda {|it| format_boolean it['export'] } },
193
+ {"MASKED" => lambda {|it| format_boolean it['mask'] } },
194
+ ]
195
+ print as_pretty_table(evars, evar_columns)
196
+ else
197
+ # print yellow,"No environment variables found for this node type.","\n",reset
198
+ end
199
+
200
+ exposed_ports = container_type['containerPorts']
201
+ if exposed_ports && exposed_ports.size > 0
202
+ print_h2 "Exposed Ports"
203
+ columns = [
204
+ #{"ID" => lambda {|it| it['id'] } },
205
+ {"NAME" => lambda {|it| it['name'] } },
206
+ {"PORT" => lambda {|it| it['port'] } },
207
+ {"LB PROTOCOL" => lambda {|it| it['loadBalanceProtocol'] } },
208
+ ]
209
+ print as_pretty_table(exposed_ports, columns)
210
+ else
211
+ # print yellow,"No exposed ports found for this node type.","\n",reset
212
+ end
213
+
214
+ container_scripts = container_type['containerScripts'] || container_type['scripts']
215
+ if container_scripts && container_scripts.size > 0
216
+ print_h2 "Scripts"
217
+ columns = [
218
+ {"ID" => lambda {|it| it['id'] } },
219
+ {"NAME" => lambda {|it| it['name'] } }
220
+ ]
221
+ print as_pretty_table(container_scripts, columns)
222
+ else
223
+ # print yellow,"No scripts found for this node type.","\n",reset
224
+ end
225
+
226
+ container_file_templates = container_type['containerTemplates'] || container_type['templates']
227
+ if container_file_templates && container_file_templates.size > 0
228
+ print_h2 "File Templates"
229
+ columns = [
230
+ {"ID" => lambda {|it| it['id'] } },
231
+ {"NAME" => lambda {|it| it['name'] } }
232
+ ]
233
+ print as_pretty_table(container_file_templates, columns)
234
+ else
235
+ # print yellow,"No scripts found for this node type.","\n",reset
236
+ end
237
+
238
+ print reset,"\n"
239
+
240
+ rescue RestClient::Exception => e
241
+ print_rest_exception(e, options)
242
+ return 1
243
+ end
244
+ end
245
+
246
+ def add(args)
247
+ options = {}
248
+ params = {}
249
+ layout = nil
250
+ layout_id = nil
251
+ script_ids = nil
252
+ file_template_ids = nil
253
+ evars = nil
254
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
255
+ opts.banner = subcommand_usage()
256
+ opts.on('--name VALUE', String, "Name for this node type") do |val|
257
+ params['name'] = val
258
+ end
259
+ opts.on('--shortName VALUE', String, "Short Name") do |val|
260
+ params['shortName'] = val
261
+ end
262
+ opts.on('--version VALUE', String, "Version") do |val|
263
+ params['containerVersion'] = val
264
+ end
265
+ opts.on('--technology CODE', String, "Technology. This is the provision type code.") do |val|
266
+ params['provisionTypeCode'] = val
267
+ end
268
+ opts.on('--scripts x,y,z', Array, "List of Script IDs") do |val|
269
+ script_ids = val #.collect {|it| it.to_i }
270
+ end
271
+ opts.on('--file-templates x,y,z', Array, "List of File Template IDs") do |val|
272
+ file_template_ids = val #.collect {|it| it.to_i }
273
+ end
274
+ #build_option_type_options(opts, options, add_layout_option_types())
275
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
276
+ opts.footer = "Create a node type." + "\n" +
277
+ "[name] is required and can be passed as --name instead."
278
+ "Technology --technology is required. Additional options vary by type."
279
+ end
280
+ optparse.parse!(args)
281
+ connect(options)
282
+ if args.count > 1
283
+ print_error Morpheus::Terminal.angry_prompt
284
+ puts_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
285
+ return 1
286
+ end
287
+ if args[0]
288
+ params['name'] = args[0]
289
+ end
290
+ begin
291
+ # construct payload
292
+ if layout_id
293
+ layout = find_layout_by_name_or_id(instance_type_id)
294
+ return 1 if layout.nil?
295
+ layout_id = layout['id']
296
+ end
297
+ payload = nil
298
+ if options[:payload]
299
+ payload = options[:payload]
300
+ else
301
+ payload = {}
302
+ # support the old -O OPTION switch
303
+ payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
304
+ # prompt for options
305
+ prompt_params = params.merge(:no_prompt=>options[:no_prompt]) # usually of options[:options]
306
+ if !params['name']
307
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true}], prompt_params)
308
+ params['name'] = v_prompt['name']
309
+ end
310
+ if !params['shortName']
311
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'shortName', 'type' => 'text', 'fieldLabel' => 'Short Name', 'required' => true, 'description' => 'The short name is a lowercase name with no spaces used for display in your container list.'}], prompt_params)
312
+ params['shortName'] = v_prompt['shortName']
313
+ end
314
+ if !params['containerVersion']
315
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'containerVersion', 'type' => 'text', 'fieldLabel' => 'Version', 'required' => true}], prompt_params)
316
+ params['containerVersion'] = v_prompt['containerVersion']
317
+ end
318
+
319
+ # prompt for all the ProvisionType.customOptionTypes
320
+ # err, these optionTypes have the fieldContext
321
+ # so merge them at the root level of the request.
322
+
323
+ provision_types = @provision_types_interface.get({customSupported: true})['provisionTypes']
324
+ if provision_types.empty?
325
+ print_red_alert "No available provision types found!"
326
+ return 1
327
+ end
328
+ provision_type_options = provision_types.collect {|it| { 'name' => it['name'], 'value' => it['code']} }
329
+ provision_type = nil
330
+ if !params['provisionTypeCode']
331
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'provisionTypeCode', 'type' => 'select', 'selectOptions' => provision_type_options, 'fieldLabel' => 'Technology', 'required' => true, 'description' => 'The type of container technology.'}], prompt_params)
332
+ params['provisionTypeCode'] = v_prompt['provisionTypeCode']
333
+ end
334
+ provision_type = provision_types.find {|it| it['code'] == params['provisionTypeCode'] }
335
+ if provision_type.nil?
336
+ print_red_alert "Provision Type not found by code '#{params['provisionTypeCode']}'!"
337
+ return 1
338
+ end
339
+
340
+ # prompt custom options for the selected provision type
341
+ provision_type_custom_option_types = provision_type['customOptionTypes']
342
+ if (!provision_type_custom_option_types || provision_type_custom_option_types.empty?)
343
+ print yellow,"Sorry, no options were found for provision type #{provision_type['name']}.","\n",reset
344
+ return 1
345
+ end
346
+ field_group_name = provision_type_custom_option_types.first['fieldGroup'] || "#{provision_type['name']} Options"
347
+ field_group_name = "#{provision_type['name']} Options"
348
+ # print "\n"
349
+ puts field_group_name
350
+ puts "==============="
351
+ provision_type_v_prompt = Morpheus::Cli::OptionTypes.prompt(provision_type_custom_option_types,options[:options],@api_client, {provisionTypCode: params['provisionTypeCode']})
352
+
353
+ # payload.deep_merge!(provision_type_v_prompt)
354
+
355
+ # ENVIRONMENT VARIABLES
356
+ if evars
357
+ params['environmentVariables'] = evars
358
+ else
359
+ # prompt
360
+ # parsed_evars = parse_environment_variables
361
+ end
362
+
363
+ # SCRIPTS
364
+ if script_ids
365
+ params['scripts'] = script_ids.collect {|it| it.to_i }.select { |it| it != 0 }
366
+ else
367
+ # prompt
368
+ end
369
+
370
+ # FILE TEMPLATES
371
+ if file_template_ids
372
+ params['scripts'] = file_template_ids.collect {|it| it.to_i }.select { |it| it != 0 }
373
+ else
374
+ # prompt
375
+ end
376
+
377
+ # payload = {'containerType' => params}
378
+ payload['containerType'] ||= {}
379
+ payload['containerType'].deep_merge!(params)
380
+ payload.deep_merge!(provision_type_v_prompt)
381
+
382
+
383
+ end
384
+
385
+ if options[:dry_run]
386
+ print_dry_run @library_container_types_interface.dry.create(layout_id, payload)
387
+ return
388
+ end
389
+
390
+ json_response = @library_container_types_interface.create(layout_id, payload)
391
+
392
+ if options[:json]
393
+ print JSON.pretty_generate(json_response), "\n"
394
+ return
395
+ end
396
+ container_type = json_response['containerType']
397
+ print_green_success "Added Node Type #{container_type['name']}"
398
+ get([json_response['containerType']['id']])
399
+ rescue RestClient::Exception => e
400
+ print_rest_exception(e, options)
401
+ exit 1
402
+ end
403
+ end
404
+
405
+ def update(args)
406
+ options = {}
407
+ params = {}
408
+ layout = nil
409
+ layout_id = nil
410
+ script_ids = nil
411
+ file_template_ids = nil
412
+ evars = nil
413
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
414
+ opts.banner = subcommand_usage("[name] [options]")
415
+ opts.on('--name VALUE', String, "Name for this layout") do |val|
416
+ params['name'] = val
417
+ end
418
+ opts.on('--shortName VALUE', String, "Short Name") do |val|
419
+ params['shortName'] = val
420
+ end
421
+ opts.on('--version VALUE', String, "Version") do |val|
422
+ params['containerVersion'] = val
423
+ end
424
+ # opts.on('--technology CODE', String, "Technology") do |val|
425
+ # params['provisionTypeCode'] = val
426
+ # end
427
+ opts.on('--scripts x,y,z', Array, "List of Script IDs") do |val|
428
+ script_ids = val #.collect {|it| it.to_i }
429
+ end
430
+ opts.on('--file-templates x,y,z', Array, "List of File Template IDs") do |val|
431
+ file_template_ids = val #.collect {|it| it.to_i }
432
+ end
433
+ #build_option_type_options(opts, options, update_layout_option_types())
434
+ build_common_options(opts, options, [:options, :json, :dry_run, :remote])
435
+ opts.footer = "Update a node type."
436
+ end
437
+ optparse.parse!(args)
438
+ if args.count < 1
439
+ puts optparse
440
+ exit 1
441
+ end
442
+ connect(options)
443
+ begin
444
+ container_type = find_container_type_by_name_or_id(layout_id, args[0])
445
+ if container_type.nil?
446
+ return 1
447
+ end
448
+ # construct payload
449
+ payload = nil
450
+ if options[:payload]
451
+ payload = options[:payload]
452
+ else
453
+ payload = {}
454
+ # option_types = update_layout_option_types(instance_type)
455
+ # params = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options], @api_client, options[:params])
456
+ payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
457
+
458
+ # ENVIRONMENT VARIABLES
459
+ if evars
460
+
461
+ else
462
+ # prompt
463
+ end
464
+
465
+ # SCRIPTS
466
+ if script_ids
467
+ params['scripts'] = script_ids.collect {|it| it.to_i }.select { |it| it != 0 }
468
+ else
469
+ # prompt
470
+ end
471
+
472
+ # FILE TEMPLATES
473
+ if file_template_ids
474
+ params['templates'] = file_template_ids.collect {|it| it.to_i }.select { |it| it != 0 }
475
+ else
476
+ # prompt
477
+ end
478
+
479
+ if params.empty?
480
+ puts optparse
481
+ exit 1
482
+ end
483
+
484
+ # payload = {'containerType' => params}
485
+ payload['containerType'] ||= {}
486
+ payload['containerType'].deep_merge!(params)
487
+
488
+ end
489
+
490
+ if options[:dry_run]
491
+ print_dry_run @library_container_types_interface.dry.update(layout_id, container_type['id'], payload)
492
+ return
493
+ end
494
+
495
+ json_response = @library_container_types_interface.update(layout_id, container_type['id'], payload)
496
+ if options[:json]
497
+ print JSON.pretty_generate(json_response), "\n"
498
+ return
499
+ end
500
+ container_type = json_response['containerType']
501
+ print_green_success "Updated Node Type #{container_type['name']}"
502
+ get([container_type['id']])
503
+ rescue RestClient::Exception => e
504
+ print_rest_exception(e, options)
505
+ exit 1
506
+ end
507
+ end
508
+
509
+ def remove(args)
510
+ options = {}
511
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
512
+ opts.banner = subcommand_usage("[name]")
513
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
514
+ opts.footer = "Delete a node type."
515
+ end
516
+ optparse.parse!(args)
517
+ if args.count < 1
518
+ puts optparse
519
+ exit 1
520
+ end
521
+ connect(options)
522
+
523
+ begin
524
+ container_type = find_container_type_by_name_or_id(layout_id, id)
525
+ if container_type.nil?
526
+ return 1
527
+ end
528
+
529
+ unless Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the node type #{container_type['name']}?", options)
530
+ exit
531
+ end
532
+ if options[:dry_run]
533
+ print_dry_run @library_container_types_interface.dry.destroy(nil, container_type['id'])
534
+ return
535
+ end
536
+ json_response = @library_container_types_interface.destroy(nil, container_type['id'])
537
+
538
+ if options[:json]
539
+ print JSON.pretty_generate(json_response), "\n"
540
+ return
541
+ end
542
+
543
+ print_green_success "Removed Node Type #{container_type['name']}"
544
+ #list([])
545
+ rescue RestClient::Exception => e
546
+ print_rest_exception(e, options)
547
+ exit 1
548
+ end
549
+ end
550
+
551
+ private
552
+
553
+ def find_container_type_by_name_or_id(layout_id, val)
554
+ if val.to_s =~ /\A\d{1,}\Z/
555
+ return find_container_type_by_id(layout_id, val)
556
+ else
557
+ return find_container_type_by_name(layout_id, val)
558
+ end
559
+ end
560
+
561
+ def find_container_type_by_id(layout_id, id)
562
+ begin
563
+ json_response = @library_container_types_interface.get(layout_id, id.to_i)
564
+ return json_response['containerType']
565
+ rescue RestClient::Exception => e
566
+ if e.response && e.response.code == 404
567
+ print_red_alert "Instance Type not found by id #{id}"
568
+ else
569
+ raise e
570
+ end
571
+ end
572
+ end
573
+
574
+ def find_container_type_by_name(layout_id, name)
575
+ container_types = @library_container_types_interface.list(layout_id, {name: name.to_s})['containerTypes']
576
+ if container_types.empty?
577
+ print_red_alert "Node Type not found by name #{name}"
578
+ return nil
579
+ elsif container_types.size > 1
580
+ print_red_alert "#{container_types.size} node types found by name #{name}"
581
+ print_container_types_table(container_types, {color: red})
582
+ print_red_alert "Try using ID instead"
583
+ print reset,"\n"
584
+ return nil
585
+ else
586
+ return container_types[0]
587
+ end
588
+ end
589
+
590
+ def print_container_types_table(container_types, opts={})
591
+ columns = [
592
+ {"ID" => lambda {|it| it['id'] } },
593
+ {"TECHNOLOGY" => lambda {|it| format_container_type_technology(it) } },
594
+ {"NAME" => lambda {|it| it['name'] } },
595
+ {"SHORT NAME" => lambda {|it| it['shortName'] } },
596
+ {"VERSION" => lambda {|it| it['containerVersion'] } },
597
+ {"CATEGORY" => lambda {|it| it['category'] } },
598
+ {"OWNER" => lambda {|it| it['account'] ? it['account']['name'] : '' } }
599
+ ]
600
+ if opts[:include_fields]
601
+ columns = opts[:include_fields]
602
+ end
603
+ print as_pretty_table(container_types, columns, opts)
604
+ end
605
+
606
+ def format_container_type_technology(container_type)
607
+ if container_type
608
+ container_type['provisionType'] ? container_type['provisionType']['name'] : ''
609
+ else
610
+ ""
611
+ end
612
+ end
613
+
614
+
615
+ def find_layout_by_name_or_id(instance_type_id, val)
616
+ if val.to_s =~ /\A\d{1,}\Z/
617
+ return find_layout_by_id(instance_type_id, val)
618
+ else
619
+ return find_layout_by_name(instance_type_id, val)
620
+ end
621
+ end
622
+
623
+ def find_layout_by_id(instance_type_id, id)
624
+ begin
625
+ json_response = @library_layouts_interface.get(instance_type_id, id.to_i)
626
+ return json_response['instanceTypeLayout']
627
+ rescue RestClient::Exception => e
628
+ if e.response && e.response.code == 404
629
+ print_red_alert "Instance Type not found by id #{id}"
630
+ else
631
+ raise e
632
+ end
633
+ end
634
+ end
635
+
636
+ def find_layout_by_name(instance_type_id, name)
637
+ layouts = @library_layouts_interface.list(instance_type_id, {name: name.to_s})['instanceTypeLayouts']
638
+ if layouts.empty?
639
+ print_red_alert "Layout not found by name #{name}"
640
+ return nil
641
+ elsif layouts.size > 1
642
+ print_red_alert "#{layouts.size} layouts found by name #{name}"
643
+ print_layouts_table(layouts, {color: red})
644
+ print_red_alert "Try using ID instead"
645
+ print reset,"\n"
646
+ return nil
647
+ else
648
+ return layouts[0]
649
+ end
650
+ end
651
+
652
+
653
+ end