morpheus-cli 5.5.0 → 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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +4 -0
  4. data/lib/morpheus/api/clusters_interface.rb +12 -0
  5. data/lib/morpheus/api/network_pool_servers_interface.rb +7 -0
  6. data/lib/morpheus/api/scale_thresholds_interface.rb +9 -0
  7. data/lib/morpheus/cli/cli_command.rb +39 -20
  8. data/lib/morpheus/cli/commands/apps.rb +1 -1
  9. data/lib/morpheus/cli/commands/cloud_resource_pools_command.rb +33 -2
  10. data/lib/morpheus/cli/commands/clouds.rb +12 -6
  11. data/lib/morpheus/cli/commands/clusters.rb +66 -5
  12. data/lib/morpheus/cli/commands/hosts.rb +5 -1
  13. data/lib/morpheus/cli/commands/instances.rb +1 -1
  14. data/lib/morpheus/cli/commands/integrations_command.rb +1 -1
  15. data/lib/morpheus/cli/commands/invoices_command.rb +8 -1
  16. data/lib/morpheus/cli/commands/jobs_command.rb +45 -225
  17. data/lib/morpheus/cli/commands/library_container_types_command.rb +52 -3
  18. data/lib/morpheus/cli/commands/library_option_types_command.rb +56 -62
  19. data/lib/morpheus/cli/commands/load_balancers.rb +11 -19
  20. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +5 -2
  21. data/lib/morpheus/cli/commands/roles.rb +475 -70
  22. data/lib/morpheus/cli/commands/scale_thresholds.rb +103 -0
  23. data/lib/morpheus/cli/commands/tasks.rb +19 -12
  24. data/lib/morpheus/cli/commands/user_sources_command.rb +107 -39
  25. data/lib/morpheus/cli/commands/users.rb +10 -10
  26. data/lib/morpheus/cli/commands/view.rb +1 -0
  27. data/lib/morpheus/cli/commands/workflows.rb +21 -14
  28. data/lib/morpheus/cli/error_handler.rb +13 -4
  29. data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
  30. data/lib/morpheus/cli/mixins/execution_request_helper.rb +1 -1
  31. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +3 -3
  32. data/lib/morpheus/cli/mixins/jobs_helper.rb +173 -0
  33. data/lib/morpheus/cli/mixins/print_helper.rb +120 -38
  34. data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -3
  35. data/lib/morpheus/cli/mixins/rest_command.rb +41 -14
  36. data/lib/morpheus/cli/option_types.rb +68 -37
  37. data/lib/morpheus/cli/version.rb +1 -1
  38. data/lib/morpheus/logging.rb +6 -8
  39. metadata +6 -4
@@ -61,13 +61,24 @@ module Morpheus
61
61
  if option_type['fieldName'] == 'sshHosts'
62
62
  option_type['type'] = 'multiText'
63
63
  end
64
+ # swap types to multiSelect when flag is set..
65
+ if option_type["config"] && ["true","on"].include?(option_type["config"]["multiSelect"].to_s)
66
+ if option_type["type"] == "typeahead"
67
+ option_type["type"] = "multiTypeahead"
68
+ elsif option_type["type"] == "select"
69
+ option_type["type"] = "multiSelect"
70
+ elsif option_type["type"] == "textarea"
71
+ option_type["type"] = "multiText"
72
+ end
73
+ end
64
74
  end
65
- credential_option_types = {}
75
+
66
76
  # puts "Options Prompt #{options}"
67
77
  # Sort options by default, group, advanced
68
78
  cur_field_group = 'default'
69
- self.sorted_option_types(option_types).each do |option_type|
70
- next if option_type[:for_help_only] == true # hacky
79
+ prompt_local_credentials = true
80
+ self.sort_option_types(option_types.reject {|it| it[:for_help_only]}).each do |option_type|
81
+ next if option_type['localCredential'] && !prompt_local_credentials
71
82
  context_map = results
72
83
  value = nil
73
84
  value_found = false
@@ -147,28 +158,9 @@ module Morpheus
147
158
  next if !found_dep_value
148
159
  end
