morpheus-cli 8.0.5 → 8.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36e5150354f68d0d1bf97da71cfc98e20bd78e68ab59a919d464b8d453a06ed3
4
- data.tar.gz: 7bf57c87149c0eb357886fccafe0c1b8ead22b289c23127d5b6a6b0947ae12e1
3
+ metadata.gz: 5bd49f7ba0c5284049c949b7eb9abab30586335cf7994071467ac2e40e5052f8
4
+ data.tar.gz: 8042138fa3aa60542f6a042a035172f15aac37483fd3fea25fd11ed550e1ba29
5
5
  SHA512:
6
- metadata.gz: f3d3be35646cafaf52af86eeef145350af72995ee762b5b958e2d49a10f263eb2803a4223b286f4358bf0d2904e2a1694a5282520ade5941184b7628bcc379d0
7
- data.tar.gz: b744429719628a8048759e8844f3687f1800e5e3bb45b5369c87efc76d577a0fa626821b8ff468f3f4166d12f6bef40ee4381a6e208cd9ea6c5f7836896edf3c
6
+ metadata.gz: 24dd7b12d6f4a3884844af6ad53736cfecf3c28102aae2f2b8a710bac97433955aae2d7771f367ae8241f721a701c5a8d375a95fe065af5162280ebbe737d342
7
+ data.tar.gz: 1dca804ca56f509dcf13d9a35312de4429b0163e74f4140952fa06d15b8928f8ebe3132537b77ae1939307a2fcb69aa9d9ea52e2293753a042fdf5a6cf8da2f2
data/Dockerfile CHANGED
@@ -1,5 +1,5 @@
1
1
  FROM ruby:2.7.5
2
2
 
3
- RUN gem install morpheus-cli -v 8.0.5
3
+ RUN gem install morpheus-cli -v 8.0.6
4
4
 
5
5
  ENTRYPOINT ["morpheus"]
@@ -746,6 +746,10 @@ class Morpheus::APIClient
746
746
  Morpheus::StorageVolumeTypesInterface.new(common_interface_options).setopts(@options)
747
747
  end
748
748
 
749
+ def storage_datastores
750
+ Morpheus::StorageDatastoresInterface.new(common_interface_options).setopts(@options)
751
+ end
752
+
749
753
  def library_instance_types
750
754
  Morpheus::LibraryInstanceTypesInterface.new(common_interface_options).setopts(@options)
751
755
  end
@@ -345,4 +345,12 @@ class Morpheus::ClustersInterface < Morpheus::APIClient
345
345
  execute(method: :get, url: url, headers: headers)
346
346
  end
347
347
 
348
+ def load_balancer_port(params={})
349
+ url = "#{@base_url}/api/clusters/load-balancer-port"
350
+ headers = { params: {}, authorization: "Bearer #{@access_token}" }
351
+ headers[:params].merge!(params)
352
+
353
+ execute(method: :get, url: url, headers: headers)
354
+ end
355
+
348
356
  end
@@ -34,4 +34,7 @@ class Morpheus::NetworkFloatingIpsInterface < Morpheus::APIClient
34
34
  execute(method: :put, url: "#{base_path}/#{CGI::escape(id.to_s)}/release", params: params, payload: payload, headers: headers)
35
35
  end
36
36
 
37
+ def allocate(payload={}, params={}, headers={})
38
+ execute(method: :post, url: "#{base_path}/allocate", params: params, payload: payload, headers: headers)
39
+ end
37
40
  end
