morpheus-cli 5.3.3 → 5.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +12 -0
  4. data/lib/morpheus/api/clouds_interface.rb +4 -11
  5. data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
  6. data/lib/morpheus/api/load_balancer_profiles_interface.rb +10 -0
  7. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +4 -4
  8. data/lib/morpheus/api/network_routers_interface.rb +21 -0
  9. data/lib/morpheus/api/network_servers_interface.rb +42 -0
  10. data/lib/morpheus/api/rest_interface.rb +2 -1
  11. data/lib/morpheus/api/virtual_servers_interface.rb +9 -0
  12. data/lib/morpheus/cli/cli_command.rb +2 -1
  13. data/lib/morpheus/cli/cloud_resource_pools_command.rb +1 -1
  14. data/lib/morpheus/cli/clouds.rb +22 -40
  15. data/lib/morpheus/cli/hosts.rb +0 -1
  16. data/lib/morpheus/cli/instances.rb +111 -7
  17. data/lib/morpheus/cli/invoices_command.rb +42 -38
  18. data/lib/morpheus/cli/library_option_lists_command.rb +3 -3
  19. data/lib/morpheus/cli/load_balancer_pools.rb +111 -0
  20. data/lib/morpheus/cli/load_balancer_virtual_servers.rb +136 -0
  21. data/lib/morpheus/cli/load_balancers.rb +0 -155
  22. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +2 -2
  23. data/lib/morpheus/cli/mixins/provisioning_helper.rb +32 -11
  24. data/lib/morpheus/cli/mixins/rest_command.rb +53 -37
  25. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +488 -0
  26. data/lib/morpheus/cli/network_routers_command.rb +291 -7
  27. data/lib/morpheus/cli/network_scopes_command.rb +442 -0
  28. data/lib/morpheus/cli/networks_command.rb +2 -2
  29. data/lib/morpheus/cli/option_types.rb +20 -0
  30. data/lib/morpheus/cli/subnets_command.rb +7 -2
  31. data/lib/morpheus/cli/tasks.rb +25 -2
  32. data/lib/morpheus/cli/version.rb +1 -1
  33. data/lib/morpheus/cli/virtual_images.rb +2 -0
  34. data/lib/morpheus/cli.rb +9 -1
  35. metadata +9 -2
@@ -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,6 +617,7 @@ 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
623
  network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,(options[:options] || {}).merge(payload),@api_client, api_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
- # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'select', 'optionSource' => 'networkPools', 'required' => false, 'description' => ''}], options, @api_client, {zoneId: cloud['id']})
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
@@ -992,6 +992,26 @@ module Morpheus
992
992
  return option_type['required'] ? '' : ' (optional)'
993
993
  end
994
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
995
1015
  end
996
1016
  end
997
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
- payload['subnet'].deep_merge!(subnet_type_params['subnet'])
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
 
@@ -198,7 +198,14 @@ class Morpheus::Cli::Tasks
198
198
  end
199
199
  else
200
200
  task_option_types << optionType
201
- task_option_columns << {(optionType['fieldLabel']) => lambda {|it| task['taskOptions'][optionType['fieldName']] || optionType['defaultValue'] } }
201
+ task_option_columns << {(optionType['fieldLabel']) => lambda {|it|
202
+ value = task['taskOptions'][optionType['code']] || task['taskOptions'][optionType['fieldName']] || optionType['defaultValue']
203
+ if optionType['type'] == 'checkbox'
204
+ value.to_s.empty? ? 'off' : value.to_s
205
+ else
206
+ value.to_s
207
+ end
208
+ } }
202
209
  end
203
210
  end
204
211
  else
@@ -430,6 +437,10 @@ class Morpheus::Cli::Tasks
430
437
  if it['fieldContext'].nil? || it['fieldContext'] == ''
431
438
  it['fieldContext'] = 'taskOptions'
432
439
  end
