morpheus-cli 5.5.3.1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +44 -2
- data/lib/morpheus/cli/commands/tasks.rb +1 -1
- data/lib/morpheus/cli/commands/workflows.rb +1 -1
- data/lib/morpheus/cli/credentials.rb +2 -1
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +148 -0
- data/lib/morpheus/cli/option_types.rb +15 -8
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli.rb +13 -0
- data/test/cli/doc_test.rb +1 -1
- data/test/test_case.rb +3 -0
- 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
|
|