morpheus-cli 6.2.2 → 6.2.3

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +12 -0
  4. data/lib/morpheus/api/clusters_interface.rb +7 -0
  5. data/lib/morpheus/api/network_security_server_types_interface.rb +9 -0
  6. data/lib/morpheus/api/network_server_types_interface.rb +9 -0
  7. data/lib/morpheus/api/network_servers_interface.rb +4 -0
  8. data/lib/morpheus/cli/cli_command.rb +1 -0
  9. data/lib/morpheus/cli/commands/clouds.rb +101 -28
  10. data/lib/morpheus/cli/commands/clouds_types.rb +141 -0
  11. data/lib/morpheus/cli/commands/clusters.rb +44 -0
  12. data/lib/morpheus/cli/commands/instances.rb +1 -0
  13. data/lib/morpheus/cli/commands/network_dhcp_relays_command.rb +1 -42
  14. data/lib/morpheus/cli/commands/network_dhcp_servers_command.rb +3 -44
  15. data/lib/morpheus/cli/commands/network_edge_clusters_command.rb +1 -42
  16. data/lib/morpheus/cli/commands/network_firewalls_command.rb +1 -41
  17. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +3 -1
  18. data/lib/morpheus/cli/commands/network_routers_command.rb +4 -6
  19. data/lib/morpheus/cli/commands/network_security_server_types.rb +20 -0
  20. data/lib/morpheus/cli/commands/network_server_types_command.rb +20 -0
  21. data/lib/morpheus/cli/commands/network_servers_command.rb +368 -0
  22. data/lib/morpheus/cli/commands/network_transport_zones_command.rb +1 -41
  23. data/lib/morpheus/cli/commands/networks_command.rb +1 -1
  24. data/lib/morpheus/cli/commands/options.rb +135 -2
  25. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +103 -2
  26. data/lib/morpheus/cli/mixins/networks_helper.rb +62 -0
  27. data/lib/morpheus/cli/mixins/print_helper.rb +28 -7
  28. data/lib/morpheus/cli/mixins/prompt_helper.rb +15 -0
  29. data/lib/morpheus/cli/mixins/provisioning_helper.rb +25 -9
  30. data/lib/morpheus/cli/mixins/rest_command.rb +1 -1
  31. data/lib/morpheus/cli/option_types.rb +3 -3
  32. data/lib/morpheus/cli/version.rb +1 -1
  33. data/lib/morpheus/logging.rb +6 -3
  34. metadata +10 -2
@@ -15,9 +15,22 @@ class Morpheus::Cli::Options
15
15
  end
16
16
 
17
17
  def handle(args)
18
- list(args)
18
+ # todo: probably just make these proper subcommands
19
+ # handle_subcommand(args)
20
+ # handle some special cases that do not conform to name, value
21
+ # This also provides some help on their by documenting the required parameters.
22
+ source_name = args[0]
23
+ if source_name == "networkServices"
24
+ network_services(args[1..-1])
25
+ elsif source_name == "zoneNetworkOptions"
26
+ zone_network_options(args[1..-1])
27
+ else
28
+ list(args)
29
+ end
19
30
  end
20
31
 
32
+ # This is the default handler for the options command.
33
+ # It shows the NAME and VALUE for the list of "data" returned.
21
34
  def list(args)
22
35
  options = {}
23
36
  params = {}
@@ -67,6 +80,9 @@ EOT
67
80
  begin
68
81
  json_response = @options_interface.options_for_source(source_name, params)
69
82
  rescue RestClient::Exception => e
83
+ if Morpheus::Logging.debug? # or options[:debug]
84
+ raise e
85
+ end
70
86
  if e.response && e.response.code == 404
71
87
  raise_command_error("Options source not found by name '#{source_name}'", args, optparse)
72
88
  elsif e.response && e.response.code == 500
@@ -88,8 +104,125 @@ EOT
88
104
  print cyan,"No options found.",reset,"\n"
89
105
  else
90
106
  print as_pretty_table(records, [:name, :value], options)