440
+ # taskOptions should prompt for code instead of fieldName, oy vey
441
+ if it['fieldContext'] == 'taskOptions'
442
+ it['fieldName'] = it['code']
443
+ end
433
444
  end
434
445
  end
435
446
  # inject file_params into options for file-content prompt
@@ -444,8 +455,20 @@ class Morpheus::Cli::Tasks
444
455
  end
445
456
  end
446
457
  # prompt
458
+
459
+ # tasks are different in that they use the optionType code instead of fieldName for the key values
447
460
  input_options = Morpheus::Cli::OptionTypes.prompt(task_option_types, options[:options],@api_client, options[:params])
448
- payload.deep_merge!({'task' => input_options}) unless input_options.empty?
461
+ # flatten taskOptions as serverside expects
462
+ if input_options['taskOptions']
463
+ input_options['taskOptions'] = Morpheus::RestClient.grails_params(input_options['taskOptions'])
464
+ # remove "off" checkbox values, like the UI does
465
+ input_options['taskOptions'].keys.each do |k|
466
+ if input_options['taskOptions'][k] == "off"
467
+ input_options['taskOptions'].delete(k)
468
+ end
469
+ end
470
+ end
471
+ payload.deep_merge!({'task' => input_options}) unless input_options.empty?
449
472
 
450
473
 
451
474
  # Target Options
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "5.3.3"
4
+ VERSION = "5.3.4"
5
5
  end
6
6
  end
@@ -83,6 +83,7 @@ class Morpheus::Cli::VirtualImages
83
83
  json_response = @virtual_images_interface.list(params)
84
84
  images = json_response['virtualImages']
85
85
  render_response(json_response, options, 'virtualImages') do
86
+ get_available_virtual_image_types() # preload
86
87
  title = "Morpheus Virtual Images"
87
88
  subtitles = parse_list_subtitles(options)
88
89
  if options[:imageType]
@@ -192,6 +193,7 @@ EOT
192
193
  image_type = virtual_image_type_for_name_or_code(image['imageType'])
193
194
  image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
194
195
  render_response(json_response, options, 'virtualImage') do
196
+ get_available_virtual_image_types() # preload
195
197
  print_h1 "Virtual Image Details", [], options
