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
@@ -10,7 +10,10 @@ class Morpheus::Cli::SecurityGroupRules
10
10
 
11
11
  register_subcommands :list, :'add-custom-rule', :'add-instance-rule', :remove
12
12
  set_default_subcommand :list
13
-
13
+
14
+ # replaced by security-groups add-rule
15
+ set_command_hidden
16
+
14
17
  def connect(opts)
15
18
  @api_client = establish_remote_appliance_connection(opts)
16
19
  @security_group_rules_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).security_group_rules
@@ -18,6 +21,7 @@ class Morpheus::Cli::SecurityGroupRules
18
21
  end
19
22
 
20
23
  def handle(args)
24
+ print_error "#{yellow}DEPRECATION WARNING: `security-group-rules` is deprecated. Please use `security-groups` instead.#{reset}\n"
21
25
  handle_subcommand(args)
22
26
  end
23
27
 
@@ -4,16 +4,24 @@ require 'rest_client'
4
4
  require 'optparse'
5
5
  require 'filesize'
6
6
  require 'morpheus/cli/cli_command'
7
+ require 'morpheus/cli/mixins/infrastructure_helper'
7
8
 
8
9
  class Morpheus::Cli::SecurityGroups
9
10
  include Morpheus::Cli::CliCommand
11
+ include Morpheus::Cli::InfrastructureHelper
10
12
 
11
- register_subcommands :list, :get, :add, :remove, :use, :unuse
13
+ register_subcommands :list, :get, :add, :update, :remove
14
+ register_subcommands :'add-location', :'remove-location'
15
+ register_subcommands :'add-rule', :'update-rule', :'remove-rule'
12
16
  set_default_subcommand :list
13
17
 
14
18
  def connect(opts)
15
19
  @api_client = establish_remote_appliance_connection(opts)
16
- @security_groups_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).security_groups
20
+ @security_groups_interface = @api_client.security_groups
21
+ @security_group_rules_interface = @api_client.security_group_rules
22
+ @cloud_resource_pools_interface = @api_client.cloud_resource_pools
23
+ @clouds_interface = @api_client.clouds
24
+ @options_interface = @api_client.options
17
25
  @active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
18
26
  end
19
27
 
@@ -27,8 +35,12 @@ class Morpheus::Cli::SecurityGroups
27
35
  optparse = Morpheus::Cli::OptionParser.new do |opts|
28
36
  opts.banner = subcommand_usage()
29
37
  build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
38
+ opts.footer = "List security groups."
30
39
  end
31
40
  optparse.parse!(args)
41
+ if args.count != 0
42
+ raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
43
+ end
32
44
  connect(options)
33
45
  begin
34
46
  params = {}
@@ -73,8 +85,11 @@ class Morpheus::Cli::SecurityGroups
73
85
  columns = {
74
86
  "ID" => 'id',
75
87
  "NAME" => 'name',
76
- "DESCRIPTION" => 'description',
77
- # need more to show here
88
+ #"DESCRIPTION" => 'description',
89
+ "DESCRIPTION" => lambda {|it| truncate_string(it['description'], 30) },
90
+ #"USED BY" => lambda {|it| it['associations'] ? it['associations'] : '' },
91
+ "SCOPED CLOUD" => lambda {|it| it['zone'] ? it['zone']['name'] : 'All' },
92
+ "SOURCE" => lambda {|it| it['syncSource'] == 'external' ? 'SYNCED' : 'CREATED' }
78
93
  }
79
94
  # custom pretty table columns ...
80
95
  if options[:include_fields]
@@ -83,9 +98,9 @@ class Morpheus::Cli::SecurityGroups
83
98
  print as_pretty_table(security_groups, columns, options)
84
99
  print reset
85
100
  if json_response['meta']
86
- print_results_pagination(json_response, {:label => "security group", :n_label => "security groups"})
101
+ print_results_pagination(json_response)
87
102
  else
88
- print_results_pagination({'meta'=>{'total'=>(json_response['securityGroupCount'] ? json_response['securityGroupCount'] : security_groups.size),'size'=>security_groups.size,'max'=>(params['max']||25),'offset'=>(params['offset']||0)}}, {:label => "security group", :n_label => "security groups"})
103
+ print_results_pagination({'meta'=>{'total'=>(json_response['securityGroupCount'] ? json_response['securityGroupCount'] : security_groups.size),'size'=>security_groups.size,'max'=>(params['max']||25),'offset'=>(params['offset']||0)}})
89
104
  end
90
105
  # print reset
91
106
  end
@@ -101,21 +116,34 @@ class Morpheus::Cli::SecurityGroups
101
116
  options = {}
102
117
  optparse = Morpheus::Cli::OptionParser.new do |opts|
103
118
  opts.banner = subcommand_usage("[id]")
104
- build_common_options(opts, options, [:json, :dry_run])
119
+ build_common_options(opts, options, [:json, :dry_run, :remote])
120
+ opts.footer = "Get details about a security group."
105
121
  end
106
122
  optparse.parse!(args)
107
- if args.count < 1
108
- puts optparse
109
- exit 1
123
+ if args.count != 1
124
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
110
125
  end
111
126
  connect(options)
112
127
  begin
113
128
  @security_groups_interface.setopts(options)
129
+
114
130
  if options[:dry_run]
115
- print_dry_run @security_groups_interface.dry.get({id: args[0]})
116
- return
131
+ if args[0].to_s =~ /\A\d{1,}\Z/
132
+ print_dry_run @security_groups_interface.dry.get(args[0].to_i)
133
+ else
134
+ print_dry_run @security_groups_interface.dry.list({name:args[0]})
135
+ end
136
+ return 0
117
137
  end
