morpheus-cli 5.5.3.2 → 6.0.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/lib/morpheus/api/api_client.rb +8 -0
- data/lib/morpheus/api/cloud_resource_pools_interface.rb +28 -3
- data/lib/morpheus/api/containers_interface.rb +10 -0
- data/lib/morpheus/api/doc_interface.rb +1 -10
- data/lib/morpheus/api/key_pairs_interface.rb +9 -0
- data/lib/morpheus/api/network_floating_ips_interface.rb +37 -0
- data/lib/morpheus/api/resource_pool_groups_interface.rb +51 -0
- data/lib/morpheus/cli/cli_command.rb +17 -11
- data/lib/morpheus/cli/commands/appliance_settings_command.rb +5 -0
- data/lib/morpheus/cli/commands/apps.rb +11 -5
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +42 -12
- data/lib/morpheus/cli/commands/clusters.rb +23 -2
- data/lib/morpheus/cli/commands/containers_command.rb +129 -4
- data/lib/morpheus/cli/commands/doc.rb +14 -13
- data/lib/morpheus/cli/commands/hosts.rb +2 -0
- data/lib/morpheus/cli/commands/instances.rb +8 -2
- data/lib/morpheus/cli/commands/key_pairs.rb +94 -33
- data/lib/morpheus/cli/commands/network_floating_ips.rb +109 -0
- data/lib/morpheus/cli/commands/reports_command.rb +8 -1
- data/lib/morpheus/cli/commands/resource_pool_groups_command.rb +586 -0
- data/lib/morpheus/cli/commands/roles.rb +10 -10
- data/lib/morpheus/cli/commands/service_catalog_command.rb +8 -0
- data/lib/morpheus/cli/commands/tasks.rb +1 -1
- data/lib/morpheus/cli/commands/workflows.rb +1 -1
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +148 -0
- data/lib/morpheus/cli/option_types.rb +1 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/test/cli/doc_test.rb +1 -1
- metadata +6 -2
@@ -8,7 +8,7 @@ class Morpheus::Cli::ContainersCommand
|
|
8
8
|
set_command_name :containers
|
9
9
|
set_command_description "View and manage containers (nodes)."
|
10
10
|
register_subcommands :get, :stop, :start, :restart, :suspend, :eject, :action, :actions, :logs,
|
11
|
-
{:exec => :execution_request}, :clone_image, :import
|
11
|
+
{:exec => :execution_request}, :clone_image, :import, :attach_floating_ip, :detach_floating_ip
|
12
12
|
|
13
13
|
def connect(opts)
|
14
14
|
@api_client = establish_remote_appliance_connection(opts)
|
@@ -17,6 +17,7 @@ class Morpheus::Cli::ContainersCommand
|
|
17
17
|
@provision_types_interface = @api_client.provision_types
|
18
18
|
@logs_interface = @api_client.logs
|
19
19
|
@execution_request_interface = @api_client.execution_request
|
20
|
+
@clouds_interface = @api_client.clouds
|
20
21
|
end
|
21
22
|
|
22
23
|
def handle(args)
|
@@ -696,7 +697,7 @@ EOT
|
|
696
697
|
end
|
697
698
|
json_response = @containers_interface.import(container['id'], payload)
|
698
699
|
render_response(json_response, options) do
|
699
|
-
print_green_success "Import initiated for container
|
700
|
+
print_green_success "Import initiated for container #{container['id']}"
|
700
701
|
end
|
701
702
|
return 0, nil
|
702
703
|
end
|
@@ -768,12 +769,121 @@ EOT
|
|
768
769
|
end
|
769
770
|
json_response = @containers_interface.clone_image(container['id'], payload)
|
770
771
|
render_response(json_response, options) do
|
771
|
-
print_green_success "Clone Image initiated for container
|
772
|
+
print_green_success "Clone Image initiated for container #{container['id']}"
|
772
773
|
end
|
773
774
|
return 0, nil
|
774
775
|
end
|
775
776
|
|
776
|
-
|
777
|
+
def attach_floating_ip(args)
|
778
|
+
options = {}
|
779
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
780
|
+
opts.banner = subcommand_usage("[id]")
|
781
|
+
opts.on('--ip ID', String, "Floating IP Address, in the format 'ip-ID'.") do |val|
|
782
|
+
options[:ip] = val
|
783
|
+
end
|
784
|
+
opts.on('--pool ID', String, "Floating IP Pool Identifier, in the format 'pool-ID'.") do |val|
|
785
|
+
options[:pool] = val
|
786
|
+
end
|
787
|
+
opts.on('--bandwidth VALUE', String, "Floating IP Bandidth (Mbit/s). Only cloud types Huawei and OpenTelekom support this option.") do |val|
|
788
|
+
options[:bandwidth] = val
|
789
|
+
end
|
790
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
791
|
+
opts.footer = <<-EOT
|
792
|
+
Attach a floating IP to a container.
|
793
|
+
[id] is required. This is the id of a container.
|
794
|
+
Only the following cloud types support this command: OpenStack, Huawei and OpenTelekom
|
795
|
+
EOT
|
796
|
+
end
|
797
|
+
optparse.parse!(args)
|
798
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
799
|
+
connect(options)
|
800
|
+
container = find_container_by_id(args[0])
|
801
|
+
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."
|
805
|
+
end
|
806
|
+
payload = parse_payload(options)
|
807
|
+
if payload.nil?
|
808
|
+
payload = parse_passed_options(options)
|
809
|
+
attach_floating_ip_option_types = cloud_type['floatingIpTypes']
|
810
|
+
if attach_floating_ip_option_types && !attach_floating_ip_option_types.empty?
|
811
|
+
if options[:ip]
|
812
|
+
floating_ip = options[:ip].to_s.sub(/\Aip\-/i, '')
|
813
|
+
floating_ip = (floating_ip =~ /\A\d{1,}\Z/) ? "ip-#{floating_ip.to_s}" : floating_ip
|
814
|
+
options[:options]['config'] ||= {}
|
815
|
+
options[:options]['config']['osExternalNetworkId'] = floating_ip
|
816
|
+
elsif options[:pool]
|
817
|
+
floating_ip = options[:pool].to_s.sub(/\Apool\-/i, '')
|
818
|
+
floating_ip = (floating_ip =~ /\A\d{1,}\Z/) ? "pool-#{floating_ip.to_s}" : floating_ip
|
819
|
+
options[:options]['config'] ||= {}
|
820
|
+
options[:options]['config']['osExternalNetworkId'] = floating_ip
|
821
|
+
end
|
822
|
+
if options[:bandwidth]
|
823
|
+
options[:options]['config'] ||= {}
|
824
|
+
options[:options]['config']['floatingIpBandwidth'] = options[:bandwidth].to_i
|
825
|
+
end
|
826
|
+
#api_params = {zoneId: container['cloud'] ? container['cloud']['id'] : nil, resourcePoolId: container['resourcePool'] ? container['resourcePool']['id'] : nil}
|
827
|
+
api_params = {containerId: container['id']}
|
828
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(attach_floating_ip_option_types, options[:options], @api_client, api_params)
|
829
|
+
# payload.deep_merge!({'container' => v_prompt})
|
830
|
+
payload.deep_merge!(v_prompt)
|
831
|
+
else
|
832
|
+
# raise_command_error "Cloud Type #{cloud_type['name']} does not defined any floating IP inputs."
|
833
|
+
end
|
834
|
+
end
|
835
|
+
confirm!("Are you sure you would like to attach this floating IP to container #{container['id']}?", options)
|
836
|
+
@containers_interface.setopts(options)
|
837
|
+
if options[:dry_run]
|
838
|
+
print_dry_run @containers_interface.dry.attach_floating_ip(container['id'], payload)
|
839
|
+
return
|
840
|
+
end
|
841
|
+
json_response = @containers_interface.attach_floating_ip(container['id'], payload)
|
842
|
+
render_response(json_response, options) do
|
843
|
+
print_green_success "Attaching floating IP to container #{container['id']}"
|
844
|
+
end
|
845
|
+
return 0, nil
|
846
|
+
end
|
847
|
+
|
848
|
+
def detach_floating_ip(args)
|
849
|
+
options = {}
|
850
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
851
|
+
opts.banner = subcommand_usage("[id]")
|
852
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
853
|
+
opts.footer = <<-EOT
|
854
|
+
Detach a floating IP from a container.
|
855
|
+
[id] is required. This is the id of a container.
|
856
|
+
Only the following cloud types support this command: OpenStack, Huawei and OpenTelekom
|
857
|
+
EOT
|
858
|
+
end
|
859
|
+
optparse.parse!(args)
|
860
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
861
|
+
connect(options)
|
862
|
+
container = find_container_by_id(args[0])
|
863
|
+
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."
|
867
|
+
end
|
868
|
+
payload = parse_payload(options)
|
869
|
+
if payload.nil?
|
870
|
+
payload = parse_passed_options(options)
|
871
|
+
# prompt
|
872
|
+
end
|
873
|
+
confirm!("Are you sure you would like to detach the floating IP from container #{container['id']}?", options)
|
874
|
+
@containers_interface.setopts(options)
|
875
|
+
if options[:dry_run]
|
876
|
+
print_dry_run @containers_interface.dry.detach_floating_ip(container['id'], payload)
|
877
|
+
return
|
878
|
+
end
|
879
|
+
json_response = @containers_interface.detach_floating_ip(container['id'], payload)
|
880
|
+
render_response(json_response, options) do
|
881
|
+
print_green_success "Detaching floating IP from container #{container['id']}"
|
882
|
+
end
|
883
|
+
return 0, nil
|
884
|
+
end
|
885
|
+
|
886
|
+
private
|
777
887
|
|
778
888
|
def find_container_by_id(id)
|
779
889
|
begin
|
@@ -837,4 +947,19 @@ private
|
|
837
947
|
end
|
838
948
|
return provision_type
|
839
949
|
end
|
950
|
+
|
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
|
959
|
+
else
|
960
|
+
raise_command_error "Unable to determine cloud type for container #{container['id']}"
|
961
|
+
end
|
962
|
+
return cloud_type
|
963
|
+
end
|
964
|
+
|
840
965
|
end
|
@@ -22,7 +22,8 @@ class Morpheus::Cli::Doc
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def connect(options)
|
25
|
-
@api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
|
25
|
+
# @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
|
26
|
+
@api_client = establish_remote_appliance_connection(options)
|
26
27
|
@doc_interface = @api_client.doc
|
27
28
|
end
|
28
29
|
|
@@ -72,12 +73,12 @@ EOT
|
|
72
73
|
params, options = {}, {}
|
73
74
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
74
75
|
opts.banner = subcommand_usage()
|
75
|
-
opts.on(nil, "--refresh", "Refresh the document. By default the openapi.yml and openapi.json are cached by the server.") do
|
76
|
-
|
77
|
-
end
|
78
|
-
opts.on('-g', '--generate', "Alias for --refresh") do
|
79
|
-
|
80
|
-
end
|
76
|
+
# opts.on(nil, "--refresh", "Refresh the document. By default the openapi.yml and openapi.json are cached by the server.") do
|
77
|
+
# params['refresh'] = true
|
78
|
+
# end
|
79
|
+
# opts.on('-g', '--generate', "Alias for --refresh") do
|
80
|
+
# params['refresh'] = true
|
81
|
+
# end
|
81
82
|
build_standard_get_options(opts, options, [], [:csv])
|
82
83
|
opts.footer = <<-EOT
|
83
84
|
Print the Morpheus API OpenAPI Documentation (swagger).
|
@@ -121,12 +122,12 @@ EOT
|
|
121
122
|
options[:yaml] = true
|
122
123
|
options[:format] = :yaml
|
123
124
|
end
|
124
|
-
opts.on(nil, "--refresh", "Refresh the document. By default the openapi.yml and openapi.json are cached by the server.") do
|
125
|
-
|
126
|
-
end
|
127
|
-
opts.on('-g', '--generate', "Alias for --refresh") do
|
128
|
-
|
129
|
-
end
|
125
|
+
# opts.on(nil, "--refresh", "Refresh the document. By default the openapi.yml and openapi.json are cached by the server.") do
|
126
|
+
# params['refresh'] = true
|
127
|
+
# end
|
128
|
+
# opts.on('-g', '--generate', "Alias for --refresh") do
|
129
|
+
# params['refresh'] = true
|
130
|
+
# end
|
130
131
|
opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
|
131
132
|
options[:overwrite] = true
|
132
133
|
end
|
@@ -2936,9 +2936,15 @@ EOT
|
|
2936
2936
|
opts.on('--preserve-volumes [on|off]', ['on','off'], "Preserve Volumes. Default is off. Applies to certain types only.") do |val|
|
2937
2937
|
query_params[:preserveVolumes] = val.nil? ? 'on' : val
|
2938
2938
|
end
|
2939
|
-
opts.on('--
|
2940
|
-
query_params[:
|
2939
|
+
opts.on('--release-ips [on|off]', ['on','off'], "Release Floating IPs. Default is on. Applies to certain types only.") do |val|
|
2940
|
+
query_params[:releaseFloatingIps] = val.nil? ? 'on' : val
|
2941
|
+
query_params[:releaseEIPs] = query_params[:releaseFloatingIps] # old parameter before 6.0
|
2941
2942
|
end
|
2943
|
+
opts.on('--releaseEIPs [on|off]', ['on','off'], "Alias for Release Floating IPs") do |val|
|
2944
|
+
query_params[:releaseFloatingIps] = val.nil? ? 'on' : val
|
2945
|
+
query_params[:releaseEIPs] = query_params[:releaseFloatingIps] # old parameter before 6.0
|
2946
|
+
end
|
2947
|
+
opts.add_hidden_option('--releaseEIPs')
|
2942
2948
|
opts.on( '-f', '--force', "Force Delete" ) do
|
2943
2949
|
query_params[:force] = 'on'
|
2944
2950
|
end
|
@@ -3,7 +3,7 @@ require 'morpheus/cli/cli_command'
|
|
3
3
|
class Morpheus::Cli::KeyPairs
|
4
4
|
include Morpheus::Cli::CliCommand
|
5
5
|
include Morpheus::Cli::AccountsHelper
|
6
|
-
register_subcommands :list, :get, :add, :update, :remove
|
6
|
+
register_subcommands :list, :get, :add, :update, :remove, :generate
|
7
7
|
alias_subcommand :details, :get
|
8
8
|
|
9
9
|
def initialize()
|
@@ -102,38 +102,7 @@ class Morpheus::Cli::KeyPairs
|
|
102
102
|
return 0 if render_result
|
103
103
|
|
104
104
|
unless options[:quiet]
|
105
|
-
|
106
|
-
print cyan
|
107
|
-
if account
|
108
|
-
# print_description_list({"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' } }, key_pair)
|
109
|
-
print_description_list({"Account" => lambda {|it| account['name'] } }, key_pair)
|
110
|
-
end
|
111
|
-
print_description_list({
|
112
|
-
"ID" => 'id',
|
113
|
-
"Name" => 'name',
|
114
|
-
"Fingerprint" => 'fingerprint',
|
115
|
-
#"MD5" => 'md5',
|
116
|
-
# "Has Private Key" => lambda {|it| format_boolean(it['hasPrivateKey']) },
|
117
|
-
# "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
118
|
-
"Created" => lambda {|it| format_local_dt(it['dateCreated']) }
|
119
|
-
#"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
120
|
-
}, key_pair)
|
121
|
-
|
122
|
-
print_h2 "Public Key"
|
123
|
-
print cyan
|
124
|
-
puts "#{key_pair['publicKey']}"
|
125
|
-
|
126
|
-
if key_pair['hasPrivateKey']
|
127
|
-
# print_h2 "Private Key"
|
128
|
-
# print cyan
|
129
|
-
# puts "(hidden)"
|
130
|
-
else
|
131
|
-
# print_h2 "Private Key"
|
132
|
-
print cyan, "\n"
|
133
|
-
puts "This is only a public key. It does not include a private key."
|
134
|
-
end
|
135
|
-
|
136
|
-
print reset,"\n"
|
105
|
+
print_key_pair_details(account, key_pair)
|
137
106
|
end
|
138
107
|
rescue RestClient::Exception => e
|
139
108
|
print_rest_exception(e, options)
|
@@ -180,6 +149,9 @@ class Morpheus::Cli::KeyPairs
|
|
180
149
|
end
|
181
150
|
|
182
151
|
build_common_options(opts, options, [:account, :options, :json, :dry_run, :remote])
|
152
|
+
opts.footer = <<-EOT
|
153
|
+
Add a key pair.
|
154
|
+
EOT
|
183
155
|
end
|
184
156
|
optparse.parse!(args)
|
185
157
|
# if args.count < 1
|
@@ -237,6 +209,10 @@ class Morpheus::Cli::KeyPairs
|
|
237
209
|
opts.banner = subcommand_usage("[name] [options]")
|
238
210
|
build_option_type_options(opts, options, update_key_pair_option_types)
|
239
211
|
build_common_options(opts, options, [:account, :options, :json, :dry_run, :remote])
|
212
|
+
opts.footer = <<-EOT
|
213
|
+
Update a key pair.
|
214
|
+
[name] is required. This is the name or id of a key pair.
|
215
|
+
EOT
|
240
216
|
end
|
241
217
|
optparse.parse!(args)
|
242
218
|
|
@@ -290,6 +266,10 @@ class Morpheus::Cli::KeyPairs
|
|
290
266
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
291
267
|
opts.banner = subcommand_usage("[name]")
|
292
268
|
build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
|
269
|
+
opts.footer = <<-EOT
|
270
|
+
Delete a key pair.
|
271
|
+
[name] is required. This is the name or id of a key pair.
|
272
|
+
EOT
|
293
273
|
end
|
294
274
|
optparse.parse!(args)
|
295
275
|
|
@@ -329,6 +309,50 @@ class Morpheus::Cli::KeyPairs
|
|
329
309
|
end
|
330
310
|
end
|
331
311
|
|
312
|
+
def generate(args)
|
313
|
+
options = {}
|
314
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
315
|
+
opts.banner = subcommand_usage("[name]")
|
316
|
+
build_common_options(opts, options, [:account, :options, :json, :dry_run, :remote])
|
317
|
+
opts.footer = <<-EOT
|
318
|
+
Generate a key pair.
|
319
|
+
EOT
|
320
|
+
end
|
321
|
+
optparse.parse!(args)
|
322
|
+
# if args.count < 1
|
323
|
+
# puts optparse
|
324
|
+
# exit 1
|
325
|
+
# end
|
326
|
+
if args[0]
|
327
|
+
options[:options] ||= {}
|
328
|
+
options[:options]['name'] ||= args[0]
|
329
|
+
end
|
330
|
+
connect(options)
|
331
|
+
begin
|
332
|
+
account = find_account_from_options(options)
|
333
|
+
account_id = account ? account['id'] : nil
|
334
|
+
params = Morpheus::Cli::OptionTypes.prompt(add_key_pair_option_types.select {|it| ['name'].include?(it['fieldName'])}, options[:options], @api_client, options[:params])
|
335
|
+
key_pair_payload = params.select {|k,v| ['name'].include?(k) }
|
336
|
+
payload = {keyPair: key_pair_payload}
|
337
|
+
@key_pairs_interface.setopts(options)
|
338
|
+
if options[:dry_run]
|
339
|
+
print_dry_run @key_pairs_interface.dry.generate(account_id, payload)
|
340
|
+
return
|
341
|
+
end
|
342
|
+
json_response = @key_pairs_interface.generate(account_id, payload)
|
343
|
+
if options[:json]
|
344
|
+
print JSON.pretty_generate(json_response)
|
345
|
+
print "\n"
|
346
|
+
else
|
347
|
+
print_green_success "Key Pair #{key_pair_payload['name']} added"
|
348
|
+
print_key_pair_details(account, json_response['keyPair'])
|
349
|
+
end
|
350
|
+
rescue RestClient::Exception => e
|
351
|
+
print_rest_exception(e, options)
|
352
|
+
exit 1
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
332
356
|
private
|
333
357
|
def find_key_pair_by_name_or_id(account_id, val)
|
334
358
|
if val.to_s =~ /\A\d{1,}\Z/
|
@@ -390,6 +414,43 @@ class Morpheus::Cli::KeyPairs
|
|
390
414
|
print reset
|
391
415
|
end
|
392
416
|
|
417
|
+
def print_key_pair_details(account, key_pair)
|
418
|
+
print_h1 "Key Pair Details"
|
419
|
+
print cyan
|
420
|
+
if account
|
421
|
+
# print_description_list({"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' } }, key_pair)
|
422
|
+
print_description_list({"Account" => lambda {|it| account['name'] } }, key_pair)
|
423
|
+
end
|
424
|
+
print_description_list({
|
425
|
+
"ID" => 'id',
|
426
|
+
"Name" => 'name',
|
427
|
+
"Fingerprint" => 'fingerprint',
|
428
|
+
#"MD5" => 'md5',
|
429
|
+
# "Has Private Key" => lambda {|it| format_boolean(it['hasPrivateKey']) },
|
430
|
+
# "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
431
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) }
|
432
|
+
#"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
433
|
+
}, key_pair)
|
434
|
+
|
435
|
+
print_h2 "Public Key"
|
436
|
+
print cyan
|
437
|
+
puts "#{key_pair['publicKey']}"
|
438
|
+
|
439
|
+
# only happens after generate
|
440
|
+
if key_pair['hasPrivateKey']
|
441
|
+
if key_pair['privateKey']
|
442
|
+
print_h2 "Private Key"
|
443
|
+
print cyan
|
444
|
+
puts "#{key_pair['privateKey']}"
|
445
|
+
end
|
446
|
+
else
|
447
|
+
# print_h2 "Private Key"
|
448
|
+
print cyan, "\n"
|
449
|
+
puts "This is only a public key. It does not include a private key."
|
450
|
+
end
|
451
|
+
|
452
|
+
print reset,"\n"
|
453
|
+
end
|
393
454
|
|
394
455
|
def add_key_pair_option_types
|
395
456
|
[
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::NetworkFloatingIps
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::RestCommand
|
6
|
+
|
7
|
+
set_command_name :'network-floating-ips'
|
8
|
+
set_command_description "View and manage network floating IPs."
|
9
|
+
register_subcommands :list, :get, :release
|
10
|
+
|
11
|
+
# RestCommand settings
|
12
|
+
register_interfaces :network_floating_ips
|
13
|
+
set_rest_has_name false
|
14
|
+
set_rest_arg "id"
|
15
|
+
|
16
|
+
def release(args)
|
17
|
+
params = {}
|
18
|
+
options = {}
|
19
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
20
|
+
opts.banner = subcommand_usage("[#{rest_arg}]")
|
21
|
+
build_standard_remove_options(opts, options)
|
22
|
+
opts.footer = <<-EOT
|
23
|
+
Release an existing #{rest_label.downcase}.
|
24
|
+
[#{rest_arg}] is required. This is the #{rest_has_name ? 'name or id' : 'id'} of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
25
|
+
Only the following cloud types support this command: OpenStack, Huawei and OpenTelekom
|
26
|
+
EOT
|
27
|
+
end
|
28
|
+
optparse.parse!(args)
|
29
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
30
|
+
connect(options)
|
31
|
+
params.merge!(parse_query_options(options))
|
32
|
+
id = args[0]
|
33
|
+
record = rest_find_by_name_or_id(id)
|
34
|
+
if record.nil?
|
35
|
+
return 1, "#{rest_name} not found for '#{id}'"
|
36
|
+
end
|
37
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to release the #{rest_label.downcase} #{record['name'] || record['id']}?")
|
38
|
+
return 9, "aborted"
|
39
|
+
end
|
40
|
+
rest_interface.setopts(options)
|
41
|
+
if options[:dry_run]
|
42
|
+
print_dry_run rest_interface.dry.release(record['id'], params)
|
43
|
+
return 0, nil
|
44
|
+
end
|
45
|
+
json_response = rest_interface.release(record['id'], params)
|
46
|
+
render_response(json_response, options) do
|
47
|
+
print_green_success "Releasing #{rest_label.downcase} #{record['ipAddress'] || record['id']}"
|
48
|
+
end
|
49
|
+
return 0, nil
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def build_list_options(opts, options, params)
|
55
|
+
opts.on('--cloud CLOUD', String, "Cloud Name or ID") do |val|
|
56
|
+
options[:cloud] = val
|
57
|
+
end
|
58
|
+
opts.on('--server SERVER', String, "Server Name or ID") do |val|
|
59
|
+
options[:server] = val
|
60
|
+
end
|
61
|
+
opts.on('--vm VM', String, "Alias for --server") do |val|
|
62
|
+
options[:server] = val
|
63
|
+
end
|
64
|
+
opts.add_hidden_option('--vm')
|
65
|
+
opts.on('--ip-address VALUE', String, "Filter by IP Address") do |val|
|
66
|
+
add_query_parameter(params, 'ipAddress', val)
|
67
|
+
end
|
68
|
+
opts.on('--status VALUE', String, "Filter by Status (free, assigned, pending)") do |val|
|
69
|
+
add_query_parameter(params, 'ipStatus', val)
|
70
|
+
end
|
71
|
+
# build_standard_list_options(opts, options)
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_list_options!(args, options, params)
|
76
|
+
parse_parameter_as_resource_id!(:cloud, options, params, 'zoneId')
|
77
|
+
parse_parameter_as_resource_id!(:server, options, params)
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
def network_floating_ip_list_column_definitions(options)
|
82
|
+
{
|
83
|
+
"ID" => 'id',
|
84
|
+
"IP Address" => 'ipAddress',
|
85
|
+
"Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' },
|
86
|
+
"Status" => lambda {|it| it['ipStatus'].to_s.capitalize },
|
87
|
+
"VM" => lambda {|it| it['server'] ? it['server']['name'] : '' },
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def network_floating_ip_column_definitions(options)
|
92
|
+
{
|
93
|
+
"ID" => 'id',
|
94
|
+
"IP Address" => 'ipAddress',
|
95
|
+
"Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' },
|
96
|
+
"Status" => lambda {|it| it['ipStatus'].to_s.capitalize },
|
97
|
+
"VM" => lambda {|it| it['server'] ? it['server']['name'] : '' },
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_network_floating_ip_option_types()
|
102
|
+
[]
|
103
|
+
end
|
104
|
+
|
105
|
+
def update_network_floating_ip_option_types()
|
106
|
+
[]
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -303,7 +303,8 @@ class Morpheus::Cli::ReportsCommand
|
|
303
303
|
|
304
304
|
end
|
305
305
|
|
306
|
-
|
306
|
+
|
307
|
+
if check_payload_dates(payload)
|
307
308
|
print_green_success "The CLI generates a query that will use only month and year. However, the API does support yyyy-mm-dd from a previous version of Morpheus.\nReplace startMonth/endMonth keys with startDate,endDate ie:"
|
308
309
|
payload['report'].delete('startMonth')
|
309
310
|
payload['report'].delete('endMonth')
|
@@ -713,5 +714,11 @@ EOT
|
|
713
714
|
return metadata_filter
|
714
715
|
end
|
715
716
|
|
717
|
+
def check_payload_dates(payload)
|
718
|
+
if payload['report']['startMonth'] && payload['report']['endMonth']
|
719
|
+
return payload['report']['startMonth'].size > 7 || payload['report']['endMonth'].size > 7
|
720
|
+
end
|
721
|
+
return false
|
722
|
+
end
|
716
723
|
end
|
717
724
|
|