morpheus-cli 3.6.28 → 3.6.29

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/api_client.rb +16 -0
  3. data/lib/morpheus/api/cloud_folders_interface.rb +47 -0
  4. data/lib/morpheus/api/cloud_resource_pools_interface.rb +47 -0
  5. data/lib/morpheus/api/network_types_interface.rb +26 -0
  6. data/lib/morpheus/api/reports_interface.rb +77 -0
  7. data/lib/morpheus/api/security_group_rules_interface.rb +6 -0
  8. data/lib/morpheus/api/security_groups_interface.rb +21 -15
  9. data/lib/morpheus/cli.rb +3 -0
  10. data/lib/morpheus/cli/accounts.rb +1 -1
  11. data/lib/morpheus/cli/apps.rb +2 -2
  12. data/lib/morpheus/cli/archives_command.rb +18 -18
  13. data/lib/morpheus/cli/blueprints_command.rb +1 -1
  14. data/lib/morpheus/cli/boot_scripts_command.rb +6 -6
  15. data/lib/morpheus/cli/cli_command.rb +4 -0
  16. data/lib/morpheus/cli/cloud_datastores_command.rb +58 -20
  17. data/lib/morpheus/cli/cloud_folders_command.rb +463 -0
  18. data/lib/morpheus/cli/cloud_resource_pools_command.rb +707 -0
  19. data/lib/morpheus/cli/clouds.rb +2 -0
  20. data/lib/morpheus/cli/hosts.rb +33 -8
  21. data/lib/morpheus/cli/instances.rb +79 -54
  22. data/lib/morpheus/cli/library_option_lists_command.rb +1 -1
  23. data/lib/morpheus/cli/library_option_types_command.rb +1 -1
  24. data/lib/morpheus/cli/mixins/provisioning_helper.rb +11 -2
  25. data/lib/morpheus/cli/monitoring_contacts_command.rb +1 -1
  26. data/lib/morpheus/cli/monitoring_incidents_command.rb +1 -1
  27. data/lib/morpheus/cli/network_services_command.rb +7 -3
  28. data/lib/morpheus/cli/networks_command.rb +164 -63
  29. data/lib/morpheus/cli/option_types.rb +16 -15
  30. data/lib/morpheus/cli/policies_command.rb +76 -9
  31. data/lib/morpheus/cli/preseed_scripts_command.rb +2 -2
  32. data/lib/morpheus/cli/remote.rb +26 -28
  33. data/lib/morpheus/cli/reports_command.rb +594 -0
  34. data/lib/morpheus/cli/security_group_rules.rb +5 -1
  35. data/lib/morpheus/cli/security_groups.rb +882 -45
  36. data/lib/morpheus/cli/tasks.rb +158 -23
  37. data/lib/morpheus/cli/tenants_command.rb +1 -1
  38. data/lib/morpheus/cli/users.rb +1 -1
  39. data/lib/morpheus/cli/version.rb +1 -1
  40. metadata +9 -2