118
- json_response = @security_groups_interface.get({id: args[0]})
138
+ security_group = find_security_group_by_name_or_id(args[0])
139
+ return 1 if security_group.nil?
140
+ json_response = nil
141
+ if args[0].to_s =~ /\A\d{1,}\Z/
142
+ json_response = {'securityGroup' => security_group} # skip redundant request
143
+ else
144
+ json_response = @security_groups_interface.get(security_group['id'])
145
+ end
146
+
119
147
  if options[:json]
120
148
  print JSON.pretty_generate(json_response)
121
149
  print "\n"
@@ -128,10 +156,72 @@ class Morpheus::Cli::SecurityGroups
128
156
  "ID" => 'id',
129
157
  "Name" => 'name',
130
158
  "Description" => 'description',
131
- #"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
159
+ "Scoped Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : 'All' },
160
+ "Source" => lambda {|it| it['syncSource'] == 'external' ? 'SYNCED' : 'CREATED' }
132
161
  }
133
162
  print_description_list(description_cols, security_group)
134
- print reset,"\n"
163
+ # print reset,"\n"
164
+
165
+ if security_group['locations'] && security_group['locations'].size > 0
166
+ print_h2 "Locations"
167
+ print cyan
168
+ location_cols = {
169
+ "ID" => 'id',
170
+ "CLOUD" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
171
+ "EXTERNAL ID" => lambda {|it| it['externalId'] },
172
+ "RESOURCE POOL" => lambda {|it| it['zonePool'] ? it['zonePool']['name'] : '' }
173
+ }
174
+ puts as_pretty_table(security_group['locations'], location_cols)
175
+ else
176
+ print reset,"\n"
177
+ end
178
+
179
+ if security_group['rules']
180
+ if security_group['rules'].size == 0
181
+ #print cyan,"No rules.",reset,"\n"
182
+ else
183
+ print_h2 "Rules"
184
+ print cyan
185
+ # NAME DIRECTION SOURCE DESTINATION RULE TYPE PROTOCOL PORT RANGE
186
+ rule_cols = {
187
+ "ID" => 'id',
188
+ "NAME" => 'name',
189
+ "DIRECTION" => lambda {|it| it['direction'] },
190
+ "SOURCE" => lambda {|it|
191
+ if it['sourceType'] == 'cidr'
192
+ "Network: #{it['source']}"
193
+ elsif it['sourceType'] == 'group'
194
+ "Group: #{it['sourceGroup'] ? it['sourceGroup']['name'] : ''}"
195
+ elsif it['sourceType'] == 'tier'
196
+ "Tier: #{it['sourceTier'] ? it['sourceTier']['name'] : ''}"
197
+ elsif it['sourceType'] == 'instance'
198
+ "Instance"
199
+ else
200
+ it['sourceType']
201
+ end
202
+ },
203
+ "DESTINATION" => lambda {|it|
204
+ if it['destinationType'] == 'cidr'
205
+ "Network: #{it['destination']}"
206
+ elsif it['destinationType'] == 'group'
207
+ "Group: #{it['destinationGroup'] ? it['destinationGroup']['name'] : ''}"
208
+ elsif it['destinationType'] == 'tier'
209
+ "Tier: #{it['destinationTier'] ? it['destinationTier']['name'] : ''}"
210
+ elsif it['destinationType'] == 'instance'
211
+ "Instance"
212
+ else
213
+ it['destinationType']
214
+ end
215
+ },
216
+ "RULE TYPE" => lambda {|it| it['ruleType'] == 'customRule' ? 'Custom' : it['ruleType'] },
217
+ "PROTOCOL" => lambda {|it| it['protocol'] },
218
+ "PORT RANGE" => lambda {|it| it['portRange'] }
219
+ }
220
+ puts as_pretty_table(security_group['rules'], rule_cols)
221
+ end
222
+ end
223
+
224
+ return 0
135
225
  rescue RestClient::Exception => e
136
226
  print_rest_exception(e, options)
137
227
  exit 1
@@ -139,35 +229,165 @@ class Morpheus::Cli::SecurityGroups
139
229
  end
140
230
 
141
231
  def add(args)
142
- params = {:securityGroup => {}}
143
- options = {}
232
+ params = {}
233
+ options = {:options => {}}
234
+ cloud_id = nil
144
235
  optparse = Morpheus::Cli::OptionParser.new do |opts|
145
236
  opts.banner = subcommand_usage("[name] [options]")
146
- opts.on( '-d', '--description Description', "Description of the security group" ) do |description|
147
- params[:securityGroup][:description] = description
237
+ opts.on( '--name Name', String, "Name of the security group" ) do |val|
238
+ options[:options]['name'] = val
239
+ end
240
+ opts.on( '--description Description', String, "Description of the security group" ) do |val|
241
+ options[:options]['description'] = val
148
242
  end
149
- build_common_options(opts, options, [:json, :dry_run])
243
+ opts.on( '-c', '--cloud CLOUD', "Scoped Cloud Name or ID" ) do |val|
244
+ cloud_id = val
245
+ end
246
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
247
+ opts.footer = "Create a security group." + "\n" +
248
+ "[name] is required. This is the name of the security group."
150
249
  end
151
250
  optparse.parse!(args)