@@ -0,0 +1,44 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::StorageDatastoresInterface < Morpheus::APIClient
4
+
5
+ def base_path
6
+ "#{@base_url}/api/data-stores"
7
+ end
8
+
9
+ def get(id, params={})
10
+ raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
11
+ url = "#{@base_url}/api/data-stores/#{id}"
12
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
13
+ opts = {method: :get, url: url, headers: headers}
14
+ execute(opts)
15
+ end
16
+
17
+ def list(params={})
18
+ url = base_path
19
+ headers = { params: params, authorization: "Bearer #{@access_token}" }
20
+ opts = {method: :get, url: url, headers: headers}
21
+ execute(opts)
22
+ end
23
+
24
+ def load_type_options(datastore_type)
25
+ url = "/api/data-stores/#{datastore_type}/option-types"
26
+ headers = { params: {}, authorization: "Bearer #{@access_token}" }
27
+ opts = {method: :get, url: url, headers: headers}
28
+ execute(opts)
29
+ end
30
+
31
+ def create(options)
32
+ url = "#{@base_url}/api/data-stores"
33
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
34
+ payload = options
35
+ execute(method: :post, url: url, headers: headers, payload: payload.to_json)
36
+ end
37
+
38
+ def update(id, payload)
39
+ url = "#{@base_url}/api/data-stores/#{id}"
40
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
41
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
42
+ execute(opts)
43
+ end
44
+ end
@@ -102,9 +102,10 @@ class Morpheus::Cli::ClientsCommand
102
102
  "ID" => 'id',
103
103
  "Client ID" => 'clientId',
104
104
  "Access Token Validity Seconds" => 'accessTokenValiditySeconds',
105
- "Refresh Token Validity Seconds" => 'refreshTokenValiditySeconds'
105
+ "Refresh Token Validity Seconds" => 'refreshTokenValiditySeconds',
106
+ # "Scopes" => lambda {|client| client['scopes'].join(", ")},
107
+ "Redirect URI" => lambda {|client| client['redirectUris'].join(", ")}
106
108
  }
107
-
108
109
  print_description_list(client_columns, client)
109
110
  print reset,"\n"
110
111
 
@@ -122,7 +123,7 @@ class Morpheus::Cli::ClientsCommand
122
123
  optparse = Morpheus::Cli::OptionParser.new do |opts|
123
124
  opts.banner = subcommand_usage("[clientId] [options]")
124
125
  build_option_type_options(opts, options, add_client_option_types)
125
- build_common_options(opts, options, [:payload, :options, :json, :dry_run, :remote])
126
+ build_standard_add_options(opts, options)
126
127
  opts.footer = "Add New Oauth Client Record."
127
128
  end
128
129
  optparse.parse!(args)
@@ -150,6 +151,9 @@ class Morpheus::Cli::ClientsCommand
150
151
  payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
151
152
  # prompt for options
152
153
  params = Morpheus::Cli::OptionTypes.prompt(add_client_option_types, options[:options], @api_client, options[:params])
154
+ if params['redirectUris'] && params['redirectUris'].is_a?(String)
155
+ params['redirectUris'] = params['redirectUris'].split(',').collect {|it| it.strip}.reject {|it| it.empty?}
156
+ end
153
157
  payload.deep_merge!({'client' => params}) unless params.empty?
154
158
  end
155
159
 
@@ -179,7 +183,7 @@ class Morpheus::Cli::ClientsCommand
179
183
  optparse = Morpheus::Cli::OptionParser.new do |opts|
180
184
  opts.banner = subcommand_usage("[clientId] [options]")
181
185
  build_option_type_options(opts, options, client_option_types)
182
- build_common_options(opts, options, [:payload, :options, :json, :dry_run, :remote])
186
+ build_standard_update_options(opts, options)
183
187
  opts.footer = "Update Oauth Client Record."
184
188
  end
185
189
  optparse.parse!(args)
@@ -206,11 +210,13 @@ class Morpheus::Cli::ClientsCommand
206
210
  }
207
211
  }
208
212
  # allow arbitrary -O options
209
- payload.deep_merge!({'page' => passed_options}) unless passed_options.empty?
213
+ payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
210
214
  # prompt for options
211
215
  #params = Morpheus::Cli::OptionTypes.prompt(update_wiki_page_option_types, options[:options], @api_client, options[:params])
212
216
  params = passed_options
213
-
217
+ if params['redirectUris'] && params['redirectUris'].is_a?(String)
218
+ params['redirectUris'] = params['redirectUris'].split(',').collect {|it| it.strip}.reject {|it| it.empty?}
219
+ end
214
220
  if params.empty?