91
- print_results_pagination(json_response)
107
+ print_results_pagination({size: records.size, total: records.size})
108
+ end
109
+ print reset,"\n"
110
+ end
111
+ return 0, nil
112
+ end
113
+
114
+ # handle some well option sources by name
115
+
116
+ def network_services(args)
117
+ options = {}
118
+ params = {}
119
+ source_name = "networkServices"
120
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
121
+ opts.banner = "Usage: morpheus #{command_name} #{source_name} #{args[0]}"
122
+ # build_standard_list_options(opts, options)
123
+ build_standard_get_options(opts, options)
124
+ opts.footer = <<-EOT
125
+ View list of options for source '#{source_name}'.
126
+ This is the list of network service types (network server types) that can be added.
127
+ EOT
128
+ end
129
+ optparse.parse!(args)
130
+ verify_args!(args:args, optparse:optparse, count: 0)
131
+ connect(options)
132
+ params.merge!(parse_list_options(options))
133
+ @options_interface.setopts(options)
134
+ if options[:dry_run]
135
+ print_dry_run @options_interface.dry.options_for_source(source_name, params)
136
+ return
137
+ end
138
+ json_response = @options_interface.options_for_source(source_name, params)
139
+ render_response(json_response, options, "data") do
140
+ records = json_response["data"].collect {|r| r['services']}.compact.flatten
141
+ print_h1 "Morpheus Options", ["Source: #{source_name}"] + parse_list_subtitles(options), options, ""
142
+ if records.nil? || records.empty?
143
+ print cyan,"No options found.",reset,"\n"
144
+ else
145
+ json_response["data"].each do |data_row|
146
+ if data_row['services'] && !data_row['services'].empty?
147
+ services = []
148
+ data_row['services'].each do |service_row|
149
+ services << {name: service_row['name'], code: service_row['code'] , id: service_row['id'], value: service_row['id']}
150
+ end
151
+ # print_h2 "#{data_row['name']} Options", [], options
152
+ print_h2 "#{data_row['name']}", [], options
153
+ print as_pretty_table(services, [:id, :name, :code], options)
154
+ end
155
+ end
156
+ end
157
+ print_results_pagination({size: records.size, total: records.size})
158
+ print reset,"\n"
159
+ end
160
+ return 0, nil
161
+ end
162
+
163
+ # # this is a really slow one right now, need to look into that.
164
+ # def networks(args)
165
+ # end
166
+
167
+ def zone_network_options(args)
168
+ options = {}
169
+ params = {}
170
+ source_name = "zoneNetworkOptions"
171
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
172
+ opts.banner = "Usage: morpheus #{command_name} #{source_name} #{args[0]}"
173
+ # build_standard_list_options(opts, options)
174
+ build_standard_get_options(opts, options)
175
+ opts.footer = <<-EOT
176
+ View list of options for source '#{source_name}'.
177
+ This is the list of networks available when provisioning to a particular cloud and layout.
178
+
179
+ Required Parameters:
180
+ Cloud ID (zoneId)
181
+ Layout ID (layoutId)
182
+
183
+ Examples:
184
+ options #{source_name} -Q zoneId=40&layoutId=1954
185
+ EOT
186
+ end
187
+ optparse.parse!(args)
188
+ verify_args!(args:args, optparse:optparse, count: 0)
189
+ connect(options)
190
+ params.merge!(parse_list_options(options))
191
+ @options_interface.setopts(options)
192
+ if options[:dry_run]
193
+ print_dry_run @options_interface.dry.options_for_source(source_name, params)
194
+ return
195
+ end
196
+ # This requires Cloud and Layout -Q zoneId=40&layoutId=1954
197
+ # todo: prompt
198
+ json_response = @options_interface.options_for_source(source_name, params)
199
+ render_response(json_response, options, "data") do
200
+ # This is different, data is a Hash, not an Array...
201
+ networks = json_response["data"]["networks"]
202
+ network_groups = json_response["data"]["networkGroups"]
203
+ network_subnets = json_response["data"]["networkSubnets"]
204
+ records = [networks, network_groups, network_subnets].compact.flatten
205
+ print_h1 "Morpheus Options", ["Source: #{source_name}"] + parse_list_subtitles(options), options, ""
206
+ if records.nil? || records.empty?
207
+ print cyan,"No options found.",reset,"\n"
208
+ else
209
+ if networks && !networks.empty?
210
+ print_h2 "Networks", [], options
211
+ rows = networks.collect {|row| {name: row['name'], value: row['id']} }
212
+ print as_pretty_table(rows, [:name, :value], options)
213
+ end
214
+ if network_groups && !network_groups.empty?
215
+ print_h2 "Network Groups", [], options
216
+ rows = network_groups.collect {|row| {name: row['name'], value: row['id']} }
217
+ print as_pretty_table(rows, [:name, :value], options)
218
+ end
219
+ if network_subnets && !network_subnets.empty?
220
+ print_h2 "Subnets", [], options
221
+ rows = network_subnets.collect {|row| {name: row['name'], value: row['id']} }
222
+ print as_pretty_table(rows, [:name, :value], options)
223
+ end
92
224
  end
