morpheus-cli 4.1.5 → 4.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,708 @@
1
+ require 'rest_client'
2
+ require 'optparse'
3
+ require 'filesize'
4
+ require 'morpheus/cli/cli_command'
5
+ require 'morpheus/cli/mixins/infrastructure_helper'
6
+
7
+ class Morpheus::Cli::SubnetsCommand
8
+ include Morpheus::Cli::CliCommand
9
+ include Morpheus::Cli::InfrastructureHelper
10
+
11
+ set_command_name :subnets
12
+
13
+ register_subcommands :list, :get, :add, :update, :remove
14
+ # register_subcommands :'types' => :list_subnet_types
15
+ register_subcommands :'types' => :list_subnet_types
16
+ register_subcommands :'get-type' => :get_subnet_type
17
+
18
+ # set_default_subcommand :list
19
+
20
+ def initialize()
21
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
22
+ end
23
+
24
+ def connect(opts)
25
+ @api_client = establish_remote_appliance_connection(opts)
26
+ @networks_interface = @api_client.networks
27
+ @network_types_interface = @api_client.network_types
28
+ @subnets_interface = @api_client.subnets
29
+ @subnet_types_interface = @api_client.subnet_types
30
+ @clouds_interface = @api_client.clouds
31
+ @options_interface = @api_client.options
32
+ end
33
+
34
+ def handle(args)
35
+ handle_subcommand(args)
36
+ end
37
+
38
+ def list(args)
39
+ options = {}
40
+ params = {}
41
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
42
+ opts.banner = subcommand_usage("")
43
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
44
+ opts.on( '--network NETWORK', '--network NETWORK', "Filter results to a specific network" ) do |val|
45
+ options[:network] = val
46
+ end
47
+ opts.footer = "List subnets."
48
+ end
49
+ optparse.parse!(args)
50
+ if args.count > 0
51
+ raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args}\n#{optparse}"
52
+ end
53
+ connect(options)
54
+
55
+ params.merge!(parse_list_options(options))
56
+ network = nil
57
+ if options[:network]
58
+ network = find_network_by_name_or_id(options[:network])
59
+ if network
60
+ params['networkId'] = network['id']
61
+ else
62
+ return 1, "Network not found"
63
+ end
64
+ # params['networksId'] = params.delete('networkId')
65
+ end
66
+
67
+ exit_code, err = 0, nil
68
+
69
+ @subnets_interface.setopts(options)
70
+ if options[:dry_run]
71
+ print_dry_run @subnets_interface.dry.list(params)
72
+ return exit_code, err
73
+ end
74
+ json_response = @subnets_interface.list(params)
75
+ subnets = json_response["subnets"]
76
+
77
+ render_result = render_with_format(json_response, options, 'subnets')
78
+ return exit_code, err if render_result
79
+
80
+ title = "Morpheus Subnets"
81
+ subtitles = []
82
+ if network
83
+ subtitles << "Network: #{network['name']}"
84
+ end
85
+ subtitles += parse_list_subtitles(options)
86
+ print_h1 title, subtitles
87
+
88
+ if subnets.empty?
89
+ print cyan,"No subnets found.",reset,"\n"
90
+ else
91
+ subnet_columns = {
92
+ "ID" => 'id',
93
+ "Name" => 'name',
94
+ #"Description" => 'description',
95
+ "Network" => lambda {|it| it['network']['name'] rescue it['network'] },
96
+ "Type" => lambda {|it| it['type']['name'] rescue it['type'] },
97
+ "Cloud" => lambda {|it| it['zone']['name'] rescue it['zone'] },
98
+ "CIDR" => lambda {|it| it['cidr'] },
99
+ "DHCP" => lambda {|it| format_boolean(it['dhcpServer']) },
100
+ "Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
101
+ "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.join(', ') : '' }
102
+ }
103
+ print cyan
104
+ print as_pretty_table(subnets, subnet_columns)
105
+ print_results_pagination(json_response, {:label => "subnet", :n_label => "subnets"})
106
+ end
107
+ print reset,"\n"
108
+ return exit_code, err
109
+
110
+ end
111
+
112
+
113
+ def get(args)
114
+ options = {}
115
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
116
+ opts.banner = subcommand_usage("[network] [subnet]")
117
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
118
+ opts.footer = "Get details about a subnet." + "\n" +
119
+ "[subnet] is required. This is the name or id of a subnet."
120
+ end
121
+ optparse.parse!(args)
122
+ if args.count != 1
123
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
124
+ end
125
+ connect(options)
126
+ begin
127
+ subnet_id = nil
128
+ if args[0].to_s =~ /\A\d{1,}\Z/
129
+ subnet_id = args[0].to_i
130
+ else
131
+ subnet = find_subnet_by_name(args[0])
132
+ return 1, "Security Group not found" if subnet.nil?
133
+ subnet_id = subnet['id']
134
+ end
135
+ @subnets_interface.setopts(options)
136
+ if options[:dry_run]
137
+ print_dry_run @subnets_interface.dry.get(subnet_id)
138
+ return exit_code, err
139
+ end
140
+ json_response = @subnets_interface.get(subnet_id)
141
+ render_result = render_with_format(json_response, options, 'subnet')
142
+ return exit_code, err if render_result
143
+
144
+ subnet = json_response['subnet']
145
+ if options[:json]
146
+ puts as_json(json_response, options, "subnet")
147
+ return 0
148
+ elsif options[:yaml]
149
+ puts as_yaml(json_response, options, "subnet")
150
+ return 0
151
+ elsif options[:csv]
152
+ puts records_as_csv([subnet], options)
153
+ return 0
154
+ end
155
+ print_h1 "Subnet Details", [], options
156
+ print cyan
157
+ description_cols = {
158
+ "ID" => 'id',
159
+ "Name" => 'name',
160
+ "Description" => 'description',
161
+ "Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
162
+ "Network" => lambda {|it| subnet['network']['name'] rescue subnet['network'] },
163
+ "Cloud" => lambda {|it| subnet['zone']['name'] rescue subnet['zone'] },
164
+ "CIDR" => 'cidr',
165
+ "Gateway" => 'gateway',
166
+ "Netmask" => 'netmask',
167
+ "Subnet" => 'subnetAddress',
168
+ "Primary DNS" => 'dnsPrimary',
169
+ "Secondary DNS" => 'dnsSecondary',
170
+ "Pool" => lambda {|it| it['pool'] ? it['pool']['name'] : '' },
171
+ "DHCP" => lambda {|it| format_boolean it['dhcpServer'] },
172
+ #"Allow IP Override" => lambda {|it| it['allowStaticOverride'] ? 'Yes' : 'No' },
173
+ "Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
174
+ "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.join(', ') : '' },
175
+ # "Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
176
+ }
177
+ print_description_list(description_cols, subnet)
178
+
179
+ if subnet['resourcePermission'].nil?
180
+ print "\n", "No group access found", "\n"
181
+ else
182
+ print_h2 "Group Access"
183
+ rows = []
184
+ if subnet['resourcePermission']['all']
185
+ rows.push({"name" => 'All'})
186
+ end
187
+ if subnet['resourcePermission']['sites']
188
+ subnet['resourcePermission']['sites'].each do |site|
189
+ rows.push(site)
190
+ end
191
+ end
192
+ rows = rows.collect do |site|
193
+ {group: site['name'], default: site['default'] ? 'Yes' : ''}
194
+ end
195
+ columns = [:group, :default]
196
+ print cyan
197
+ print as_pretty_table(rows, columns)
198
+ end
199
+
200
+ print reset,"\n"
201
+ return 0
202
+ rescue RestClient::Exception => e
203
+ print_rest_exception(e, options)
204
+ return 1
205
+ end
206
+ end
207
+
208
+ def add(args)
209
+ options = {}
210
+ network_id = nil
211
+ subnet_type_id = nil
212
+ tenants = nil
213
+ group_access_all = nil
214
+ group_access_list = nil
215
+ group_defaults_list = nil
216
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
217
+ opts.banner = subcommand_usage("[name] --network NETWORK")
218
+ opts.on('--network NETWORK', String, "Network name or ID that this subnet will be a part of.") do |val|
219
+ network_id = val
220
+ end
221
+ opts.on('-t', '--type ID', "Subnet Type Name or ID") do |val|
222
+ subnet_type_id = val
223
+ end
224
+ opts.on('--name VALUE', String, "Name for this subnet") do |val|
225
+ options[:options]['name'] = val
226
+ # fill in silly names that vary by type
227
+ options[:options].deep_merge!({'config' => {'subnetName' => val}})
228
+ end
229
+ opts.on('--cidr VALUE', String, "Name for this subnet") do |val|
230
+ options[:options]['cidr'] = val
231
+ # fill in silly names that vary by type
232
+ options[:options].deep_merge!({'config' => {'subnetCidr' => val}})
233
+ end
234
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
235
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
236
+ end
237
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
238
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
239
+ group_access_list = []
240
+ else
241
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
242
+ end
243
+ end
244
+ opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
245
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
246
+ group_defaults_list = []
247
+ else
248
+ group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
249
+ end
250
+ end
251
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
252
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
253
+ options['tenants'] = []
254
+ else
255
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
256
+ end
257
+ end
258
+ opts.on('--accounts LIST', Array, "alias for --tenants") do |list|
259
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
260
+ options['tenants'] = []
261
+ else
262
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
263
+ end
264
+ end
265
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
266
+ options['visibility'] = val
267
+ end
268
+ # opts.on('--active [on|off]', String, "Can be used to disable a subnet") do |val|
269
+ # options['active'] = val.to_s == 'on' || val.to_s == 'true'
270
+ # end
271
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
272
+ opts.footer = "Create a new subnet." + "\n" +
273
+ "--network is required. This is the name or id of a network." #+ "\n" +
274
+ #"[name] is required and can be passed as --name instead."
275
+ end
276
+ optparse.parse!(args)
277
+ # if args.count < 1 || args.count > 2
278
+ if args.count > 1
279
+ raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args}\n#{optparse}"
280
+ end
281
+ if args[1]
282
+ options[:options]['name'] = args[1]
283
+ end
284
+ connect(options)
285
+ begin
286
+ passed_options = (options[:options] || {}).reject {|k,v| k.is_a?(Symbol) }
287
+ payload = nil
288
+ if options[:payload]
289
+ payload = options[:payload]
290
+ payload.deep_merge!({'subnet' => passed_options}) unless passed_options.empty?
291
+
292
+ else
293
+ payload = {'subnet' => {}}
294
+ payload.deep_merge!({'subnet' => passed_options}) unless passed_options.empty?
295
+
296
+ # Network
297
+ prompt_results = prompt_for_network(network_id, options)
298
+ if prompt_results[:success]
299
+ network = prompt_results[:network]
300
+ else
301
+ return 1, "Network prompt failed."
302
+ end
303
+
304
+ # Name
305
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this subnet.'}], options[:options])
306
+ # payload['subnet']['name'] = v_prompt['name']
307
+
308
+ # Subnet Type
309
+ if !subnet_type_id
310
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Subnet Type', 'type' => 'select', 'optionSource' => 'subnetTypes', 'required' => true, 'description' => 'Choose a subnet type.'}], options[:options], @api_client, {networkId: network['id']})
311
+ subnet_type_id = v_prompt['type']
312
+ end
313
+ subnet_type = find_subnet_type_by_name_or_id(subnet_type_id)
314
+ return 1 if subnet_type.nil?
315
+ payload['subnet']['type'] = {'id' => subnet_type['id'] }
316
+ #payload['subnet']['type'] = {'code' => subnet_type['code'] }
317
+
318
+ subnet_type_option_types = subnet_type['optionTypes']
319
+ if subnet_type_option_types && subnet_type_option_types.size > 0
320
+ # prompt for option types
321
+ subnet_type_params = Morpheus::Cli::OptionTypes.prompt(subnet_type_option_types,options[:options],@api_client, {networkId: network['id']})
322
+ payload['subnet'].deep_merge!(subnet_type_params)
323
+
324
+ else
325
+ # DEFAULT INPUTS
326
+
327
+ # CIDR
328
+ # if options['cidr']
329
+ # payload['subnet']['cidr'] = options['cidr']
330
+ # else
331
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => false, 'description' => ''}], options)
332
+ # payload['subnet']['cidr'] = v_prompt['cidr']
333
+ # end
334
+
335
+ end
336
+
337
+ # Group Access
338
+ # Group Access (default is All)
339
+ if group_access_all.nil?
340
+ if payload['resourcePermissions'].nil?
341
+ payload['resourcePermissions'] ||= {}
342
+ payload['resourcePermissions']['all'] = true
343
+ end
344
+ else
345
+ payload['resourcePermissions'] ||= {}
346
+ payload['resourcePermissions']['all'] = group_access_all
347
+ end
348
+ if group_access_list != nil
349
+ payload['resourcePermissions'] ||= {}
350
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
351
+ site = {"id" => site_id.to_i}
352
+ if group_defaults_list && group_defaults_list.include?(site_id)
353
+ site["default"] = true
354
+ end
355
+ site
356
+ end
357
+ end
358
+
359
+ # Tenants
360
+ if options['tenants']
361
+ payload['tenantPermissions'] = {}
362
+ payload['tenantPermissions']['accounts'] = options['tenants']
363
+ end
364
+
365
+ # Active
366
+ if options['active'] != nil
367
+ payload['subnet']['active'] = options['active']
368
+ end
369
+
370
+ # Visibility
371
+ if options['visibility'] != nil
372
+ payload['subnet']['visibility'] = options['visibility']
373
+ end
374
+
375
+ end
376
+
377
+ @subnets_interface.setopts(options)
378
+ if options[:dry_run]
379
+ print_dry_run @subnets_interface.dry.create(network['id'], payload)
380
+ return
381
+ end
382
+ json_response = @subnets_interface.create(network['id'], payload)
383
+ if options[:json]
384
+ puts as_json(json_response, options)
385
+ elsif !options[:quiet]
386
+ subnet = json_response['subnet']
387
+ print_green_success "Added subnet #{subnet['name']}"
388
+ get_args = [network['id'], subnet['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
389
+ get(get_args)
390
+ end
391
+ return 0
392
+ rescue RestClient::Exception => e
393
+ print_rest_exception(e, options)
394
+ return 1
395
+ end
396
+ end
397
+
398
+
399
+ def update(args)
400
+ options = {}
401
+ tenants = nil
402
+ group_access_all = nil
403
+ group_access_list = nil
404
+ group_defaults_list = nil
405
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
406
+ opts.banner = subcommand_usage("[subnet]")
407
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
408
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
409
+ end
410
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
411
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
412
+ group_access_list = []
413
+ else
414
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
415
+ end
416
+ end
417
+ opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
418
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
419
+ group_defaults_list = []
420
+ else
421
+ group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
422
+ end
423
+ end
424
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
425
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
426
+ options['tenants'] = []
427
+ else
428
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
429
+ end
430
+ end
431
+ opts.on('--accounts LIST', Array, "alias for --tenants") do |list|
432
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
433
+ options['tenants'] = []
434
+ else
435
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
436
+ end
437
+ end
438
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
439
+ options['visibility'] = val
440
+ end
441
+ # opts.on('--active [on|off]', String, "Can be used to disable a network") do |val|
442
+ # options['active'] = val.to_s == 'on' || val.to_s == 'true'
443
+ # end
444
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
445
+ opts.footer = "Update a subnet." + "\n" +
446
+ "[subnet] is required. This is the name or id of a subnet."
447
+ end
448
+ optparse.parse!(args)
449
+ if args.count != 1
450
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
451
+ end
452
+ connect(options)
453
+ begin
454
+ network = find_network_by_name_or_id(args[0])
455
+ return 1 if network.nil?
456
+
457
+ subnet = find_subnet_by_name_or_id(network['id'], args[1])
458
+ return 1 if subnet.nil?
459
+
460
+ # merge -O options into normally parsed options
461
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
462
+
463
+ # construct payload
464
+ payload = nil
465
+ if options[:payload]
466
+ payload = options[:payload]
467
+ else
468
+ # prompt for network options
469
+ payload = {
470
+ 'subnet' => {
471
+ }
472
+ }
473
+
474
+ # allow arbitrary -O options
475
+ payload['subnet'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
476
+
477
+ # Group Access
478
+ if group_access_all != nil
479
+ payload['resourcePermissions'] ||= {}
480
+ payload['resourcePermissions']['all'] = group_access_all
481
+ end
482
+ if group_access_list != nil
483
+ payload['resourcePermissions'] ||= {}
484
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
485
+ site = {"id" => site_id.to_i}
486
+ if group_defaults_list && group_defaults_list.include?(site_id)
487
+ site["default"] = true
488
+ end
489
+ site
490
+ end
491
+ end
492
+
493
+ # Tenants
494
+ if options['tenants']
495
+ payload['tenantPermissions'] = {}
496
+ payload['tenantPermissions']['accounts'] = options['tenants']
497
+ end
498
+
499
+ # Active
500
+ if options['active'] != nil
501
+ payload['subnet']['active'] = options['active']
502
+ end
503
+
504
+ # Visibility
505
+ if options['visibility'] != nil
506
+ payload['subnet']['visibility'] = options['visibility']
507
+ end
508
+
509
+ end
510
+
511
+ @subnets_interface.setopts(options)
512
+ if options[:dry_run]
513
+ print_dry_run @subnets_interface.dry.update(network['id'], subnet['id'], payload)
514
+ return
515
+ end
516
+ json_response = @subnets_interface.update(network['id'], subnet['id'], payload)
517
+ if options[:json]
518
+ puts as_json(json_response, options)
519
+ elsif !options[:quiet]
520
+ subnet = json_response['subnet']
521
+ print_green_success "Updated subnet #{subnet['name']}"
522
+ get_args = [network['id'], subnet['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
523
+ get(get_args)
524
+ end
525
+ return 0
526
+ rescue RestClient::Exception => e
527
+ print_rest_exception(e, options)
528
+ return 1
529
+ end
530
+ end
531
+
532
+ def remove(args)
533
+ options = {}
534
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
535
+ opts.banner = subcommand_usage("[subnet]")
536
+ build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
537
+ opts.footer = "Delete a subnet." + "\n" +
538
+ "[subnet] is required. This is the name or id of a subnet."
539
+ end
540
+ optparse.parse!(args)
541
+ if args.count != 1
542
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
543
+ end
544
+ connect(options)
545
+ begin
546
+ subnet = find_subnet_by_name_or_id(args[0])
547
+ return 1 if subnet.nil?
548
+
549
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the subnet: #{subnet['name']}?")
550
+ return 9, "aborted command"
551
+ end
552
+ @subnets_interface.setopts(options)
553
+ if options[:dry_run]
554
+ print_dry_run @subnets_interface.dry.destroy(subnet['id'])
555
+ return 0
556
+ end
557
+ json_response = @subnets_interface.destroy(subnet['id'])
558
+ if options[:json]
559
+ puts as_json(json_response, options)
560
+ else
561
+ print_green_success "Removed subnet #{subnet['name']}"
562
+ end
563
+ return 0
564
+ rescue RestClient::Exception => e
565
+ print_rest_exception(e, options)
566
+ return 1
567
+ end
568
+ end
569
+
570
+ def get_subnet_type(args)
571
+ options = {}
572
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
573
+ opts.banner = subcommand_usage("[type]")
574
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
575
+ opts.footer = "Get details about a subnet type.\n" +
576
+ "[type] is required. This is the id or name of a subnet type."
577
+ end
578
+ optparse.parse!(args)
579
+ connect(options)
580
+ begin
581
+ params = {}
582
+ @subnet_types_interface.setopts(options)
583
+ if options[:dry_run]
584
+ if args[0].to_s =~ /\A\d{1,}\Z/
585
+ print_dry_run @subnet_types_interface.dry.get(args[0].to_i)
586
+ else
587
+ print_dry_run @subnet_types_interface.dry.list({name:args[0]})
588
+ end
589
+ return
590
+ end
591
+
592
+ subnet_type = find_subnet_type_by_name_or_id(args[0])
593
+ return 1 if subnet_type.nil?
594
+ json_response = {'subnetType' => subnet_type} # skip redundant request
595
+ # json_response = @networks_interface.get(subnet_type['id'])
596
+
597
+ render_result = render_with_format(json_response, options, 'subnetType')
598
+ return 0 if render_result
599
+
600
+ subnet_type = json_response['subnetType']
601
+
602
+ title = "Morpheus Subnet Type"
603
+
604
+ print_h1 "Morpheus Subnet Type", [], options
605
+
606
+ print cyan
607
+ description_cols = {
608
+ "ID" => 'id',
609
+ "Name" => 'name',
610
+ "Code" => 'name',
611
+ "Description" => 'description',
612
+ "Createable" => lambda {|it| format_boolean(it['creatable']) },
613
+ "Deletable" => lambda {|it| format_boolean(it['deleteable']) },
614
+ }
615
+ print_description_list(description_cols, subnet_type)
616
+
617
+
618
+
619
+ option_types = subnet_type['optionTypes'] || []
620
+ option_types = option_types.sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
621
+ if !option_types.empty?
622
+ print_h2 "Config Option Types", [], options
623
+ option_type_cols = {
624
+ "Name" => lambda {|it| it['fieldContext'].to_s != '' ? "#{it['fieldContext']}.#{it['fieldName']}" : it['fieldName'] },
625
+ "Label" => lambda {|it| it['fieldLabel'] },
626
+ "Type" => lambda {|it| it['type'] },
627
+ }
628
+ print cyan
629
+ print as_pretty_table(option_types, option_type_cols)
630
+ end
631
+
632
+ print reset,"\n"
633
+ return 0
634
+ rescue RestClient::Exception => e
635
+ print_rest_exception(e, options)
636
+ exit 1
637
+ end
638
+ end
639
+
640
+ def list_subnet_types(args)
641
+ options = {}
642
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
643
+ opts.banner = subcommand_usage()
644
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
645
+ options[:cloud] = val
646
+ end
647
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
648
+ opts.footer = "List subnet types."
649
+ end
650
+ optparse.parse!(args)
651
+ connect(options)
652
+ begin
653
+ params = {}
654
+ params.merge!(parse_list_options(options))
655
+ if options[:cloud]
656
+ #return network_types_for_cloud(options[:cloud], options)
657
+ zone = find_zone_by_name_or_id(nil, options[:cloud])
658
+ #params["zoneTypeId"] = zone['zoneTypeId']
659
+ params["zoneId"] = zone['id']
660
+ params["creatable"] = true
661
+ end
662
+ @subnet_types_interface.setopts(options)
663
+ if options[:dry_run]
664
+ print_dry_run @subnet_types_interface.dry.list(params)
665
+ return
666
+ end
667
+ json_response = @subnet_types_interface.list(params)
668
+
669
+ render_result = render_with_format(json_response, options, 'subnetTypes')
670
+ return 0 if render_result
671
+
672
+ subnet_types = json_response['subnetTypes']
673
+
674
+ title = "Morpheus Subnet Types"
675
+ subtitles = []
676
+ subtitles += parse_list_subtitles(options)
677
+ if options[:cloud]
678
+ subtitles << "Cloud: #{options[:cloud]}"
679
+ end
680
+ print_h1 title, subtitles
681
+ if subnet_types.empty?
682
+ print cyan,"No subnet types found.",reset,"\n"
683
+ else
684
+ rows = subnet_types.collect do |subnet_type|
685
+ {
686
+ id: subnet_type['id'],
687
+ code: subnet_type['code'],
688
+ name: subnet_type['name']
689
+ }
690
+ end
691
+ columns = [:id, :name, :code]
692
+ print cyan
693
+ print as_pretty_table(rows, columns, options)
694
+ print reset
695
+ print_results_pagination(json_response)
696
+ end
697
+ print reset,"\n"
698
+ return 0
699
+
700
+ rescue RestClient::Exception => e
701
+ print_rest_exception(e, options)
702
+ exit 1
703
+ end
704
+ end
705
+
706
+ private
707
+
708
+ end