@@ -0,0 +1,707 @@
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::CloudResourcePoolsCommand
8
+ include Morpheus::Cli::CliCommand
9
+ include Morpheus::Cli::InfrastructureHelper
10
+
11
+ #set_command_name :'cloud-resource-pools'
12
+ set_command_name :'resource-pools'
13
+
14
+ register_subcommands :list, :get, :add, :update, :remove
15
+
16
+ def initialize()
17
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
18
+ end
19
+
20
+ def connect(opts)
21
+ @api_client = establish_remote_appliance_connection(opts)
22
+ @cloud_resource_pools_interface = @api_client.cloud_resource_pools
23
+ @clouds_interface = @api_client.clouds
24
+ @options_interface = @api_client.options
25
+ end
26
+
27
+ def handle(args)
28
+ handle_subcommand(args)
29
+ end
30
+
31
+ def list(args)
32
+ cloud_id = nil
33
+ options = {}
34
+ params = {}
35
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
36
+ opts.banner = subcommand_usage("[cloud]")
37
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
38
+ cloud_id = val
39
+ end
40
+ opts.add_hidden_option('-c') # prefer args[0] for [cloud]
41
+ build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
42
+ opts.footer = "List resource pools for a cloud." + "\n" +
43
+ "[cloud] is required. This is the name or id of the cloud."
44
+ end
45
+ optparse.parse!(args)
46
+ if args.count == 1
47
+ cloud_id = args[0]
48
+ elsif args.count == 0 && cloud_id
49
+ # support -c
50
+ else
51
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
52
+ end
53
+ connect(options)
54
+ begin
55
+ # load cloud
56
+ if cloud_id.nil?
57
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
58
+ return 1
59
+ end
60
+ cloud = find_cloud_by_name_or_id(cloud_id)
61
+ return 1 if cloud.nil?
62
+
63
+ params.merge!(parse_list_options(options))
64
+ @cloud_resource_pools_interface.setopts(options)
65
+ if options[:dry_run]
66
+ print_dry_run @cloud_resource_pools_interface.dry.list(cloud['id'], params)
67
+ return
68
+ end
69
+ json_response = @cloud_resource_pools_interface.list(cloud['id'], params)
70
+ resource_pools = json_response["resourcePools"]
71
+ if options[:json]
72
+ puts as_json(json_response, options, "resourcePools")
73
+ return 0
74
+ elsif options[:yaml]
75
+ puts as_yaml(json_response, options, "resourcePools")
76
+ return 0
77
+ elsif options[:csv]
78
+ puts records_as_csv(resource_pools, options)
79
+ return 0
80
+ end
81
+ title = "Morpheus Resource Pools - Cloud: #{cloud['name']}"
82
+ subtitles = []
83
+ subtitles += parse_list_subtitles(options)
84
+ print_h1 title, subtitles
85
+ if resource_pools.empty?
86
+ print cyan,"No resource pools found.",reset,"\n"
87
+ else
88
+ rows = resource_pools.collect {|resource_pool|
89
+ formatted_name = (resource_pool['depth'] && resource_pool['depth'] > 0) ? ((' ' * resource_pool['depth'].to_i) + resource_pool['name'].to_s) : resource_pool['name'].to_s
90
+ row = {
91
+ id: resource_pool['id'],
92
+ # name: resource_pool['name'],
93
+ name: formatted_name,
94
+ type: resource_pool['type'].to_s.capitalize,
95
+ description: resource_pool['description'],
96
+ active: format_boolean(resource_pool['active']),
97
+ status: resource_pool['status'].to_s.upcase,
98
+ visibility: resource_pool['visibility'].to_s.capitalize,
99
+ default: format_boolean(resource_pool['defaultPool']),
100
+ tenants: resource_pool['tenants'] ? resource_pool['tenants'].collect {|it| it['name'] }.uniq.join(', ') : ''
101
+ # owner: resource_pool['owner'] ? resource_pool['owner']['name'] : ''
102
+ }
103
+ row
104
+ }
105
+ columns = [:id, :name, :description, :active, :default, :visibility, :tenants]
106
+ if options[:include_fields]
107
+ columns = options[:include_fields]
108
+ end
109
+ print cyan
110
+ print as_pretty_table(rows, columns, options)
111
+ print reset
112
+ print_results_pagination(json_response)
113
+ end
114
+ print reset,"\n"
115
+ return 0
116
+ rescue RestClient::Exception => e
117
+ print_rest_exception(e, options)
118
+ exit 1
119
+ end
120
+ end
121
+
122
+ def get(args)
123
+ resource_pool_id = nil
124
+ cloud_id = nil
125
+ options = {}
126
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
127
+ opts.banner = subcommand_usage("[cloud] [pool]")
128
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
129
+ cloud_id = val
130
+ end
131
+ opts.add_hidden_option('-c') # prefer args[0] for [cloud]
132
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
133
+ opts.footer = "Get details about a resource pool." + "\n" +
134
+ "[cloud] is required. This is the name or id of the cloud." + "\n"
135
+ "[pool] is required. This is the name or id of a resource pool."
136
+ end
137
+ optparse.parse!(args)
138
+ if args.count == 2
139
+ cloud_id = args[0]
140
+ resource_pool_id = args[1]
141
+ elsif args.count == 1 && cloud_id
142
+ resource_pool_id = args[0]
143
+ else
144
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
145
+ end
146
+ connect(options)
147
+ begin
148
+ # load cloud
149
+ if cloud_id.nil?
150
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
151
+ return 1
152
+ end
153
+ cloud = find_cloud_by_name_or_id(cloud_id)
154
+ return 1 if cloud.nil?
155
+ @cloud_resource_pools_interface.setopts(options)
156
+ if options[:dry_run]
157
+ if args[0].to_s =~ /\A\d{1,}\Z/
158
+ print_dry_run @cloud_resource_pools_interface.dry.get(cloud['id'], resource_pool_id.to_i)
159
+ else
160
+ print_dry_run @cloud_resource_pools_interface.dry.list(cloud['id'], {name:resource_pool_id})
161
+ end
162
+ return
163
+ end
164
+ resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
165
+ return 1 if resource_pool.nil?
166
+ json_response = {'resourcePool' => resource_pool} # skip redundant request
167
+ # json_response = @resource_pools_interface.get(resource_pool['id'])
168
+ resource_pool = json_response['resourcePool']
169
+ if options[:json]
170
+ puts as_json(json_response, options, "resourcePool")
171
+ return 0
172
+ elsif options[:yaml]
173
+ puts as_yaml(json_response, options, "resourcePool")
174
+ return 0
175
+ elsif options[:csv]
176
+ puts records_as_csv([resource_pool], options)
177
+ return 0
178
+ end
179
+
180
+ print_h1 "Resource Pool Details"
181
+ print cyan
182
+ description_cols = {
183
+ "ID" => 'id',
184
+ "Name" => 'name',
185
+ "Description" => 'description',
186
+ #"Type" => lambda {|it| it['type'].to_s.capitalize },
187
+ "Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
188
+ "Active" => lambda {|it| format_boolean(it['active']) },
189
+ "Default" => lambda {|it| format_boolean(it['defaultPool']) },
190
+ "Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
191
+ "Status" => lambda {|it| it['status'].to_s.capitalize },
192
+ "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.join(', ') : '' }
193
+ }
194
+ print_description_list(description_cols, resource_pool)
195
+
196
+ if resource_pool['resourcePermission'].nil?
197
+ #print "\n", "No group access found", "\n"
198
+ else
199
+ print_h2 "Group Access"
200
+ rows = []
201
+ if resource_pool['resourcePermission']['all']
202
+ rows.push({"name" => 'All'})
203
+ end
204
+ if resource_pool['resourcePermission']['sites']
205
+ resource_pool['resourcePermission']['sites'].each do |site|
206
+ rows.push(site)
207
+ end
208
+ end
209
+ group_columns = {
210
+ "GROUP" => 'name',
211
+ "DEFAULT" => lambda {|it| it['default'].nil? ? '' : format_boolean(it['default']) }
212
+ }
213
+ print cyan
214
+ print as_pretty_table(rows, group_columns)
215
+ end
216
+
217
+ if resource_pool['resourcePermission'] && resource_pool['resourcePermission']['plans'] && resource_pool['resourcePermission']['plans'].size > 0
218
+ print_h2 "Service Plan Access"
219
+ rows = []
220
+ if resource_pool['resourcePermission']['allPlans']
221
+ rows.push({"name" => 'All'})
222
+ end
223
+ if resource_pool['resourcePermission']['plans']
224
+ resource_pool['resourcePermission']['plans'].each do |plan|
225
+ rows.push(plan)
226
+ end
227
+ end
228
+ # rows = rows.collect do |site|
229
+ # {plan: site['name'], default: site['default'] ? 'Yes' : ''}
230
+ # #{group: site['name']}
231
+ # end
232
+ plan_columns = {
233
+ "PLAN" => 'name',
234
+ "DEFAULT" => lambda {|it| it['default'].nil? ? '' : format_boolean(it['default']) }
235
+ }
236
+ print cyan
237
+ print as_pretty_table(rows, plan_columns)
238
+ end
239
+
240
+ if resource_pool['tenants'].nil? || resource_pool['tenants'].empty?
241
+ #print "\n", "No tenant permissions found", "\n"
242
+ else
243
+ print_h2 "Tenant Permissions"
244
+ rows = []
245
+ rows = resource_pool['tenants'] || []
246
+ tenant_columns = {
247
+ "TENANT" => 'name',
248
+ "DEFAULT" => lambda {|it| format_boolean(it['defaultTarget']) },
249
+ "IMAGE TARGET" => lambda {|it| format_boolean(it['defaultStore']) }
250
+ }
251
+ print cyan
252
+ print as_pretty_table(rows, tenant_columns)
253
+ end
254
+
255
+ print reset,"\n"
256
+ return 0
257
+ rescue RestClient::Exception => e
258
+ print_rest_exception(e, options)
259
+ return 1
260
+ end
261
+ end
262
+
263
+ def add(args)
264
+ options = {}
265
+ cloud_id = nil
266
+ tenants = nil
267
+ group_access_all = nil
268
+ group_access_list = nil
269
+ group_defaults_list = nil
270
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
271
+ opts.banner = subcommand_usage("[cloud] [pool] [options]")
272
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
273
+ cloud_id = val
274
+ end
275
+ opts.add_hidden_option('-c') # prefer args[0] for [cloud]
276
+ opts.on( '--name VALUE', String, "Name" ) do |val|
277
+ options['name'] = val
278
+ end
279
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
280
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
281
+ end
282
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
283
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
284
+ group_access_list = []
285
+ else
286
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
287
+ end
288
+ end
289
+ # opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
290
+ # if list.size == 1 && list[0] == 'null' # hacky way to clear it
291
+ # group_defaults_list = []
292
+ # else
293
+ # group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
294
+ # end
295
+ # end
296
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
297
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
298
+ options['tenants'] = []
299
+ else
300
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
301
+ end
302
+ end
303
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
304
+ options['visibility'] = val
305
+ end
306
+ opts.on('--active [on|off]', String, "Can be used to disable a resource pool") do |val|
307
+ options['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
308
+ end
309
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
310
+ opts.footer = "Update a resource pool." + "\n" +
311
+ "[cloud] is required. This is the name or id of the cloud."
312
+ end
313
+ optparse.parse!(args)
314
+ if args.count == 2
315
+ cloud_id = args[0]
316
+ options['name'] = args[1]
317
+ elsif args.count == 1 # && cloud_id
318
+ if cloud_id
319
+ options['name'] = args[0]
320
+ else
321
+ cloud_id = args[0]
322
+ end
323
+ else
324
+ raise_command_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
325
+ end
326
+
327
+ connect(options)
328
+
329
+ begin
330
+ # load cloud
331
+ if cloud_id.nil?
332
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
333
+ return 1
334
+ end
335
+ cloud = find_cloud_by_name_or_id(cloud_id)
336
+ return 1 if cloud.nil?
337
+
338
+ # merge -O options into normally parsed options
339
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
340
+
341
+ # construct payload
342
+ payload = nil
343
+ if options[:payload]
344
+ payload = options[:payload]
345
+ else
346
+ # prompt for resource pool options
347
+ payload = {
348
+ 'resourcePool' => {
349
+ }
350
+ }
351
+
352
+ # allow arbitrary -O options
353
+ payload['resourcePool'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
354
+
355
+
356
+ # Name
357
+ if options['name']
358
+ payload['resourcePool']['name'] = options['name']
359
+ else
360
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name'}], options)
361
+ payload['resourcePool']['name'] = v_prompt['name']
362
+ end
363
+
364
+ # Group Access
365
+ if group_access_all != nil
366
+ payload['resourcePermissions'] ||= {}
367
+ payload['resourcePermissions']['all'] = group_access_all
368
+ end
369
+ if group_access_list != nil
370
+ payload['resourcePermissions'] ||= {}
371
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
372
+ site = {"id" => site_id.to_i}
373
+ if group_defaults_list && group_defaults_list.include?(site_id)
374
+ site["default"] = true
375
+ end
376
+ site
377
+ end
378
+ end
379
+
380
+ # Tenants
381
+ if options['tenants']
382
+ payload['tenantPermissions'] = {}
383
+ payload['tenantPermissions']['accounts'] = options['tenants']
384
+ end
385
+
386
+ # Active
387
+ if options['active'] != nil
388
+ payload['resourcePool']['active'] = options['active']
389
+ else
390
+ payload['resourcePool']['active'] = true
391
+ end
392
+
393
+ # Visibility
394
+ if options['visibility'] != nil
395
+ payload['resourcePool']['visibility'] = options['visibility']
396
+ else
397
+ payload['resourcePool']['visibility'] = 'private'
398
+ end
399
+
400
+
401
+ # Config options depend on type (until api returns these as optionTypes)
402
+ zone_type = cloud['zoneType'] ? cloud['zoneType']['code'] : ''
403
+ if zone_type == 'amazon'
404
+ payload['resourcePool']['config'] ||= {}
405
+ # CIDR
406
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'config', 'fieldName' => 'cidrBlock', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => true, 'description' => 'Provide the base CIDR Block to use for this VPC (must be between a /16 and /28 Block)'}], options)
407
+ payload['resourcePool']['config']['cidrBlock'] = v_prompt['config']['cidrBlock']
408
+ # Tenancy
409
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'config', 'fieldName' => 'tenancy', 'fieldLabel' => 'Tenancy', 'type' => 'select', 'selectOptions' => [{'name' => 'Default', 'value' => 'default'}, {'name' => 'Dedicated', 'value' => 'dedicated'}], 'defaultValue' => 'default'}], options)
410
+ payload['resourcePool']['config']['tenancy'] = v_prompt['config']['tenancy']
411
+
412
+ elsif zone_type == 'azure'
413
+ # no options
414
+ elsif zone_type == 'cloudFoundry' || zone_type == 'bluemixCloudFoundry'
415
+
416
+ elsif zone_type == 'standard'
417
+ # no options
418
+ else
419
+ #raise_command_error "Cloud type '#{zone_type}' does not allow creating resource pools"
420
+ end
421
+
422
+ end
423
+ @cloud_resource_pools_interface.setopts(options)
424
+ if options[:dry_run]
425
+ print_dry_run @cloud_resource_pools_interface.dry.create(cloud['id'], payload)
426
+ return
427
+ end
428
+ json_response = @cloud_resource_pools_interface.create(cloud['id'], payload)
429
+ if options[:json]
430
+ puts as_json(json_response)
431
+ else
432
+ resource_pool = json_response['resourcePool']
433
+ print_green_success "Created resource pool #{resource_pool['name']}"
434
+ get([cloud['id'].to_s, resource_pool['id'].to_s])
435
+ end
436
+ return 0
437
+ rescue RestClient::Exception => e
438
+ print_rest_exception(e, options)
439
+ return 1
440
+ end
441
+ end
442
+
443
+ def update(args)
444
+ options = {}
445
+ cloud_id = nil
446
+ resource_pool_id = nil
447
+ tenants = nil
448
+ group_access_all = nil
449
+ group_access_list = nil
450
+ group_defaults_list = nil
451
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
452
+ opts.banner = subcommand_usage("[cloud] [pool] [options]")
453
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
454
+ cloud_id = val
455
+ end
456
+ opts.add_hidden_option('-c') # prefer args[0] for [cloud]
457
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
458
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
459
+ end
460
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
461
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
462
+ group_access_list = []
463
+ else
464
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
465
+ end
466
+ end
467
+ # opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
468
+ # if list.size == 1 && list[0] == 'null' # hacky way to clear it
469
+ # group_defaults_list = []
470
+ # else
471
+ # group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
472
+ # end
473
+ # end
474
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
475
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
476
+ options['tenants'] = []
477
+ else
478
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
479
+ end
480
+ end
481
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
482
+ options['visibility'] = val
483
+ end
484
+ opts.on('--active [on|off]', String, "Can be used to disable a resource pool") do |val|
485
+ options['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
486
+ end
487
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
488
+ opts.footer = "Update a resource pool." + "\n" +
489
+ "[cloud] is required. This is the name or id of the cloud." + "\n"
490
+ "[pool] is required. This is the name or id of a resource pool."
491
+ end
492
+ optparse.parse!(args)
493
+ if args.count == 2
494
+ cloud_id = args[0]
495
+ resource_pool_id = args[1]
496
+ elsif args.count == 1 && cloud_id
497
+ resource_pool_id = args[0]
498
+ else
499
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
500
+ end
501
+
502
+ connect(options)
503
+
504
+ begin
505
+ # load cloud
506
+ if cloud_id.nil?
507
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
508
+ return 1
509
+ end
510
+ cloud = find_cloud_by_name_or_id(cloud_id)
511
+ return 1 if cloud.nil?
512
+
513
+ resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
514
+ return 1 if resource_pool.nil?
515
+
516
+ # merge -O options into normally parsed options
517
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
518
+
519
+ # construct payload
520
+ payload = nil
521
+ if options[:payload]
522
+ payload = options[:payload]
523
+ else
524
+ # prompt for resource pool options
525
+ payload = {
526
+ 'resourcePool' => {
527
+ }
528
+ }
529
+
530
+ # allow arbitrary -O options
531
+ payload['resourcePool'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
532
+
533
+
534
+ # Group Access
535
+ if group_access_all != nil
536
+ payload['resourcePermissions'] ||= {}
537
+ payload['resourcePermissions']['all'] = group_access_all
538
+ end
539
+ if group_access_list != nil
540
+ payload['resourcePermissions'] ||= {}
541
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
542
+ site = {"id" => site_id.to_i}
543
+ if group_defaults_list && group_defaults_list.include?(site_id)
544
+ site["default"] = true
545
+ end
546
+ site
547
+ end
548
+ end
549
+
550
+ # Tenants
551
+ if options['tenants']
552
+ payload['tenantPermissions'] = {}
553
+ payload['tenantPermissions']['accounts'] = options['tenants']
554
+ end
555
+
556
+ # Active
557
+ if options['active'] != nil
558
+ payload['resourcePool']['active'] = options['active']
559
+ end
560
+
561
+ # Visibility
562
+ if options['visibility'] != nil
563
+ payload['resourcePool']['visibility'] = options['visibility']
564
+ end
565
+
566
+ if payload['resourcePool'].empty? && payload['resourcePermissions'].nil? && payload['tenantPermissions'].nil?
567
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
568
+ end
569
+
570
+ end
571
+ @cloud_resource_pools_interface.setopts(options)
572
+ if options[:dry_run]
573
+ print_dry_run @cloud_resource_pools_interface.dry.update(cloud['id'], resource_pool["id"], payload)
574
+ return
575
+ end
576
+ json_response = @cloud_resource_pools_interface.update(cloud['id'], resource_pool["id"], payload)
577
+ if options[:json]
578
+ puts as_json(json_response)
579
+ else
580
+ resource_pool = json_response['resourcePool']
581
+ print_green_success "Updated resource pool #{resource_pool['name']}"
582
+ get([cloud['id'].to_s, resource_pool['id'].to_s])
583
+ end
584
+ return 0
585
+ rescue RestClient::Exception => e
586
+ print_rest_exception(e, options)
587
+ return 1
588
+ end
589
+ end
590
+
591
+ def remove(args)
592
+ cloud_id = nil
593
+ resource_pool_id = nil
594
+ options = {}
595
+ params = {}
596
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
597
+ opts.banner = subcommand_usage("[cloud] [pool]")
598
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
599
+ opts.footer = "Delete a resource pool." + "\n" +
600
+ "[cloud] is required. This is the name or id of the cloud." + "\n"
601
+ "[pool] is required. This is the name or id of a resource pool."
602
+ end
603
+ optparse.parse!(args)
604
+
605
+ if args.count == 2
606
+ cloud_id = args[0]
607
+ resource_pool_id = args[1]
608
+ elsif args.count == 1 && cloud_id
609
+ resource_pool_id = args[0]
610
+ else
611
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
612
+ end
613
+
614
+ connect(options)
615
+ begin
616
+ # load cloud
617
+ if cloud_id.nil?
618
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
619
+ return 1
620
+ end
621
+ cloud = find_cloud_by_name_or_id(cloud_id)
622
+ return 1 if cloud.nil?
623
+
624
+ resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
625
+ return 1 if resource_pool.nil?
626
+
627
+ zone_type = cloud['zoneType'] ? cloud['zoneType']['code'] : ''
628
+ if zone_type == ['amazon','azure','cloudFoundry','bluemixCloudFoundry','standard'].include?(zone_type)
629
+ else
630
+ #raise_command_error "Cloud type '#{zone_type}' does not allow deleting resource pools"
631
+ end
632
+
633
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the resource pool: #{resource_pool['name']}?")
634
+ return 9, "aborted command"
635
+ end
636
+ @cloud_resource_pools_interface.setopts(options)
637
+ if options[:dry_run]
638
+ print_dry_run @cloud_resource_pools_interface.dry.destroy(cloud['id'], resource_pool["id"], params)
639
+ return
640
+ end
641
+ json_response = @cloud_resource_pools_interface.destroy(cloud['id'], resource_pool["id"], params)
642
+ if options[:json]
643
+ puts as_json(json_response, options)
644
+ else
645
+ print_green_success "Removed resource pool #{resource_pool['name']}"
646
+ end
647
+ return 0
648
+ rescue RestClient::Exception => e
649
+ print_rest_exception(e, options)
650
+ return 1
651
+ end
652
+ end
653
+
654
+ private
655
+
656
+
657
+ def find_resource_pool_by_name_or_id(cloud_id, val)
658
+ if val.to_s =~ /\A\d{1,}\Z/
659
+ return find_resource_pool_by_id(cloud_id, val)
660
+ else
661
+ return find_resource_pool_by_name(cloud_id, val)
662
+ end
663
+ end
664
+
665
+ def find_resource_pool_by_id(cloud_id, id)
666
+ begin
667
+ json_response = @cloud_resource_pools_interface.get(cloud_id, id.to_i)
668
+ return json_response['resourcePool']
669
+ rescue RestClient::Exception => e
670
+ if e.response && e.response.code == 404
671
+ print_red_alert "Resource Pool not found by id #{id}"
672
+ return nil
673
+ else
674
+ raise e
675
+ end
676
+ end
677
+ end
678
+
679
+ def find_resource_pool_by_name(cloud_id, name)
680
+ json_response = @cloud_resource_pools_interface.list(cloud_id, {name: name.to_s})
681
+ resource_pools = json_response['resourcePools']
682
+ if resource_pools.empty?
683
+ print_red_alert "Resource Pool not found by name #{name}"
684
+ return nil
685
+ elsif resource_pools.size > 1
686
+ matching_resource_pools = folders.select { |it| name && (it['name'] == name || it['externalId'] == name) }
687
+ if matching_resource_pools.size == 1
688
+ return matching_resource_pools[0]
689
+ end
690
+ print_red_alert "#{resource_pools.size} resource pools found by name #{name}"
691
+ rows = resource_pools.collect do |it|
692
+ {id: it['id'], name: it['name']}
693
+ end
694
+ print "\n"
695
+ puts as_pretty_table(rows, [:id, :name], {color:red})
696
+ return nil
697
+ else
698
+ resource_pool = resource_pools[0]
699
+ # merge in tenants map
700
+ if json_response['tenants'] && json_response['tenants'][resource_pool['id']]
701
+ resource_pool['tenants'] = json_response['tenants'][resource_pool['id']]
702
+ end
703
+ return resource_pool
704
+ end
705
+ end
706
+
707
+ end