225
+ print_results_pagination({size: records.size, total: records.size})
93
226
  print reset,"\n"
94
227
  end
95
228
  return 0, nil
@@ -137,6 +137,7 @@ module Morpheus::Cli::InfrastructureHelper
137
137
  return cloud_type_for_name(val)
138
138
  end
139
139
  end
140
+
140
141
  def cloud_type_for_id(id)
141
142
  return get_available_cloud_types().find { |z| z['id'].to_i == id.to_i}
142
143
  end
@@ -633,7 +634,6 @@ module Morpheus::Cli::InfrastructureHelper
633
634
  "Name" => lambda {|it| it['name'] },
634
635
  "Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
635
636
  "URL" => lambda {|it| it['serviceUrl'] },
636
- #"Pools" => lambda {|it| it['pools'] ? anded_list(it['pools'].collect {|p| p['name'] }, 3) : '' },
637
637
  "Enabled" => lambda {|it| format_boolean(it['enabled']) },
638
638
  "Status" => lambda {|it| format_network_pool_server_status(it) },
639
639
  "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
@@ -661,7 +661,6 @@ module Morpheus::Cli::InfrastructureHelper
661
661
  "Extra Attributes" => lambda {|it| it['config'] ? it['config']['extraAttributes'] : nil },
662
662
  "Enabled" => lambda {|it| format_boolean(it['enabled']) },
663
663
  "Status" => lambda {|it| format_network_pool_server_status(it) },
664
- #"Pools" => lambda {|it| it['pools'] ? anded_list(it['pools'].collect {|p| p['name'] }, 3) : '' },
665
664
  "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
666
665
  "Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
667
666
  }
@@ -706,4 +705,106 @@ module Morpheus::Cli::InfrastructureHelper
706
705
  }
707
706
  end
708
707
 
