morpheus-cli 6.2.2 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/README.md +6 -0
- 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 +43 -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/commands/policies_command.rb +112 -128
- data/lib/morpheus/cli/commands/roles.rb +3 -0
- data/lib/morpheus/cli/mixins/accounts_helper.rb +2 -0
- 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
|
@@ -763,61 +763,49 @@ class Morpheus::Cli::PoliciesCommand
|
|
763
763
|
params = {}
|
764
764
|
options = {}
|
765
765
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
766
|
-
opts.banner = subcommand_usage()
|
767
|
-
|
766
|
+
opts.banner = subcommand_usage("[search]")
|
767
|
+
build_standard_list_options(opts, options, [], [:search])
|
768
|
+
opts.footer = <<-EOT
|
769
|
+
Get details about a policy type.
|
770
|
+
[policy-type] is required. This is Name or ID of a policy type.
|
771
|
+
EOT
|
768
772
|
opts.footer = "List policy types."
|
769
773
|
end
|
770
774
|
optparse.parse!(args)
|
771
|
-
|
772
|
-
if args.count
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
end
|
777
|
-
|
775
|
+
verify_args!(args:args, optparse:optparse, count:0)
|
776
|
+
# if args.count > 0
|
777
|
+
# options[:phrase] = args.join(" ")
|
778
|
+
# end
|
779
|
+
params.merge!(parse_list_options(options))
|
778
780
|
connect(options)
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
781
|
+
@policies_interface.setopts(options)
|
782
|
+
if options[:dry_run]
|
783
|
+
print_dry_run @policies_interface.dry.list_policy_types(params)
|
784
|
+
return 0
|
785
|
+
end
|
786
|
+
json_response = @policies_interface.list_policy_types(params)
|
787
|
+
render_response(json_response, options, 'policyTypes') do
|
786
788
|
policy_types = json_response['policyTypes']
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
puts records_as_csv(policy_types, options)
|
795
|
-
return 0
|
796
|
-
else
|
797
|
-
print_h1 "Morpheus Policy Types"
|
798
|
-
rows = policy_types.collect {|policy_type|
|
799
|
-
row = {
|
800
|
-
id: policy_type['id'],
|
801
|
-
name: policy_type['name'],
|
802
|
-
code: policy_type['code'],
|
803
|
-
description: policy_type['description']
|
804
|
-
}
|
805
|
-
row
|
789
|
+
print_h1 "Morpheus Policy Types"
|
790
|
+
rows = policy_types.collect {|policy_type|
|
791
|
+
row = {
|
792
|
+
id: policy_type['id'],
|
793
|
+
name: policy_type['name'],
|
794
|
+
code: policy_type['code'],
|
795
|
+
description: policy_type['description']
|
806
796
|
}
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
print as_pretty_table(rows, columns, options)
|
813
|
-
print_results_pagination(json_response, {:label => "policy type", :n_label => "policy types"})
|
814
|
-
print reset, "\n"
|
797
|
+
row
|
798
|
+
}
|
799
|
+
columns = [:id, :name]
|
800
|
+
if options[:include_fields]
|
801
|
+
columns = options[:include_fields]
|
815
802
|
end
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
803
|
+
print cyan
|
804
|
+
print as_pretty_table(rows, columns, options)
|
805
|
+
print_results_pagination(json_response)
|
806
|
+
print reset, "\n"
|
820
807
|
end
|
808
|
+
return 0
|
821
809
|
end
|
822
810
|
|
823
811
|
def get_type(args)
|
@@ -825,91 +813,54 @@ class Morpheus::Cli::PoliciesCommand
|
|
825
813
|
options = {}
|
826
814
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
827
815
|
opts.banner = subcommand_usage("[policy-type]")
|
828
|
-
|
829
|
-
opts.footer =
|
830
|
-
|
816
|
+
build_standard_get_options(opts, options)
|
817
|
+
opts.footer = <<-EOT
|
818
|
+
Get details about a policy type.
|
819
|
+
[policy-type] is required. This is Name or ID of a policy type.
|
820
|
+
EOT
|
831
821
|
end
|
832
822
|
optparse.parse!(args)
|
833
|
-
|
834
|
-
if args.count != 1
|
835
|
-
print_error Morpheus::Terminal.angry_prompt
|
836
|
-
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
837
|
-
return 1
|
838
|
-
end
|
839
|
-
|
823
|
+
verify_args!(args:args, optparse:optparse, count: 1)
|
840
824
|
connect(options)
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
puts as_json(json_response)
|
852
|
-
else
|
853
|
-
print_h1 "Policy Type Details"
|
854
|
-
print cyan
|
855
|
-
description_cols = {
|
856
|
-
"ID" => 'id',
|
857
|
-
"Name" => 'name',
|
858
|
-
# "Description" => 'description',
|
859
|
-
"Code" => 'code',
|
860
|
-
"Category" => 'category',
|
861
|
-
# "Load Method" => 'loadMethod',
|
862
|
-
# "Enforce Method" => 'enforceMethod',
|
863
|
-
# "Prepare Method" => 'prepareMethod',
|
864
|
-
# "Validate Method" => 'validateMethod',
|
865
|
-
"Provision Enforced" => lambda {|it| it['enforceOnProvision'] ? 'Yes' : 'No' },
|
866
|
-
"Managed Enforced" => lambda {|it| it['enforceOnManaged'] ? 'Yes' : 'No' },
|
867
|
-
}
|
868
|
-
print_description_list(description_cols, policy_type)
|
869
|
-
print reset,"\n"
|
870
|
-
|
871
|
-
# show option types
|
872
|
-
print_h2 "Policy Type Options"
|
873
|
-
policy_type_option_types = policy_type['optionTypes']
|
874
|
-
if !policy_type_option_types || policy_type_option_types.size() == 0
|
875
|
-
puts "No options found for policy type"
|
876
|
-
else
|
877
|
-
rows = policy_type_option_types.collect {|option_type|
|
878
|
-
field_str = option_type['fieldName'].to_s
|
879
|
-
if !option_type['fieldContext'].to_s.empty?
|
880
|
-
field_str = option_type['fieldContext'] + "." + field_str
|
881
|
-
end
|
882
|
-
description_str = option_type['description'].to_s
|
883
|
-
if option_type['helpBlock']
|
884
|
-
if description_str.empty?
|
885
|
-
description_str = option_type['helpBlock']
|
886
|
-
else
|
887
|
-
description_str += " " + option_type['helpBlock']
|
888
|
-
end
|
889
|
-
end
|
890
|
-
row = {
|
891
|
-
#code: option_type['code'],
|
892
|
-
field: field_str,
|
893
|
-
type: option_type['type'],
|
894
|
-
description: description_str,
|
895
|
-
default: option_type['defaultValue'],
|
896
|
-
required: option_type['required'] ? 'Yes' : 'No'
|
897
|
-
}
|
898
|
-
row
|
899
|
-
}
|
900
|
-
columns = [:field, :type, :description, :default, :required]
|
901
|
-
print cyan
|
902
|
-
print as_pretty_table(rows, columns)
|
903
|
-
print reset,"\n"
|
904
|
-
end
|
905
|
-
return 0
|
906
|
-
end
|
825
|
+
params.merge!(parse_query_options(options))
|
826
|
+
policy_type_id = args[0]
|
827
|
+
if policy_type_id.to_s !~ /\A\d{1,}\Z/
|
828
|
+
policy_type = find_policy_type_by_name_or_id(args[0])
|
829
|
+
return [1, "Policy Type not found for #{args[0]}"] if policy_type.nil?
|
830
|
+
policy_type_id = policy_type['id']
|
831
|
+
end
|
832
|
+
@policies_interface.setopts(options)
|
833
|
+
if options[:dry_run]
|
834
|
+
print_dry_run @policies_interface.dry.get_policy_type(policy_type_id, params)
|
907
835
|
return 0
|
908
|
-
rescue RestClient::Exception => e
|
909
|
-
print_rest_exception(e, options)
|
910
|
-
return 1
|
911
836
|
end
|
912
|
-
@policies_interface.
|
837
|
+
json_response = @policies_interface.get_policy_type(policy_type_id, params)
|
838
|
+
render_response(json_response, options, 'policyType') do
|
839
|
+
policy_type = json_response['policyType']
|
840
|
+
print_h1 "Policy Type Details"
|
841
|
+
print cyan
|
842
|
+
description_cols = {
|
843
|
+
"ID" => 'id',
|
844
|
+
"Name" => 'name',
|
845
|
+
# "Description" => 'description',
|
846
|
+
"Code" => 'code',
|
847
|
+
"Category" => 'category',
|
848
|
+
# "Load Method" => 'loadMethod',
|
849
|
+
# "Enforce Method" => 'enforceMethod',
|
850
|
+
# "Prepare Method" => 'prepareMethod',
|
851
|
+
# "Validate Method" => 'validateMethod',
|
852
|
+
"Provision Enforced" => lambda {|it| it['enforceOnProvision'] ? 'Yes' : 'No' },
|
853
|
+
"Managed Enforced" => lambda {|it| it['enforceOnManaged'] ? 'Yes' : 'No' },
|
854
|
+
}
|
855
|
+
print_description_list(description_cols, policy_type)
|
856
|
+
print reset,"\n"
|
857
|
+
|
858
|
+
# show option types
|
859
|
+
print_h2 "Policy Type Options"
|
860
|
+
print format_option_types_table(policy_type['optionTypes'], options, 'policy')
|
861
|
+
print reset,"\n"
|
862
|
+
end
|
863
|
+
return 0
|
913
864
|
end
|
914
865
|
|
915
866
|
private
|
@@ -978,9 +929,42 @@ class Morpheus::Cli::PoliciesCommand
|
|
978
929
|
end
|
979
930
|
end
|
980
931
|
|
932
|
+
def find_policy_type_by_name_or_id(val)
|
933
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
934
|
+
return find_policy_type_by_id(val)
|
935
|
+
else
|
936
|
+
return find_policy_type_by_name(val)
|
937
|
+
end
|
938
|
+
end
|
939
|
+
|
940
|
+
def find_policy_type_by_name(name)
|
941
|
+
json_response = nil
|
942
|
+
|
943
|
+
# json_response = @policies_interface.list_policy_types({name: name.to_s})
|
944
|
+
json_response = @policies_interface.list_policy_types({max: 10000})
|
945
|
+
policy_types = json_response['policyTypes']
|
946
|
+
match_value = name.to_s.downcase
|
947
|
+
policy_types = policy_types.select {|it| it['name'].to_s.downcase == match_value || it['code'].to_s.downcase == match_value }
|
948
|
+
if policy_types.empty?
|
949
|
+
print_red_alert "Policy not found by name #{name}"
|
950
|
+
return nil
|
951
|
+
elsif policy_types.size > 1
|
952
|
+
print_red_alert "#{policy_types.size} policy types found by name or code #{name}"
|
953
|
+
# print_policies_table(policy_types, {color: red})
|
954
|
+
rows = policy_types.collect do |it|
|
955
|
+
{id: it['id'], name: it['name'], code: it['code']}
|
956
|
+
end
|
957
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
958
|
+
return nil
|
959
|
+
else
|
960
|
+
policy_type = policy_types[0]
|
961
|
+
return policy_type
|
962
|
+
end
|
963
|
+
end
|
964
|
+
|
981
965
|
def find_policy_type_by_id(id)
|
982
966
|
begin
|
983
|
-
json_response = @policies_interface.
|
967
|
+
json_response = @policies_interface.get_policy_type(id.to_s)
|
984
968
|
return json_response['policyType']
|
985
969
|
rescue RestClient::Exception => e
|
986
970
|
if e.response && e.response.code == 404
|
@@ -631,6 +631,8 @@ EOT
|
|
631
631
|
params['authority'] = v_prompt['authority']
|
632
632
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2}], options[:options])
|
633
633
|
params['description'] = v_prompt['description']
|
634
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'landingUrl', 'fieldLabel' => 'landingUrl', 'type' => 'text', 'displayOrder' => 3, 'description' => 'An optional override for the default landing page after login for a user.'}], options[:options])
|
635
|
+
params['landingUrl'] = v_prompt['landingUrl']
|
634
636
|
|
635
637
|
if params['owner']
|
636
638
|
if @is_master_account && has_complete_access
|
@@ -2479,6 +2481,7 @@ Update default workflow access for a role.
|
|
2479
2481
|
[
|
2480
2482
|
{'fieldName' => 'authority', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
2481
2483
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
|
2484
|
+
{'fieldName' => 'landingUrl', 'fieldLabel' => 'Landing URL', 'type' => 'text', 'description' => 'An optional override for the default landing page after login for a user.'},
|
2482
2485
|
{'fieldName' => 'roleType', 'fieldLabel' => 'Role Type', 'type' => 'select', 'selectOptions' => [{'name' => 'User Role', 'value' => 'user'}, {'name' => 'Account Role', 'value' => 'account'}], 'defaultValue' => 'user'},
|
2483
2486
|
{'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'text'},
|
2484
2487
|
{'fieldName' => 'multitenant', 'fieldLabel' => 'Multitenant', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'A Multitenant role is automatically copied into all existing subaccounts as well as placed into a subaccount when created. Useful for providing a set of predefined roles a Customer can use'},
|
@@ -131,6 +131,7 @@ module Morpheus::Cli::AccountsHelper
|
|
131
131
|
"ID" => 'id',
|
132
132
|
"Name" => 'authority',
|
133
133
|
"Description" => 'description',
|
134
|
+
"Landing URL" => 'landingUrl',
|
134
135
|
#"Scope" => lambda {|it| it['scope'] },
|
135
136
|
"Type" => lambda {|it| format_role_type(it) },
|
136
137
|
"Multitenant" => lambda {|it|
|
@@ -149,6 +150,7 @@ module Morpheus::Cli::AccountsHelper
|
|
149
150
|
"ID" => 'id',
|
150
151
|
"Name" => 'authority',
|
151
152
|
"Description" => 'description',
|
153
|
+
"Landing URL" => 'landingUrl',
|
152
154
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
153
155
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
154
156
|
}
|
@@ -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
|