215
221
  raise_command_error "Specify at least one option to update.\n#{optparse}"
216
222
  end
@@ -332,7 +338,8 @@ class Morpheus::Cli::ClientsCommand
332
338
  {'fieldName' => 'clientId', 'fieldLabel' => 'Client Id', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
333
339
  {'fieldName' => 'clientSecret', 'fieldLabel' => 'Client Secret', 'type' => 'text', 'displayOrder' => 2},
334
340
  {'fieldName' => 'accessTokenValiditySeconds', 'fieldLabel' => 'Access Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 3},
335
- {'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 4}
341
+ {'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 4},
342
+ {'fieldName' => 'redirectUris', 'fieldLabel' => 'Redirect URI', 'type' => 'text', 'displayOrder' => 5}
336
343
  ]
337
344
  end
338
345
  end
@@ -7,7 +7,7 @@ class Morpheus::Cli::CloudDatastoresCommand
7
7
  # set_command_name :'cloud-datastores'
8
8
  set_command_name :'datastores'
9
9
 
10
- register_subcommands :list, :get, :update
10
+ register_subcommands :list, :get, :update, :add
11
11
 
12
12
  def initialize()
13
13
  # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -18,6 +18,7 @@ class Morpheus::Cli::CloudDatastoresCommand
18
18
  @cloud_datastores_interface = @api_client.cloud_datastores
19
19
  @clouds_interface = @api_client.clouds
20
20
  @options_interface = @api_client.options
21
+ @storage_datastore_interface = @api_client.storage_datastores
21
22
  end
22
23
 
23
24
  def handle(args)
@@ -379,6 +380,114 @@ class Morpheus::Cli::CloudDatastoresCommand
379
380
  end
380
381
  end
381
382
 
383
+ def add(args)
384
+ options = {}
385
+ params = {}
386
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
387
+ opts.banner = subcommand_usage("[name] [options]")
388
+ build_common_options(opts, options, [:options, :payload, :json, :yaml, :dry_run, :quiet])
389
+ opts.on( '-n', '--name NAME', "Name" ) do |val|
390
+ options['name'] = val
391
+ end
392
+ opts.on( '-t', '--type DATASTORE_TYPE', "Datastore Type" ) do |val|
393
+ options['datastoreType'] = val
394
+ end
395
+ opts.on( '-c', '--cloud DATASTORE_CLOUD', "Datastore Cloud" ) do |val|
396
+ options['cloud'] = val
397
+ end
398
+ opts.footer = "Create a new Datastore.\n" +
399
+ "[name] is required. This is the name of the new datastore. It may also be passed as --name or inside your config."
400
+ end
401
+ optparse.parse!(args)
402
+ if args.count > 1
403
+ print_error Morpheus::Terminal.angry_prompt
404
+ puts_error "#{command_name} add expects 0-1 arguments and received #{args.count}: #{args}\n#{optparse}"
405
+ return 1
406
+ end
407
+ # allow name as first argument
408
+ if args[0] # && !options[:name]
409
+ options[:name] = args[0]
410
+ end
411
+ connect(options)
412
+ begin
413
+ options[:options] ||= {}
414
+ passed_options = (options[:options] || {}).reject {|k,v| k.is_a?(Symbol) }
415
+ payload = {}
416
+ if options[:payload]
417
+ # payload is from parsed json|yaml files or arguments.
418
+ payload = options[:payload]
419
+ # merge -O options
420
+ payload.deep_merge!(passed_options) unless passed_options.empty?
421
+ # support some options on top of --payload
422
+ [:name, :description, :environment].each do |k|
423
+ if options.key?(k)
424
+ payload[k.to_s] = options[k]
425
+ end
426
+ end
427
+ else
428
+ # prompt for payload
429
+ payload = {}
430
+ # merge -O options
431
+ payload.deep_merge!(passed_options) unless passed_options.empty?
432
+
433
+ # Name
434
+ if passed_options['name']
435
+ payload['name'] = passed_options['name']
436
+ else
437
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this archive bucket.'}], options, @api_client)
438
+ payload['name'] = v_prompt['name']
439
+ end
440
+
441
+ #Datastore Type
442
+ if passed_options['datastoreType']
443
+ payload['datastoreType'] = passed_options['datastoreType']
444
+ else
445
+ payload['datastoreType'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'datastoreType', 'fieldLabel' => 'Type', 'type' => 'select', 'required' => true, 'optionSource' => 'datastoreTypes'}], options[:options], @api_client)['datastoreType']
446
+ end
447
+
448
+ if passed_options['cloud']
449
+ zone = passed_options['cloud']
450
+ else
451
+ zone = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zone', 'fieldLabel' => 'Cloud', 'type' => 'select', 'required' => true, 'optionSource' => 'cloudsForDatastores'}], options[:options], @api_client)['zone']
452
+ end
453
+
454
+ if zone
455
+ payload['refType'] = 'ComputeZone'
456
+ payload['refId'] = zone
457
+ end
458
+
459
+ option_types = load_option_types_for_datastore_type(payload['datastoreType'])
460
+
461
+ values = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options], @api_client)
462
+ if values['domain']
463
+ payload.merge!(values['domain']) if values['domain'].is_a?(Hash)
464
+ end
465
+ if values['config']
466
+ payload['config'] = {}
467
+ payload['config'].merge!(values['config']) if values['config'].is_a?(Hash)
468
+ end
469
+
470
+ @storage_datastore_interface.setopts(options)
471
+ if options[:dry_run]
472
+ print_dry_run @storage_datastore_interface.dry.create({'datastore' => payload})
473
+ return
474
+ end
475
+ json_response = @storage_datastore_interface.create({'datastore' => payload})
476
+ datastore = json_response['datastore']
477
+ if options[:json]
478
+ print JSON.pretty_generate(json_response),"\n"
479
+ elsif !options[:quiet]
480
+ datastore = json_response['datastore']
481
+ print_green_success "Datastore #{datastore['name']} created"
482
+ #get([datastore['id']])
483
+ end
484
+ end
485
+ rescue RestClient::Exception => e
486
+ print_rest_exception(e, options)
487
+ exit 1
488
+ end
489
+ end
490
+
382
491
  private