708
+ def find_network_server_type_by_name_or_id(val)
709
+ if val.to_s =~ /\A\d{1,}\Z/
710
+ return find_network_server_type_by_id(val)
711
+ else
712
+ # always find by code too
713
+ #return find_network_server_type_by_name(val)
714
+ return find_network_server_type_by_name_or_code(val)
715
+ end
716
+ end
717
+
718
+ def find_network_server_type_by_id(id)
719
+ begin
720
+ json_response = @network_server_types_interface.get(id.to_i)
721
+ return json_response['networkServerType']
722
+ rescue RestClient::Exception => e
723
+ if e.response && e.response.code == 404
724
+ print_red_alert "Network Server Type not found by id #{id}"
725
+ return nil
726
+ else
727
+ raise e
728
+ end
729
+ end
730
+ end
731
+
732
+ def find_network_server_type_by_name(name)
733
+ json_response = @network_server_types_interface.list({name: name.to_s})
734
+ network_server_types = json_response['networkServerTypes']
735
+ if network_server_types.empty?
736
+ print_red_alert "Network Server Type not found by name #{name}"
737
+ return nil
738
+ elsif network_server_types.size > 1
739
+ print_red_alert "#{network_server_types.size} network server types found by name #{name}"
740
+ # print_networks_table(networks, {color: red})
741
+ rows = network_server_types.collect do |it|
742
+ {id: it['id'], name: it['name']}
743
+ end
744
+ puts as_pretty_table(rows, [:id, :code, :name], {color:red})
745
+ return nil
746
+ else
747
+ return network_server_types[0]
748
+ end
749
+ end
750
+
751
+ def find_network_server_type_by_name_or_code(name)
752
+ json_response = @network_server_types_interface.list({phrase: name.to_s, max: 100})
753
+ downcase_name = name.to_s.downcase
754
+ network_server_types = json_response['networkServerTypes'].select { |it|
755
+ it['code'].to_s.downcase == downcase_name || it['name'].to_s.downcase == downcase_name
756
+ }
757
+ if network_server_types.empty?
758
+ print_red_alert "Network Server Type not found by name or code '#{name}'"
759
+ return nil
760
+ elsif network_server_types.size > 1
761
+ print_red_alert "#{network_server_types.size} network server types found with name or code '#{name}'"
762
+ # print_networks_table(networks, {color: red})
763
+ rows = network_server_types.collect do |it|
764
+ {id: it['id'], name: it['name']}
765
+ end
766
+ puts as_pretty_table(rows, [:id, :code, :name], {color:red})
767
+ return nil
768
+ else
769
+ return network_server_types[0]
770
+ end
771
+ end
772
+
773
+ def network_server_type_list_column_definitions(options)
774
+ {
775
+ "ID" => 'id',
776
+ "Name" => 'name',
777
+ "Code" => 'code',
778
+ "Description" => 'description',
779
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) }
780
+ }
781
+ end
782
+
783
+ def network_server_type_column_definitions(options)
784
+ {
785
+ "ID" => 'id',
786
+ "Name" => 'name',
787
+ "Code" => 'code',
788
+ "Description" => 'description',
789
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
790
+ "Selectable" => lambda {|it| format_boolean(it['selectable']) },
791
+ "Creatable" => lambda {|it| format_boolean(it['creatable']) },
792
+ "Plugin" => lambda {|it| format_boolean(it['isPlugin']) },
793
+ "Embedded" => lambda {|it| format_boolean(it['isEmbedded']) },
794
+ #"Integration Code" => lambda {|it| it['integrationCode'] },
795
+ "Networks" => lambda {|it| format_boolean(it['hasNetworks']) },
796
+ "Gateways" => lambda {|it| format_boolean(it['hasGateways']) },
797
+ "DHCP Servers" => lambda {|it| format_boolean(it['hasDhcpServers']) },
798
+ "DHCP Relays" => lambda {|it| format_boolean(it['hasDhcpRelays']) },
799
+ # "Route Tables" => lambda {|it| format_boolean(it['hasRouteTables']) },
800
+ "Routers" => lambda {|it| format_boolean(it['hasRouters']) },
801
+ "Switches" => lambda {|it| format_boolean(it['hasSwitches']) },
802
+ "Firewall" => lambda {|it| format_boolean(it['hasFirewall']) },
803
+ "Security Groups" => lambda {|it| format_boolean(it['hasSecurityGroups']) },
804
+ "Load Balancers" => lambda {|it| format_boolean(it['hasLoadBalancers']) },
805
+ # "Security Code" => lambda {|it| it['securityCode'] },
806
+ # "User Visible" => lambda {|it| format_boolean(it['userVisible']) },
807
+ }
808
+ end
809
+
709
810
  end