152
- if args.count < 1
153
- puts optparse
251
+ if args.count > 1
252
+ raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
253
+ end
254
+ if args[0]
255
+ options[:options]['name'] = args[0]
256
+ end
257
+ connect(options)
258
+ begin
259
+
260
+ # load cloud
261
+ cloud = nil
262
+ if cloud_id
263
+ cloud = find_cloud_by_name_or_id(cloud_id)
264
+ return 1 if cloud.nil?
265
+ options[:options]['zoneId'] = cloud['id'].to_s
266
+ end
267
+
268
+ # construct payload
269
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
270
+ payload = nil
271
+ if options[:payload]
272
+ payload = options[:payload]
273
+ payload.deep_merge!({'securityGroup' => passed_options}) unless passed_options.empty?
274
+ else
275
+ # prompt for resource folder options
276
+ payload = {
277
+ 'securityGroup' => {
278
+ }
279
+ }
280
+ # allow arbitrary -O options
281
+ payload.deep_merge!({'securityGroup' => passed_options}) unless passed_options.empty?
282
+
283
+ # Name
284
+ options[:options]['name'] = options[:name] if options.key?(:name)
285
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}], options[:options])
286
+ payload['securityGroup']['name'] = v_prompt['name']
287
+
288
+ # Description
289
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false}], options[:options])
290
+ payload['securityGroup']['description'] = v_prompt['description']
291
+
292
+ # Scoped Cloud
293
+ # /api/options/clouds requires groupId...
294
+
295
+
296
+ begin
297
+ scoped_clouds = [{"name" => "All", "value" => "all"}]
298
+ clouds_response = @options_interface.options_for_source('cloudsForSecurityGroup',{})
299
+ if clouds_response['data']
300
+ clouds_response['data'].each do |it|
301
+ scoped_clouds << {"name" => it['name'], "value" => it['value']}
302
+ end
303
+ end
304
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneId', 'fieldLabel' => 'Scoped Cloud', 'type' => 'select', 'selectOptions' => scoped_clouds, 'required' => false, 'defaultValue' => (payload['securityGroup']['zoneId'] || 'all')}], options[:options], @api_client)
305
+ #v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneId', 'fieldLabel' => 'Scoped Cloud', 'type' => 'select', 'optionSource' => 'cloudsForSecurityGroup', 'required' => false}], options[:options], @api_client)
306
+ if !v_prompt['zoneId'].to_s.empty? && v_prompt['zoneId'].to_s != 'all' && v_prompt['zoneId'].to_s != '-1'
307
+ payload['securityGroup']['zoneId'] = v_prompt['zoneId']
308
+ end
309
+ rescue => ex
310
+ print yellow,"Failed to determine the available scoped clouds.",reset,"\n"
311
+ end
312
+
313
+ end
314
+
315
+ @security_groups_interface.setopts(options)
316
+ if options[:dry_run]
317
+ print_dry_run @security_groups_interface.dry.create(payload)
318
+ return 0
319
+ end
320
+ json_response = @security_groups_interface.create(payload)
321
+ if options[:json]
322
+ puts as_json(json_response, options)
323
+ return 0
324
+ end
325
+ print_green_success "Created security group #{json_response['securityGroup']['name']}"
326
+ return 0
327
+ rescue RestClient::Exception => e
328
+ print_rest_exception(e, options)
154
329
  exit 1
155
330
  end
156
- params[:securityGroup][:name] = args[0]
331
+ end
332
+
333
+ def update(args)
334
+ params = {}
335
+ options = {:options => {}}
336
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
337
+ opts.banner = subcommand_usage("[security-group] [options]")
338
+ opts.on( '--name Name', String, "Name of the security group" ) do |val|
339
+ options[:options]['name'] = val
340
+ end
341
+ opts.on( '--description Description', String, "Description of the security group" ) do |val|
342
+ options[:options]['description'] = val
343
+ end
344
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
345
+ opts.footer = "Update a security group." + "\n" +
346
+ "[security-group] is required. This is the name or id of the security group."
347
+ end
348
+ optparse.parse!(args)
349
+ if args.count != 1
350
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
351
+ end
157
352
  connect(options)
158
353
  begin
354
+ security_group = find_security_group_by_name_or_id(args[0])
355
+ return 1 if security_group.nil?
356
+
357
+ # construct payload
358
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
359
+ payload = nil
360
+ if options[:payload]
361
+ payload = options[:payload]
362
+ payload['securityGroup'].deep_merge!(passed_options) unless passed_options.empty?
363
+ else
364
+ # prompt for resource folder options
365
+ payload = {
366
+ 'securityGroup' => {
367
+ }
368
+ }
369
+ # allow arbitrary -O options
370
+ payload['securityGroup'].deep_merge!(passed_options) unless passed_options.empty?
371
+
372
+ if passed_options.empty?
373
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
374
+ end
375
+
376
+ end
377
+
159
378
  @security_groups_interface.setopts(options)
160
379
  if options[:dry_run]
161
- print_dry_run @security_groups_interface.dry.create(params)
162
- return
380
+ print_dry_run @security_groups_interface.dry.update(security_group['id'], payload)
381
+ return 0
163
382
  end
164
- json_response = @security_groups_interface.create(params)
383
+ json_response = @security_groups_interface.update(security_group['id'], payload)
165
384
  if options[:json]
166
- print JSON.pretty_generate(json_response)
167
- print "\n"
168
- return
385
+ puts as_json(json_response, options)
386
+ return 0
169
387
  end
170
- list([])
388
+ print_green_success "Updated security group #{json_response['securityGroup']['name']}"
389
+ get([security_group['id']])
390
+ return 0
171
391
  rescue RestClient::Exception => e
172
392
  print_rest_exception(e, options)
173
393
  exit 1
@@ -178,21 +398,23 @@ class Morpheus::Cli::SecurityGroups
178
398
  options = {}
179
399
  optparse = Morpheus::Cli::OptionParser.new do |opts|
180
400
  opts.banner = subcommand_usage("[id]")
181
- build_common_options(opts, options, [:json, :dry_run])
401
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
402
+ opts.footer = "Delete a security group." + "\n" +
403
+ "[security-group] is required. This is the name or id of the security group."
182
404
  end
183
405
  optparse.parse!(args)
184
- if args.count < 1
185
- puts optparse
186
- return
406
+ if args.count != 1
407
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
187
408
  end
188
409
  connect(options)
189
410
  begin
