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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +6 -0
  4. data/lib/morpheus/api/api_client.rb +12 -0
  5. data/lib/morpheus/api/clusters_interface.rb +7 -0
  6. data/lib/morpheus/api/network_security_server_types_interface.rb +9 -0
  7. data/lib/morpheus/api/network_server_types_interface.rb +9 -0
  8. data/lib/morpheus/api/network_servers_interface.rb +4 -0
  9. data/lib/morpheus/cli/cli_command.rb +1 -0
  10. data/lib/morpheus/cli/commands/clouds.rb +101 -28
  11. data/lib/morpheus/cli/commands/clouds_types.rb +141 -0
  12. data/lib/morpheus/cli/commands/clusters.rb +43 -0
  13. data/lib/morpheus/cli/commands/instances.rb +1 -0
  14. data/lib/morpheus/cli/commands/network_dhcp_relays_command.rb +1 -42
  15. data/lib/morpheus/cli/commands/network_dhcp_servers_command.rb +3 -44
  16. data/lib/morpheus/cli/commands/network_edge_clusters_command.rb +1 -42
  17. data/lib/morpheus/cli/commands/network_firewalls_command.rb +1 -41
  18. data/lib/morpheus/cli/commands/network_pool_servers_command.rb +3 -1
  19. data/lib/morpheus/cli/commands/network_routers_command.rb +4 -6
  20. data/lib/morpheus/cli/commands/network_security_server_types.rb +20 -0
  21. data/lib/morpheus/cli/commands/network_server_types_command.rb +20 -0
  22. data/lib/morpheus/cli/commands/network_servers_command.rb +368 -0
  23. data/lib/morpheus/cli/commands/network_transport_zones_command.rb +1 -41
  24. data/lib/morpheus/cli/commands/networks_command.rb +1 -1
  25. data/lib/morpheus/cli/commands/options.rb +135 -2
  26. data/lib/morpheus/cli/commands/policies_command.rb +112 -128
  27. data/lib/morpheus/cli/commands/roles.rb +3 -0
  28. data/lib/morpheus/cli/mixins/accounts_helper.rb +2 -0
  29. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +103 -2
  30. data/lib/morpheus/cli/mixins/networks_helper.rb +62 -0
  31. data/lib/morpheus/cli/mixins/print_helper.rb +28 -7
  32. data/lib/morpheus/cli/mixins/prompt_helper.rb +15 -0
  33. data/lib/morpheus/cli/mixins/provisioning_helper.rb +25 -9
  34. data/lib/morpheus/cli/mixins/rest_command.rb +1 -1
  35. data/lib/morpheus/cli/option_types.rb +3 -3
  36. data/lib/morpheus/cli/version.rb +1 -1
  37. data/lib/morpheus/logging.rb +6 -3
  38. 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
@@ -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
- build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
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 != 0
773
- print_error Morpheus::Terminal.angry_prompt
774
- puts_error "wrong number of arguments, expected 0 and got #{args.count}\n#{optparse}"
775
- return 1
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
- begin
780
- @policies_interface.setopts(options)
781
- if options[:dry_run]
782
- print_dry_run @policies_interface.dry.list_policy_types(params)
783
- return 0
784
- end
785
- json_response = @policies_interface.list_policy_types()
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
- if options[:json]
788
- puts as_json(json_response, options, "policyTypes")
789
- return 0
790
- elsif options[:yaml]
791
- puts as_yaml(json_response, options, "policyTypes")
792
- return 0
793
- elsif options[:csv]
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
- columns = [:id, :name]
808
- if options[:include_fields]
809
- columns = options[:include_fields]
810
- end
811
- print cyan
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
- return 0
817
- rescue RestClient::Exception => e
818
- print_rest_exception(e, options)
819
- return 1
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
- build_common_options(opts, options, [:json, :dry_run, :remote])
829
- opts.footer = "Get details about a policy type." + "\n" +
830
- "[policy-type] is required. This is ID of a policy type."
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
- begin
842
- policy_type_id = args[0].to_s
843
- @policies_interface.setopts(options)
844
- if options[:dry_run]
845
- print_dry_run @policies_interface.dry.get_policy_type(policy_type_id, params)
846
- return 0
847
- end
848
- json_response = @policies_interface.get_policy_type(policy_type_id, params)
849
- policy_type = json_response['policyType']
850
- if options[:json]
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.list_policy_types
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.get_type(id.to_s)
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