@@ -0,0 +1,62 @@
1
+ require 'morpheus/cli/mixins/print_helper'
2
+ require 'morpheus/cli/option_types'
3
+ require 'morpheus/rest_client'
4
+ # Mixin for Morpheus::Cli command classes
5
+ # Provides common methods for networking commands
6
+ module Morpheus::Cli::NetworksHelper
7
+
8
+ def self.included(klass)
9
+ klass.send :include, Morpheus::Cli::PrintHelper
10
+ end
11
+
12
+ def network_servers_interface
13
+ # @api_client.network_servers
14
+ raise "#{self.class} has not defined @network_servers_interface" if @network_servers_interface.nil?
15
+ @network_servers_interface
16
+ end
17
+
18
+ def find_network_server(val)
19
+ if val.to_s =~ /\A\d{1,}\Z/
20
+ return find_network_server_by_id(val)
21
+ else
22
+ if server = find_network_server_by_name(val)
23
+ return find_network_server_by_id(server['id'])
24
+ end
25
+ end
26
+ end
27
+
28
+ def find_network_server_by_id(id)
29
+ begin
30
+ # Use query parameter `details=true` to get the full type object with all its configuration settings and optionTypes
31
+ json_response = @network_servers_interface.get(id.to_i, {details:true})
32
+ return json_response['networkServer']
33
+ rescue RestClient::Exception => e
34
+ if e.response && e.response.code == 404
35
+ print_red_alert "Network Server not found by id #{id}"
36
+ return nil
37
+ else
38
+ raise e
39
+ end
40
+ end
41
+ end
42
+
43
+ def find_network_server_by_name(name)
44
+ # Use query parameter `details=true` to get the full type object with all its configuration settings and optionTypes
45
+ json_response = @network_servers_interface.list({phrase: name.to_s, details:true})
46
+ servers = json_response['networkServers']
47
+ if servers.empty?
48
+ print_red_alert "Network Server not found by name #{name}"
49
+ return nil
50
+ elsif servers.size > 1
51
+ print_red_alert "#{servers.size} network servers found by name #{name}"
52
+ rows = servers.collect do |it|
53
+ {id: it['id'], name: it['name']}
54
+ end
55
+ puts as_pretty_table(rows, [:id, :name], {color:red})
56
+ return nil
57
+ else
58
+ return servers[0]
59
+ end
60
+ end
61
+
62
+ end
@@ -58,7 +58,7 @@ module Morpheus::Cli::PrintHelper
58
58
  # title - subtitle1, subtitle2
59
59
  # ==================
60
60
  #
61
- def print_h1(title, subtitles=nil, options=nil)
61
+ def print_h1(title, subtitles=nil, options=nil, suffix_content="\n")
62
62
  # ok, support all these formats for now:
63
63
  # print_h1(title, options={})
64
64
  # print_h1(title, subtitles, options={})
@@ -89,14 +89,18 @@ module Morpheus::Cli::PrintHelper
89
89
  end
90
90
  out << "\n"
91
91
  if options[:border_style] == :thin
92
- out << "\n"
92
+
93
93
  else
94
- out << "#{color}#{bold}==================#{reset}\n\n"
94
+ out << "#{color}#{bold}==================#{reset}\n"
95
+ end
96
+ # Default suffix_content is typically one extra newline
97
+ if !suffix_content.to_s.empty?
98
+ out << suffix_content.to_s
95
99
  end
96
100
  print out
97
101
  end
98
102
 
99
- def print_h2(title, subtitles=nil, options=nil)
103
+ def print_h2(title, subtitles=nil, options=nil, suffix_content="\n")
100
104
  # ok, support all these formats for now:
101
105
  # print_h2(title={})
102
106
  # print_h2(title, options={})
@@ -117,9 +121,13 @@ module Morpheus::Cli::PrintHelper
117
121
  end
118
122
  out << "\n"
119
123
  if options[:border_style] == :thin
120
- out << "\n"
124
+
121
125
  else
122
- out << "#{color}---------------------#{reset}\n\n"
126
+ out << "#{color}---------------------#{reset}\n"
127
+ end
128
+ # Default suffix_content is typically one extra newline
129
+ if !suffix_content.to_s.empty?
130
+ out << suffix_content.to_s
123
131
  end
124
132
  print out
125
133
  end
@@ -1505,8 +1513,21 @@ module Morpheus::Cli::PrintHelper
1505
1513
  def format_option_types_table(option_types, options={}, domain_name=nil)
