morpheus-cli 6.3.0 → 6.3.2
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/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
|