morpheus-cli 3.1.1 → 3.1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,148 @@
1
+ require 'rest_client'
2
+ require 'optparse'
3
+ require 'filesize'
4
+ require 'table_print'
5
+ require 'morpheus/cli/cli_command'
6
+ require 'morpheus/cli/mixins/infrastructure_helper'
7
+
8
+ class Morpheus::Cli::NetworkServicesCommand
9
+ include Morpheus::Cli::CliCommand
10
+ include Morpheus::Cli::InfrastructureHelper
11
+
12
+ set_command_name :'network-services'
13
+
14
+ # register_subcommands :list, :get, :add, :update, :remove
15
+ register_subcommands :list
16
+
17
+ # set_default_subcommand :list
18
+
19
+ def initialize()
20
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
21
+ end
22
+
23
+ def connect(opts)
24
+ @api_client = establish_remote_appliance_connection(opts)
25
+ @network_services_interface = @api_client.network_services
26
+ @clouds_interface = @api_client.clouds
27
+ @options_interface = @api_client.options
28
+ end
29
+
30
+ def handle(args)
31
+ handle_subcommand(args)
32
+ end
33
+
34
+ def list(args)
35
+ options = {}
36
+ params = {}
37
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
38
+ opts.banner = subcommand_usage()
39
+ build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
40
+ opts.footer = "List network services."
41
+ end
42
+ optparse.parse!(args)
43
+ connect(options)
44
+ begin
45
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
46
+ params[k] = options[k] unless options[k].nil?
47
+ end
48
+ if options[:dry_run]
49
+ print_dry_run @network_services_interface.dry.list(params)
50
+ return
51
+ end
52
+ json_response = @network_services_interface.list(params)
53
+ network_services = json_response["networkServices"]
54
+ if options[:include_fields]
55
+ json_response = {"networkServices" => filter_data(network_services, options[:include_fields]) }
56
+ end
57
+ if options[:json]
58
+ puts as_json(json_response, options)
59
+ return 0
60
+ elsif options[:yaml]
61
+ puts as_yaml(json_response, options)
62
+ return 0
63
+ elsif options[:csv]
64
+ puts records_as_csv(network_services, options)
65
+ return 0
66
+ end
67
+ title = "Morpheus Network Services"
68
+ subtitles = []
69
+ if params[:phrase]
70
+ subtitles << "Search: #{params[:phrase]}".strip
71
+ end
72
+ print_h1 title, subtitles
73
+ if network_services.empty?
74
+ print cyan,"No network services found.",reset,"\n"
75
+ else
76
+ rows = network_services.collect {|network_service|
77
+ row = {
78
+ id: network_service['id'],
79
+ name: network_service['name'],
80
+ type: network_service['type'] ? network_service['type']['name'] : '',
81
+ }
82
+ row
83
+ }
84
+ columns = [:id, :name, :type]
85
+ if options[:include_fields]
86
+ columns = options[:include_fields]
87
+ end
88
+ print cyan
89
+ print as_pretty_table(rows, columns, options)
90
+ print reset
91
+ print_results_pagination(json_response, {:label => "network service", :n_label => "network services"})
92
+ end
93
+ print reset,"\n"
94
+ return 0
95
+ rescue RestClient::Exception => e
96
+ print_rest_exception(e, options)
97
+ exit 1
98
+ end
99
+ end
100
+
101
+
102
+ private
103
+
104
+
105
+ def find_network_service_by_name_or_id(val)
106
+ if val.to_s =~ /\A\d{1,}\Z/
107
+ return find_network_service_by_id(val)
108
+ else
109
+ return find_network_service_by_name(val)
110
+ end
111
+ end
112
+
113
+ def find_network_service_by_id(id)
114
+ begin
115
+ json_response = @network_services_interface.get(id.to_i)
116
+ return json_response['networkService']
117
+ rescue RestClient::Exception => e
118
+ if e.response && e.response.code == 404
119
+ print_red_alert "Network Service not found by id #{id}"
120
+ return nil
121
+ else
122
+ raise e
123
+ end
124
+ end
125
+ end
126
+
127
+ def find_network_service_by_name(name)
128
+ json_response = @network_services_interface.list({name: name.to_s})
129
+ network_services = json_response['networkServices']
130
+ if network_services.empty?
131
+ print_red_alert "Network Service not found by name #{name}"
132
+ return nil
133
+ elsif network_services.size > 1
134
+ print_red_alert "#{network_services.size} network services found by name #{name}"
135
+ # print_networks_table(networks, {color: red})
136
+ rows = network_services.collect do |network_service|
137
+ {id: it['id'], name: it['name']}
138
+ end
139
+ print red
140
+ tp rows, [:id, :name]
141
+ print reset,"\n"
142
+ return nil
143
+ else
144
+ return network_services[0]
145
+ end
146
+ end
147
+
148
+ end
@@ -0,0 +1,855 @@
1
+ require 'rest_client'
2
+ require 'optparse'
3
+ require 'filesize'
4
+ require 'table_print'
5
+ require 'morpheus/cli/cli_command'
6
+ require 'morpheus/cli/mixins/infrastructure_helper'
7
+
8
+ class Morpheus::Cli::NetworksCommand
9
+ include Morpheus::Cli::CliCommand
10
+ include Morpheus::Cli::InfrastructureHelper
11
+
12
+ set_command_name :networks
13
+
14
+ register_subcommands :list, :get, :add, :update, :remove #, :generate_pool
15
+
16
+ # set_default_subcommand :list
17
+
18
+ def initialize()
19
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
20
+ end
21
+
22
+ def connect(opts)
23
+ @api_client = establish_remote_appliance_connection(opts)
24
+ @networks_interface = @api_client.networks
25
+ @clouds_interface = @api_client.clouds
26
+ @options_interface = @api_client.options
27
+ end
28
+
29
+ def handle(args)
30
+ handle_subcommand(args)
31
+ end
32
+
33
+ def list(args)
34
+ options = {}
35
+ params = {}
36
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
37
+ opts.banner = subcommand_usage()
38
+ opts.on('--cidr VALUE', String, "Filter by cidr, matches beginning of value.") do |val|
39
+ params['cidr'] = val
40
+ end
41
+ build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
42
+ opts.footer = "List networks."
43
+ end
44
+ optparse.parse!(args)
45
+ connect(options)
46
+ begin
47
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
48
+ params[k] = options[k] unless options[k].nil?
49
+ end
50
+ if options[:dry_run]
51
+ print_dry_run @networks_interface.dry.list(params)
52
+ return
53
+ end
54
+ json_response = @networks_interface.list(params)
55
+ networks = json_response["networks"]
56
+ if options[:include_fields]
57
+ json_response = {"networks" => filter_data(networks, options[:include_fields]) }
58
+ end
59
+ if options[:json]
60
+ puts as_json(json_response, options)
61
+ return 0
62
+ elsif options[:yaml]
63
+ puts as_yaml(json_response, options)
64
+ return 0
65
+ elsif options[:csv]
66
+ puts records_as_csv(networks, options)
67
+ return 0
68
+ end
69
+ title = "Morpheus Networks"
70
+ subtitles = []
71
+ if params[:phrase]
72
+ subtitles << "Search: #{params[:phrase]}".strip
73
+ end
74
+ print_h1 title, subtitles
75
+ if networks.empty?
76
+ print cyan,"No networks found.",reset,"\n"
77
+ else
78
+ rows = networks.collect {|network|
79
+ row = {
80
+ id: network['id'],
81
+ name: network['name'],
82
+ type: network['type'] ? network['type']['name'] : '',
83
+ cloud: network['zone'] ? network['zone']['name'] : '',
84
+ cidr: network['cidr'],
85
+ pool: network['pool'] ? network['pool']['name'] : '',
86
+ dhcp: network['dhcpServer'] ? 'Yes' : 'No',
87
+ visibility: network['visibility'].to_s.capitalize,
88
+ tenants: network['tenants'] ? network['tenants'].collect {|it| it['name'] }.uniq.join(', ') : ''
89
+ }
90
+ row
91
+ }
92
+ columns = [:id, :name, :type, :cloud, :cidr, :pool, :dhcp, :visibility, :tenants]
93
+ if options[:include_fields]
94
+ columns = options[:include_fields]
95
+ end
96
+ print cyan
97
+ print as_pretty_table(rows, columns, options)
98
+ print reset
99
+ print_results_pagination(json_response, {:label => "network", :n_label => "networks"})
100
+ end
101
+ print reset,"\n"
102
+ return 0
103
+ rescue RestClient::Exception => e
104
+ print_rest_exception(e, options)
105
+ exit 1
106
+ end
107
+ end
108
+
109
+ def get(args)
110
+ options = {}
111
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
112
+ opts.banner = subcommand_usage("[network]")
113
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
114
+ opts.footer = "Get details about a network." + "\n" +
115
+ "[network] is required. This is the name or id of a network."
116
+ end
117
+ optparse.parse!(args)
118
+ if args.count != 1
119
+ print_error Morpheus::Terminal.angry_prompt
120
+ puts_error "#{command_name} missing argument: [network]\n#{optparse}"
121
+ return 1
122
+ end
123
+ connect(options)
124
+ begin
125
+ if options[:dry_run]
126
+ if args[0].to_s =~ /\A\d{1,}\Z/
127
+ print_dry_run @networks_interface.dry.get(args[0].to_i)
128
+ else
129
+ print_dry_run @networks_interface.dry.list({name:args[0]})
130
+ end
131
+ return
132
+ end
133
+ network = find_network_by_name_or_id(args[0])
134
+ return 1 if network.nil?
135
+ json_response = {'network' => network} # skip redundant request
136
+ # json_response = @networks_interface.get(network['id'])
137
+ network = json_response['network']
138
+ if options[:include_fields]
139
+ json_response = {'network' => filter_data(network, options[:include_fields]) }
140
+ end
141
+ if options[:json]
142
+ puts as_json(json_response, options)
143
+ return 0
144
+ elsif options[:yaml]
145
+ puts as_yaml(json_response, options)
146
+ return 0
147
+ elsif options[:csv]
148
+ puts records_as_csv([network], options)
149
+ return 0
150
+ end
151
+ print_h1 "Network Details"
152
+ print cyan
153
+ description_cols = {
154
+ "ID" => 'id',
155
+ "Name" => 'name',
156
+ "Description" => 'description',
157
+ "Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
158
+ "Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
159
+ "CIDR" => 'cidr',
160
+ "Gateway" => 'gateway',
161
+ "Netmask" => 'netmask',
162
+ "Subnet" => 'subnetAddress',
163
+ "Primary DNS" => 'dnsPrimary',
164
+ "Secondary DNS" => 'dnsSecondary',
165
+ "Pool" => lambda {|it| it['pool'] ? it['pool']['name'] : '' },
166
+ "DHCP" => lambda {|it| it['dhcpServer'] ? 'Yes' : 'No' },
167
+ "Allow IP Override" => lambda {|it| it['allowStaticOverride'] ? 'Yes' : 'No' },
168
+ "Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
169
+ "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.join(', ') : '' },
170
+ # "Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
171
+ }
172
+ print_description_list(description_cols, network)
173
+
174
+ if network['resourcePermission'].nil?
175
+ print "\n", "No group access found", "\n"
176
+ else
177
+ print_h2 "Group Access"
178
+ rows = []
179
+ if network['resourcePermission']['all']
180
+ rows.push({"name" => 'All'})
181
+ end
182
+ if network['resourcePermission']['sites']
183
+ network['resourcePermission']['sites'].each do |site|
184
+ rows.push(site)
185
+ end
186
+ end
187
+ rows = rows.collect do |site|
188
+ {group: site['name'], default: site['default'] ? 'Yes' : ''}
189
+ end
190
+ columns = [:group, :default]
191
+ print cyan
192
+ print as_pretty_table(rows, columns)
193
+ end
194
+
195
+ print reset,"\n"
196
+ return 0
197
+ rescue RestClient::Exception => e
198
+ print_rest_exception(e, options)
199
+ return 1
200
+ end
201
+ end
202
+
203
+ def add(args)
204
+ options = {}
205
+ network_type_id = nil
206
+ tenants = nil
207
+ group_access_all = nil
208
+ group_access_list = nil
209
+ group_defaults_list = nil
210
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
211
+ opts.banner = subcommand_usage("-t TYPE")
212
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
213
+ options[:cloud] = val
214
+ end
215
+ opts.on('-t', '--type ID', "Network Type Name or ID") do |val|
216
+ options['type'] = val
217
+ end
218
+ opts.on('--name VALUE', String, "Name for this network") do |val|
219
+ options['name'] = val
220
+ end
221
+ opts.on('--description VALUE', String, "Description of network") do |val|
222
+ options['description'] = val
223
+ end
224
+ opts.on('--gateway VALUE', String, "Gateway") do |val|
225
+ options['gateway'] = val
226
+ end
227
+ opts.on('--dns-primary VALUE', String, "DNS Primary") do |val|
228
+ options['dnsPrimary'] = val
229
+ end
230
+ opts.on('--dns-secondary VALUE', String, "DNS Secondary") do |val|
231
+ options['dnsSecondary'] = val
232
+ end
233
+ opts.on('--cidr VALUE', String, "CIDR") do |val|
234
+ options['cidr'] = val
235
+ end
236
+ opts.on('--vlan-id VALUE', String, "VLAN ID") do |val|
237
+ options['vlanId'] = val.to_i
238
+ end
239
+ opts.on('--pool ID', String, "Network Pool") do |val|
240
+ options['pool'] = val.to_i
241
+ end
242
+ opts.on('--dhcp-server [on|off]', String, "DHCP Server") do |val|
243
+ options['dhcpServer'] = val.to_s == 'on' || val.to_s == 'true'
244
+ end
245
+ opts.on('--allow-ip-override [on|off]', String, "Allow IP Override") do |val|
246
+ options['allowStaticOverride'] = val.to_s == 'on' || val.to_s == 'true'
247
+ end
248
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
249
+ group_access_all = val.to_s == 'on' || val.to_s == 'true'
250
+ end
251
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
252
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
253
+ group_access_list = []
254
+ else
255
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
256
+ end
257
+ end
258
+ opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
259
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
260
+ group_defaults_list = []
261
+ else
262
+ group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
263
+ end
264
+ end
265
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
266
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
267
+ options['tenants'] = []
268
+ else
269
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
270
+ end
271
+ end
272
+ opts.on('--accounts LIST', Array, "alias for --tenants") do |list|
273
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
274
+ options['tenants'] = []
275
+ else
276
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
277
+ end
278
+ end
279
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
280
+ options['visibility'] = val
281
+ end
282
+ opts.on('--active [on|off]', String, "Can be used to disable a network") do |val|
283
+ options['active'] = val.to_s == 'on' || val.to_s == 'true'
284
+ end
285
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
286
+ opts.footer = "Create a new network." + "\n" +
287
+ "[name] is required and can be passed as --name instead."
288
+ end
289
+ optparse.parse!(args)
290
+ if args.count > 1
291
+ print_error Morpheus::Terminal.angry_prompt
292
+ puts_error "wrong number of arguments, expected 0-1 and got #{args.count}\n#{optparse}"
293
+ return 1
294
+ end
295
+ connect(options)
296
+ begin
297
+ # merge -O options into normally parsed options
298
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
299
+
300
+ # support [name] as first argument
301
+ if args[0]
302
+ options['name'] = args[0]
303
+ end
304
+
305
+ # construct payload
306
+ payload = nil
307
+ if options[:payload]
308
+ payload = options[:payload]
309
+ else
310
+ # prompt for network options
311
+ payload = {
312
+ 'network' => {
313
+ # 'config' => {}
314
+ }
315
+ }
316
+
317
+ # allow arbitrary -O options
318
+ payload['network'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
319
+
320
+ # Cloud
321
+ cloud = nil
322
+ if options[:cloud]
323
+ cloud = find_cloud_by_name_or_id(options[:cloud])
324
+ # meh, should validate cloud is in the cloudsForNetworks dropdown..
325
+ return 1 if cloud.nil?
326
+ else
327
+ # print_red_alert "Cloud not specified!"
328
+ # exit 1
329
+ cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'cloudsForNetworks', 'required' => true, 'description' => 'Select Cloud.'}],options,@api_client,{})
330
+ cloud_id = cloud_prompt['cloud']
331
+ cloud = find_cloud_by_name_or_id(cloud_id) if cloud_id
332
+ return 1 if cloud.nil?
333
+ end
334
+ payload['network']['zone'] = {'id' => cloud['id']}
335
+
336
+ # Network Type
337
+ network_type_id = nil
338
+ api_params = {"network.zone.id" => cloud['id']} #{network:{zone:{id: cloud['id']}}}
339
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Network Type', 'type' => 'select', 'optionSource' => 'networkTypesForCloud', 'required' => true, 'description' => 'Choose a network type.'}], options, @api_client, api_params)
340
+ network_type_id = v_prompt['type']
341
+ if network_type_id.nil? || network_type_id.to_s.empty?
342
+ print_red_alert "Network Type not found by id '#{options['type']}'"
343
+ return 1
344
+ end
345
+ payload['network']['type'] = {'id' => network_type_id.to_i }
346
+
347
+ # Name
348
+ if options['name']
349
+ payload['network']['name'] = options['name']
350
+ else
351
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this network.'}], options)
352
+ payload['network']['name'] = v_prompt['name']
353
+ end
354
+
355
+ # Description
356
+ if options['description']
357
+ payload['network']['description'] = options['description']
358
+ else
359
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false, 'description' => 'Description of network.'}], options)
360
+ payload['network']['description'] = v_prompt['description']
361
+ end
362
+
363
+ # Gateway
364
+ if options['gateway']
365
+ payload['network']['gateway'] = options['gateway']
366
+ else
367
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'gateway', 'fieldLabel' => 'Gateway', 'type' => 'text', 'required' => false, 'description' => ''}], options)
368
+ payload['network']['gateway'] = v_prompt['gateway']
369
+ end
370
+
371
+ # DNS Primary
372
+ if options['dnsPrimary']
373
+ payload['network']['dnsPrimary'] = options['dnsPrimary']
374
+ else
375
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dnsPrimary', 'fieldLabel' => 'DNS Primary', 'type' => 'text', 'required' => false, 'description' => ''}], options)
376
+ payload['network']['dnsPrimary'] = v_prompt['dnsPrimary']
377
+ end
378
+
379
+ # DNS Secondary
380
+ if options['dnsSecondary']
381
+ payload['network']['dnsSecondary'] = options['dnsSecondary']
382
+ else
383
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dnsSecondary', 'fieldLabel' => 'DNS Secondary', 'type' => 'text', 'required' => false, 'description' => ''}], options)
384
+ payload['network']['dnsSecondary'] = v_prompt['dnsSecondary']
385
+ end
386
+
387
+ # CIDR
388
+ if options['cidr']
389
+ payload['network']['cidr'] = options['cidr']
390
+ else
391
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => false, 'description' => ''}], options)
392
+ payload['network']['cidr'] = v_prompt['cidr']
393
+ end
394
+
395
+ # VLAN ID
396
+ if options['vlanId']
397
+ payload['network']['vlanId'] = options['vlanId']
398
+ else
399
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'vlanId', 'fieldLabel' => 'VLAN ID', 'type' => 'number', 'required' => false, 'description' => ''}], options)
400
+ payload['network']['vlanId'] = v_prompt['vlanId']
401
+ end
402
+
403
+ # Network Pool
404
+ if options['pool']
405
+ payload['network']['pool'] = options['pool'].to_i
406
+ else
407
+ # todo: select dropdown
408
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'select', 'optionSource' => 'networkPools', 'required' => false, 'description' => ''}], options, @api_client, {zoneId: cloud['id']})
409
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'text', 'required' => false, 'description' => ''}], options)
410
+ payload['network']['pool'] = v_prompt['pool'].to_i if v_prompt['pool']
411
+ end
412
+
413
+ # DHCP Server
414
+ if options['dhcpServer'] != nil
415
+ payload['network']['dhcpServer'] = options['dhcpServer']
416
+ else
417
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dhcpServer', 'fieldLabel' => 'DHCP Server', 'type' => 'checkbox', 'required' => false, 'description' => ''}], options)
418
+ payload['network']['dhcpServer'] = v_prompt['dhcpServer']
419
+ end
420
+
421
+ # Allow IP Override
422
+ if options['allowStaticOverride'] != nil
423
+ payload['network']['allowStaticOverride'] = options['allowStaticOverride']
424
+ else
425
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'allowStaticOverride', 'fieldLabel' => 'Allow IP Override', 'type' => 'checkbox', 'required' => false, 'description' => ''}], options)
426
+ payload['network']['allowStaticOverride'] = v_prompt['allowStaticOverride']
427
+ end
428
+
429
+ # Group Access
430
+ if group_access_all != nil
431
+ payload['resourcePermissions'] ||= {}
432
+ payload['resourcePermissions']['all'] = group_access_all
433
+ end
434
+ if group_access_list != nil
435
+ payload['resourcePermissions'] ||= {}
436
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
437
+ site = {"id" => site_id.to_i}
438
+ if group_defaults_list && group_defaults_list.include?(site_id)
439
+ site["default"] = true
440
+ end
441
+ site
442
+ end
443
+ end
444
+
445
+ # Tenants
446
+ if options['tenants']
447
+ payload['tenantPermissions'] = {}
448
+ payload['tenantPermissions']['accounts'] = options['tenants']
449
+ end
450
+
451
+ # Active
452
+ if options['active'] != nil
453
+ payload['network']['active'] = options['active']
454
+ end
455
+
456
+ # Visibility
457
+ if options['visibility'] != nil
458
+ payload['network']['visibility'] = options['visibility']
459
+ end
460
+
461
+ end
462
+
463
+
464
+ if options[:dry_run]
465
+ print_dry_run @networks_interface.dry.create(payload)
466
+ return
467
+ end
468
+ json_response = @networks_interface.create(payload)
469
+ if options[:json]
470
+ print JSON.pretty_generate(json_response)
471
+ print "\n"
472
+ elsif !options[:quiet]
473
+ network = json_response['network']
474
+ print_green_success "Added network #{network['name']}"
475
+ get([network['id']])
476
+ end
477
+ return 0
478
+ rescue RestClient::Exception => e
479
+ print_rest_exception(e, options)
480
+ exit 1
481
+ end
482
+ end
483
+
484
+ def update(args)
485
+ options = {}
486
+ # network_type_id = nil
487
+ tenants = nil
488
+ group_access_all = nil
489
+ group_access_list = nil
490
+ group_defaults_list = nil
491
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
492
+ opts.banner = subcommand_usage("[network] [options]")
493
+ # opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
494
+ # options[:cloud] = val
495
+ # end
496
+ # opts.on('-t', '--type ID', "Network Type Name or ID") do |val|
497
+ # options['type'] = val
498
+ # end
499
+ opts.on('--name VALUE', String, "Name for this network") do |val|
500
+ options['name'] = val
501
+ end
502
+ opts.on('--description VALUE', String, "Description of network") do |val|
503
+ options['description'] = val
504
+ end
505
+ opts.on('--gateway VALUE', String, "Gateway") do |val|
506
+ options['gateway'] = val
507
+ end
508
+ opts.on('--dns-primary VALUE', String, "DNS Primary") do |val|
509
+ options['dnsPrimary'] = val
510
+ end
511
+ opts.on('--dns-secondary VALUE', String, "DNS Secondary") do |val|
512
+ options['dnsSecondary'] = val
513
+ end
514
+ opts.on('--cidr VALUE', String, "CIDR") do |val|
515
+ options['cidr'] = val
516
+ end
517
+ opts.on('--vlan-id VALUE', String, "VLAN ID") do |val|
518
+ options['vlanId'] = val.to_i
519
+ end
520
+ opts.on('--pool ID', String, "Network Pool") do |val|
521
+ options['pool'] = val.to_i
522
+ end
523
+ opts.on('--dhcp-server [on|off]', String, "DHCP Server") do |val|
524
+ options['dhcpServer'] = val.to_s == 'on' || val.to_s == 'true'
525
+ end
526
+ opts.on('--allow-ip-override [on|off]', String, "Allow IP Override") do |val|
527
+ options['allowStaticOverride'] = val.to_s == 'on' || val.to_s == 'true'
528
+ end
529
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
530
+ group_access_all = val.to_s == 'on' || val.to_s == 'true'
531
+ end
532
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
533
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
534
+ group_access_list = []
535
+ else
536
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
537
+ end
538
+ end
539
+ opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
540
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
541
+ group_defaults_list = []
542
+ else
543
+ group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
544
+ end
545
+ end
546
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
547
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
548
+ options['tenants'] = []
549
+ else
550
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
551
+ end
552
+ end
553
+ opts.on('--accounts LIST', Array, "alias for --tenants") do |list|
554
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
555
+ options['tenants'] = []
556
+ else
557
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
558
+ end
559
+ end
560
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
561
+ options['visibility'] = val
562
+ end
563
+ opts.on('--active [on|off]', String, "Can be used to disable a network") do |val|
564
+ options['active'] = val.to_s == 'on' || val.to_s == 'true'
565
+ end
566
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
567
+ opts.footer = "Update a network." + "\n" +
568
+ "[network] is required. This is the id of a network."
569
+ end
570
+ optparse.parse!(args)
571
+ if args.count != 1
572
+ print_error Morpheus::Terminal.angry_prompt
573
+ puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
574
+ return 1
575
+ end
576
+ connect(options)
577
+
578
+ begin
579
+ network = find_network_by_name_or_id(args[0])
580
+ return 1 if network.nil?
581
+
582
+ # merge -O options into normally parsed options
583
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
584
+
585
+ # construct payload
586
+ payload = nil
587
+ if options[:payload]
588
+ payload = options[:payload]
589
+ else
590
+ # prompt for network options
591
+ payload = {
592
+ 'network' => {
593
+ # 'config' => {}
594
+ }
595
+ }
596
+
597
+ # allow arbitrary -O options
598
+ payload['network'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
599
+
600
+ # # Cloud
601
+ # cloud = nil
602
+ # if options[:cloud]
603
+ # cloud = find_cloud_by_name_or_id(options[:cloud])
604
+ # # meh, should validate cloud is in the cloudsForNetworks dropdown..
605
+ # return 1 if cloud.nil?
606
+ # else
607
+ # # print_red_alert "Cloud not specified!"
608
+ # # exit 1
609
+ # cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'cloudsForNetworks', 'required' => true, 'description' => 'Select Cloud.'}],options,@api_client,{})
610
+ # cloud_id = cloud_prompt['cloud']
611
+ # cloud = find_cloud_by_name_or_id(cloud_id) if cloud_id
612
+ # return 1 if cloud.nil?
613
+ # end
614
+
615
+ # # Network Type
616
+ # network_type_id = nil
617
+ # api_params = {"network.zone.id" => cloud['id']} #{network:{zone:{id: cloud['id']}}}
618
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Network Type', 'type' => 'select', 'optionSource' => 'networkTypesForCloud', 'required' => true, 'description' => 'Choose a network type.'}], options, @api_client, api_params)
619
+ # network_type_id = v_prompt['type']
620
+ # if network_type_id.nil? || network_type_id.to_s.empty?
621
+ # print_red_alert "Network Type not found by id '#{options['type']}'"
622
+ # return 1
623
+ # end
624
+ # payload['network']['type'] = {'id' => network_type_id.to_i }
625
+
626
+ # Name
627
+ if options['name']
628
+ payload['network']['name'] = options['name']
629
+ else
630
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this network.'}], options)
631
+ # payload['network']['name'] = v_prompt['name']
632
+ end
633
+
634
+ # Description
635
+ if options['description']
636
+ payload['network']['description'] = options['description']
637
+ else
638
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false, 'description' => 'Description of network.'}], options)
639
+ # payload['network']['description'] = v_prompt['description']
640
+ end
641
+
642
+ # Gateway
643
+ if options['gateway']
644
+ payload['network']['gateway'] = options['gateway']
645
+ else
646
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'gateway', 'fieldLabel' => 'Gateway', 'type' => 'text', 'required' => false, 'description' => ''}], options)
647
+ # payload['network']['gateway'] = v_prompt['gateway']
648
+ end
649
+
650
+ # DNS Primary
651
+ if options['dnsPrimary']
652
+ payload['network']['dnsPrimary'] = options['dnsPrimary']
653
+ else
654
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dnsPrimary', 'fieldLabel' => 'DNS Primary', 'type' => 'text', 'required' => false, 'description' => ''}], options)
655
+ # payload['network']['dnsPrimary'] = v_prompt['dnsPrimary']
656
+ end
657
+
658
+ # DNS Secondary
659
+ if options['dnsSecondary']
660
+ payload['network']['dnsSecondary'] = options['dnsSecondary']
661
+ else
662
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dnsSecondary', 'fieldLabel' => 'DNS Secondary', 'type' => 'text', 'required' => false, 'description' => ''}], options)
663
+ # payload['network']['dnsSecondary'] = v_prompt['dnsSecondary']
664
+ end
665
+
666
+ # CIDR
667
+ if options['cidr']
668
+ payload['network']['cidr'] = options['cidr']
669
+ else
670
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => false, 'description' => ''}], options)
671
+ # payload['network']['cidr'] = v_prompt['cidr']
672
+ end
673
+
674
+ # VLAN ID
675
+ if options['vlanId']
676
+ payload['network']['vlanId'] = options['vlanId']
677
+ else
678
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'vlanId', 'fieldLabel' => 'VLAN ID', 'type' => 'number', 'required' => false, 'description' => ''}], options)
679
+ # payload['network']['vlanId'] = v_prompt['vlanId']
680
+ end
681
+
682
+ # Network Pool
683
+ if options['pool']
684
+ payload['network']['pool'] = options['pool'].to_i
685
+ else
686
+ # todo: select dropdown
687
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'select', 'optionSource' => 'networkPools', 'required' => false, 'description' => ''}], options, @api_client, {zoneId: cloud['id']})
688
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'text', 'required' => false, 'description' => ''}], options)
689
+ # payload['network']['pool'] = v_prompt['pool'].to_i if v_prompt['pool']
690
+ end
691
+
692
+ # DHCP Server
693
+ if options['dhcpServer'] != nil
694
+ payload['network']['dhcpServer'] = options['dhcpServer']
695
+ else
696
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dhcpServer', 'fieldLabel' => 'DHCP Server', 'type' => 'checkbox', 'required' => false, 'description' => ''}], options)
697
+ # payload['network']['dhcpServer'] = v_prompt['dhcpServer']
698
+ end
699
+
700
+ # Allow IP Override
701
+ if options['allowStaticOverride'] != nil
702
+ payload['network']['allowStaticOverride'] = options['allowStaticOverride']
703
+ else
704
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'allowStaticOverride', 'fieldLabel' => 'Allow IP Override', 'type' => 'checkbox', 'required' => false, 'description' => ''}], options)
705
+ # payload['network']['allowStaticOverride'] = v_prompt['allowStaticOverride']
706
+ end
707
+
708
+ # Group Access
709
+ if group_access_all != nil
710
+ payload['resourcePermissions'] ||= {}
711
+ payload['resourcePermissions']['all'] = group_access_all
712
+ end
713
+ if group_access_list != nil
714
+ payload['resourcePermissions'] ||= {}
715
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
716
+ site = {"id" => site_id.to_i}
717
+ if group_defaults_list && group_defaults_list.include?(site_id)
718
+ site["default"] = true
719
+ end
720
+ site
721
+ end
722
+ end
723
+
724
+ # Tenants
725
+ if options['tenants']
726
+ payload['tenantPermissions'] = {}
727
+ payload['tenantPermissions']['accounts'] = options['tenants']
728
+ end
729
+
730
+ # Active
731
+ if options['active'] != nil
732
+ payload['network']['active'] = options['active']
733
+ end
734
+
735
+ # Visibility
736
+ if options['visibility'] != nil
737
+ payload['network']['visibility'] = options['visibility']
738
+ end
739
+
740
+ end
741
+
742
+ if options[:dry_run]
743
+ print_dry_run @networks_interface.dry.update(network["id"], payload)
744
+ return
745
+ end
746
+ json_response = @networks_interface.update(network["id"], payload)
747
+ if options[:json]
748
+ puts as_json(json_response)
749
+ else
750
+ network = json_response['network']
751
+ print_green_success "Updated network #{network['name']}"
752
+ get([network['id']])
753
+ end
754
+ return 0
755
+ rescue RestClient::Exception => e
756
+ print_rest_exception(e, options)
757
+ return 1
758
+ end
759
+ end
760
+
761
+ def remove(args)
762
+ options = {}
763
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
764
+ opts.banner = subcommand_usage("[network]")
765
+ build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
766
+ opts.footer = "Delete a network." + "\n" +
767
+ "[network] is required. This is the name or id of a network."
768
+ end
769
+ optparse.parse!(args)
770
+
771
+ if args.count < 1
772
+ print_error Morpheus::Terminal.angry_prompt
773
+ puts_error "#{command_name} missing argument: [network]\n#{optparse}"
774
+ return 1
775
+ end
776
+
777
+ connect(options)
778
+ begin
779
+ network = find_network_by_name_or_id(args[0])
780
+ return 1 if network.nil?
781
+
782
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the network: #{network['name']}?")
783
+ return 9, "aborted command"
784
+ end
785
+ if options[:dry_run]
786
+ print_dry_run @networks_interface.dry.destroy(network['id'])
787
+ return 0
788
+ end
789
+ json_response = @networks_interface.destroy(network['id'])
790
+ if options[:json]
791
+ print JSON.pretty_generate(json_response)
792
+ print "\n"
793
+ else
794
+ print_green_success "Removed network #{network['name']}"
795
+ # list([])
796
+ end
797
+ return 0
798
+ rescue RestClient::Exception => e
799
+ print_rest_exception(e, options)
800
+ return 1
801
+ end
802
+ end
803
+
804
+ private
805
+
806
+
807
+ def find_network_by_name_or_id(val)
808
+ if val.to_s =~ /\A\d{1,}\Z/
809
+ return find_network_by_id(val)
810
+ else
811
+ return find_network_by_name(val)
812
+ end
813
+ end
814
+
815
+ def find_network_by_id(id)
816
+ begin
817
+ json_response = @networks_interface.get(id.to_i)
818
+ return json_response['network']
819
+ rescue RestClient::Exception => e
820
+ if e.response && e.response.code == 404
821
+ print_red_alert "Network not found by id #{id}"
822
+ return nil
823
+ else
824
+ raise e
825
+ end
826
+ end
827
+ end
828
+
829
+ def find_network_by_name(name)
830
+ json_response = @networks_interface.list({name: name.to_s})
831
+ networks = json_response['networks']
832
+ if networks.empty?
833
+ print_red_alert "Network not found by name #{name}"
834
+ return nil
835
+ elsif networks.size > 1
836
+ print_red_alert "#{networks.size} networks found by name #{name}"
837
+ # print_networks_table(networks, {color: red})
838
+ rows = networks.collect do |network|
839
+ {id: it['id'], name: it['name']}
840
+ end
841
+ print red
842
+ tp rows, [:id, :name]
843
+ print reset,"\n"
844
+ return nil
845
+ else
846
+ network = networks[0]
847
+ # merge in tenants map
848
+ if json_response['tenants'] && json_response['tenants'][network['id']]
849
+ network['tenants'] = json_response['tenants'][network['id']]
850
+ end
851
+ return network
852
+ end
853
+ end
854
+
855
+ end