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.
@@ -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
- if option_type["config"] && ["true","on"].include?(option_type["config"]["multiSelect"].to_s)
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'] == 'number'
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
- value = load_source_options(option_type['optionSource'], option_type['optionSourceType'], api_client, api_params || {})
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
- display_select_options(option_type, matched_options)
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
- display_select_options(option_type, matched_options)
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
- display_select_options(option_type, matched_options)
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
- display_select_options(option_type, select_options)
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
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "6.3.0"
4
+ VERSION = "6.3.2"
5
5
  end
6
6
  end
@@ -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.0
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-10-30 00:00:00.000000000 Z
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