383
492
 
384
493
 
@@ -428,4 +537,7 @@ class Morpheus::Cli::CloudDatastoresCommand
428
537
  end
429
538
  end
430
539
 
540
+ def load_option_types_for_datastore_type(datastore_type)
541
+ return @storage_datastore_interface.load_type_options(datastore_type)
542
+ end
431
543
  end
@@ -848,7 +848,6 @@ EOT
848
848
  "Discovery" => lambda {|it| format_boolean it['hasDiscovery'] },
849
849
  "Cloud Init" => lambda {|it| format_boolean it['hasCloudInit'] },
850
850
  "Folders" => lambda {|it| format_boolean it['hasFolders'] },
851
- "Floating Ips" => lambda {|it| format_boolean it['hasFloatingIps'] },
852
851
  # "Marketplace" => lambda {|it| format_boolean it['hasMarketplace'] },
853
852
  "Public Cloud" => lambda {|it| format_boolean(it['cloud'] == 'public') },
854
853
  }
@@ -123,7 +123,6 @@ EOT
123
123
  "Discovery" => lambda {|it| format_boolean it['hasDiscovery'] },
124
124
  "Cloud Init" => lambda {|it| format_boolean it['hasCloudInit'] },
125
125
  "Folders" => lambda {|it| format_boolean it['hasFolders'] },
126
- "Floating Ips" => lambda {|it| format_boolean it['hasFloatingIps'] },
127
126
  # "Marketplace" => lambda {|it| format_boolean it['hasMarketplace'] },
128
127
  "Public Cloud" => lambda {|it| format_boolean(it['cloud'] == 'public') },
129
128
  }
@@ -652,6 +652,10 @@ class Morpheus::Cli::Clusters
652
652
  metadata_option_type = option_type_list.find {|type| type['fieldName'] == 'metadata' }
653
653
  option_type_list = option_type_list.reject {|type| type['fieldName'] == 'metadata' }
654
654
 