190
- json_response = @security_groups_interface.get({id: args[0]})
191
- security_group = json_response['securityGroup']
192
- if security_group.nil?
193
- puts "Security Group not found by id #{args[0]}"
194
- return
411
+ security_group = find_security_group_by_name_or_id(args[0])
412
+ return 1 if security_group.nil?
413
+
414
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the security group: #{security_group['name']}?")
415
+ return 9, "aborted command"
195
416
  end
417
+
196
418
  @security_groups_interface.setopts(options)
197
419
  if options[:dry_run]
198
420
  print_dry_run @security_groups_interface.dry.delete(security_group['id'])
@@ -200,17 +422,524 @@ class Morpheus::Cli::SecurityGroups
200
422
  end
201
423
  json_response = @security_groups_interface.delete(security_group['id'])
202
424
  if options[:json]
203
- print JSON.pretty_generate(json_response)
204
- print "\n"
205
- return
425
+ puts as_json(json_response, options)
426
+ return 0
427
+ end
428
+ #list([])
429
+ print_green_success "Removed security group #{args[0]}"
430
+ return 0
431
+ rescue RestClient::Exception => e
432
+ print_rest_exception(e, options)
433
+ exit 1
434
+ end
435
+ end
436
+
437
+ def add_location(args)
438
+ cloud_id = nil
439
+ resource_pool_id = nil
440
+ params = {}
441
+ options = {:options => {}}
442
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
443
+ opts.banner = subcommand_usage("[security-group] [options]")
444
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
445
+ cloud_id = val
446
+ end
447
+ opts.on( '--resource-pool ID', String, "ID of the Resource Pool for Amazon VPC and Azure Resource Group" ) do |val|
448
+ resource_pool_id = val
449
+ end
450
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
451
+ opts.footer = "Add security group to a location (cloud)." + "\n" +
452
+ "[security-group] is required. This is the name or id of the security group."
453
+ end
454
+ optparse.parse!(args)
455
+ if args.count != 1
456
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
457
+ end
458
+ connect(options)
459
+ begin
460
+ security_group = find_security_group_by_name_or_id(args[0])
461
+ return 1 if security_group.nil?
462
+
463
+ # load cloud
464
+ if cloud_id.nil?
465
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
466
+ return 1
467
+ end
468
+ cloud = find_cloud_by_name_or_id(cloud_id)
469
+ return 1 if cloud.nil?
470
+
471
+ if resource_pool_id
472
+ resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id)
473
+ return 1 if resource_pool.nil?
474
+ end
475
+
476
+ # construct payload
477
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
478
+ payload = nil
479
+ if options[:payload]
480
+ payload = options[:payload]
481
+ payload.deep_merge!({'securityGroupLocation' => passed_options}) unless passed_options.empty?
482
+ else
483
+ # prompt for resource folder options
484
+ payload = {
485
+ 'securityGroupLocation' => {
486
+ }
487
+ }
488
+ payload.deep_merge!({'securityGroupLocation' => passed_options}) unless passed_options.empty?
489
+ if cloud
490
+ payload['securityGroupLocation']['zoneId'] = cloud['id']
491
+ end
492
+
493
+ if cloud['securityServer']
494
+ if cloud['securityServer']['type'] == 'amazon'
495
+ if resource_pool
496
+ payload['securityGroupLocation']['customOptions'] = {'vpc' => resource_pool['externalId']}
497
+ elsif cloud['config'] && cloud['config']['vpc']
498
+ payload['securityGroupLocation']['customOptions'] = {'vpc' => cloud['config']['vpc']}
499
+ end
500
+ elsif cloud['securityServer']['type'] == 'azure'
501
+ if resource_pool
502
+ payload['securityGroupLocation']['customOptions'] = {'resourceGroup' => resource_pool['externalId']}
503
+ elsif cloud['config'] && cloud['config']['resourceGroup']
504
+ payload['securityGroupLocation']['customOptions'] = {'resourceGroup' => cloud['config']['resourceGroup']}
505
+ end
506
+ end
507
+ end
508
+ end
509
+
510
+ @security_groups_interface.setopts(options)
511
+ if options[:dry_run]
512
+ print_dry_run @security_groups_interface.dry.create_location(security_group['id'], payload)
513
+ return 0
514
+ end
515
+ json_response = @security_groups_interface.create_location(security_group['id'], payload)
516
+ if options[:json]
517
+ puts as_json(json_response, options)
518
+ return 0
519
+ end
520
+ print_green_success "Created security group location #{security_group['name']} - #{cloud['name']}"
521
+ get([security_group['id']])
522
+ return 0
523
+ rescue RestClient::Exception => e
524
+ print_rest_exception(e, options)
525
+ exit 1
526
+ end
527
+ end
528
+
529
+ def remove_location(args)
530
+ cloud_id = nil
531
+ resource_pool_id = nil
532
+ params = {}
533
+ options = {:options => {}}
534
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
535
+ opts.banner = subcommand_usage("[security-group] [options]")
536
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
537
+ cloud_id = val
538
+ end
539
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
540
+ opts.footer = "Remove security group from a location (cloud)." + "\n" +
541
+ "[security-group] is required. This is the name or id of the security group."
542
+ end
543
+ optparse.parse!(args)
544
+ if args.count != 1
545
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
546
+ end
547
+ connect(options)
548
+ begin
549
+ security_group = find_security_group_by_name_or_id(args[0])
550
+ return 1 if security_group.nil?
551
+
552
+
553
+ # load cloud
554
+ if cloud_id.nil?
555
+ puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}"
556
+ return 1
557
+ end
558
+ cloud = find_cloud_by_name_or_id(cloud_id)
559
+ return 1 if cloud.nil?
560
+
561
+ security_group_location = nil
562
+ if security_group['locations']
563
+ security_group_location = security_group['locations'].find {|it| it['zone']['id'] == cloud['id'] }
564
+ end
565
+ if security_group_location.nil?
566
+ print_red_alert "Security group location not found for cloud #{cloud['name']}"
567
+ return 1
568
+ end
569
+
570
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the security group location #{security_group['name']} - #{cloud['name']}?")
571
+ return 9, "aborted command"
572
+ end
573
+
574
+ @security_groups_interface.setopts(options)
575
+ if options[:dry_run]
576
+ print_dry_run @security_groups_interface.dry.delete_location(security_group['id'], security_group_location['id'])
577
+ return 0
578
+ end
579
+ json_response = @security_groups_interface.delete_location(security_group['id'], security_group_location['id'])
580
+ if options[:json]
581
+ puts as_json(json_response, options)
582
+ return 0
583
+ end
584
+ print_green_success "Created security group location #{security_group['name']} - #{cloud['name']}"
585
+ get([security_group['id']])
586
+ return 0
587
+ rescue RestClient::Exception => e
588
+ print_rest_exception(e, options)
589
+ exit 1
590
+ end
591
+ end
592
+
593
+
594
+ def add_rule(args)
595
+ params = {}
596
+ options = {:options => {}}
597
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
598
+ opts.banner = subcommand_usage("[security-group] [options]")
599
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
600
+ opts.on( '--name VALUE', String, "Name of the rule" ) do |val|
601
+ options[:options]['name'] = val
602
+ end
603
+ opts.on( '--direction VALUE', String, "Direction" ) do |val|
604
+ options[:options]['direction'] = val
605
+ end
606
+ opts.on( '--rule-type VALUE', String, "Rule Type" ) do |val|
607
+ options[:options]['ruleType'] = val
608
+ end
609
+ opts.on( '--protocol VALUE', String, "Protocol" ) do |val|
610
+ options[:options]['protocol'] = val
611
+ end
612
+ opts.on( '--port-range VALUE', String, "Port Range" ) do |val|
613
+ options[:options]['portRange'] = val
614
+ end
615
+ opts.on( '--source-type VALUE', String, "Source Type" ) do |val|
616
+ options[:options]['sourceType'] = val
617
+ end
618
+ opts.on( '--source VALUE', String, "Source" ) do |val|
619
+ options[:options]['source'] = val
620
+ end
621
+ opts.on( '--source-group VALUE', String, "Source Security Group" ) do |val|
622
+ options[:options]['sourceGroup'] = val
206
623
  end
