morpheus-cli 6.3.0 → 6.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/README.md +3 -6
- data/lib/morpheus/api/api_client.rb +8 -0
- data/lib/morpheus/api/library_cluster_packages_interface.rb +60 -0
- data/lib/morpheus/api/option_type_forms_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +3 -1
- data/lib/morpheus/cli/cli_registry.rb +2 -4
- data/lib/morpheus/cli/commands/backups_command.rb +1 -1
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +54 -12
- data/lib/morpheus/cli/commands/certificates_command.rb +1 -1
- data/lib/morpheus/cli/commands/cloud_folders_command.rb +18 -1
- data/lib/morpheus/cli/commands/library_cluster_packages_command.rb +552 -0
- data/lib/morpheus/cli/commands/library_forms_command.rb +625 -0
- data/lib/morpheus/cli/commands/network_servers_command.rb +19 -9
- data/lib/morpheus/cli/commands/self_service_command.rb +17 -0
- data/lib/morpheus/cli/commands/service_catalog_command.rb +72 -31
- data/lib/morpheus/cli/commands/virtual_images.rb +1 -1
- data/lib/morpheus/cli/error_handler.rb +18 -3
- data/lib/morpheus/cli/mixins/print_helper.rb +20 -6
- data/lib/morpheus/cli/mixins/prompt_helper.rb +132 -11
- data/lib/morpheus/cli/option_types.rb +182 -11
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/routes.rb +9 -0
- metadata +7 -2
@@ -76,7 +76,8 @@ module Morpheus
|
|
76
76
|
option_type['type'] = 'multiText'
|
77
77
|
end
|
78
78
|
# swap types to multiSelect when flag is set..
|
79
|
-
|
79
|
+
config_multi_select = option_type["config"] && ["true","on"].include?(option_type["config"]["multiSelect"].to_s)
|
80
|
+
if config_multi_select
|
80
81
|
if option_type["type"] == "typeahead"
|
81
82
|
option_type["type"] = "multiTypeahead"
|
82
83
|
elsif option_type["type"] == "select"
|
@@ -175,10 +176,9 @@ module Morpheus
|
|
175
176
|
}
|
176
177
|
end
|
177
178
|
|
179
|
+
depends_on_field_key = depends_on_code
|
178
180
|
if depends_on_option_type
|
179
181
|
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']}"
|
180
|
-
else
|
181
|
-
depends_on_field_key = depends_on_code
|
182
182
|
end
|
183
183
|
|
184
184
|
field_value = get_object_value(results, depends_on_field_key) ||
|
@@ -198,6 +198,53 @@ module Morpheus
|
|
198
198
|
next if !found_dep_value
|
199
199
|
end
|
200
200
|
|
201
|
+
# respect optionType.requireOnCode
|
202
|
+
require_option_check_value = option_type['requireOnCode']
|
203
|
+
if !require_option_check_value.to_s.empty?
|
204
|
+
# require_on_code = check_require_on_code(option_type, option_types, options)
|
205
|
+
|
206
|
+
match_type = 'any'
|
207
|
+
|
208
|
+
if require_option_check_value.include?('::')
|
209
|
+
match_type = 'all' if require_option_check_value.start_with?('matchAll')
|
210
|
+
require_option_check_value = require_option_check_value[require_option_check_value.index('::') + 2..-1]
|
211
|
+
end
|
212
|
+
|
213
|
+
found_dep_value = match_type == 'all' ? true : false
|
214
|
+
require_option_check_value.sub(',', ' ').split(' ').each do |value|
|
215
|
+
parts = value.split(':')
|
216
|
+
depends_on_code = parts[0]
|
217
|
+
depends_on_value = parts.count > 1 ? parts[1].to_s.strip : nil
|
218
|
+
depends_on_option_type = option_types.find {|it| it["code"] == depends_on_code }
|
219
|
+
if !depends_on_option_type
|
220
|
+
depends_on_option_type = option_types.find {|it|
|
221
|
+
(it['fieldContext'] ? "#{it['fieldContext']}.#{it['fieldName']}" : it['fieldName']) == depends_on_code
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
225
|
+
depends_on_field_key = depends_on_code
|
226
|
+
if depends_on_option_type
|
227
|
+
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']}"
|
228
|
+
end
|
229
|
+
|
230
|
+
field_value = get_object_value(results, depends_on_field_key) ||
|
231
|
+
get_object_value(options, depends_on_field_key) ||
|
232
|
+
get_object_value(api_params, depends_on_field_key)
|
233
|
+
|
234
|
+
if field_value.nil? && !options['_object_key'].nil?
|
235
|
+
field_value = get_object_value({options['_object_key'] => results}, depends_on_field_key)
|
236
|
+
end
|
237
|
+
|
238
|
+
if !field_value.nil? && (depends_on_value.nil? || depends_on_value.empty? || field_value.to_s.match?(depends_on_value))
|
239
|
+
found_dep_value = true if match_type != 'all'
|
240
|
+
else
|
241
|
+
found_dep_value = false if match_type == 'all'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
option_type = option_type.merge({'required' => found_dep_value})
|
246
|
+
end
|
247
|
+
|
201
248
|
# build parameters for option source api request
|
202
249
|
option_params = (option_type['noParams'] ? {} : (api_params || {}).deep_merge(results))
|
203
250
|
option_params.merge!(option_type['optionParams']) if option_type['optionParams']
|
@@ -217,6 +264,12 @@ module Morpheus
|
|
217
264
|
context_map = context_map[ns.to_s]
|
218
265
|
end
|
219
266
|
|
267
|
+
# CLI only options that need some do some inflection to decide how to prompt
|
268
|
+
# defaultValue is it right now..
|
269
|
+
if option_type[:preprocesser].is_a?(Proc)
|
270
|
+
option_type[:preprocesser].call(option_type, api_client, option_params)
|
271
|
+
end
|
272
|
+
|
220
273
|
# credential type
|
221
274
|
handle_credential_type = -> {
|
222
275
|
credential_type = select_prompt(option_type.merge({'defaultValue' => value}), api_client, option_params.merge({'credentialTypes' => option_type['config']['credentialTypes']}), !value.nil?, nil, paging_enabled, ignore_empty, options[:edit_mode])
|
@@ -310,6 +363,23 @@ module Morpheus
|
|
310
363
|
value = typeahead_prompt(option_type, api_client, option_params, true)
|
311
364
|
value_found = !!value
|
312
365
|
end
|
366
|
+
if option_type['type'] == 'hidden'
|
367
|
+
if option_type['optionSource'].nil?
|
368
|
+
value = option_type['defaultValue']
|
369
|
+
else
|
370
|
+
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, option_params)
|
371
|
+
config_multi_select = option_type["config"] && ["true","on"].include?(option_type["config"]["multiSelect"].to_s)
|
372
|
+
if config_multi_select
|
373
|
+
value = select_options.collect { |it| it['value'] }
|
374
|
+
elsif select_options.is_a?(Array)
|
375
|
+
value = select_options[0] ? select_options[0]['value'] : nil
|
376
|
+
elsif select_options.is_a?(Hash)
|
377
|
+
value = select_options['value']
|
378
|
+
else
|
379
|
+
value = select_options
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
313
383
|
if !value_found && !ignore_empty
|
314
384
|
if option_type['required']
|
315
385
|
print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
|
@@ -326,7 +396,9 @@ module Morpheus
|
|
326
396
|
end
|
327
397
|
|
328
398
|
if !value_found
|
329
|
-
if option_type['type'] == '
|
399
|
+
if option_type['type'] == 'text'
|
400
|
+
value = generic_prompt(option_type)
|
401
|
+
elsif option_type['type'] == 'number'
|
330
402
|
value = number_prompt(option_type)
|
331
403
|
elsif option_type['type'] == 'password'
|
332
404
|
value = password_prompt(option_type)
|
@@ -376,12 +448,24 @@ module Morpheus
|
|
376
448
|
if option_type['optionSource'].nil?
|
377
449
|
value = option_type['defaultValue']
|
378
450
|
else
|
379
|
-
|
451
|
+
select_options = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, option_params)
|
452
|
+
config_multi_select = option_type["config"] && ["true","on"].include?(option_type["config"]["multiSelect"].to_s)
|
453
|
+
if config_multi_select
|
454
|
+
value = select_options.collect { |it| it['value'] }
|
455
|
+
elsif select_options.is_a?(Array)
|
456
|
+
value = select_options[0] ? select_options[0]['value'] : nil
|
457
|
+
elsif select_options.is_a?(Hash)
|
458
|
+
value = select_options['value']
|
459
|
+
else
|
460
|
+
value = select_options
|
461
|
+
end
|
380
462
|
end
|
381
463
|
elsif option_type['type'] == 'file'
|
382
464
|
value = file_prompt(option_type)
|
383
|
-
elsif option_type['type'] == 'file-content'
|
465
|
+
elsif option_type['type'] == 'file-content' || option_type['type'] == 'fileContent'
|
384
466
|
value = file_content_prompt(option_type, options, api_client, {})
|
467
|
+
elsif option_type['type'] == 'logoSelector'
|
468
|
+
value = file_prompt(option_type)
|
385
469
|
elsif option_type['type'] == 'multiText'
|
386
470
|
value = multitext_prompt(option_type)
|
387
471
|
elsif option_type['type'] == 'azureMarketplace'
|
@@ -396,7 +480,6 @@ module Morpheus
|
|
396
480
|
value = generic_prompt(option_type)
|
397
481
|
end
|
398
482
|
end
|
399
|
-
|
400
483
|
# --labels x,y,z uses processValue proc to convert strings to an array
|
401
484
|
if option_type['processValue'].is_a?(Proc)
|
402
485
|
value = option_type['processValue'].call(value)
|
@@ -409,6 +492,61 @@ module Morpheus
|
|
409
492
|
if value && value.is_a?(String)
|
410
493
|
value = value.split(",").collect {|it| it.strip }
|
411
494
|
end
|
495
|
+
# todo: Handle these types added with the new form fields:
|
496
|
+
#
|
497
|
+
# byteSize
|
498
|
+
# code-editor
|
499
|
+
# fileContent
|
500
|
+
# logoSelector
|
501
|
+
# keyValue
|
502
|
+
# textArray
|
503
|
+
# typeahead
|
504
|
+
# group
|
505
|
+
# cloud
|
506
|
+
# environment
|
507
|
+
# diskManager
|
508
|
+
# layout
|
509
|
+
# networkManager
|
510
|
+
# plan
|
511
|
+
# resourcePool
|
512
|
+
# secGroup
|
513
|
+
# tag
|
514
|
+
# httpHeader
|
515
|
+
elsif option_type['type'] == 'byteSize'
|
516
|
+
if value.to_s.empty?
|
517
|
+
value = 0 # nil
|
518
|
+
elsif value.is_a?(String)
|
519
|
+
if value.to_s.upcase.include?("G")
|
520
|
+
value = value.to_i * 1024 * 1024 * 1024
|
521
|
+
elsif value.to_s.upcase.include?("M")
|
522
|
+
value = value * 1024 * 1024
|
523
|
+
else
|
524
|
+
# assume bytes by default..
|
525
|
+
value = value.to_i
|
526
|
+
end
|
527
|
+
end
|
528
|
+
elsif option_type['type'] == 'keyValue'
|
529
|
+
value = try_as_json(value)
|
530
|
+
if value.is_a?(String)
|
531
|
+
map = {}
|
532
|
+
value.split(",").each do |it|
|
533
|
+
pair = it.split("=");
|
534
|
+
map[pair[0].to_s.strip] = pair[1..-1].join("=").strip
|
535
|
+
end
|
536
|
+
value = map
|
537
|
+
end
|
538
|
+
elsif option_type['type'] == 'textArray'
|
539
|
+
value = try_as_json(value)
|
540
|
+
if value.is_a?(String)
|
541
|
+
value = value.split(",").collect {|it| it.to_s.strip }
|
542
|
+
end
|
543
|
+
else
|
544
|
+
# default translation
|
545
|
+
# for non text inputs, try to parse value as JSON
|
546
|
+
# if option_type['type'] == 'group' || option_type['type'] == 'cloud' etc..
|
547
|
+
if value.is_a?(String) && option_type['type'] != 'text'
|
548
|
+
value = try_as_json(value)
|
549
|
+
end
|
412
550
|
end
|
413
551
|
context_map[field_name] = value if !(value.nil? || (value.is_a?(Hash) && value.empty?))
|
414
552
|
parent_context_map.reject! {|k,v| k == parent_ns && (v.nil? || (v.is_a?(Hash) && v.empty?))}
|
@@ -526,7 +664,12 @@ module Morpheus
|
|
526
664
|
if matched_options.size > 1
|
527
665
|
print Term::ANSIColor.red, "\nInvalid Option #{option_type['fieldLabel']}: [#{use_value}]\n\n", Term::ANSIColor.reset
|
528
666
|
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
|
529
|
-
|
667
|
+
if matched_options && matched_options.size > 10
|
668
|
+
display_select_options(option_type, matched_options.first(10))
|
669
|
+
puts " (#{matched_options.size-10} more)"
|
670
|
+
else
|
671
|
+
display_select_options(option_type, matched_options)
|
672
|
+
end
|
530
673
|
print "The value '#{input}' matched #{matched_options.size()} options.\n"
|
531
674
|
# print "Perhaps you meant one of these? #{ored_list(matched_options.collect {|i|i[value_field]}, 3)}\n"
|
532
675
|
print "Try using value instead of name.\n"
|
@@ -595,7 +738,12 @@ module Morpheus
|
|
595
738
|
if matched_options.size > 1
|
596
739
|
print Term::ANSIColor.red, "\nInvalid Option #{option_type['fieldLabel']}: [#{default_value}]\n\n", Term::ANSIColor.reset
|
597
740
|
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
|
598
|
-
|
741
|
+
if matched_options && matched_options.size > 10
|
742
|
+
display_select_options(option_type, matched_options.first(10))
|
743
|
+
puts " (#{matched_options.size-10} more)"
|
744
|
+
else
|
745
|
+
display_select_options(option_type, matched_options)
|
746
|
+
end
|
599
747
|
print "The value '#{default_value}' matched #{matched_options.size()} options.\n"
|
600
748
|
# print "Perhaps you meant one of these? #{ored_list(matched_options.collect {|i|i[value_field]}, 3)}\n"
|
601
749
|
print "Try using value instead of name.\n"
|
@@ -679,7 +827,12 @@ module Morpheus
|
|
679
827
|
if matched_options.size > 1
|
680
828
|
print Term::ANSIColor.red, "\nInvalid Option #{option_type['fieldLabel']}: [#{input}]\n\n", Term::ANSIColor.reset
|
681
829
|
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
|
682
|
-
|
830
|
+
if matched_options && matched_options.size > 10
|
831
|
+
display_select_options(option_type, matched_options.first(10))
|
832
|
+
puts " (#{matched_options.size-10} more)"
|
833
|
+
else
|
834
|
+
display_select_options(option_type, matched_options)
|
835
|
+
end
|
683
836
|
print "The value '#{input}' matched #{matched_options.size()} options.\n"
|
684
837
|
# print "Perhaps you meant one of these? #{ored_list(matched_options.collect {|i|i[value_field]}, 3)}\n"
|
685
838
|
print "Try using value instead of name.\n"
|
@@ -867,7 +1020,12 @@ module Morpheus
|
|
867
1020
|
exit 1
|
868
1021
|
else
|
869
1022
|
#help_prompt(option_type)
|
870
|
-
|
1023
|
+
if select_options && select_options.size > 10
|
1024
|
+
display_select_options(option_type, select_options.first(10))
|
1025
|
+
puts " (#{select_options.size-10} more)"
|
1026
|
+
else
|
1027
|
+
display_select_options(option_type, select_options)
|
1028
|
+
end
|
871
1029
|
print "\n"
|
872
1030
|
if select_options.empty?
|
873
1031
|
print "The value '#{input}' matched 0 options.\n"
|
@@ -1381,6 +1539,19 @@ module Morpheus
|
|
1381
1539
|
end
|
1382
1540
|
rtn
|
1383
1541
|
end
|
1542
|
+
|
1543
|
+
def self.try_as_json(val)
|
1544
|
+
if val.is_a?(String)
|
1545
|
+
if (val.to_s[0] == '{' && val.to_s[-1] == '}') || (val.to_s[0] == '[' && val.to_s[-1] == ']')
|
1546
|
+
begin
|
1547
|
+
val = JSON.parse(val)
|
1548
|
+
rescue
|
1549
|
+
Morpheus::Logging::DarkPrinter.puts "Failed to parse option value '#{val}' as JSON" if Morpheus::Logging.debug?
|
1550
|
+
end
|
1551
|
+
end
|
1552
|
+
end
|
1553
|
+
return val
|
1554
|
+
end
|
1384
1555
|
end
|
1385
1556
|
end
|
1386
1557
|
end
|
data/lib/morpheus/cli/version.rb
CHANGED
data/lib/morpheus/routes.rb
CHANGED
@@ -50,9 +50,12 @@ module Morpheus::Routes
|
|
50
50
|
"#!app-templates", # App Blueprints (blueprints)
|
51
51
|
"#!catalog-items",
|
52
52
|
"#!compute-type-layouts", # Cluster Layouts
|
53
|
+
"#!compute-type-packages", # Cluster Packages
|
53
54
|
],
|
54
55
|
:'virtual-images' => {},
|
55
56
|
options: [
|
57
|
+
"#!forms", # Forms
|
58
|
+
"#!option-types", # Inputs
|
56
59
|
"#!option-type-lists", # Option Lists
|
57
60
|
],
|
58
61
|
templates: [
|
@@ -181,6 +184,12 @@ module Morpheus::Routes
|
|
181
184
|
|
182
185
|
# map well known aliases
|
183
186
|
case(path.dasherize.pluralize)
|
187
|
+
# when "forms"
|
188
|
+
# path = "/library/options/#!forms"
|
189
|
+
when "inputs"
|
190
|
+
path = "/library/options/#!option-types"
|
191
|
+
when "option-lists"
|
192
|
+
path = "/library/options/#!option-type-lists"
|
184
193
|
when "backups"
|
185
194
|
path = id ? "/backups/show" : "/backups/list"
|
186
195
|
when "backup-jobs"
|
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: 6.3.
|
4
|
+
version: 6.3.2
|
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: 2023-
|
14
|
+
date: 2023-12-14 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -251,6 +251,7 @@ files:
|
|
251
251
|
- lib/morpheus/api/jobs_interface.rb
|
252
252
|
- lib/morpheus/api/key_pairs_interface.rb
|
253
253
|
- lib/morpheus/api/library_cluster_layouts_interface.rb
|
254
|
+
- lib/morpheus/api/library_cluster_packages_interface.rb
|
254
255
|
- lib/morpheus/api/library_container_scripts_interface.rb
|
255
256
|
- lib/morpheus/api/library_container_templates_interface.rb
|
256
257
|
- lib/morpheus/api/library_container_types_interface.rb
|
@@ -301,6 +302,7 @@ files:
|
|
301
302
|
- lib/morpheus/api/network_subnets_interface.rb
|
302
303
|
- lib/morpheus/api/network_types_interface.rb
|
303
304
|
- lib/morpheus/api/networks_interface.rb
|
305
|
+
- lib/morpheus/api/option_type_forms_interface.rb
|
304
306
|
- lib/morpheus/api/option_type_lists_interface.rb
|
305
307
|
- lib/morpheus/api/option_types_interface.rb
|
306
308
|
- lib/morpheus/api/options_interface.rb
|
@@ -430,9 +432,11 @@ files:
|
|
430
432
|
- lib/morpheus/cli/commands/jobs_command.rb
|
431
433
|
- lib/morpheus/cli/commands/key_pairs.rb
|
432
434
|
- lib/morpheus/cli/commands/library_cluster_layouts_command.rb
|
435
|
+
- lib/morpheus/cli/commands/library_cluster_packages_command.rb
|
433
436
|
- lib/morpheus/cli/commands/library_container_scripts_command.rb
|
434
437
|
- lib/morpheus/cli/commands/library_container_templates_command.rb
|
435
438
|
- lib/morpheus/cli/commands/library_container_types_command.rb
|
439
|
+
- lib/morpheus/cli/commands/library_forms_command.rb
|
436
440
|
- lib/morpheus/cli/commands/library_instance_types_command.rb
|
437
441
|
- lib/morpheus/cli/commands/library_layouts_command.rb
|
438
442
|
- lib/morpheus/cli/commands/library_option_lists_command.rb
|
@@ -507,6 +511,7 @@ files:
|
|
507
511
|
- lib/morpheus/cli/commands/security_package_types.rb
|
508
512
|
- lib/morpheus/cli/commands/security_packages.rb
|
509
513
|
- lib/morpheus/cli/commands/security_scans.rb
|
514
|
+
- lib/morpheus/cli/commands/self_service_command.rb
|
510
515
|
- lib/morpheus/cli/commands/service_catalog_command.rb
|
511
516
|
- lib/morpheus/cli/commands/service_plans_command.rb
|
512
517
|
- lib/morpheus/cli/commands/set_prompt_command.rb
|