655
+ # remove load balancer option_type, prompt manually
656
+ loadbalancer_option_type = option_type_list.find{|type| type['fieldName'] == 'loadBalancerId'}
657
+ option_type_list = option_type_list.reject { |type| type['fieldName'] == 'loadBalancerId' }
658
+
655
659
  server_count = layout['serverCount']
656
660
 
657
661
  # KLUDGE: google zone required for network selection
@@ -754,6 +758,37 @@ class Morpheus::Cli::Clusters
754
758
  end
755
759
  end
756
760
 
761
+ if loadbalancer_option_type
762
+ lb_payload = { computeTypeLayoutId: cluster_payload['layout']['id']}
763
+ load_balancer_id = prompt_cluster_load_balancer(cluster_payload, options)
764
+ if load_balancer_id != false
765
+ lb_payload['loadBalancerId'] = load_balancer_id
766
+ lb_payload['loadBalancerInstanceId'] = -1
767
+ lb_port_result = @clusters_interface.load_balancer_port(lb_payload)
768
+ lb_options = lb_port_result['optionTypes']
769
+ lb_option_results = Morpheus::Cli::OptionTypes.prompt(lb_options, options[:options], @api_client, api_params)
770
+
771
+ load_balancer_payload = {
772
+ port: lb_port_result.dig('loadBalancerPort', 'externalPort'),
773
+ enabled: lb_port_result.dig('loadBalancer', 'enabled'),
774
+ loadBalancerId: load_balancer_id,
775
+ backendPort: lb_port_result.dig('loadBalancerPort', 'internalPort'),
776
+ loadBalancer: { id: load_balancer_id },
777
+ vipPool: (lb_option_results.dig('domain', 'vipPool') == 'none') ? nil : lb_option_results.dig('domain', 'vipPool'),
778
+ vipAddress: lb_option_results.dig('domain', 'vipAddress'),
779
+ externalAddress: (lb_port_result.dig('loadBalancer', 'externalAddress') == true ) ? 'on': 'off',
780
+ vipShared: (lb_port_result.dig('loadBalancer', 'vipShared') == true ) ? 'on' : 'off',
781
+ vipProtocol: lb_port_result.dig('loadBalancerPort', 'loadBalanceProtocol'),
782
+ instanceId: lb_payload['loadBalancerInstanceId'],
783
+ name: lb_option_results['vipName']
784
+ }
785
+ if lb_option_results['domain']
786
+ load_balancer_payload.merge!(lb_option_results['domain']) { |key, old_val, new_val| old_val }
787
+ end
788
+ cluster_payload['lbInstances'] = [load_balancer_payload.compact!]
789
+ end
790
+ end
791
+
757
792
  cluster_payload['server'] = server_payload
758
793
  payload = {'cluster' => cluster_payload}
759
794
  end
@@ -4,6 +4,7 @@ class Morpheus::Cli::ContainersCommand
4
4
  include Morpheus::Cli::CliCommand
5
5
  include Morpheus::Cli::ProvisioningHelper
6
6
  include Morpheus::Cli::LogsHelper
7
+ include Morpheus::Cli::InfrastructureHelper
7
8
 
8
9
  set_command_name :containers
9
10
  set_command_description "View and manage containers (nodes)."
@@ -18,6 +19,7 @@ class Morpheus::Cli::ContainersCommand
18
19
  @logs_interface = @api_client.logs
19
20
  @execution_request_interface = @api_client.execution_request
20
21
  @clouds_interface = @api_client.clouds
22
+ @network_server_types_interface = @api_client.network_server_types
21
23
  end
22
24
 
23
25
  def handle(args)
@@ -799,14 +801,14 @@ EOT
799
801
  connect(options)
800
802
  container = find_container_by_id(args[0])
801
803
  return 1 if container.nil?
802
- cloud_type = load_container_cloud_type(container)
803
- if !cloud_type['hasFloatingIps']
804
- raise_command_error "Cloud Type #{cloud_type['name']} does support floating IPs."
804
+ network_server_type = load_container_network_server_type(container)
805
+ if !network_server_type['hasFloatingIps']
806
+ raise_command_error "Network Server Type #{network_server_type['name']} does support floating IPs."
805
807
  end