207
- list([])
624
+ opts.on( '--source-tier VALUE', String, "Source Tier" ) do |val|
625
+ options[:options]['sourceTier'] = val
626
+ end
627
+ opts.on( '--destination-type VALUE', String, "Destination Type" ) do |val|
628
+ options[:options]['destinationType'] = val
629
+ end
630
+ opts.on( '--destination VALUE', String, "Destination" ) do |val|
631
+ options[:options]['destination'] = val
632
+ end
633
+ opts.on( '--destination-group VALUE', String, "Destination Security Group" ) do |val|
634
+ options[:options]['destinationGroup'] = val
635
+ end
636
+ opts.on( '--destination-tier VALUE', String, "Destination Tier" ) do |val|
637
+ options[:options]['destinationTier'] = val
638
+ end
639
+ opts.footer = "Create a security group rule." + "\n" +
640
+ "[security-group] is required. This is the name or id of the security group." + "\n"
641
+ "[name] is required. This is the name of the security group rule."
642
+ end
643
+ optparse.parse!(args)
644
+ if args.count < 1 || args.count > 2
645
+ raise_command_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
646
+ end
647
+ connect(options)
648
+ begin
649
+ security_group = find_security_group_by_name_or_id(args[0])
650
+ return 1 if security_group.nil?
651
+
652
+ # construct payload
653
+ if args[1]
654
+ options[:options]['name'] = args[1]
655
+ end
656
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
657
+ payload = nil
658
+ if options[:payload]
659
+ payload = options[:payload]
660
+ payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty?
661
+ else
662
+ # prompt for resource folder options
663
+ payload = {
664
+ 'rule' => {
665
+ }
666
+ }
667
+ payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty?
668
+
669
+ # prompt
670
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}], options[:options])
671
+ payload['rule']['name'] = v_prompt['name'] unless v_prompt['name'].nil?
672
+
673
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'direction', 'fieldLabel' => 'Direction', 'type' => 'select', 'optionSource' => 'securityGroupDirection', 'required' => true, 'defaultValue' => 'ingress'}], options[:options], @api_client)
674
+ payload['rule']['direction'] = v_prompt['direction'] unless v_prompt['direction'].nil?
675
+
676
+ rule_types = [{"name" => "Custom Rule", "value" => "customRule"}]
677
+ instance_types = @options_interface.options_for_source('instanceTypes',{})
678
+ if instance_types['data']
679
+ instance_types['data'].each do |it|
680
+ rule_types << {"name" => it['name'], "value" => it['code'] || it['value']}
681
+ end
682
+ end
683
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'ruleType', 'fieldLabel' => 'Rule Type', 'type' => 'select', 'selectOptions' => rule_types, 'required' => true, 'defaultValue' => 'customRule'}], options[:options], @api_client)
684
+ payload['rule']['ruleType'] = v_prompt['ruleType'] unless v_prompt['ruleType'].nil?
685
+
686
+ if payload['rule']['ruleType'] == 'customRule'
687
+
688
+ protocols = [{"name" => "TCP", "value" => "tcp"}, {"name" => "UDP", "value" => "udp"}, {"name" => "ICMP", "value" => "icmp"}]
689
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'protocol', 'fieldLabel' => 'Protocol', 'type' => 'select', 'selectOptions' => protocols, 'required' => true, 'defaultValue' => 'tcp'}], options[:options], @api_client)
690
+ payload['rule']['protocol'] = v_prompt['protocol'] unless v_prompt['protocol'].nil?
691
+
692
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'portRange', 'fieldLabel' => 'Port Range', 'type' => 'text', 'required' => true}], options[:options])
693
+ payload['rule']['portRange'] = v_prompt['portRange'] unless v_prompt['portRange'].nil?
694
+
695
+ end
696
+
697
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceType', 'fieldLabel' => 'Source Type', 'type' => 'select', 'optionSource' => 'securityGroupSourceType', 'required' => true, 'defaultValue' => 'cidr'}], options[:options], @api_client)
698
+ payload['rule']['sourceType'] = v_prompt['sourceType'] unless v_prompt['sourceType'].nil?
699
+
700
+ if payload['rule']['sourceType'] == 'cidr'
701
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'fieldLabel' => 'Source', 'type' => 'text', 'required' => true, 'description' => 'Source CIDR eg. 0.0.0.0/0'}], options[:options])
702
+ payload['rule']['source'] = v_prompt['source'] unless v_prompt['source'].nil?
703
+ elsif payload['rule']['sourceType'] == 'group'
704
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceGroup', 'fieldLabel' => 'Source Security Group', 'type' => 'select', 'optionSource' => 'securityGroups', 'required' => true}], options[:options], @api_client)
705
+ payload['rule']['sourceGroup'] = {"id" => v_prompt['sourceGroup']} unless v_prompt['sourceGroup'].nil?
706
+ elsif payload['rule']['sourceType'] == 'tier'
707
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceTier', 'fieldLabel' => 'Source Tier', 'type' => 'select', 'optionSource' => 'tiers', 'required' => true}], options[:options], @api_client)
708
+ payload['rule']['sourceTier'] = {"id" => v_prompt['sourceTier']} unless v_prompt['sourceTier'].nil?
709
+ end
710
+
711
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationType', 'fieldLabel' => 'Destination Type', 'type' => 'select', 'optionSource' => 'securityGroupDestinationType', 'required' => true, 'defaultValue' => 'instance'}], options[:options], @api_client)
712
+ payload['rule']['destinationType'] = v_prompt['destinationType'] unless v_prompt['destinationType'].nil?
713
+
714
+ if payload['rule']['destinationType'] == 'cidr'
715
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destination', 'fieldLabel' => 'Destination', 'type' => 'text', 'required' => true, 'description' => 'Destination CIDR eg. 0.0.0.0/0'}], options[:options])
716
+ payload['rule']['destination'] = v_prompt['destination'] unless v_prompt['destination'].nil?
717
+ elsif payload['rule']['destinationType'] == 'group'
718
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationGroup', 'fieldLabel' => 'Destination Security Group', 'type' => 'select', 'optionSource' => 'securityGroups', 'required' => true}], options[:options], @api_client)
719
+ payload['rule']['destinationGroup'] = {"id" => v_prompt['destinationGroup']} unless v_prompt['destinationGroup'].nil?
720
+ elsif payload['rule']['destinationType'] == 'tier'
721
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationTier', 'fieldLabel' => 'Destination Tier', 'type' => 'select', 'optionSource' => 'tiers', 'required' => true}], options[:options], @api_client)
722
+ payload['rule']['destinationTier'] = {"id" => v_prompt['destinationTier']} unless v_prompt['destinationTier'].nil?
723
+ end
724
+
725
+ end
726
+
727
+ @security_group_rules_interface.setopts(options)
728
+ if options[:dry_run]
729
+ print_dry_run @security_group_rules_interface.dry.create(security_group['id'], payload)
730
+ return 0
731
+ end
732
+ json_response = @security_group_rules_interface.create(security_group['id'], payload)
733
+ if options[:json]
734
+ puts as_json(json_response, options)
735
+ return 0
736
+ end
737
+ display_name = (json_response['rule'] && json_response['rule']['name'].to_s != '') ? json_response['rule']['name'] : json_response['rule']['id']
738
+ print_green_success "Created security group rule #{display_name}"
739
+ get([security_group['id']])
740
+ return 0
208
741
  rescue RestClient::Exception => e
