morpheus-cli 3.6.28 → 3.6.29

Sign up to get free protection for your applications and to get access to all the features.
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