149
160
 
150
- # inject a Credentials prompt for optionTypes that have been replaced by credentials
151
- credential_code = option_type['credentialFieldContext']
152
- if !credential_code.to_s.empty?
153
- if !credential_option_types[credential_code]
154
- credential_option_type = {'code' => credential_code, 'fieldName' => credential_code, 'fieldLabel' => 'Credentials', 'type' => 'select', 'optionSource' => 'credentials', 'description' => 'Credential ID or use "local" to specify username and password', 'defaultValue' => "local", 'required' => true}
155
- credential_option_types[credential_code] = credential_option_type
156
- supported_credential_types = [option_type['credentialType'], option_type['credentialTypes']].compact.flatten.join(",").split(",").collect {|it| it.strip }
157
- credential_params = {"new" => false, "credentialTypes" => supported_credential_types}
158
- credential_value = select_prompt(credential_option_type, api_client, credential_params, no_prompt, options[credential_code])
159
- if !credential_value.to_s.empty?
160
- if credential_value == "local"
161
- context_map[credential_code] = {"type" => credential_value}
162
- elsif credential_value.to_s =~ /\A\d{1,}\Z/
163
- context_map[credential_code] = {"id" => credential_value.to_i}
164
- end
165
- end
166
- end
167
- # skip this option unless using local credentials
168
- if context_map[credential_code].is_a?(Hash) && context_map[credential_code]["type"] != "local"
169
- next
170
- end
171
- end
161
+ # build parameters for option source api request
162
+ option_params = (option_type['noParams'] ? {} : (api_params || {}).deep_merge(results))
163
+ option_params.merge!(option_type['optionParams']) if option_type['optionParams']
172
164
 
173
165
  cur_namespace = options
174
166
  parent_context_map = context_map
@@ -184,9 +176,26 @@ module Morpheus
184
176
  context_map = context_map[ns.to_s]
185
177
  end
186
178
 
187
- # build parameters for option source api request
188
- option_params = (option_type['noParams'] ? {} : (api_params || {}).deep_merge(results))
189
- option_params.merge!(option_type['optionParams']) if option_type['optionParams']
179
+ # credential type
180
+ handle_credential_type = -> {
181
+ 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)
182
+ # continue prompting for local creds
183
+ if credential_type == 'local'
184
+ parent_context_map.reject! {|k,v| k == 'credential'}
185
+ next
186
+ end
187
+ # hide local cred options
188
+ prompt_local_credentials = false
189
+ if credential_type.is_a?(Numeric)
190
+ # set as credential.id
191
+ credential = {'id' => credential_type}
192
+ else
193
+ # prompt credential type options
194
+ credential = prompt(api_client.credential_types.list({name:credential_type})['credentialTypes'][0]['optionTypes'], options, api_client, option_params, options[:no_prompt], paging_enabled, ignore_empty)['credential']
195
+ credential['type'] = credential_type
196
+ end
197
+ parent_context_map['credential'] = credential
198
+ }
190
199
 
191
200
  # use the value passed in the options map
192
201
  if cur_namespace.respond_to?('key?') && cur_namespace.key?(field_name)
@@ -219,6 +228,8 @@ module Morpheus
219
228
  select_value_list << typeahead_prompt(option_type.merge({'defaultValue' => v, 'defaultInputValue' => input_value_list[i]}), api_client, option_params, true)
220
229
  end
221
230
  value = select_value_list
231
+ elsif option_type['type'] == 'credential'
232
+ handle_credential_type.call
222
233
  end
223
234
  if options[:always_prompt] != true
224
235
  value_found = true
@@ -277,6 +288,9 @@ module Morpheus
277
288
  value = multiline_prompt(option_type)
278
289
  elsif option_type['type'] == 'code-editor'
279
290
  value = multiline_prompt(option_type)
291
+ elsif option_type['type'] == 'credential'
292
+ print "\nCREDENTIALS\n#{"=" * ("CREDENTIALS".length)}\n\n"
293
+ handle_credential_type.call
280
294
  elsif ['select', 'multiSelect'].include?(option_type['type'])