209
742
  print_rest_exception(e, options)
210
743
  exit 1
211
744
  end
212
745
  end
213
746
 
747
+ def remove_rule(args)
748
+ params = {}
749
+ options = {:options => {}}
750
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
751
+ opts.banner = subcommand_usage("[security-group] [id]")
752
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
753
+ opts.footer = "Delete a security group rule." + "\n" +
754
+ "[security-group] is required. This is the name or id of the security group." + "\n"
755
+ "[rule] is required. This is the name or id of the security group rule."
756
+ end
757
+ optparse.parse!(args)
758
+ if args.count != 2
759
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
760
+ end
761
+ connect(options)
762
+ begin
763
+ security_group = find_security_group_by_name_or_id(args[0])
764
+ return 1 if security_group.nil?
765
+
766
+ #security_group_rule = find_security_group_rule_by_id(security_group['id'], args[1])
767
+ #return 1 if security_group_rule.nil?
768
+
769
+ security_group_rule = nil
770
+ if security_group['rules']
771
+ matching_rules = []
772
+ if args[1].to_s =~ /\A\d{1,}\Z/
773
+ matching_rules = security_group['rules'].select {|it| it['id'].to_s == args[1].to_s }
774
+ else
775
+ matching_rules = security_group['rules'].select {|it| it['name'] == args[1].to_s }
776
+ end
777
+ if matching_rules.size > 1
778
+ print_red_alert "#{matching_rules.size} security group rules found by name '#{args[1]}'"
779
+ rows = matching_rules.collect do |it|
780
+ {id: it['id'], name: it['name']}
781
+ end
782
+ puts as_pretty_table(rows, [:id, :name], {color:red})
783
+ return 1
784
+ else
785
+ security_group_rule = matching_rules[0]
786
+ end
787
+ end
788
+ if security_group_rule.nil?
789
+ print_red_alert "Security group rule not found for '#{args[1]}'"
790
+ return 1
791
+ end
792
+
793
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the security group rule: #{security_group_rule['id']}?")
794
+ return 9, "aborted command"
795
+ end
796
+
797
+ @security_groups_interface.setopts(options)
798
+ if options[:dry_run]
799
+ print_dry_run @security_group_rules_interface.dry.delete(security_group['id'], security_group_rule['id'])
800
+ return 0
801
+ end
802
+ json_response = @security_group_rules_interface.delete(security_group['id'], security_group_rule['id'])
803
+ if options[:json]
804
+ puts as_json(json_response, options)
805
+ return 0
806
+ end
807
+ display_name = (security_group_rule['name'].to_s != '') ? security_group_rule['name'] : security_group_rule['id'].to_s
808
+ print_green_success "Deleted security group rule #{display_name}"
809
+ get([security_group['id']])
810
+ return 0
811
+ rescue RestClient::Exception => e
812
+ print_rest_exception(e, options)
813
+ exit 1
814
+ end
815
+ end
816
+
817
+ def update_rule(args)
818
+ params = {}
819
+ options = {:options => {}}
820
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
821
+ opts.banner = subcommand_usage("[security-group] [rule]")
822
+ opts.on( '--name VALUE', String, "Name of the rule" ) do |val|
823
+ options[:options]['name'] = val
824
+ end
825
+ opts.on( '--direction VALUE', String, "Direction" ) do |val|
826
+ options[:options]['direction'] = val
827
+ end
828
+ opts.on( '--rule-type VALUE', String, "Rule Type" ) do |val|
829
+ options[:options]['ruleType'] = val
830
+ end
831
+ opts.on( '--protocol VALUE', String, "Protocol" ) do |val|
832
+ options[:options]['protocol'] = val
833
+ end
834
+ opts.on( '--port-range VALUE', String, "Port Range" ) do |val|
835
+ options[:options]['portRange'] = val
836
+ end
837
+ opts.on( '--source-type VALUE', String, "Source Type" ) do |val|
838
+ options[:options]['sourceType'] = val
839
+ end
840
+ opts.on( '--source VALUE', String, "Source" ) do |val|
841
+ options[:options]['source'] = val
842
+ end
843
+ opts.on( '--source-group VALUE', String, "Source Security Group" ) do |val|
844
+ options[:options]['sourceGroup'] = val
845
+ end
846
+ opts.on( '--source-tier VALUE', String, "Source Tier" ) do |val|
847
+ options[:options]['sourceTier'] = val
848
+ end
849
+ opts.on( '--destination-type VALUE', String, "Destination Type" ) do |val|
850
+ options[:options]['destinationType'] = val
851
+ end
852
+ opts.on( '--destination VALUE', String, "Destination" ) do |val|
853
+ options[:options]['destination'] = val
854
+ end
855
+ opts.on( '--destination-group VALUE', String, "Destination Security Group" ) do |val|
856
+ options[:options]['destinationGroup'] = val
857
+ end
858
+ opts.on( '--destination-tier VALUE', String, "Destination Tier" ) do |val|
859
+ options[:options]['destinationTier'] = val
860
+ end
861
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
862
+ opts.footer = "Update a security group rule." + "\n" +
863
+ "[security-group] is required. This is the name or id of the security group." + "\n"
864
+ "[rule] is required. This is the name or id of the security group rule."
865
+ end
866
+ optparse.parse!(args)
867
+ if args.count != 2
868
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
869
+ end
870
+ connect(options)
871
+ begin
872
+ security_group = find_security_group_by_name_or_id(args[0])
873
+ return 1 if security_group.nil?
874
+
875
+ #security_group_rule = find_security_group_rule_by_id(security_group['id'], args[1])
876
+ #return 1 if security_group_rule.nil?
877
+
878
+ security_group_rule = nil
879
+ if security_group['rules']
880
+ matching_rules = []
881
+ if args[1].to_s =~ /\A\d{1,}\Z/
882
+ matching_rules = security_group['rules'].select {|it| it['id'].to_s == args[1].to_s }
883
+ else
884
+ matching_rules = security_group['rules'].select {|it| it['name'] == args[1].to_s }
885
+ end
886
+ if matching_rules.size > 1
887
+ print_red_alert "#{matching_rules.size} security group rules found by name '#{args[1]}'"
888
+ rows = matching_rules.collect do |it|
889
+ {id: it['id'], name: it['name']}
890
+ end
891
+ puts as_pretty_table(rows, [:id, :name], {color:red})
892
+ return 1
893
+ else
894
+ security_group_rule = matching_rules[0]
895
+ end
896
+ end
897
+ if security_group_rule.nil?
898
+ print_red_alert "Security group rule not found for '#{args[1]}'"
899
+ return 1
900
+ end
901
+
902
+ passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
903
+ payload = nil
904
+ if options[:payload]
905
+ payload = options[:payload]
906
+ payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty?
907
+ else
908
+ # prompt for resource folder options
909
+ payload = {
910
+ 'rule' => {
911
+ }
912
+ }
913
+ payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty?
914
+
915
+ if passed_options.empty?
916
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
917
+ end
918
+
919
+ end
920
+
921
+ @security_groups_interface.setopts(options)
922
+ if options[:dry_run]
923
+ print_dry_run @security_group_rules_interface.dry.update(security_group['id'], security_group_rule['id'], payload)
924
+ return 0
925
+ end
926
+ json_response = @security_group_rules_interface.update(security_group['id'], security_group_rule['id'], payload)
927
+ if options[:json]
928
+ puts as_json(json_response, options)
929
+ return 0
930
+ end
931
+ security_group_rule = json_response['rule']
932
+ display_name = (security_group_rule['name'].to_s != '') ? security_group_rule['name'] : security_group_rule['id'].to_s
933
+ print_green_success "Updated security group rule #{display_name}"
934
+ get([security_group['id']])
935
+ return 0
936
+ rescue RestClient::Exception => e
937
+ print_rest_exception(e, options)
938
+ exit 1
939
+ end
940
+ end
941
+
942
+ # JD: still need this??
214
943
  def use(args)
