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.
- checksums.yaml +4 -4
- data/lib/morpheus/api/api_client.rb +16 -0
- data/lib/morpheus/api/cloud_folders_interface.rb +47 -0
- data/lib/morpheus/api/cloud_resource_pools_interface.rb +47 -0
- data/lib/morpheus/api/network_types_interface.rb +26 -0
- data/lib/morpheus/api/reports_interface.rb +77 -0
- data/lib/morpheus/api/security_group_rules_interface.rb +6 -0
- data/lib/morpheus/api/security_groups_interface.rb +21 -15
- data/lib/morpheus/cli.rb +3 -0
- data/lib/morpheus/cli/accounts.rb +1 -1
- data/lib/morpheus/cli/apps.rb +2 -2
- data/lib/morpheus/cli/archives_command.rb +18 -18
- data/lib/morpheus/cli/blueprints_command.rb +1 -1
- data/lib/morpheus/cli/boot_scripts_command.rb +6 -6
- data/lib/morpheus/cli/cli_command.rb +4 -0
- data/lib/morpheus/cli/cloud_datastores_command.rb +58 -20
- data/lib/morpheus/cli/cloud_folders_command.rb +463 -0
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +707 -0
- data/lib/morpheus/cli/clouds.rb +2 -0
- data/lib/morpheus/cli/hosts.rb +33 -8
- data/lib/morpheus/cli/instances.rb +79 -54
- data/lib/morpheus/cli/library_option_lists_command.rb +1 -1
- data/lib/morpheus/cli/library_option_types_command.rb +1 -1
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +11 -2
- data/lib/morpheus/cli/monitoring_contacts_command.rb +1 -1
- data/lib/morpheus/cli/monitoring_incidents_command.rb +1 -1
- data/lib/morpheus/cli/network_services_command.rb +7 -3
- data/lib/morpheus/cli/networks_command.rb +164 -63
- data/lib/morpheus/cli/option_types.rb +16 -15
- data/lib/morpheus/cli/policies_command.rb +76 -9
- data/lib/morpheus/cli/preseed_scripts_command.rb +2 -2
- data/lib/morpheus/cli/remote.rb +26 -28
- data/lib/morpheus/cli/reports_command.rb +594 -0
- data/lib/morpheus/cli/security_group_rules.rb +5 -1
- data/lib/morpheus/cli/security_groups.rb +882 -45
- data/lib/morpheus/cli/tasks.rb +158 -23
- data/lib/morpheus/cli/tenants_command.rb +1 -1
- data/lib/morpheus/cli/users.rb +1 -1
- data/lib/morpheus/cli/version.rb +1 -1
- 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, :
|
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 =
|
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
|
-
|
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
|
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)}}
|
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
|
108
|
-
|
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
|
-
|
116
|
-
|
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
|
-
|
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
|
-
|
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 = {
|
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( '
|
147
|
-
|
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
|
-
|
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
|
153
|
-
|
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
|
-
|
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.
|
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.
|
383
|
+
json_response = @security_groups_interface.update(security_group['id'], payload)
|
165
384
|
if options[:json]
|
166
|
-
|
167
|
-
|
168
|
-
return
|
385
|
+
puts as_json(json_response, options)
|
386
|
+
return 0
|
169
387
|
end
|
170
|
-
|
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
|
185
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
204
|
-
|
205
|
-
|
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
|
-
|
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
|
-
|
246
|
-
|
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
|