1506
1514
  columns = [
1507
1515
  {"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
1508
- {"FIELD NAME" => lambda {|it| [it['fieldContext'] == domain_name ? nil : it['fieldContext'], it['fieldName']].select {|it| !it.to_s.empty? }.join('.') } },
1516
+ {"FIELD NAME" => lambda {|it|
1517
+ if it['fieldContext'] && it['fieldContext'] != domain_name && it['fieldContext'] != 'domain'
1518
+ "#{it['fieldContext']}.#{it['fieldName']}"
1519
+ else
1520
+ "#{it['fieldName']}"
1521
+ end
1522
+ } },
1509
1523
  {"TYPE" => lambda {|it| it['type'] } },
1524
+ {"OPTION SOURCE" => lambda {|it|
1525
+ if it['optionSourceType']
1526
+ "#{it['optionSourceType']}/#{it['optionSource']}"
1527
+ else
1528
+ "#{it['optionSource']}"
1529
+ end
1530
+ } },
1510
1531
  {"DEFAULT" => lambda {|it| it['defaultValue'] } },
1511
1532
  {"REQUIRED" => lambda {|it| format_boolean it['required'] } },
1512
1533
  ]
@@ -0,0 +1,15 @@
1
+ # Mixin for Morpheus::Cli command classes
2
+ # Provides common methods for prompting for input
3
+ module Morpheus::Cli::PromptHelper
4
+
5
+ # prompt for a single option type and and return the input value
6
+ # @param option_type [Hash] The OptionType input record to prompt for , contians fieldName, fieldLabel, etc.
7
+ # @param options [Hash] The context being constructed, checks this for the value before prompting the user for input.
8
+ # @param no_prompt [Boolean] The context being constructed, checks this for the value before prompting the user for input.
9
+ # @param api_params [Hash] Optional map of parameters to include in API request for select option types
10
+ # @return input value for the option type, usually a string or number if the value is an ID or of type: number
11
+ def prompt_value(option_type, options, no_prompt=false, api_params={})
12
+ # this does not work with fieldContext, so get rid of it
13
+ return Morpheus::Cli::OptionTypes.prompt([option_type.merge({'fieldContext' => nil})], options, @api_client, api_params, no_prompt)[option_type['fieldName']]
14
+ end
15
+ end
@@ -915,8 +915,8 @@ module Morpheus::Cli::ProvisioningHelper
915
915
 
916
916
  # Security Groups
917
917
  # look for securityGroups option type... this is old and goofy
918
- sg_option_type = option_type_list.find {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['name'] == 'securityId')) }
919
- option_type_list = option_type_list.reject {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['name'] == 'securityId')) }
918
+ sg_option_type = option_type_list.find {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['fieldName'] == 'securityId' || opt['name'] == 'securityId')) }
919
+ option_type_list = option_type_list.reject {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['fieldName'] == 'securityId' || opt['name'] == 'securityId')) }
920
920
  if locked_fields.include?('securityGroups')
921
921
  # payload['securityGroups'] = options[:options]['securityGroups'] if options[:options]['securityGroups']
922
922
  else
@@ -924,19 +924,35 @@ module Morpheus::Cli::ProvisioningHelper
924
924
  # ok.. seed data has changed and serverTypes do not have this optionType anymore...
925
925
  if sg_option_type.nil?
926
926
  if provision_type && (provision_type["code"] == 'amazon')
927
- sg_option_type = {'fieldContext' => 'config', 'fieldName' => 'securityId', 'type' => 'select', 'fieldLabel' => 'Security Group', 'optionSource' => 'amazonSecurityGroup', 'required' => true, 'description' => 'Select security group.', 'defaultValue' => options[:default_security_group]}
927
+ sg_option_type = {'fieldContext' => 'config', 'fieldName' => 'securityId', 'type' => 'select', 'fieldLabel' => 'Security Group', 'optionSource' => 'amazonSecurityGroup', 'optionSourceType' => 'amazon', 'required' => true, 'description' => 'Select security group.', 'defaultValue' => options[:default_security_group]}
928
928
  end
929
929
  end
930
930
  sg_api_params = {zoneId: cloud_id, poolId: pool_id}
931
- has_security_groups = !!sg_option_type
932
- available_security_groups = []
933
- if sg_option_type && sg_option_type['type'] == 'select' && sg_option_type['optionSource']
934
- sg_option_results = options_interface.options_for_source(sg_option_type['optionSource'], sg_api_params, sg_option_type['optionSourceType'])
935
- available_security_groups = sg_option_results['data'].collect do |it|
936
- {"id" => it["value"] || it["id"], "name" => it["name"], "value" => it["value"] || it["id"]}
931
+ # The amazon plugin uses a new optionSource options/amazon/awsPluginEc2SecurityGroup
932
+ # which expects parameter config.resourcePoolId=pool-ID
933
+ if sg_option_type
934
+ if sg_option_type['optionSource'] == 'awsPluginEc2SecurityGroup'
935
+ if pool_id
936
+ sg_api_params[:config] ||= {}
937
+ sg_api_params[:config][:resourcePoolId] = pool_id
938
+ end
939
+ # convert multiSelect to select to make prompt_security_groups() work
940
+ # though we should should be able to skip the prompt_security_groups and use multiSelect instead
941
+ sg_option_type['type'] = 'select' if sg_option_type['type'] == 'multiSelect'
942
+ sg_option_type['type'] = 'typeahead' if sg_option_type['type'] == 'multiTypeahead'
943
+ sg_option_type['fieldLabel'] = 'Security Group' if sg_option_type['fieldLabel'] == 'Security Groups'
944
+ sg_option_type['required'] = true
937
945
  end