281
295
  # so, the /api/options/source is may need ALL the previously
282
296
  # selected values that are being accumulated in options
@@ -287,7 +301,8 @@ module Morpheus
287
301
  value = select_prompt(option_type, api_client, option_params, options[:no_prompt], nil, paging_enabled, ignore_empty)
288
302
  if value && option_type['type'] == 'multiSelect'
289
303
  value = [value]
290
- while self.confirm("Add another #{option_type['fieldLabel']}?", {:default => false}) do
304
+ recommended_count = (option_type['config'] || {})['recommendedCount'] || 0
305
+ while self.confirm("Add another #{option_type['fieldLabel']}?", {:default => recommended_count > value.count}) do
291
306
  if addn_value = select_prompt(option_type, api_client, option_params, options[:no_prompt], nil, paging_enabled, ignore_empty)
292
307
  value << addn_value
293
308
  else
@@ -391,7 +406,6 @@ module Morpheus
391
406
  return value
392
407
  end
393
408
 
394
-
395
409
  def self.set_last_select(obj)
396
410
  Thread.current[:_last_select] = obj
397
411
  end
@@ -766,15 +780,18 @@ module Morpheus
766
780
  help_prompt(option_type)
767
781
  next
768
782
  end
769
- if input.downcase == 'yes'
783
+ if input.downcase == 'yes' || input.downcase == 'y' || input.downcase == 'on'
770
784
  value_found = true
771
785
  value = 'on'
772
- elsif input.downcase == 'no'
786
+ elsif input.downcase == 'no' || input.downcase == 'n' || input.downcase == 'off'
773
787
  value_found = true
774
788
  value = 'off'
775
789
  elsif input == '' && has_default
776
790
  value_found = true
777
791
  value = default_yes ? 'on' : 'off'
792
+ elsif input != ""
793
+ puts "Invalid Option... Please try again."
794
+ next
778
795
  end
779
796
  if value.nil? && option_type['required']
780
797
  puts "Invalid Option... Please try again."
@@ -820,6 +837,20 @@ module Morpheus
820
837
  elsif !value.nil? || option_type['required'] != true
821
838
  value_found = true
822
839
  end
840
+ # attempt to parse Java regex and validate it
841
+ if option_type["verifyPattern"].to_s != "" && !(value.to_s == "" && option_type['required'])
842
+ begin
843
+ # pattern is matched on the entire string
844
+ verify_pattern = Regexp.compile("^" + option_type["verifyPattern"] + "$")
845
+ if !verify_pattern.match(value)
846
+ value_found = false
847
+ puts "Invalid Option. Value must match the pattern '#{option_type['verifyPattern']}'. Please try again."
848
+ next
849
+ end
850
+ rescue => regex_ex
851
+ puts "Failed to parse verifyPattern '#{option_type['verifyPattern']}' as a regular expression"
852
+ end
853
+ end
823
854
  end
824
855
  return value
825
856
  end
@@ -1083,10 +1114,10 @@ module Morpheus
1083
1114
  return out
1084
1115
  end
1085
1116
 
1086
- def self.sorted_option_types(option_types)
1087
- option_types.reject {|it| (it['fieldGroup'] || 'default') != 'default'}.sort {|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i} +
1088
- option_types.reject {|it| ['default', 'advanced'].include?(it['fieldGroup'] || 'default')}.sort{|a,b| a['displayOrder'] <=> b['displayOrder']}.group_by{|it| it['fieldGroup']}.values.collect { |it| it.sort{|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i}}.flatten +
1089
- option_types.reject {|it| it['fieldGroup'] != 'advanced'}.sort {|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i}
1117
+ def self.sort_option_types(option_types)
1118
+ option_types.select {|it| (it['fieldGroup'] || 'default').casecmp?('default')}.sort {|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i} +
1119
+ option_types.reject {|it| ['default', 'advanced'].include?((it['fieldGroup'] || 'default').downcase)}.sort{|a,b| a['displayOrder'] <=> b['displayOrder']}.group_by{|it| it['fieldGroup']}.values.collect { |it| it.sort{|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i}}.flatten +
1120
+ option_types.select {|it| 'advanced'.casecmp?(it['fieldGroup'])}.sort {|a,b| a['displayOrder'].to_i <=> b['displayOrder'].to_i}
1090
1121
  end