806
808
  payload = parse_payload(options)
807
809
  if payload.nil?
808
810
  payload = parse_passed_options(options)
809
- attach_floating_ip_option_types = cloud_type['floatingIpTypes']
811
+ attach_floating_ip_option_types = network_server_type['floatingIpTypes']
810
812
  if attach_floating_ip_option_types && !attach_floating_ip_option_types.empty?
811
813
  if options[:ip]
812
814
  floating_ip = options[:ip].to_s.sub(/\Aip\-/i, '')
@@ -829,7 +831,7 @@ EOT
829
831
  # payload.deep_merge!({'container' => v_prompt})
830
832
  payload.deep_merge!(v_prompt)
831
833
  else
832
- # raise_command_error "Cloud Type #{cloud_type['name']} does not defined any floating IP inputs."
834
+ # raise_command_error "Network Server Type #{network_server_type['name']} does not defined any floating IP inputs."
833
835
  end
834
836
  end
835
837
  confirm!("Are you sure you would like to attach this floating IP to container #{container['id']}?", options)
@@ -861,9 +863,9 @@ EOT
861
863
  connect(options)
862
864
  container = find_container_by_id(args[0])
863
865
  return 1 if container.nil?
864
- cloud_type = load_container_cloud_type(container)
865
- if !cloud_type['hasFloatingIps']
866
- raise_command_error "Cloud Type #{cloud_type['name']} does support floating IPs."
866
+ network_server_type = load_container_network_server_type(container)
867
+ if !network_server_type['hasFloatingIps']
868
+ raise_command_error "Network Type #{network_server_type['name']} does support floating IPs."
867
869
  end
868
870
  payload = parse_payload(options)
869
871
  if payload.nil?
@@ -948,18 +950,18 @@ EOT
948
950
  return provision_type
949
951
  end
950
952
 
951
- def load_container_cloud_type(container)
952
- cloud_type_code = container['cloud']['type'] rescue nil
953
- cloud_type = nil
954
- if cloud_type_code
955
- cloud_type = @clouds_interface.cloud_types({code:cloud_type_code})['zoneTypes'][0]
956
- if cloud_type.nil?
957
- raise_command_error "Cloud Type not found by code #{cloud_type_code}"
958
- end
953
+ def load_container_network_server_type(container)
954
+ cloud = find_cloud_by_id(container['cloud']['id'])
955
+ network_server_type_code = cloud['networkServer']['type'] rescue nil
956
+ network_server_type = nil
957
+ if network_server_type_code
958
+ network_server_type = @network_server_types_interface.list({code:network_server_type_code})['networkServerTypes'][0]
959
+ if network_server_type.nil?
960
+ raise_command_error "Network Server Type not found by code #{network_server_type_code}"
961
+ end
959
962
  else
960
- raise_command_error "Unable to determine cloud type for container #{container['id']}"
963
+ raise_command_error "Unable to determine network server type for container #{container['id']}"
961
964
  end
962
- return cloud_type
965
+ return network_server_type
963
966
  end
964
-
965
967
  end
@@ -840,7 +840,7 @@ class Morpheus::Cli::NetworkDomainsCommand
840
840
  print_red_alert "#{network_domains.size} network domains found by name #{name}"
841
841
  # print_networks_table(networks, {color: red})
842
842
  rows = network_domains.collect do |network_domain|
843
- {id: it['id'], name: it['name']}
843
+ {id: network_domain['id'], name: network_domain['name']}
844
844
  end
845
845
  puts as_pretty_table(rows, [:id, :name], {color:red})
846
846
  return nil
@@ -6,7 +6,7 @@ class Morpheus::Cli::NetworkFloatingIps
6
6
 
7
7
  set_command_name :'network-floating-ips'
8
8
  set_command_description "View and manage network floating IPs."
9
- register_subcommands :list, :get, :release
9
+ register_subcommands :list, :get, :release, :allocate
10
10
 