938
946
  end
947
+ has_security_groups = !!sg_option_type
939
948
  if options[:security_groups]
949
+ available_security_groups = []
950
+ if sg_option_type && sg_option_type['optionSource']
951
+ sg_option_results = options_interface.options_for_source(sg_option_type['optionSource'], sg_api_params, sg_option_type['optionSourceType'])
952
+ available_security_groups = sg_option_results['data'].collect do |it|
953
+ {"id" => it["value"] || it["id"], "name" => it["name"], "value" => it["value"] || it["id"]}
954
+ end
955
+ end
940
956
  # work with id or names, API expects ids though.
941
957
  payload['securityGroups'] = options[:security_groups].collect {|sg_id|
942
958
  found_sg = available_security_groups.find {|it| sg_id && (sg_id.to_s == it['id'].to_s || sg_id.to_s == it['name'].to_s) }
@@ -982,7 +982,7 @@ EOT
982
982
  # print_description_list(config.keys, config)
983
983
  # end
984
984
  # Option Types
985
- if record['optionTypes'] && record['optionTypes'].sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.size > 0
985
+ if record['optionTypes'] && record['optionTypes'].size > 0
986
986
  print_h2 "Option Types", options
987
987
  print format_option_types_table(record['optionTypes'], options, rest_object_key)
988
988
  end
@@ -673,9 +673,9 @@ module Morpheus
673
673
  if input.empty? && default_value
674
674
  input = default_value.to_s
675
675
  end
676
- matched_option = select_options.find{|it| (!it['value'].nil? && it['value'].to_s == input) || (!it[value_field].nil? && it[value_field].to_s == input) || (it[value_field].nil? && input.empty?)}
676
+ matched_option = (select_options || []).find{|it| (!it['value'].nil? && it['value'].to_s == input) || (!it[value_field].nil? && it[value_field].to_s == input) || (it[value_field].nil? && input.empty?)}
677
677
  if matched_option.nil?
678
- matched_options = select_options.select {|it| it['name'] == input } # should probably be case insensitive
678
+ matched_options = (select_options || []).select {|it| it['name'] == input } # should probably be case insensitive
679
679
  if matched_options.size > 1
680
680
  print Term::ANSIColor.red, "\nInvalid Option #{option_type['fieldLabel']}: [#{input}]\n\n", Term::ANSIColor.reset
681
681
  print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
@@ -699,7 +699,7 @@ module Morpheus
699
699
 
700
700
  if input == '?'
701
701
  help_prompt(option_type)
702
- display_select_options(option_type, select_options, paging)
702
+ display_select_options(option_type, (select_options || []), paging)
703
703
  if paging
704
704
  paging[:cur_page] = (paging[:cur_page] + 1) * paging[:page_size] < paging[:total] ? paging[:cur_page] + 1 : 0
705
705
  end
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "6.2.2"
4
+ VERSION = "6.2.3"
5
5
  end
6
6
  end
@@ -94,9 +94,12 @@ module Morpheus::Logging
94
94
  end
95
95
  msg.gsub!(/password\"\: "[^"]+/, 'password": "************') # json properties ending with password
96
96
  msg.gsub!(/Password\"\: "[^"]+/, 'Password": "************') # json properties ending with Password
97
- msg.gsub!(/password\"\s?\=\>\s?\"[^"]+/i, 'password"=>"************')
98
- msg.gsub!(/password\=\"[^"]+/i, 'password="************')
99
- msg.gsub!(/password\=[^"'&]+/i, 'password=************') # buggy, wont work with ampersand or quotes in passwords! heh
97
+ msg.gsub!(/password\"\s?\=\>\s?\"[^"]+/, 'password"=>"************')
98
+ msg.gsub!(/Password\"\s?\=\>\s?\"[^"]+/, 'Password"=>"************')
99
+ msg.gsub!(/password\=\"[^"]+/, 'password="************')
100
+ msg.gsub!(/Password\=\"[^"]+/, 'Password="************')
101
+ msg.gsub!(/password\=[^"'&]+/, 'password=************') # buggy, wont work with ampersand or quotes in passwords! heh
102
+ msg.gsub!(/Password\=[^"'&]+/, 'Password=************')
100
103
  msg.gsub!(/passwordConfirmation\=[^" ]+/i, 'passwordConfirmation="************')
101
104
  msg.gsub!(/passwordConfirmation\=[^" ]+/i, 'passwordConfirmation=************')
102
105
  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: 6.2.2
4
+ version: 6.2.3
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-09-13 00:00:00.000000000 Z
14
+ date: 2023-10-13 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -291,8 +291,10 @@ files:
291
291
  - lib/morpheus/api/network_pools_interface.rb
292
292
  - lib/morpheus/api/network_proxies_interface.rb
293
293
  - lib/morpheus/api/network_routers_interface.rb
294
+ - lib/morpheus/api/network_security_server_types_interface.rb
294
295
  - lib/morpheus/api/network_security_servers_interface.rb
295
296
  - lib/morpheus/api/network_server_groups_interface.rb
297
+ - lib/morpheus/api/network_server_types_interface.rb
296
298
  - lib/morpheus/api/network_servers_interface.rb
297
299
  - lib/morpheus/api/network_services_interface.rb
298
300
  - lib/morpheus/api/network_static_routes_interface.rb
@@ -391,6 +393,7 @@ files:
391
393
  - lib/morpheus/cli/commands/cloud_folders_command.rb
392
394
  - lib/morpheus/cli/commands/cloud_resource_pools_command.rb
393
395
  - lib/morpheus/cli/commands/clouds.rb
396
+ - lib/morpheus/cli/commands/clouds_types.rb
394
397
  - lib/morpheus/cli/commands/clusters.rb
395
398
  - lib/morpheus/cli/commands/coloring_command.rb
396
399
  - lib/morpheus/cli/commands/containers_command.rb
@@ -469,7 +472,10 @@ files:
469
472
  - lib/morpheus/cli/commands/network_pools_command.rb
470
473
  - lib/morpheus/cli/commands/network_proxies_command.rb
471
474
  - lib/morpheus/cli/commands/network_routers_command.rb
475
+ - lib/morpheus/cli/commands/network_security_server_types.rb
472
476
  - lib/morpheus/cli/commands/network_server_groups_command.rb
477
+ - lib/morpheus/cli/commands/network_server_types_command.rb
478
+ - lib/morpheus/cli/commands/network_servers_command.rb
473
479
  - lib/morpheus/cli/commands/network_services_command.rb
474
480
  - lib/morpheus/cli/commands/network_static_routes_command.rb
475
481
  - lib/morpheus/cli/commands/network_transport_zones_command.rb
@@ -552,10 +558,12 @@ files:
552
558
  - lib/morpheus/cli/mixins/load_balancers_helper.rb
553
559
  - lib/morpheus/cli/mixins/logs_helper.rb
554
560
  - lib/morpheus/cli/mixins/monitoring_helper.rb
561
+ - lib/morpheus/cli/mixins/networks_helper.rb
555
562
  - lib/morpheus/cli/mixins/operations_helper.rb
556
563
  - lib/morpheus/cli/mixins/option_source_helper.rb
557
564
  - lib/morpheus/cli/mixins/print_helper.rb
558
565
  - lib/morpheus/cli/mixins/processes_helper.rb
566
+ - lib/morpheus/cli/mixins/prompt_helper.rb
559
567
  - lib/morpheus/cli/mixins/provisioning_helper.rb
560
568
  - lib/morpheus/cli/mixins/remote_helper.rb
561
569
  - lib/morpheus/cli/mixins/rest_command.rb