215
944
  options = {}
216
945
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -242,8 +971,9 @@ class Morpheus::Cli::SecurityGroups
242
971
  return # exit 0
243
972
  end
244
973
 
245
- json_response = @security_groups_interface.get({id: args[0]})
246
- security_group = json_response['securityGroup']
974
+ security_group = find_security_group_by_name_or_id(args[0])
975
+ return 1 if security_group.nil?
976
+
247
977
  if !security_group.nil?
248
978
  @active_security_group[@appliance_name.to_sym] = security_group['id']
249
979
  ::Morpheus::Cli::SecurityGroups.save_security_group(@active_security_group)
@@ -251,6 +981,7 @@ class Morpheus::Cli::SecurityGroups
251
981
  else
252
982
  puts red, "Security Group not found", reset
253
983
  end
984
+ return 0
254
985
  rescue RestClient::Exception => e
255
986
  print_rest_exception(e, options)
256
987
  exit 1
@@ -284,4 +1015,110 @@ class Morpheus::Cli::SecurityGroups
284
1015
  new_config
285
1016
  end
286
1017
 
1018
+ private
1019
+
1020
+ def find_security_group_by_name_or_id(val)
1021
+ if val.to_s =~ /\A\d{1,}\Z/
1022
+ return find_security_group_by_id(val)
1023
+ else
1024
+ return find_security_group_by_name(val)
1025
+ end
1026
+ end
1027
+
1028
+ def find_security_group_by_id(id)
1029
+ begin
1030
+ json_response = @security_groups_interface.get(id.to_i)
1031
+ return json_response['securityGroup']
1032
+ rescue RestClient::Exception => e
1033
+ if e.response && e.response.code == 404
1034
+ print_red_alert "Security Group not found by id #{id}"
1035
+ return nil
1036
+ else
1037
+ raise e
1038
+ end
1039
+ end
1040
+ end
1041
+
1042
+ def find_security_group_by_name(name)
1043
+ json_response = @security_groups_interface.list({name: name.to_s})
1044
+ security_groups = json_response['securityGroups']
1045
+ if security_groups.empty?
1046
+ print_red_alert "Security Group not found by name #{name}"
1047
+ return nil
1048
+ elsif security_groups.size > 1
1049
+ print_red_alert "#{security_groups.size} security groups found by name #{name}"
1050
+ rows = security_groups.collect do |it|
1051
+ {id: it['id'], name: it['name']}
1052
+ end
1053
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1054
+ return nil
1055
+ else
1056
+ return security_groups[0]
1057
+ end
1058
+ end
1059
+
1060
+ def find_security_group_rule_by_id(security_group_id, id)
1061
+ begin
1062
+ json_response = @security_groups_interface.get(security_group_id.to_i, id.to_i)
1063
+ return json_response['rule']
1064
+ rescue RestClient::Exception => e
1065
+ if e.response && e.response.code == 404
1066
+ print_red_alert "Security Group Rule not found by id #{id}"
1067
+ return nil
1068
+ else
1069
+ raise e
1070
+ end
1071
+ end
1072
+ end
1073
+
1074
+ def find_resource_pool_by_name_or_id(cloud_id, val)
1075
+ if val.to_s =~ /\A\d{1,}\Z/
1076
+ return find_resource_pool_by_id(cloud_id, val)
1077
+ else
1078
+ return find_resource_pool_by_name(cloud_id, val)
1079
+ end
1080
+ end
1081
+
1082
+ def find_resource_pool_by_id(cloud_id, id)
1083
+ begin
1084
+ json_response = @cloud_resource_pools_interface.get(cloud_id, id.to_i)
1085
+ return json_response['resourcePool']
1086
+ rescue RestClient::Exception => e
1087
+ if e.response && e.response.code == 404
1088
+ print_red_alert "Resource Pool not found by id #{id}"
1089
+ return nil
1090
+ else
1091
+ raise e
1092
+ end
1093
+ end
1094
+ end
1095
+
1096
+ def find_resource_pool_by_name(cloud_id, name)
1097
+ json_response = @cloud_resource_pools_interface.list(cloud_id, {name: name.to_s})
1098
+ resource_pools = json_response['resourcePools']
1099
+ if resource_pools.empty?
1100
+ print_red_alert "Resource Pool not found by name #{name}"
1101
+ return nil
1102
+ elsif resource_pools.size > 1
1103
+ matching_resource_pools = resource_pools.select { |it| name && (it['name'] == name || it['externalId'] == name) }
1104
+ if matching_resource_pools.size == 1
1105
+ return matching_resource_pools[0]
1106
+ end
1107
+ print_red_alert "#{resource_pools.size} resource pools found by name #{name}"
1108
+ rows = resource_pools.collect do |it|
1109
+ {id: it['id'], name: it['name']}
1110
+ end
1111
+ print "\n"
1112
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1113
+ return nil
1114
+ else
1115
+ resource_pool = resource_pools[0]
1116
+ # merge in tenants map
1117
+ if json_response['tenants'] && json_response['tenants'][resource_pool['id']]
1118
+ resource_pool['tenants'] = json_response['tenants'][resource_pool['id']]
1119
+ end
1120
+ return resource_pool
1121
+ end
1122
+ end
1123
+
287
1124
  end