morpheus-cli 3.3.1.4 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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