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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +12 -0
- data/lib/morpheus/api/clusters_interface.rb +7 -0
- data/lib/morpheus/api/network_security_server_types_interface.rb +9 -0
- data/lib/morpheus/api/network_server_types_interface.rb +9 -0
- data/lib/morpheus/api/network_servers_interface.rb +4 -0
- data/lib/morpheus/cli/cli_command.rb +1 -0
- data/lib/morpheus/cli/commands/clouds.rb +101 -28
- data/lib/morpheus/cli/commands/clouds_types.rb +141 -0
- data/lib/morpheus/cli/commands/clusters.rb +44 -0
- data/lib/morpheus/cli/commands/instances.rb +1 -0
- data/lib/morpheus/cli/commands/network_dhcp_relays_command.rb +1 -42
- data/lib/morpheus/cli/commands/network_dhcp_servers_command.rb +3 -44
- data/lib/morpheus/cli/commands/network_edge_clusters_command.rb +1 -42
- data/lib/morpheus/cli/commands/network_firewalls_command.rb +1 -41
- data/lib/morpheus/cli/commands/network_pool_servers_command.rb +3 -1
- data/lib/morpheus/cli/commands/network_routers_command.rb +4 -6
- data/lib/morpheus/cli/commands/network_security_server_types.rb +20 -0
- data/lib/morpheus/cli/commands/network_server_types_command.rb +20 -0
- data/lib/morpheus/cli/commands/network_servers_command.rb +368 -0
- data/lib/morpheus/cli/commands/network_transport_zones_command.rb +1 -41
- data/lib/morpheus/cli/commands/networks_command.rb +1 -1
- data/lib/morpheus/cli/commands/options.rb +135 -2
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +103 -2
- data/lib/morpheus/cli/mixins/networks_helper.rb +62 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +28 -7
- data/lib/morpheus/cli/mixins/prompt_helper.rb +15 -0
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +25 -9
- data/lib/morpheus/cli/mixins/rest_command.rb +1 -1
- data/lib/morpheus/cli/option_types.rb +3 -3
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/logging.rb +6 -3
- metadata +10 -2
@@ -15,9 +15,22 @@ class Morpheus::Cli::Options
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def handle(args)
|
18
|
-
|
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(
|
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
|
-
|
92
|
+
|
93
93
|
else
|
94
|
-
out << "#{color}#{bold}==================#{reset}\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
|
-
|
124
|
+
|
121
125
|
else
|
122
|
-
out << "#{color}---------------------#{reset}\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|
|
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
|
-
|
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
|
-
|
932
|
-
|
933
|
-
if sg_option_type
|
934
|
-
|
935
|
-
|
936
|
-
|
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'].
|
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
|
data/lib/morpheus/cli/version.rb
CHANGED
data/lib/morpheus/logging.rb
CHANGED
@@ -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?\"[^"]
|
98
|
-
msg.gsub!(/
|
99
|
-
msg.gsub!(/password
|
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.
|
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-
|
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
|