196
198
  description_cols = {
197
199
  "ID" => 'id',
data/lib/morpheus/cli.rb CHANGED
@@ -50,7 +50,7 @@ module Morpheus
50
50
  Dir[File.dirname(__FILE__) + "/api/**/*.rb"].each {|file| load file }
51
51
 
52
52
  # load mixins
53
- Dir[File.dirname(__FILE__) + "/cli/mixins/*.rb"].each {|file| load file }
53
+ Dir[File.dirname(__FILE__) + "/cli/mixins/**/*.rb"].each {|file| load file }
54
54
 
55
55
  # load commands
56
56
  # Dir[File.dirname(__FILE__) + "/cli/*.rb"].each {|file| load file }
@@ -93,6 +93,13 @@ module Morpheus
93
93
  load 'morpheus/cli/cloud_folders_command.rb'
94
94
  load 'morpheus/cli/hosts.rb'
95
95
  load 'morpheus/cli/load_balancers.rb'
96
+ load 'morpheus/cli/load_balancer_virtual_servers.rb'
97
+ # load 'morpheus/cli/load_balancer_monitors.rb'
98
+ # load 'morpheus/cli/load_balancer_nodes.rb'
99
+ # load 'morpheus/cli/load_balancer_policies.rb'
100
+ load 'morpheus/cli/load_balancer_pools.rb'
101
+ # load 'morpheus/cli/load_balancer_profiles.rb'
102
+ # load 'morpheus/cli/load_balancer_scripts.rb'
96
103
  load 'morpheus/cli/load_balancer_types.rb'
97
104
  load 'morpheus/cli/shell.rb'
98
105
  load 'morpheus/cli/tasks.rb'
@@ -186,6 +193,7 @@ module Morpheus
186
193
  load 'morpheus/cli/vdi_gateways_command.rb'
187
194
  load 'morpheus/cli/vdi_command.rb' # (VDI persona)
188
195
  load 'morpheus/cli/certificates_command.rb' # (VDI persona)
196
+ #load 'morpheus/cli/network_scopes_command.rb'
189
197
  # add new commands here...
190
198
 
191
199
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpheus-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.3
4
+ version: 5.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Estes
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2021-09-14 00:00:00.000000000 Z
14
+ date: 2021-11-09 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -237,6 +237,7 @@ files:
237
237
  - lib/morpheus/api/library_spec_templates_interface.rb
238
238
  - lib/morpheus/api/license_interface.rb
239
239
  - lib/morpheus/api/load_balancer_pools_interface.rb
240
+ - lib/morpheus/api/load_balancer_profiles_interface.rb
240
241
  - lib/morpheus/api/load_balancer_types_interface.rb
241
242
  - lib/morpheus/api/load_balancer_virtual_servers_interface.rb
242
243
  - lib/morpheus/api/load_balancers_interface.rb
@@ -258,6 +259,7 @@ files:
258
259
  - lib/morpheus/api/network_proxies_interface.rb
259
260
  - lib/morpheus/api/network_routers_interface.rb
260
261
  - lib/morpheus/api/network_security_servers_interface.rb
262
+ - lib/morpheus/api/network_servers_interface.rb
261
263
  - lib/morpheus/api/network_services_interface.rb
262
264
  - lib/morpheus/api/network_subnets_interface.rb
263
265
  - lib/morpheus/api/network_types_interface.rb
@@ -307,6 +309,7 @@ files:
307
309
  - lib/morpheus/api/vdi_interface.rb
308
310
  - lib/morpheus/api/vdi_pools_interface.rb
309
311
  - lib/morpheus/api/virtual_images_interface.rb
312
+ - lib/morpheus/api/virtual_servers_interface.rb
310
313
  - lib/morpheus/api/whitelabel_settings_interface.rb
311
314
  - lib/morpheus/api/whoami_interface.rb
312
315
  - lib/morpheus/api/wiki_interface.rb
@@ -397,7 +400,9 @@ files:
397
400
  - lib/morpheus/cli/library_spec_templates_command.rb
398
401
  - lib/morpheus/cli/library_upgrades_command.rb
399
402
  - lib/morpheus/cli/license.rb
403
+ - lib/morpheus/cli/load_balancer_pools.rb
400
404
  - lib/morpheus/cli/load_balancer_types.rb
405
+ - lib/morpheus/cli/load_balancer_virtual_servers.rb
401
406
  - lib/morpheus/cli/load_balancers.rb
402
407
  - lib/morpheus/cli/log_settings_command.rb
403
408
  - lib/morpheus/cli/login.rb
@@ -418,6 +423,7 @@ files:
418
423
  - lib/morpheus/cli/mixins/provisioning_helper.rb
419
424
  - lib/morpheus/cli/mixins/remote_helper.rb
420
425
  - lib/morpheus/cli/mixins/rest_command.rb
426
+ - lib/morpheus/cli/mixins/secondary_rest_command.rb
421
427
  - lib/morpheus/cli/mixins/vdi_helper.rb
422
428
  - lib/morpheus/cli/mixins/whoami_helper.rb
423
429
  - lib/morpheus/cli/monitoring_alerts_command.rb
@@ -432,6 +438,7 @@ files:
432
438
  - lib/morpheus/cli/network_pools_command.rb
433
439
  - lib/morpheus/cli/network_proxies_command.rb
434
440
  - lib/morpheus/cli/network_routers_command.rb
441
+ - lib/morpheus/cli/network_scopes_command.rb
435
442
  - lib/morpheus/cli/network_services_command.rb
436
443
  - lib/morpheus/cli/networks_command.rb
437
444
  - lib/morpheus/cli/option_parser.rb