1091
1122
 
1092
1123
  def self.display_select_options(opt, select_options = [], paging = nil)
@@ -1094,7 +1125,7 @@ module Morpheus
1094
1125
  end
1095
1126
 
1096
1127
  def self.format_option_types_help(option_types, opts={})
1097
- option_types = self.sorted_option_types(option_types).reject {|it| it['hidden']}
1128
+ option_types = self.sort_option_types(option_types).reject {|it| it['hidden']}
1098
1129
 
1099
1130
  if option_types.empty?
1100
1131
  "#{opts[:color]}#{opts[:title] || "Available Options:"}\nNone\n\n"
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "5.5.0"
4
+ VERSION = "5.5.1"
5
5
  end
6
6
  end
@@ -155,10 +155,9 @@ module Morpheus::Logging
155
155
 
156
156
  def print(*messages)
157
157
  if @io
158
- messages = messages.flatten.collect {|it| scrub_message(it) }
159
- print_with_color do
160
- messages.each do |msg|
161
- @io.print msg
158
+ print_with_color do
159
+ messages.flatten.each do |msg|
160
+ @io.print scrub_message(msg)
162
161
  end
163
162
  end
164
163
  end
@@ -166,10 +165,9 @@ module Morpheus::Logging
166
165
 
167
166
  def puts(*messages)
168
167
  if @io
169
- messages = messages.flatten.collect {|it| scrub_message(it) }
170
- print_with_color do
171
- messages.each do |msg|
172
- @io.puts msg
168
+ print_with_color do
169
+ messages.flatten.each do |msg|
170
+ @io.puts scrub_message(msg)
173
171
  end
174
172
  end
175
173
  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.5.0
4
+ version: 5.5.1
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: 2022-05-13 00:00:00.000000000 Z
14
+ date: 2022-07-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -292,6 +292,7 @@ files:
292
292
  - lib/morpheus/api/reports_interface.rb
293
293
  - lib/morpheus/api/rest_interface.rb
294
294
  - lib/morpheus/api/roles_interface.rb
295
+ - lib/morpheus/api/scale_thresholds_interface.rb
295
296
  - lib/morpheus/api/search_interface.rb
296
297
  - lib/morpheus/api/secondary_read_interface.rb
297
298
  - lib/morpheus/api/secondary_rest_interface.rb
@@ -451,6 +452,7 @@ files:
451
452
  - lib/morpheus/cli/commands/reports_command.rb
452
453
  - lib/morpheus/cli/commands/rm_command.rb
453
454
  - lib/morpheus/cli/commands/roles.rb
455
+ - lib/morpheus/cli/commands/scale_thresholds.rb
454
456
  - lib/morpheus/cli/commands/search_command.rb
455
457
  - lib/morpheus/cli/commands/security_group_rules.rb
456
458
  - lib/morpheus/cli/commands/security_groups.rb
@@ -500,6 +502,7 @@ files:
500
502
  - lib/morpheus/cli/mixins/deployments_helper.rb
501
503
  - lib/morpheus/cli/mixins/execution_request_helper.rb
502
504
  - lib/morpheus/cli/mixins/infrastructure_helper.rb
505
+ - lib/morpheus/cli/mixins/jobs_helper.rb
503
506
  - lib/morpheus/cli/mixins/library_helper.rb
504
507
  - lib/morpheus/cli/mixins/load_balancers_helper.rb
505
508
  - lib/morpheus/cli/mixins/logs_helper.rb
@@ -550,8 +553,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
550
553
  - !ruby/object:Gem::Version
551
554
  version: '0'
552
555
  requirements: []
553
- rubyforge_project:
554
- rubygems_version: 2.7.6
556
+ rubygems_version: 3.1.6
555
557
  signing_key:
556
558
  specification_version: 4
557
559
  summary: Provides CLI Interface to the Morpheus Public/Private Cloud Appliance