morpheus-cli 6.2.2 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
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