11
11
  # RestCommand settings
12
12
  register_interfaces :network_floating_ips
@@ -49,6 +49,44 @@ EOT
49
49
  return 0, nil
50
50
  end
51
51
 
52
+ def allocate(args)
53
+ options = {}
54
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
55
+ opts.banner = subcommand_usage()
56
+ build_standard_add_options(opts, options)
57
+ opts.footer = <<-EOT
58
+ Allocate a new #{rest_label.downcase}.
59
+ Only the following cloud types support this command: OpenStack, Huawei and OpenTelekom
60
+ EOT
61
+ end
62
+ optparse.parse!(args)
63
+ verify_args!(args:args, optparse:optparse, count:0)
64
+ connect(options)
65
+ payload = {}
66
+ if options[:payload]
67
+ payload = options[:payload]
68
+ payload.deep_merge!(parse_passed_options(options))
69
+ else
70
+ payload.deep_merge!(parse_passed_options(options))
71
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkServerId', 'fieldLabel' => 'Network Service', 'type' => 'select', 'optionSource' => 'floatingIpNetworkServers', 'required' => true, 'description' => 'Choose a network service.'}], options[:options], @api_client, {})
72
+ payload[:networkServerId] = v_prompt['networkServerId']
73
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'floatingIpPoolId', 'fieldLabel' => 'Network Floating Ip Pool', 'type' => 'select', 'optionSource' => 'floatingIpPools', 'required' => true, 'description' => 'Choose a network service.'}], options[:options], @api_client, {networkServerId: v_prompt['networkServerId']})
74
+ payload[:floatingIpPoolId] = v_prompt['floatingIpPoolId']
75
+ end
76
+
77
+ rest_interface.setopts(options)
78
+ if options[:dry_run]
79
+ print_dry_run rest_interface.dry.allocate(payload)
80
+ return 0, nil
81
+ end
82
+ json_response = rest_interface.allocate(payload)
83
+ render_response(json_response, options) do
84
+ print_green_success "Allocating #{rest_label.downcase} with ipAddress: #{json_response['networkFloatingIp']['ipAddress'] }"
85
+ id = json_response['networkFloatingIp']['id']
86
+ _get(id.to_s, {}, options )
87
+ end
88
+ end
89
+
52
90
  protected
53
91
 
54
92
  def build_list_options(opts, options, params)
@@ -328,6 +328,8 @@ class Morpheus::Cli::NetworkRoutersCommand
328
328
  cloud = {'id' => cloud_id}
329
329
  end
330
330
  router['zone'] = params['zone'] = {'id' => cloud['id']}
331
+ # add router type to be used for option prompts
332
+ params['router']['zone'] = {'id' => cloud['id']}
331
333
  end
332
334
 
333
335
  # prompt for enabled
@@ -337,7 +339,18 @@ class Morpheus::Cli::NetworkRoutersCommand
337
339
 
338
340
  # prompt options
339
341
  option_opts = options[:options].deep_merge!({'config' => options[:options].clone})
340
- option_result = Morpheus::Cli::OptionTypes.prompt(option_types, option_opts.merge({:context_map => {'networkRouter' => ''}}), @api_client, params)
342
+ # option types are mixing context router and networkRouter, so we need to copy these to avoid prompt for router.name if passed in
343
+ if option_opts['name'] || option_opts['description']
344
+ option_opts['router'] ||= {}
345
+ option_opts['router']['name'] = option_opts['name'] if option_opts['name']
346
+ option_opts['router']['description'] = option_opts['description'] if option_opts['description']
347
+ end
348
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, option_opts.merge({:context_map => {'networkRouter' => 'router'}}), @api_client, params)
349
+ # option types are mixing context router and networkRouter, so we need to clean up the payload
350
+ router_params = option_result.delete('router')
351
+ if router_params.is_a?(Hash)
352
+ option_result = router_params.deep_merge(option_result)
353
+ end
341
354
  payload = {'networkRouter' => router.deep_merge(option_result)}
342
355
  payload['networkRouter']['config'] = option_result['config'] if option_result['config']
343
356
  end