morpheus-cli 5.3.2.1 → 5.3.4
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/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +12 -0
- data/lib/morpheus/api/clouds_interface.rb +4 -11
- data/lib/morpheus/api/instances_interface.rb +18 -5
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
- data/lib/morpheus/api/network_routers_interface.rb +21 -0
- data/lib/morpheus/api/network_servers_interface.rb +42 -0
- data/lib/morpheus/api/rest_interface.rb +2 -1
- data/lib/morpheus/api/virtual_images_interface.rb +23 -2
- data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
- data/lib/morpheus/cli/apps.rb +3 -2
- data/lib/morpheus/cli/cli_command.rb +14 -6
- data/lib/morpheus/cli/cli_registry.rb +55 -2
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +170 -134
- data/lib/morpheus/cli/clouds.rb +22 -40
- data/lib/morpheus/cli/clusters.rb +51 -33
- data/lib/morpheus/cli/hosts.rb +0 -1
- data/lib/morpheus/cli/instances.rb +372 -150
- data/lib/morpheus/cli/invoices_command.rb +117 -133
- data/lib/morpheus/cli/library_cluster_layouts_command.rb +20 -0
- data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
- data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
- data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
- data/lib/morpheus/cli/load_balancers.rb +0 -155
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +155 -112
- data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +2 -0
- data/lib/morpheus/cli/network_routers_command.rb +291 -7
- data/lib/morpheus/cli/network_scopes_command.rb +442 -0
- data/lib/morpheus/cli/networks_command.rb +3 -3
- data/lib/morpheus/cli/option_parser.rb +25 -17
- data/lib/morpheus/cli/option_types.rb +42 -15
- data/lib/morpheus/cli/subnets_command.rb +7 -2
- data/lib/morpheus/cli/tasks.rb +25 -2
- data/lib/morpheus/cli/vdi_pools_command.rb +4 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +251 -29
- data/lib/morpheus/cli.rb +9 -1
- data/morpheus-cli.gemspec +1 -1
- metadata +11 -4
@@ -0,0 +1,442 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'optparse'
|
3
|
+
require 'filesize'
|
4
|
+
require 'morpheus/cli/cli_command'
|
5
|
+
require 'morpheus/cli/mixins/infrastructure_helper'
|
6
|
+
|
7
|
+
class Morpheus::Cli::NetworkScopesCommand
|
8
|
+
include Morpheus::Cli::CliCommand
|
9
|
+
include Morpheus::Cli::ProvisioningHelper
|
10
|
+
include Morpheus::Cli::WhoamiHelper
|
11
|
+
|
12
|
+
set_command_name :'network-scopes'
|
13
|
+
register_subcommands :list, :get, :add, :update, :remove
|
14
|
+
|
15
|
+
def connect(opts)
|
16
|
+
@api_client = establish_remote_appliance_connection(opts)
|
17
|
+
@account_interface = @api_client.accounts
|
18
|
+
@network_servers_interface = @api_client.network_servers
|
19
|
+
@options_interface = @api_client.options
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle(args)
|
23
|
+
handle_subcommand(args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def list(args)
|
27
|
+
options = {}
|
28
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
29
|
+
opts.banner = subcommand_usage("[server]")
|
30
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
31
|
+
opts.footer = "List network scopes." + "\n" +
|
32
|
+
"[server] is required. This is the name or id of a network server."
|
33
|
+
end
|
34
|
+
|
35
|
+
optparse.parse!(args)
|
36
|
+
connect(options)
|
37
|
+
|
38
|
+
if args.count < 1
|
39
|
+
puts optparse
|
40
|
+
return 1
|
41
|
+
end
|
42
|
+
|
43
|
+
server = find_network_server(args[0])
|
44
|
+
if server.nil?
|
45
|
+
return 1
|
46
|
+
end
|
47
|
+
|
48
|
+
_list(server, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def _list(server, options)
|
52
|
+
@network_servers_interface.setopts(options)
|
53
|
+
|
54
|
+
if options[:dry_run]
|
55
|
+
print_dry_run @network_servers_interface.dry.list_scopes(server['id'])
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
if server['type']['hasScopes']
|
60
|
+
json_response = @network_servers_interface.list_scopes(server['id'])
|
61
|
+
render_response(json_response, options, 'networkScopes') do
|
62
|
+
print_h1 "Network Scopes For: #{server['name']}"
|
63
|
+
print cyan
|
64
|
+
print_scopes(server, json_response['networkScopes'])
|
65
|
+
end
|
66
|
+
else
|
67
|
+
print_red_alert "Scopes not supported for #{server['type']['name']}"
|
68
|
+
end
|
69
|
+
print reset
|
70
|
+
end
|
71
|
+
|
72
|
+
def get(args)
|
73
|
+
options = {}
|
74
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
75
|
+
opts.banner = subcommand_usage("[server] [scope]")
|
76
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
77
|
+
opts.footer = "Display details on a network scope." + "\n" +
|
78
|
+
"[server] is required. This is the name or id of a network server.\n" +
|
79
|
+
"[scope] is required. This is the id of a network scope.\n"
|
80
|
+
end
|
81
|
+
|
82
|
+
optparse.parse!(args)
|
83
|
+
connect(options)
|
84
|
+
|
85
|
+
if args.count < 2
|
86
|
+
puts optparse
|
87
|
+
return 1
|
88
|
+
end
|
89
|
+
|
90
|
+
server = find_network_server(args[0])
|
91
|
+
if server.nil?
|
92
|
+
return 1
|
93
|
+
end
|
94
|
+
|
95
|
+
_get(server, args[1], options)
|
96
|
+
end
|
97
|
+
|
98
|
+
def _get(server, scope_id, options)
|
99
|
+
@network_servers_interface.setopts(options)
|
100
|
+
|
101
|
+
if options[:dry_run]
|
102
|
+
if scope_id.to_s =~ /\A\d{1,}\Z/
|
103
|
+
print_dry_run @network_servers_interface.dry.get_scope(server['id'], scope_id.to_i)
|
104
|
+
else
|
105
|
+
print_dry_run @network_servers_interface.dry.list_scopes(server['id'], {name: scope_id})
|
106
|
+
end
|
107
|
+
return
|
108
|
+
end
|
109
|
+
|
110
|
+
if server['type']['hasScopes']
|
111
|
+
scope = find_scope(server['id'], scope_id)
|
112
|
+
|
113
|
+
return 1 if scope.nil?
|
114
|
+
|
115
|
+
render_response({networkScope: scope}, options, 'networkScope') do
|
116
|
+
print_h1 "Network Scope Details"
|
117
|
+
print cyan
|
118
|
+
|
119
|
+
description_cols = {
|
120
|
+
"ID" => lambda {|it| it['id']},
|
121
|
+
"Name" => lambda {|it| it['name']},
|
122
|
+
"Description" => lambda {|it| it['description']},
|
123
|
+
"Status" => lambda {|it| it['status']}
|
124
|
+
}
|
125
|
+
|
126
|
+
if is_master_account
|
127
|
+
description_cols["Visibility"] = lambda {|it| it['visibility']}
|
128
|
+
description_cols["Tenants"] = lambda {|it| it['tenants'].collect {|tenant| tenant['name']}.join(', ')}
|
129
|
+
end
|
130
|
+
|
131
|
+
server['type']['scopeOptionTypes'].sort_by {|it| it['displayOrder']}.each do |option_type|
|
132
|
+
description_cols[option_type['fieldLabel']] = lambda {|it| Morpheus::Cli::OptionTypes.get_option_value(it, option_type, true)}
|
133
|
+
end
|
134
|
+
print_description_list(description_cols, scope)
|
135
|
+
end
|
136
|
+
else
|
137
|
+
print_red_alert "Scopes not supported for #{server['type']['name']}"
|
138
|
+
end
|
139
|
+
println reset
|
140
|
+
end
|
141
|
+
|
142
|
+
def add(args)
|
143
|
+
options = {:options=>{}}
|
144
|
+
params = {}
|
145
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
146
|
+
opts.banner = subcommand_usage("[server]")
|
147
|
+
opts.on( '--name NAME', "Name" ) do |val|
|
148
|
+
options[:name] = val.to_s
|
149
|
+
end
|
150
|
+
opts.on("--description [TEXT]", String, "Description") do |val|
|
151
|
+
options[:description] = val.to_s
|
152
|
+
end
|
153
|
+
add_perms_options(opts, options, ['plans', 'groups'])
|
154
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
155
|
+
opts.footer = "Create a network scope." + "\n" +
|
156
|
+
"[server] is required. This is the name or id of a network server.\n";
|
157
|
+
end
|
158
|
+
optparse.parse!(args)
|
159
|
+
connect(options)
|
160
|
+
if args.count < 1
|
161
|
+
print_error Morpheus::Terminal.angry_prompt
|
162
|
+
puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
|
163
|
+
return 1
|
164
|
+
end
|
165
|
+
|
166
|
+
server = find_network_server(args[0])
|
167
|
+
if server.nil?
|
168
|
+
return 1
|
169
|
+
end
|
170
|
+
|
171
|
+
if !server['type']['hasScopes']
|
172
|
+
print_red_alert "Scopes not supported for #{server['type']['name']}"
|
173
|
+
return 1
|
174
|
+
end
|
175
|
+
|
176
|
+
if options[:payload]
|
177
|
+
payload = options[:payload]
|
178
|
+
else
|
179
|
+
params['name'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true, 'description' => 'Name.'}],options[:options],@api_client,{})['name']
|
180
|
+
params['description'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => false, 'description' => 'Description.'}],options[:options],@api_client,{})['description']
|
181
|
+
|
182
|
+
option_types = server['type']['scopeOptionTypes'].sort_by {|it| it['displayOrder']}
|
183
|
+
|
184
|
+
# prompt options
|
185
|
+
option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'scope' => ''}}), @api_client, {'networkServerId' => server['id']}, nil, true)
|
186
|
+
|
187
|
+
# prompt permissions
|
188
|
+
perms = prompt_permissions(options, ['plans', 'groups'])
|
189
|
+
perms = {'visibility' => perms['resourcePool']['visibility'], 'tenants' => perms['tenantPermissions']['accounts'].collect {|it| {'id' => it}}}
|
190
|
+
payload = {'networkScope' => params.deep_merge(option_result).deep_merge(perms)}
|
191
|
+
end
|
192
|
+
|
193
|
+
@network_servers_interface.setopts(options)
|
194
|
+
|
195
|
+
if options[:dry_run]
|
196
|
+
print_dry_run @network_servers_interface.dry.create_scope(server['id'], payload)
|
197
|
+
return
|
198
|
+
end
|
199
|
+
|
200
|
+
json_response = @network_servers_interface.create_scope(server['id'], payload)
|
201
|
+
render_response(json_response, options, 'networkScope') do
|
202
|
+
print_green_success "\nAdded Network Scope #{json_response['id']}\n"
|
203
|
+
_get(server, json_response['id'], options)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def update(args)
|
208
|
+
options = {:options=>{}}
|
209
|
+
params = {}
|
210
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
211
|
+
opts.banner = subcommand_usage("[server] [scope]")
|
212
|
+
opts.on( '--name NAME', "Name" ) do |val|
|
213
|
+
params['name'] = val.to_s
|
214
|
+
end
|
215
|
+
opts.on("--description [TEXT]", String, "Description") do |val|
|
216
|
+
params['description'] = val.to_s
|
217
|
+
end
|
218
|
+
add_perms_options(opts, options, ['plans', 'groups'])
|
219
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
220
|
+
opts.footer = "Update a network scope.\n" +
|
221
|
+
"[server] is required. This is the name or id of an existing network server.\n" +
|
222
|
+
"[scope] is required. This is the name or id of an existing network scope."
|
223
|
+
end
|
224
|
+
optparse.parse!(args)
|
225
|
+
if args.count != 2
|
226
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
|
227
|
+
end
|
228
|
+
connect(options)
|
229
|
+
|
230
|
+
server = find_network_server(args[0])
|
231
|
+
if server.nil?
|
232
|
+
return 1
|
233
|
+
end
|
234
|
+
|
235
|
+
if !server['type']['hasScopes']
|
236
|
+
print_red_alert "Scopes not supported for #{server['type']['name']}"
|
237
|
+
return 1
|
238
|
+
end
|
239
|
+
|
240
|
+
scope = find_scope(server['id'], args[1])
|
241
|
+
return 1 if scope.nil?
|
242
|
+
|
243
|
+
payload = parse_payload(options) || {'networkScope' => params}
|
244
|
+
payload['networkScope'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options] && !payload['networkScope'].nil?
|
245
|
+
|
246
|
+
if !options[:visibility].nil?
|
247
|
+
payload['networkScope']['visibility'] = options[:visibility]
|
248
|
+
end
|
249
|
+
if !options[:tenants].nil?
|
250
|
+
payload['networkScope']['tenants'] = options[:tenants].collect {|id| {id: id.to_i}}
|
251
|
+
end
|
252
|
+
|
253
|
+
if payload['networkScope'].empty?
|
254
|
+
option_types = server['type']['scopeOptionTypes'].sort_by {|it| it['displayOrder']}
|
255
|
+
print_green_success "Nothing to update"
|
256
|
+
println cyan
|
257
|
+
print Morpheus::Cli::OptionTypes.display_option_types_help(
|
258
|
+
option_types,
|
259
|
+
{:include_context => true, :context_map => {'scope' => ''}, :color => cyan, :title => "Available Scope Options"}
|
260
|
+
)
|
261
|
+
exit 1
|
262
|
+
end
|
263
|
+
|
264
|
+
#payload = {'networkScope' => scope.deep_merge(payload['networkScope'])}
|
265
|
+
|
266
|
+
@network_servers_interface.setopts(options)
|
267
|
+
|
268
|
+
if options[:dry_run]
|
269
|
+
print_dry_run @network_servers_interface.dry.update_scope(server['id'], scope['id'], payload)
|
270
|
+
return
|
271
|
+
end
|
272
|
+
|
273
|
+
json_response = @network_servers_interface.update_scope(server['id'], scope['id'], payload)
|
274
|
+
render_response(json_response, options, 'networkScope') do
|
275
|
+
print_green_success "\nUpdated Network Scope #{scope['id']}\n"
|
276
|
+
_get(server, scope['id'], options)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def remove(args)
|
281
|
+
options = {}
|
282
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
283
|
+
opts.banner = subcommand_usage("[server] [scope]")
|
284
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
|
285
|
+
opts.footer = "Delete a network scope.\n" +
|
286
|
+
"[server] is required. This is the name or id of an existing network server.\n" +
|
287
|
+
"[scope] is required. This is the name or id of an existing network scope."
|
288
|
+
end
|
289
|
+
optparse.parse!(args)
|
290
|
+
if args.count != 2
|
291
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
|
292
|
+
end
|
293
|
+
connect(options)
|
294
|
+
|
295
|
+
server = find_network_server(args[0])
|
296
|
+
if server.nil?
|
297
|
+
return 1
|
298
|
+
end
|
299
|
+
|
300
|
+
if !server['type']['hasScopes']
|
301
|
+
print_red_alert "Scopes not supported for #{server['type']['name']}"
|
302
|
+
return 1
|
303
|
+
end
|
304
|
+
|
305
|
+
scope = find_scope(server['id'], args[1])
|
306
|
+
return 1 if scope.nil?
|
307
|
+
|
308
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the network scope '#{scope['name']}' from server '#{server['name']}'?", options)
|
309
|
+
return 9, "aborted command"
|
310
|
+
end
|
311
|
+
|
312
|
+
@network_servers_interface.setopts(options)
|
313
|
+
|
314
|
+
if options[:dry_run]
|
315
|
+
print_dry_run @network_servers_interface.dry.destroy_scope(server['id'], scope['id'])
|
316
|
+
return
|
317
|
+
end
|
318
|
+
json_response = @network_servers_interface.destroy_scope(server['id'], scope['id'])
|
319
|
+
render_response(json_response, options, 'networkScope') do
|
320
|
+
print_green_success "\nDeleted Network Scope #{scope['name']}\n"
|
321
|
+
_list(server, options)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
private
|
326
|
+
|
327
|
+
def print_scopes(server, scopes)
|
328
|
+
if scopes.count > 0
|
329
|
+
cols = [:id, :name, :description, :status]
|
330
|
+
server['type']['scopeOptionTypes'].sort_by {|it| it['displayOrder']}.each do |option_type|
|
331
|
+
cols << option_type['fieldLabel']
|
332
|
+
end
|
333
|
+
cols += [:visibility, :tenants] if is_master_account
|
334
|
+
rows = scopes.collect do |it|
|
335
|
+
row = {
|
336
|
+
id: it['id'],
|
337
|
+
name: it['name'],
|
338
|
+
description: it['description'],
|
339
|
+
status: it['statusMessage'],
|
340
|
+
}
|
341
|
+
server['type']['scopeOptionTypes'].sort_by {|it| it['displayOrder']}.each do |option_type|
|
342
|
+
row[option_type['fieldLabel']] = Morpheus::Cli::OptionTypes.get_option_value(it, option_type, true)
|
343
|
+
end
|
344
|
+
if is_master_account
|
345
|
+
row = row.merge({
|
346
|
+
visibility: it['visibility'],
|
347
|
+
tenants: it['tenants'].collect {|it| it['name']}.join(', ')
|
348
|
+
})
|
349
|
+
end
|
350
|
+
row
|
351
|
+
end
|
352
|
+
puts as_pretty_table(rows, cols)
|
353
|
+
else
|
354
|
+
println "No Scopes\n"
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def find_network_server(val)
|
359
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
360
|
+
return find_network_server_by_id(val)
|
361
|
+
else
|
362
|
+
if server = find_network_server_by_name(val)
|
363
|
+
return find_network_server_by_id(server['id'])
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def find_network_server_by_id(id)
|
369
|
+
begin
|
370
|
+
json_response = @network_servers_interface.get(id.to_i)
|
371
|
+
return json_response['networkServer']
|
372
|
+
rescue RestClient::Exception => e
|
373
|
+
if e.response && e.response.code == 404
|
374
|
+
print_red_alert "Network Server not found by id #{id}"
|
375
|
+
return nil
|
376
|
+
else
|
377
|
+
raise e
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def find_network_server_by_name(name)
|
383
|
+
json_response = @network_servers_interface.list({phrase: name.to_s})
|
384
|
+
servers = json_response['networkServers']
|
385
|
+
if servers.empty?
|
386
|
+
print_red_alert "Network Server not found by name #{name}"
|
387
|
+
return nil
|
388
|
+
elsif servers.size > 1
|
389
|
+
print_red_alert "#{servers.size} network servers found by name #{name}"
|
390
|
+
rows = servers.collect do |it|
|
391
|
+
{id: it['id'], name: it['name']}
|
392
|
+
end
|
393
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
394
|
+
return nil
|
395
|
+
else
|
396
|
+
return servers[0]
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
def find_scope(server_id, val)
|
401
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
402
|
+
return find_scope_by_id(server_id, val)
|
403
|
+
else
|
404
|
+
if scope = find_scope_by_name(server_id, val)
|
405
|
+
return find_scope_by_id(server_id, scope['id'])
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def find_scope_by_id(server_id, scope_id)
|
411
|
+
begin
|
412
|
+
json_response = @network_servers_interface.get_scope(server_id, scope_id.to_i)
|
413
|
+
return json_response['networkScope']
|
414
|
+
rescue RestClient::Exception => e
|
415
|
+
if e.response && e.response.code == 404
|
416
|
+
print_red_alert "Network Scope not found by id #{id}"
|
417
|
+
return nil
|
418
|
+
else
|
419
|
+
raise e
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
def find_scope_by_name(server_id, name)
|
425
|
+
json_response = @network_servers_interface.list_scope(server_id, {phrase: name.to_s})
|
426
|
+
scopes = json_response['networkScopes']
|
427
|
+
if scopes.empty?
|
428
|
+
print_red_alert "Network Scope not found by name #{name}"
|
429
|
+
return nil
|
430
|
+
elsif scopes.size > 1
|
431
|
+
print_red_alert "#{scopes.size} network scopes found by name #{name}"
|
432
|
+
rows = scopes.collect do |it|
|
433
|
+
{id: it['id'], name: it['name']}
|
434
|
+
end
|
435
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
436
|
+
return nil
|
437
|
+
else
|
438
|
+
return scopes[0]
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
end
|
@@ -617,9 +617,10 @@ class Morpheus::Cli::NetworksCommand
|
|
617
617
|
if network_type_option_types && network_type_option_types.size > 0
|
618
618
|
api_params = {}
|
619
619
|
api_params['network.site.id'] = group ? group['id'] : 'shared'
|
620
|
+
api_params['network.zone.id'] = cloud['id'] if !cloud.nil?
|
620
621
|
api_params['network.type.id'] = network_type['id']
|
621
622
|
api_params['network.networkServer.id'] = network_server_id if !network_server_id.nil?
|
622
|
-
network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,options[:options],@api_client, api_params)
|
623
|
+
network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,(options[:options] || {}).merge(payload),@api_client, api_params)
|
623
624
|
# network context options belong at network level and not network.network
|
624
625
|
network_context_params = network_type_params.delete('network')
|
625
626
|
payload['network'].deep_merge!(network_context_params) if network_context_params
|
@@ -660,8 +661,7 @@ class Morpheus::Cli::NetworksCommand
|
|
660
661
|
payload['network']['pool'] = options['pool'].to_i
|
661
662
|
else
|
662
663
|
# todo: select dropdown
|
663
|
-
|
664
|
-
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'text', 'required' => false, 'description' => ''}], options)
|
664
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'select', 'optionSource' => 'networkPools', 'required' => false, 'description' => ''}], options, @api_client, api_params)
|
665
665
|
payload['network']['pool'] = v_prompt['pool'].to_i if v_prompt['pool']
|
666
666
|
end
|
667
667
|
end
|
@@ -32,27 +32,35 @@ module Morpheus
|
|
32
32
|
#out << "Options:\n"
|
33
33
|
# the default way..
|
34
34
|
# out << summarize().join("")
|
35
|
-
|
36
35
|
# super hacky, should be examining the option, not the fully formatted description
|
37
36
|
my_summaries = summarize()
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
37
|
+
if opts[:show_hidden_options]
|
38
|
+
my_summaries.each do |full_line|
|
39
|
+
out << full_line
|
40
|
+
end
|
41
|
+
else
|
42
|
+
on_hidden_option = false
|
43
|
+
my_summaries.each do |full_line|
|
44
|
+
opt_description = full_line.to_s.strip
|
45
|
+
if opt_description.start_with?("-")
|
46
|
+
is_hidden = (@hidden_options || []).find { |hidden_switch|
|
47
|
+
if hidden_switch.start_with?("-")
|
48
|
+
opt_description.start_with?("#{hidden_switch} ")
|
49
|
+
else
|
50
|
+
opt_description.start_with?("--#{hidden_switch} ")
|
51
|
+
end
|
52
|
+
}
|
53
|
+
if is_hidden
|
54
|
+
on_hidden_option = true
|
55
|
+
else
|
56
|
+
on_hidden_option = false
|
57
|
+
out << full_line
|
58
|
+
end
|
51
59
|
else
|
52
|
-
|
60
|
+
if on_hidden_option == false
|
61
|
+
out << full_line
|
62
|
+
end
|
53
63
|
end
|
54
|
-
else
|
55
|
-
out << opt_description
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -61,11 +61,11 @@ module Morpheus
|
|
61
61
|
).each do |option_type|
|
62
62
|
context_map = results
|
63
63
|
value = nil
|
64
|
-
value_found=false
|
64
|
+
value_found = false
|
65
|
+
field_group = (option_type['fieldGroup'] || 'default').to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
|
65
66
|
|
66
|
-
if cur_field_group !=
|
67
|
-
cur_field_group =
|
68
|
-
cur_field_group = cur_field_group.to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
|
67
|
+
if cur_field_group != field_group
|
68
|
+
cur_field_group = field_group
|
69
69
|
print "\n#{cur_field_group.upcase} OPTIONS\n#{"=" * ("#{cur_field_group} OPTIONS".length)}\n\n"
|
70
70
|
end
|
71
71
|
|
@@ -102,10 +102,10 @@ module Morpheus
|
|
102
102
|
end
|
103
103
|
|
104
104
|
found_dep_value = match_type == 'all' ? true : false
|
105
|
-
visible_option_check_value.
|
105
|
+
visible_option_check_value.sub(',', ' ').split(' ').each do |value|
|
106
106
|
parts = value.split(':')
|
107
107
|
depends_on_code = parts[0]
|
108
|
-
depends_on_value = parts.count > 1 ? parts[1].to_s.strip :
|
108
|
+
depends_on_value = parts.count > 1 ? parts[1].to_s.strip : nil
|
109
109
|
depends_on_option_type = option_types.find {|it| it["code"] == depends_on_code }
|
110
110
|
if !depends_on_option_type
|
111
111
|
depends_on_option_type = option_types.find {|it|
|
@@ -115,13 +115,18 @@ module Morpheus
|
|
115
115
|
|
116
116
|
if depends_on_option_type
|
117
117
|
depends_on_field_key = depends_on_option_type['fieldContext'].nil? || depends_on_option_type['fieldContext'].empty? ? "#{depends_on_option_type['fieldName']}" : "#{depends_on_option_type['fieldContext']}.#{depends_on_option_type['fieldName']}"
|
118
|
-
|
118
|
+
else
|
119
|
+
depends_on_field_key = depends_on_code
|
120
|
+
end
|
119
121
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
122
|
+
field_value = get_object_value(results, depends_on_field_key) ||
|
123
|
+
get_object_value(options, depends_on_field_key) ||
|
124
|
+
get_object_value(api_params, depends_on_field_key)
|
125
|
+
|
126
|
+
if !field_value.nil? && (depends_on_value.nil? || depends_on_value.empty? || field_value.match?(depends_on_value))
|
127
|
+
found_dep_value = true if match_type != 'all'
|
128
|
+
else
|
129
|
+
found_dep_value = false if match_type == 'all'
|
125
130
|
end
|
126
131
|
end
|
127
132
|
next if !found_dep_value
|
@@ -237,7 +242,7 @@ module Morpheus
|
|
237
242
|
# I suppose the entered value should take precedence
|
238
243
|
# api_params = api_params.merge(options) # this might be good enough
|
239
244
|
# dup it
|
240
|
-
value = select_prompt(option_type, api_client, (option_type['noParams'] ? {} : (api_params || {}).
|
245
|
+
value = select_prompt(option_type, api_client, (option_type['noParams'] ? {} : (api_params || {}).deep_merge(results)), options[:no_prompt], nil, paging_enabled)
|
241
246
|
if value && option_type['type'] == 'multiSelect'
|
242
247
|
value = [value]
|
243
248
|
while self.confirm("Add another #{option_type['fieldLabel']}?", {:default => false}) do
|
@@ -276,7 +281,8 @@ module Morpheus
|
|
276
281
|
value = [value] if !value.nil? && !value.is_a?(Array)
|
277
282
|
# parent_context_map[parent_ns] = value
|
278
283
|
end
|
279
|
-
context_map[field_name] = value
|
284
|
+
context_map[field_name] = value if !(value.nil? || (value.is_a?(Hash) && value.empty?))
|
285
|
+
parent_context_map.reject! {|k,v| k == parent_ns && (v.nil? || (v.is_a?(Hash) && v.empty?))}
|
280
286
|
end
|
281
287
|
results
|
282
288
|
end
|
@@ -947,8 +953,9 @@ module Morpheus
|
|
947
953
|
out << "\n"
|
948
954
|
out << "#{header}\n"
|
949
955
|
out << "#{'=' * header.length}\n"
|
956
|
+
|
950
957
|
select_options.each do |option|
|
951
|
-
out << " * #{option['name']} [#{option['value']}]\n"
|
958
|
+
out << (option['isGroup'] ? "- #{option['name']}\n" : " * #{option['name']} [#{option['value']}]\n")
|
952
959
|
end
|
953
960
|
return out
|
954
961
|
end
|
@@ -985,6 +992,26 @@ module Morpheus
|
|
985
992
|
return option_type['required'] ? '' : ' (optional)'
|
986
993
|
end
|
987
994
|
end
|
995
|
+
|
996
|
+
def self.get_option_value(obj, option_type, format=false)
|
997
|
+
context = option_type['fieldContext'] == 'config' ? obj['config'] : obj
|
998
|
+
name = option_type['fieldName']
|
999
|
+
tokens = name.split('.')
|
1000
|
+
|
1001
|
+
if tokens.length > 1
|
1002
|
+
tokens.slice(0, tokens.length - 1).each do |token|
|
1003
|
+
context = context[name = token]
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
rtn = context[name]
|
1008
|
+
|
1009
|
+
if format
|
1010
|
+
rtn = (rtn ? 'On' : 'Off') if option_type['type'] == 'checkbox'
|
1011
|
+
rtn = rtn.join(', ') if rtn.is_a?(Array)
|
1012
|
+
end
|
1013
|
+
rtn
|
1014
|
+
end
|
988
1015
|
end
|
989
1016
|
end
|
990
1017
|
end
|
@@ -350,8 +350,13 @@ class Morpheus::Cli::SubnetsCommand
|
|
350
350
|
if subnet_type_option_types && subnet_type_option_types.size > 0
|
351
351
|
# prompt for option types
|
352
352
|
subnet_type_params = Morpheus::Cli::OptionTypes.prompt(subnet_type_option_types,options[:options],@api_client, {networkId: network['id'], zoneId: network['zone']['id']})
|
353
|
-
|
354
|
-
|
353
|
+
if subnet_type_params['subnet']
|
354
|
+
payload['subnet'].deep_merge!(subnet_type_params['subnet'])
|
355
|
+
end
|
356
|
+
if subnet_type_params['config']
|
357
|
+
payload['subnet']['config'] ||= {}
|
358
|
+
payload['subnet']['config'].deep_merge!(subnet_type_params['config'])
|
359
|
+
end
|
355
360
|
else
|
356
361
|
# DEFAULT INPUTS
|
357
362
|
|