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
@@ -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