morpheus-cli 5.4.5 → 5.5.1
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 +4 -0
- data/lib/morpheus/api/clusters_interface.rb +12 -0
- data/lib/morpheus/api/network_pool_servers_interface.rb +7 -0
- data/lib/morpheus/api/prices_interface.rb +6 -0
- data/lib/morpheus/api/scale_thresholds_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +55 -23
- data/lib/morpheus/cli/commands/apps.rb +2 -2
- data/lib/morpheus/cli/commands/cloud_resource_pools_command.rb +33 -2
- data/lib/morpheus/cli/commands/clouds.rb +61 -31
- data/lib/morpheus/cli/commands/clusters.rb +66 -5
- data/lib/morpheus/cli/commands/cypher_command.rb +22 -23
- data/lib/morpheus/cli/commands/hosts.rb +5 -1
- data/lib/morpheus/cli/commands/instances.rb +12 -12
- data/lib/morpheus/cli/commands/integrations_command.rb +1 -1
- data/lib/morpheus/cli/commands/invoices_command.rb +8 -1
- data/lib/morpheus/cli/commands/jobs_command.rb +45 -225
- data/lib/morpheus/cli/commands/library_container_types_command.rb +52 -3
- data/lib/morpheus/cli/commands/library_option_lists_command.rb +18 -8
- data/lib/morpheus/cli/commands/library_option_types_command.rb +56 -62
- data/lib/morpheus/cli/commands/load_balancers.rb +11 -19
- data/lib/morpheus/cli/commands/network_pool_servers_command.rb +5 -2
- data/lib/morpheus/cli/commands/prices_command.rb +25 -11
- data/lib/morpheus/cli/commands/roles.rb +475 -70
- data/lib/morpheus/cli/commands/scale_thresholds.rb +103 -0
- data/lib/morpheus/cli/commands/tasks.rb +64 -22
- data/lib/morpheus/cli/commands/user_sources_command.rb +107 -39
- data/lib/morpheus/cli/commands/users.rb +10 -10
- data/lib/morpheus/cli/commands/view.rb +1 -0
- data/lib/morpheus/cli/commands/workflows.rb +21 -14
- data/lib/morpheus/cli/error_handler.rb +13 -4
- data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/execution_request_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +3 -3
- data/lib/morpheus/cli/mixins/jobs_helper.rb +173 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +120 -38
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -3
- data/lib/morpheus/cli/mixins/rest_command.rb +41 -14
- data/lib/morpheus/cli/option_types.rb +69 -13
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/logging.rb +6 -8
- data/lib/morpheus/routes.rb +3 -5
- metadata +6 -4
@@ -118,10 +118,10 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
118
118
|
begin
|
119
119
|
@library_container_types_interface.setopts(options)
|
120
120
|
if options[:dry_run]
|
121
|
-
if
|
122
|
-
print_dry_run @library_container_types_interface.dry.get(layout_id,
|
121
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
122
|
+
print_dry_run @library_container_types_interface.dry.get(layout_id, id.to_i)
|
123
123
|
else
|
124
|
-
print_dry_run @library_container_types_interface.dry.list(layout_id, {name:
|
124
|
+
print_dry_run @library_container_types_interface.dry.list(layout_id, {name:id})
|
125
125
|
end
|
126
126
|
return
|
127
127
|
end
|
@@ -255,6 +255,24 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
255
255
|
opts.on('--technology CODE', String, "Technology. This is the provision type code.") do |val|
|
256
256
|
params['provisionTypeCode'] = val
|
257
257
|
end
|
258
|
+
opts.on('--ports NAME=PORT,NAME=PORT', String, "List of exposed port definitions in the format NAME=PORT|PROTOCOL, Example: \"WEB=80|HTTP,SECURE=443|HTTPS\"") do |val|
|
259
|
+
params['containerPorts'] ||= []
|
260
|
+
parsed_ports = val.split(",").each do |value_pair|
|
261
|
+
k,v = value_pair.strip.split("=")
|
262
|
+
value_array = v.split("|")
|
263
|
+
port_name = k.to_s.strip
|
264
|
+
port_number = value_array[0].to_s.strip.to_i
|
265
|
+
exposed_port = {'name' => port_name,'port' => port_number }
|
266
|
+
if value_array[1]
|
267
|
+
exposed_port['loadBalanceProtocol'] = value_array[1].strip
|
268
|
+
end
|
269
|
+
if exposed_port['name'].to_s.empty? || !exposed_port['port'] || exposed_port['port'].to_i <= 0
|
270
|
+
raise_command_error "Invalid exposed port definition: '#{value_pair}'. Expected format is 'NAME=PORT'", args, optparse
|
271
|
+
end
|
272
|
+
params['containerPorts'] << exposed_port
|
273
|
+
end
|
274
|
+
# options[:options]['containerPorts'] = params['containerPorts']
|
275
|
+
end
|
258
276
|
opts.on('--scripts x,y,z', Array, "List of Script IDs") do |val|
|
259
277
|
script_ids = val #.collect {|it| it.to_i }
|
260
278
|
end
|
@@ -345,6 +363,12 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
345
363
|
|
346
364
|
# payload.deep_merge!(provision_type_v_prompt)
|
347
365
|
|
366
|
+
# PORTS
|
367
|
+
# if !params['containerPorts']
|
368
|
+
# v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'containerPorts', 'type' => 'exposedPorts', 'fieldLabel' => 'Exposed Ports', 'description' => 'The exposed ports in the format NAME=PORT,NAME=PORT for example HTTP=80,HTTPS=443'}], prompt_params)
|
369
|
+
# params['containerPorts'] = v_prompt['containerPorts']
|
370
|
+
# end
|
371
|
+
|
348
372
|
# ENVIRONMENT VARIABLES
|
349
373
|
if evars
|
350
374
|
params['environmentVariables'] = evars
|
@@ -367,6 +391,7 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
367
391
|
# prompt
|
368
392
|
end
|
369
393
|
|
394
|
+
|
370
395
|
# payload = {'containerType' => params}
|
371
396
|
payload['containerType'] ||= {}
|
372
397
|
payload['containerType'].deep_merge!(params)
|
@@ -422,6 +447,24 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
422
447
|
# opts.on('--technology CODE', String, "Technology") do |val|
|
423
448
|
# params['provisionTypeCode'] = val
|
424
449
|
# end
|
450
|
+
opts.on('--ports NAME=PORT,NAME=PORT', String, "List of exposed port definitions in the format NAME=PORT|PROTOCOL, Example: \"WEB=80|HTTP,SECURE=443|HTTPS\"") do |val|
|
451
|
+
params['containerPorts'] ||= []
|
452
|
+
parsed_ports = val.split(",").each do |value_pair|
|
453
|
+
k,v = value_pair.strip.split("=")
|
454
|
+
value_array = v.split("|")
|
455
|
+
port_name = k.to_s.strip
|
456
|
+
port_number = value_array[0].to_s.strip.to_i
|
457
|
+
exposed_port = {'name' => port_name,'port' => port_number }
|
458
|
+
if value_array[1]
|
459
|
+
exposed_port['loadBalanceProtocol'] = value_array[1].strip
|
460
|
+
end
|
461
|
+
if exposed_port['name'].to_s.empty? || !exposed_port['port'] || exposed_port['port'].to_i <= 0
|
462
|
+
raise_command_error "Invalid exposed port definition: '#{value_pair}'. Expected format is 'NAME=PORT'", args, optparse
|
463
|
+
end
|
464
|
+
params['containerPorts'] << exposed_port
|
465
|
+
end
|
466
|
+
# options[:options]['containerPorts'] = params['containerPorts']
|
467
|
+
end
|
425
468
|
opts.on('--scripts x,y,z', Array, "List of Script IDs") do |val|
|
426
469
|
script_ids = val #.collect {|it| it.to_i }
|
427
470
|
end
|
@@ -455,6 +498,12 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
455
498
|
# params = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options], @api_client, options[:params])
|
456
499
|
payload.deep_merge!({'containerType' => passed_options}) unless passed_options.empty?
|
457
500
|
|
501
|
+
# PORTS
|
502
|
+
# if !params['containerPorts']
|
503
|
+
# v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'containerPorts', 'type' => 'exposedPorts', 'fieldLabel' => 'Exposed Ports', 'description' => 'The exposed ports in the format NAME=PORT,NAME=PORT for example HTTP=80,HTTPS=443'}], prompt_params)
|
504
|
+
# params['containerPorts'] = v_prompt['containerPorts']
|
505
|
+
# end
|
506
|
+
|
458
507
|
# ENVIRONMENT VARIABLES
|
459
508
|
if evars
|
460
509
|
|
@@ -156,9 +156,15 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
156
156
|
"Source URL" => 'sourceUrl',
|
157
157
|
"Real Time" => lambda {|it| format_boolean it['realTime'] },
|
158
158
|
"Ignore SSL Errors" => lambda {|it| format_boolean it['ignoreSSLErrors'] },
|
159
|
-
"Source Method" => lambda {|it| it['sourceMethod'].to_s.upcase }
|
159
|
+
"Source Method" => lambda {|it| it['sourceMethod'].to_s.upcase },
|
160
|
+
"Credentials" => lambda {|it| it['credential'] ? (it['credential']['type'] == 'local' ? '(Local)' : it['credential']['name']) : nil },
|
161
|
+
"Username" => 'serviceUsername',
|
162
|
+
"Password" => 'servicePassword',
|
160
163
|
}
|
161
164
|
option_list_columns.delete("API Type") if option_type_list['type'] != 'api'
|
165
|
+
option_list_columns.delete("Credentials") if !['rest','ldap'].include?(option_type_list['type']) # || !(option_type_list['credential'] && option_type_list['credential']['id'])
|
166
|
+
option_list_columns.delete("Username") if !['rest','ldap'].include?(option_type_list['type']) || !(option_type_list['serviceUsername'])
|
167
|
+
option_list_columns.delete("Password") if !['rest','ldap'].include?(option_type_list['type']) || !(option_type_list['servicePassword'])
|
162
168
|
source_headers = []
|
163
169
|
if option_type_list['config'] && option_type_list['config']['sourceHeaders']
|
164
170
|
source_headers = option_type_list['config']['sourceHeaders'].collect do |header|
|
@@ -420,14 +426,18 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
420
426
|
{'dependsOnCode' => 'optionTypeList.type:rest', 'fieldName' => 'ignoreSSLErrors', 'fieldLabel' => 'Ignore SSL Errors', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 6},
|
421
427
|
{'dependsOnCode' => 'optionTypeList.type:rest', 'fieldName' => 'realTime', 'fieldLabel' => 'Real Time', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 7},
|
422
428
|
{'dependsOnCode' => 'optionTypeList.type:rest', 'fieldName' => 'sourceMethod', 'fieldLabel' => 'Source Method', 'type' => 'select', 'selectOptions' => [{'name' => 'GET', 'value' => 'GET'}, {'name' => 'POST', 'value' => 'POST'}], 'defaultValue' => 'GET', 'required' => true, 'displayOrder' => 8},
|
429
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|ldap', 'fieldName' => 'credential', 'fieldLabel' => 'Credentials', 'type' => 'select', 'optionSource' => 'credentials', 'description' => 'Credential ID or use "local" to specify username and password', 'displayOrder' => 9, 'defaultValue' => "local", 'required' => true, :for_help_only => true}, # hacky way to render this but not prompt for it
|
430
|
+
{'dependsOnCode' => 'optionTypeList.type:rest', 'fieldName' => 'serviceUsername', 'fieldLabel' => 'Username', 'type' => 'text', 'description' => "A Basic Auth Username for use when type is 'rest'.", 'displayOrder' => 9, "credentialFieldContext" => 'credential', "credentialFieldName" => 'username', "credentialType" => "username-password,oauth2"},
|
431
|
+
{'dependsOnCode' => 'optionTypeList.type:rest', 'fieldName' => 'servicePassword', 'fieldLabel' => 'Password', 'type' => 'password', 'description' => "A Basic Auth Password for use when type is 'rest'.", 'displayOrder' => 10, "credentialFieldContext" => 'credential', "credentialFieldName" => 'password', "credentialType" => "username-password,oauth2"},
|
423
432
|
# sourceHeaders component (is done afterwards manually)
|
424
|
-
{'dependsOnCode' => 'optionTypeList.type:api', 'fieldName' => 'apiType', 'fieldLabel' => 'Option List', 'type' => 'select', 'optionSource' => 'apiOptionLists', 'required' => true, 'description' => 'The code of the api option list to use, eg. clouds, environments, groups, instances, instance-wiki, networks, servicePlans, resourcePools, securityGroups, servers, server-wiki', 'displayOrder' =>
|
425
|
-
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => '
|
426
|
-
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => '
|
427
|
-
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => '
|
428
|
-
{'dependsOnCode' => 'optionTypeList.type:
|
429
|
-
{'dependsOnCode' => 'optionTypeList.type:rest|api|
|
430
|
-
{'dependsOnCode' => 'optionTypeList.type:rest|api', 'fieldName' => '
|
433
|
+
{'dependsOnCode' => 'optionTypeList.type:api', 'fieldName' => 'apiType', 'fieldLabel' => 'Option List', 'type' => 'select', 'optionSource' => 'apiOptionLists', 'required' => true, 'description' => 'The code of the api option list to use, eg. clouds, environments, groups, instances, instance-wiki, networks, servicePlans, resourcePools, securityGroups, servers, server-wiki', 'displayOrder' => 10},
|
434
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|ldap', 'fieldName' => 'credential', 'fieldLabel' => 'Credentials', 'type' => 'select', 'optionSource' => 'credentials', 'description' => 'Credential ID or use "local" to specify username and password', 'displayOrder' => 9, 'defaultValue' => "local", 'required' => true, :for_help_only => true}, # hacky way to render this but not prompt for it
|
435
|
+
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => 'serviceUsername', 'fieldLabel' => 'Username', 'type' => 'text', 'description' => "An LDAP Username for use when type is 'ldap'.", 'displayOrder' => 11, "credentialFieldContext" => 'credential', "credentialFieldName" => 'username', "credentialType" => "username-password"},
|
436
|
+
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => 'servicePassword', 'fieldLabel' => 'Password', 'type' => 'password', 'description' => "An LDAP Password for use when type is 'ldap'.", 'displayOrder' => 12, "credentialFieldContext" => 'credential', "credentialFieldName" => 'password', "credentialType" => "username-password"},
|
437
|
+
{'dependsOnCode' => 'optionTypeList.type:ldap', 'fieldName' => 'ldapQuery', 'fieldLabel' => 'LDAP Query', 'type' => 'text', 'description' => "LDAP Queries are standard LDAP formatted queries where different objects can be searched. Dependent parameters can be loaded into the query using the <%=phrase%> syntax.", 'displayOrder' => 13},
|
438
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|api|manual', 'fieldName' => 'initialDataset', 'fieldLabel' => 'Initial Dataset', 'type' => 'code-editor', 'description' => "Create an initial json dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'. However, if there is a translation script, that will also be passed through.", 'displayOrder' => 14, 'dataType' => 'string'},
|
439
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|api|ldap', 'fieldName' => 'translationScript', 'fieldLabel' => 'Translation Script', 'type' => 'code-editor', 'description' => "Create a js script to translate the result data object into an Array containing objects with properties name, and value. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 15, 'dataType' => 'string'},
|
440
|
+
{'dependsOnCode' => 'optionTypeList.type:rest|api', 'fieldName' => 'requestScript', 'fieldLabel' => 'Request Script', 'type' => 'code-editor', 'description' => "Create a js script to prepare the request. Return a data object as the body for a post, and return an array containing properties name and value for a get. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 16, 'dataType' => 'string'},
|
431
441
|
]
|
432
442
|
|
433
443
|
end
|
@@ -36,20 +36,18 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
36
36
|
options[:phrase] = args.join(" ")
|
37
37
|
end
|
38
38
|
connect(options)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
|
40
|
+
params = {}
|
41
|
+
params.merge!(parse_list_options(options))
|
42
|
+
@option_types_interface.setopts(options)
|
43
|
+
if options[:dry_run]
|
44
|
+
print_dry_run @option_types_interface.dry.list(params)
|
45
|
+
return
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
render_result = render_with_format(json_response, options, 'optionTypes')
|
51
|
-
return 0 if render_result
|
48
|
+
json_response = @option_types_interface.list(params)
|
52
49
|
|
50
|
+
render_response(json_response, options, "optionTypes") do
|
53
51
|
option_types = json_response['optionTypes']
|
54
52
|
subtitles = []
|
55
53
|
subtitles += parse_list_subtitles(options)
|
@@ -84,10 +82,8 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
84
82
|
print_results_pagination(json_response)
|
85
83
|
end
|
86
84
|
print reset,"\n"
|
87
|
-
rescue RestClient::Exception => e
|
88
|
-
print_rest_exception(e, options)
|
89
|
-
exit 1
|
90
85
|
end
|
86
|
+
return 0, nil
|
91
87
|
end
|
92
88
|
|
93
89
|
def get(args)
|
@@ -110,23 +106,21 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
110
106
|
end
|
111
107
|
|
112
108
|
def _get(id, options)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
return
|
109
|
+
|
110
|
+
@option_types_interface.setopts(options)
|
111
|
+
if options[:dry_run]
|
112
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
113
|
+
print_dry_run @option_types_interface.dry.get(id.to_i)
|
114
|
+
else
|
115
|
+
print_dry_run @option_types_interface.dry.list({name: id})
|
122
116
|
end
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
return 0 if render_result
|
117
|
+
return
|
118
|
+
end
|
119
|
+
option_type = find_option_type_by_name_or_id(id)
|
120
|
+
return 1 if option_type.nil?
|
121
|
+
json_response = {'optionType' => option_type}
|
129
122
|
|
123
|
+
render_response(json_response, options, "optionType") do
|
130
124
|
print_h1 "Option Type Details"
|
131
125
|
print cyan
|
132
126
|
columns = {
|
@@ -144,15 +138,13 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
144
138
|
"Default Value" => 'defaultValue',
|
145
139
|
"Required" => lambda {|it| format_boolean(it['required']) },
|
146
140
|
"Export As Tag" => lambda {|it| it['exportMeta'].nil? ? '' : format_boolean(it['exportMeta']) },
|
141
|
+
"Verify Pattern" => 'verifyPattern',
|
147
142
|
}
|
148
143
|
columns.delete("Option List") if option_type['optionList'].nil?
|
149
144
|
print as_description_list(option_type, columns, options)
|
150
145
|
print reset,"\n"
|
151
|
-
return 0
|
152
|
-
rescue RestClient::Exception => e
|
153
|
-
print_rest_exception(e, options)
|
154
|
-
return 1
|
155
146
|
end
|
147
|
+
return 0, nil
|
156
148
|
end
|
157
149
|
|
158
150
|
def add(args)
|
@@ -165,37 +157,38 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
165
157
|
end
|
166
158
|
optparse.parse!(args)
|
167
159
|
connect(options)
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
return
|
160
|
+
verify_args!(args:args, optparse:optparse, max:1)
|
161
|
+
if args[0]
|
162
|
+
options[:options]['name'] = args[0]
|
163
|
+
end
|
164
|
+
|
165
|
+
payload = nil
|
166
|
+
if options[:payload]
|
167
|
+
payload = options[:payload]
|
168
|
+
payload.deep_merge!({'optionType' => parse_passed_options(options)})
|
169
|
+
else
|
170
|
+
payload = {}
|
171
|
+
payload.deep_merge!({'optionType' => parse_passed_options(options)})
|
172
|
+
option_type_payload = Morpheus::Cli::OptionTypes.prompt(new_option_type_option_types, options[:options], @api_client)
|
173
|
+
# tweak payload for API
|
174
|
+
option_type_payload['optionList'] = {'id' => option_type_payload['optionList'].to_i} if option_type_payload['optionList'].is_a?(String) || option_type_payload['optionList'].is_a?(Numeric)
|
175
|
+
option_type_payload['required'] = ['on','true'].include?(option_type_payload['required'].to_s) if option_type_payload.key?('required')
|
176
|
+
option_type_payload['exportMeta'] = ['on','true'].include?(option_type_payload['exportMeta'].to_s) if option_type_payload.key?('exportMeta')
|
177
|
+
payload.deep_merge!({'optionType' => option_type_payload})
|
178
|
+
end
|
179
|
+
@option_types_interface.setopts(options)
|
180
|
+
if options[:dry_run]
|
181
|
+
print_dry_run @option_types_interface.dry.create(payload)
|
182
|
+
return
|
183
|
+
end
|
184
|
+
json_response = @option_types_interface.create(payload)
|
185
|
+
|
186
|
+
render_response(json_response, options, "optionType") do
|
191
187
|
option_type = json_response['optionType']
|
192
188
|
print_green_success "Added Option Type #{option_type['name']}"
|
193
|
-
|
194
|
-
get([option_type['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
|
195
|
-
rescue RestClient::Exception => e
|
196
|
-
print_rest_exception(e, options)
|
197
|
-
exit 1
|
189
|
+
_get(option_type['id'], options)
|
198
190
|
end
|
191
|
+
return 0, nil
|
199
192
|
end
|
200
193
|
|
201
194
|
def update(args)
|
@@ -302,6 +295,7 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
302
295
|
{'fieldName' => 'defaultValue', 'fieldLabel' => 'Default Value', 'type' => 'text', 'displayOrder' => 9},
|
303
296
|
{'fieldName' => 'required', 'fieldLabel' => 'Required', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 10},
|
304
297
|
{'fieldName' => 'exportMeta', 'fieldLabel' => 'Export As Tag', 'type' => 'checkbox', 'defaultValue' => false, 'description' => 'Export as Tag.', 'displayOrder' => 11},
|
298
|
+
{'fieldName' => 'verifyPattern', 'fieldLabel' => 'Verify Pattern', 'type' => 'text', 'dependsOnCode' => 'optionType.type:text', 'description' => 'A regexp string that validates the input, use (?i) to make the matcher case insensitive', 'displayOrder' => 12},
|
305
299
|
]
|
306
300
|
end
|
307
301
|
|
@@ -4,6 +4,7 @@ class Morpheus::Cli::LoadBalancers
|
|
4
4
|
include Morpheus::Cli::CliCommand
|
5
5
|
include Morpheus::Cli::RestCommand
|
6
6
|
include Morpheus::Cli::LoadBalancersHelper
|
7
|
+
include Morpheus::Cli::ProvisioningHelper
|
7
8
|
|
8
9
|
set_command_description "View and manage load balancers."
|
9
10
|
set_command_name :'load-balancers'
|
@@ -17,10 +18,12 @@ class Morpheus::Cli::LoadBalancers
|
|
17
18
|
register_interfaces :load_balancers, :load_balancer_types
|
18
19
|
set_rest_has_type true
|
19
20
|
# set_rest_type :load_balancer_types
|
21
|
+
set_rest_perms_config({enabled:true, excludes:['plans', 'visibility']})
|
20
22
|
|
21
23
|
def render_response_for_get(json_response, options)
|
22
24
|
render_response(json_response, options, rest_object_key) do
|
23
25
|
record = json_response[rest_object_key]
|
26
|
+
options[:exclude_username] = record['username'].nil?
|
24
27
|
print_h1 rest_label, [], options
|
25
28
|
print cyan
|
26
29
|
print_description_list(rest_column_definitions(options), record, options)
|
@@ -94,19 +97,7 @@ EOT
|
|
94
97
|
|
95
98
|
# filtering for NSX-T only
|
96
99
|
def rest_list_types()
|
97
|
-
rest_type_interface.list({max:10000, creatable:true})[rest_type_list_key].reject {|it| it['code'] == 'nsx-t'}
|
98
|
-
end
|
99
|
-
|
100
|
-
def load_balancer_type_list_to_options(type_list)
|
101
|
-
type_list.reject {|it| it['code'] != 'nsx-t'}.collect {|it| {'name' => it['name'], 'value' => it['code']} }
|
102
|
-
end
|
103
|
-
|
104
|
-
def add_load_balancer_footer_addn
|
105
|
-
"#{bold}Available for NSX-T load balancers only#{reset}"
|
106
|
-
end
|
107
|
-
|
108
|
-
def update_load_balancer_footer_addn
|
109
|
-
"#{bold}Available for NSX-T load balancers only#{reset}"
|
100
|
+
rest_type_interface.list({max:10000, creatable:true})[rest_type_list_key] # .reject {|it| it['code'] == 'nsx-t'}
|
110
101
|
end
|
111
102
|
|
112
103
|
def load_balancer_list_column_definitions(options)
|
@@ -120,7 +111,7 @@ EOT
|
|
120
111
|
end
|
121
112
|
|
122
113
|
def load_balancer_column_definitions(options)
|
123
|
-
{
|
114
|
+
columns = {
|
124
115
|
"ID" => 'id',
|
125
116
|
"Name" => 'name',
|
126
117
|
"Description" => 'description',
|
@@ -130,13 +121,14 @@ EOT
|
|
130
121
|
"IP" => 'ip',
|
131
122
|
"Host" => 'host',
|
132
123
|
"Port" => 'port',
|
133
|
-
"
|
134
|
-
|
135
|
-
|
136
|
-
|
124
|
+
"Price" => lambda {|it| it['price'].nil? ? 'No pricing configured' : "#{format_money(it['price']['price'], it['price']['currency'])} / #{it['price']['unit'].capitalize}"},
|
125
|
+
"Provider ID" => 'externalId'
|
126
|
+
}
|
127
|
+
columns.merge!({"Username" => 'username'}) if !options[:exclude_username]
|
128
|
+
columns.merge({
|
137
129
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
138
130
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
139
|
-
}
|
131
|
+
})
|
140
132
|
end
|
141
133
|
|
142
134
|
# overridden to work with name or code
|
@@ -209,10 +209,13 @@ class Morpheus::Cli::NetworkPoolServersCommand
|
|
209
209
|
print_red_alert "Pool Server Type not found by id '#{options['type']}'"
|
210
210
|
return 1
|
211
211
|
end
|
212
|
-
payload['networkPoolServer']['type'] = {'id' => network_type_id.to_i }
|
213
212
|
|
214
|
-
|
213
|
+
payload['networkPoolServer']['type'] = {'id' => network_type_id.to_i }
|
215
214
|
|
215
|
+
# prompt options
|
216
|
+
network_pool_server_type = @network_pool_servers_interface.get_type(network_type_id.to_i)['networkPoolServerType']
|
217
|
+
option_result = Morpheus::Cli::OptionTypes.prompt(network_pool_server_type['optionTypes'], options[:options].deep_merge({:context_map => {'networkPoolServer' => ''}}), @api_client, {}, options[:no_prompt], true)
|
218
|
+
payload['networkPoolServer'].deep_merge!(option_result)
|
216
219
|
end
|
217
220
|
|
218
221
|
@network_pool_servers_interface.setopts(options)
|
@@ -238,11 +238,7 @@ class Morpheus::Cli::PricesCommand
|
|
238
238
|
end
|
239
239
|
end
|
240
240
|
opts.on("--currency [CURRENCY]", String, "Price currency") do |val|
|
241
|
-
|
242
|
-
params['currency'] = val.upcase
|
243
|
-
else
|
244
|
-
raise_command_error "Unsupported currency '#{val}'. Available currencies: #{avail_currencies.join(', ')}"
|
245
|
-
end
|
241
|
+
options[:currency] = val
|
246
242
|
end
|
247
243
|
opts.on("--cost [AMOUNT]", Float, "Price cost") do |val|
|
248
244
|
params['cost'] = val
|
@@ -269,6 +265,15 @@ class Morpheus::Cli::PricesCommand
|
|
269
265
|
return 1
|
270
266
|
end
|
271
267
|
|
268
|
+
if options[:currency]
|
269
|
+
if avail_currencies.include?(options[:currency].upcase)
|
270
|
+
params['currency'] = options[:currency].upcase
|
271
|
+
else
|
272
|
+
raise_command_error "Unsupported currency '#{options[:currency]}'. Available currencies: #{avail_currencies.join(', ')}"
|
273
|
+
return 1
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
272
277
|
begin
|
273
278
|
payload = parse_payload(options)
|
274
279
|
|
@@ -402,11 +407,7 @@ class Morpheus::Cli::PricesCommand
|
|
402
407
|
end
|
403
408
|
end
|
404
409
|
opts.on("--currency [CURRENCY]", String, "Price currency") do |val|
|
405
|
-
|
406
|
-
params['currency'] = val.upcase
|
407
|
-
else
|
408
|
-
raise_command_error "Unsupported currency '#{val}'. Available currencies: #{avail_currencies.join(', ')}"
|
409
|
-
end
|
410
|
+
options[:currency] = val
|
410
411
|
end
|
411
412
|
opts.on("--cost [AMOUNT]", Float, "Price cost") do |val|
|
412
413
|
params['cost'] = val
|
@@ -431,11 +432,21 @@ class Morpheus::Cli::PricesCommand
|
|
431
432
|
end
|
432
433
|
optparse.parse!(args)
|
433
434
|
connect(options)
|
435
|
+
|
434
436
|
if args.count != 1
|
435
437
|
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
|
436
438
|
return 1
|
437
439
|
end
|
438
440
|
|
441
|
+
if options[:currency]
|
442
|
+
if avail_currencies.include?(options[:currency].upcase)
|
443
|
+
params['currency'] = options[:currency].upcase
|
444
|
+
else
|
445
|
+
raise_command_error "Unsupported currency '#{options[:currency]}'. Available currencies: #{avail_currencies.join(', ')}"
|
446
|
+
return 1
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
439
450
|
begin
|
440
451
|
price = find_price(args[0])
|
441
452
|
|
@@ -608,7 +619,10 @@ class Morpheus::Cli::PricesCommand
|
|
608
619
|
end
|
609
620
|
|
610
621
|
def avail_currencies
|
611
|
-
|
622
|
+
if @avail_currencies.nil?
|
623
|
+
@avail_currencies = @prices_interface.list_currencies()['currencies'].collect {|it| it['value']}
|
624
|
+
end
|
625
|
+
@avail_currencies
|
612
626
|
end
|
613
627
|
|
614
628
|
def prompt_for_price_type(params, options, price={})
|