morpheus-cli 5.5.3.2 → 6.0.1
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/jobs_interface.rb +2 -2
- 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 +12 -6
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +44 -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 +9 -3
- data/lib/morpheus/cli/commands/jobs_command.rb +50 -3
- 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 +40 -2
- data/lib/morpheus/cli/commands/service_plans_command.rb +51 -22
- data/lib/morpheus/cli/commands/shell.rb +1 -1
- data/lib/morpheus/cli/commands/tasks.rb +130 -35
- data/lib/morpheus/cli/commands/workflows.rb +109 -23
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +148 -0
- data/lib/morpheus/cli/mixins/jobs_helper.rb +30 -3
- data/lib/morpheus/cli/mixins/processes_helper.rb +2 -26
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -1
- data/lib/morpheus/cli/option_types.rb +2 -2
- data/lib/morpheus/cli/version.rb +1 -1
- data/test/cli/doc_test.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4160be97bfb96acf0fe1091e9e8d6ecde617bd2aba547ef1cfab8a11d6134ecf
|
4
|
+
data.tar.gz: 5e0675e4e1061595e560e2395625e7a7546813e68e09a8237ccd33d92aeb948d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2992a310163d78082f7d748ca4ae50c673c32e7ae782497bb89f721135ed66509549c124290e9b4bd644cad2e3838c878331427ddd1090325f8946c7d30e731
|
7
|
+
data.tar.gz: 48ec07412e0cdcad359ea2dc050cc5017a9a39e368fb662e50b880628213fc4681b85da9cd5d8503ea7426be0fbac77b5e61d2dd8bc397ab13f0ce21695d2758
|
data/Dockerfile
CHANGED
@@ -400,6 +400,10 @@ class Morpheus::APIClient
|
|
400
400
|
Morpheus::CloudResourcePoolsInterface.new(common_interface_options).setopts(@options)
|
401
401
|
end
|
402
402
|
|
403
|
+
def resource_pool_groups
|
404
|
+
Morpheus::ResourcePoolGroupsInterface.new(common_interface_options).setopts(@options)
|
405
|
+
end
|
406
|
+
|
403
407
|
def cloud_folders
|
404
408
|
Morpheus::CloudFoldersInterface.new(common_interface_options).setopts(@options)
|
405
409
|
end
|
@@ -950,6 +954,10 @@ class Morpheus::APIClient
|
|
950
954
|
Morpheus::SecurityScansInterface.new(common_interface_options).setopts(@options)
|
951
955
|
end
|
952
956
|
|
957
|
+
def network_floating_ips
|
958
|
+
Morpheus::NetworkFloatingIpsInterface.new(common_interface_options).setopts(@options)
|
959
|
+
end
|
960
|
+
|
953
961
|
def rest(endpoint)
|
954
962
|
Morpheus::RestInterface.new(common_interface_options).setopts(@options.merge({base_path: "#{@base_url}/api/#{endpoint}"}))
|
955
963
|
end
|
@@ -4,7 +4,15 @@ class Morpheus::CloudResourcePoolsInterface < Morpheus::APIClient
|
|
4
4
|
|
5
5
|
def get(cloud_id, id, params={})
|
6
6
|
raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
|
7
|
-
url = cloud_id.nil? ? "#{@base_url}/api/zones/resource-pools/#{id}" : "#{@base_url}/api/zones/#{cloud_id}/resource-pools/#{id}"
|
7
|
+
url = cloud_id.nil? ? "#{@base_url}/api/zones/resource-pools/#{update_resource_pool_id(id)}" : "#{@base_url}/api/zones/#{cloud_id}/resource-pools/#{update_resource_pool_id(id)}"
|
8
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
9
|
+
opts = {method: :get, url: url, headers: headers}
|
10
|
+
execute(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_without_cloud(id, params={})
|
14
|
+
raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
|
15
|
+
url = "#{@base_url}/api/resource-pools/#{update_resource_pool_id(id)}"
|
8
16
|
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
9
17
|
opts = {method: :get, url: url, headers: headers}
|
10
18
|
execute(opts)
|
@@ -17,6 +25,13 @@ class Morpheus::CloudResourcePoolsInterface < Morpheus::APIClient
|
|
17
25
|
execute(opts)
|
18
26
|
end
|
19
27
|
|
28
|
+
def list_without_cloud(params={})
|
29
|
+
url = "#{@base_url}/api/resource-pools"
|
30
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
31
|
+
opts = {method: :get, url: url, headers: headers}
|
32
|
+
execute(opts)
|
33
|
+
end
|
34
|
+
|
20
35
|
def create(cloud_id, payload)
|
21
36
|
url = "#{@base_url}/api/zones/#{cloud_id}/resource-pools"
|
22
37
|
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
@@ -25,17 +40,27 @@ class Morpheus::CloudResourcePoolsInterface < Morpheus::APIClient
|
|
25
40
|
end
|
26
41
|
|
27
42
|
def update(cloud_id, id, payload)
|
28
|
-
url = "#{@base_url}/api/zones/#{cloud_id}/resource-pools/#{id}"
|
43
|
+
url = "#{@base_url}/api/zones/#{cloud_id}/resource-pools/#{update_resource_pool_id(id)}"
|
29
44
|
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
30
45
|
opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
|
31
46
|
execute(opts)
|
32
47
|
end
|
33
48
|
|
34
49
|
def destroy(cloud_id, id, params={})
|
35
|
-
url = "#{@base_url}/api/zones/#{cloud_id}/resource-pools/#{id}"
|
50
|
+
url = "#{@base_url}/api/zones/#{cloud_id}/resource-pools/#{update_resource_pool_id(id)}"
|
36
51
|
headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
37
52
|
opts = {method: :delete, url: url, headers: headers}
|
38
53
|
execute(opts)
|
39
54
|
end
|
40
55
|
|
56
|
+
private
|
57
|
+
|
58
|
+
def update_resource_pool_id(id)
|
59
|
+
id_string = id.to_s
|
60
|
+
if id_string["pool-"]
|
61
|
+
return id_string[5..-1]
|
62
|
+
end
|
63
|
+
return id
|
64
|
+
end
|
65
|
+
|
41
66
|
end
|
@@ -132,4 +132,14 @@ class Morpheus::ContainersInterface < Morpheus::APIClient
|
|
132
132
|
execute(method: :put, url: "#{base_path}/#{container_id}/clone-image", payload: payload, headers: headers)
|
133
133
|
end
|
134
134
|
|
135
|
+
def attach_floating_ip(container_id, payload={}, headers={})
|
136
|
+
validate_id!(container_id)
|
137
|
+
execute(method: :put, url: "#{base_path}/#{container_id}/attach-floating-ip", payload: payload, headers: headers)
|
138
|
+
end
|
139
|
+
|
140
|
+
def detach_floating_ip(container_id, payload={}, headers={})
|
141
|
+
validate_id!(container_id)
|
142
|
+
execute(method: :put, url: "#{base_path}/#{container_id}/detach-floating-ip", payload: payload, headers: headers)
|
143
|
+
end
|
144
|
+
|
135
145
|
end
|
@@ -1,11 +1,6 @@
|
|
1
1
|
require 'morpheus/api/api_client'
|
2
2
|
|
3
3
|
class Morpheus::DocInterface < Morpheus::APIClient
|
4
|
-
|
5
|
-
# no Authorization header is required
|
6
|
-
def authorization_required?
|
7
|
-
false
|
8
|
-
end
|
9
4
|
|
10
5
|
def list(params={})
|
11
6
|
url = "/api/doc"
|
@@ -24,8 +19,6 @@ class Morpheus::DocInterface < Morpheus::APIClient
|
|
24
19
|
execute(method: :get, url: url, headers: headers, timeout: 172800, parse_json: !is_yaml)
|
25
20
|
end
|
26
21
|
|
27
|
-
alias :swagger :openapi
|
28
|
-
|
29
22
|
def download_openapi(outfile, params={})
|
30
23
|
# note that RestClient.execute still requires the full path with base_url
|
31
24
|
url = "#{@base_url}/api/doc/openapi"
|
@@ -33,7 +26,7 @@ class Morpheus::DocInterface < Morpheus::APIClient
|
|
33
26
|
if fmt
|
34
27
|
url = url + "." + fmt
|
35
28
|
end
|
36
|
-
headers = {params: params}
|
29
|
+
headers = {params: params, authorization: "Bearer #{@access_token}"}
|
37
30
|
opts = {method: :get, url: url, headers: headers, timeout: 172800, parse_json: false}
|
38
31
|
|
39
32
|
if @dry_run
|
@@ -54,6 +47,4 @@ class Morpheus::DocInterface < Morpheus::APIClient
|
|
54
47
|
http_response
|
55
48
|
end
|
56
49
|
|
57
|
-
alias :swagger :download_openapi
|
58
|
-
|
59
50
|
end
|
@@ -43,10 +43,10 @@ class Morpheus::JobsInterface < Morpheus::APIClient
|
|
43
43
|
execute(method: :delete, url: url, headers: headers)
|
44
44
|
end
|
45
45
|
|
46
|
-
def execute_job(id, params={})
|
46
|
+
def execute_job(id, payload={}, params={})
|
47
47
|
url = "#{base_path}/#{id}/execute"
|
48
48
|
headers = { params: params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
49
|
-
execute(method: :put, url: url, headers: headers)
|
49
|
+
execute(method: :put, url: url, headers: headers, payload: payload.to_json)
|
50
50
|
end
|
51
51
|
|
52
52
|
=begin
|
@@ -45,4 +45,13 @@ class Morpheus::KeyPairsInterface < Morpheus::APIClient
|
|
45
45
|
opts = {method: :delete, url: url, headers: headers}
|
46
46
|
execute(opts)
|
47
47
|
end
|
48
|
+
|
49
|
+
def generate(account_id, options)
|
50
|
+
url = "#{@base_url}/api/key-pairs/generate"
|
51
|
+
headers = { :params => {}, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
52
|
+
headers[:params]['accountId'] = account_id if account_id
|
53
|
+
payload = options
|
54
|
+
opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
|
55
|
+
execute(opts)
|
56
|
+
end
|
48
57
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'morpheus/api/api_client'
|
2
|
+
|
3
|
+
class Morpheus::NetworkFloatingIpsInterface < Morpheus::APIClient
|
4
|
+
|
5
|
+
def base_path
|
6
|
+
"/api/networks/floating-ips"
|
7
|
+
end
|
8
|
+
|
9
|
+
def list(params={}, headers={})
|
10
|
+
execute(method: :get, url: "#{base_path}", params: params, headers: headers)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(id, params={}, headers={})
|
14
|
+
validate_id!(id)
|
15
|
+
execute(method: :get, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
|
16
|
+
end
|
17
|
+
|
18
|
+
# def create(payload, params={}, headers={})
|
19
|
+
# execute(method: :post, url: "#{base_path}", params: params, payload: payload, headers: headers)
|
20
|
+
# end
|
21
|
+
|
22
|
+
# def update(id, payload, params={}, headers={})
|
23
|
+
# validate_id!(id)
|
24
|
+
# execute(method: :put, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, payload: payload, headers: headers)
|
25
|
+
# end
|
26
|
+
|
27
|
+
def destroy(id, params = {}, headers={})
|
28
|
+
validate_id!(id)
|
29
|
+
execute(method: :delete, url: "#{base_path}/#{CGI::escape(id.to_s)}", params: params, headers: headers)
|
30
|
+
end
|
31
|
+
|
32
|
+
def release(id, payload={}, params={}, headers={})
|
33
|
+
validate_id!(id)
|
34
|
+
execute(method: :put, url: "#{base_path}/#{CGI::escape(id.to_s)}/release", params: params, payload: payload, headers: headers)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'morpheus/api/api_client'
|
2
|
+
|
3
|
+
class Morpheus::ResourcePoolGroupsInterface < Morpheus::APIClient
|
4
|
+
|
5
|
+
def get(id, params={})
|
6
|
+
raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
|
7
|
+
url = "#{@base_url}/api/resource-pools/groups/#{update_resource_pool_group_id(id)}"
|
8
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
9
|
+
opts = {method: :get, url: url, headers: headers}
|
10
|
+
execute(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def list(params={})
|
14
|
+
url = "#{@base_url}/api/resource-pools/groups"
|
15
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
16
|
+
opts = {method: :get, url: url, headers: headers}
|
17
|
+
execute(opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create(payload)
|
21
|
+
url = "#{@base_url}/api/resource-pools/groups"
|
22
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
23
|
+
opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
|
24
|
+
execute(opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(id, payload)
|
28
|
+
url = "#{@base_url}/api/resource-pools/groups/#{update_resource_pool_group_id(id)}"
|
29
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
30
|
+
opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
|
31
|
+
execute(opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
def destroy(id, params={})
|
35
|
+
url ="#{@base_url}/api/resource-pools/groups/#{update_resource_pool_group_id(id)}"
|
36
|
+
headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
37
|
+
opts = {method: :delete, url: url, headers: headers}
|
38
|
+
execute(opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def update_resource_pool_group_id(id)
|
44
|
+
id_string = id.to_s
|
45
|
+
if id_string["poolGroup-"]
|
46
|
+
return id_string[10..-1]
|
47
|
+
end
|
48
|
+
return id
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -149,6 +149,7 @@ module Morpheus
|
|
149
149
|
#opts.separator ""
|
150
150
|
#opts.separator "Options:"
|
151
151
|
options[:options] ||= {} # this is where these go..for now
|
152
|
+
options[:option_types] = (options[:option_types] || []) + option_types
|
152
153
|
custom_options = options[:options]
|
153
154
|
|
154
155
|
# add each one to the OptionParser
|
@@ -345,6 +346,7 @@ module Morpheus
|
|
345
346
|
custom_option_args = option.sub(/\s?\=\s?/, '__OPTION_DELIM__').split('__OPTION_DELIM__')
|
346
347
|
custom_options = options[:options]
|
347
348
|
option_name_args = custom_option_args[0].split('.')
|
349
|
+
option_type = (options[:option_types] || []).find {|it| it['fieldName'] == custom_option_args[0]} || {}
|
348
350
|
if option_name_args.count > 1
|
349
351
|
nested_options = custom_options
|
350
352
|
option_name_args.each_with_index do |name_element,index|
|
@@ -353,11 +355,13 @@ module Morpheus
|
|
353
355
|
nested_options = nested_options[name_element]
|
354
356
|
else
|
355
357
|
val = custom_option_args[1]
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
358
|
+
unless option_type['noParse']
|
359
|
+
if (val.to_s[0] == '{' && val.to_s[-1] == '}') || (val.to_s[0] == '[' && val.to_s[-1] == ']')
|
360
|
+
begin
|
361
|
+
val = JSON.parse(val)
|
362
|
+
rescue
|
363
|
+
Morpheus::Logging::DarkPrinter.puts "Failed to parse option value '#{val}' as JSON" if Morpheus::Logging.debug?
|
364
|
+
end
|
361
365
|
end
|
362
366
|
end
|
363
367
|
nested_options[name_element] = val
|
@@ -365,11 +369,13 @@ module Morpheus
|
|
365
369
|
end
|
366
370
|
else
|
367
371
|
val = custom_option_args[1]
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
372
|
+
unless option_type['noParse']
|
373
|
+
if (val.to_s[0] == '{' && val.to_s[-1] == '}') || (val.to_s[0] == '[' && val.to_s[-1] == ']')
|
374
|
+
begin
|
375
|
+
val = JSON.parse(val)
|
376
|
+
rescue
|
377
|
+
Morpheus::Logging::DarkPrinter.puts "Failed to parse option value '#{val}' as JSON" if Morpheus::Logging.debug?
|
378
|
+
end
|
373
379
|
end
|
374
380
|
end
|
375
381
|
custom_options[custom_option_args[0]] = val
|
@@ -1347,7 +1353,7 @@ module Morpheus
|
|
1347
1353
|
if record.nil?
|
1348
1354
|
# avoid double error render by exiting here, ew
|
1349
1355
|
exit 1
|
1350
|
-
raise_command_error "
|
1356
|
+
raise_command_error "#{type.titleize} not found for '#{val}'"
|
1351
1357
|
end
|
1352
1358
|
params[param_name] = record['id']
|
1353
1359
|
else
|
@@ -89,6 +89,8 @@ class Morpheus::Cli::ApplianceSettingsCommand
|
|
89
89
|
# Currency Settings
|
90
90
|
"Currency Provider" => lambda {|it| it['currencyProvider'] },
|
91
91
|
"Currency Provider API Key" => lambda {|it| it['currencyKey'] },
|
92
|
+
# Retention Settings
|
93
|
+
"Stats Retainment Period" => lambda {|it| it['statsRetainmentPeriod'] ? it['statsRetainmentPeriod'].to_s + ' days' : '' },
|
92
94
|
}
|
93
95
|
print_description_list(description_cols, appliance_settings)
|
94
96
|
|
@@ -215,6 +217,9 @@ class Morpheus::Cli::ApplianceSettingsCommand
|
|
215
217
|
opts.on("--disable-all-clouds", "Set all cloud types enabled status off, can be used in conjunction with --enable-clouds options") do
|
216
218
|
params['disableAllZoneTypes'] = true
|
217
219
|
end
|
220
|
+
opts.on("--stats-retainment-period DAYS", Integer, "Stats retainment period. The number of days stats should be available. Can be 30, 60, or 90.") do |val|
|
221
|
+
params['statsRetainmentPeriod'] = val.to_i
|
222
|
+
end
|
218
223
|
build_common_options(opts, options, [:json, :payload, :dry_run, :quiet, :remote])
|
219
224
|
end
|
220
225
|
|
@@ -781,11 +781,11 @@ class Morpheus::Cli::Apps
|
|
781
781
|
print_h2 "#{app_tier['tier']['name']}", options
|
782
782
|
print cyan
|
783
783
|
tier_instances = (app_tier['appInstances'] || []).collect {|it| it['instance']}
|
784
|
-
|
785
|
-
if
|
784
|
+
instance_list = tier_instances.collect { |tier_instance| instances.find { |i| i['id'] == tier_instance['id'] } }
|
785
|
+
if instance_list.empty?
|
786
786
|
puts yellow, "This tier is empty", reset
|
787
787
|
else
|
788
|
-
instances_rows =
|
788
|
+
instances_rows = instance_list.collect do |instance|
|
789
789
|
connection_string = ''
|
790
790
|
if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false
|
791
791
|
connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}"
|
@@ -1020,7 +1020,7 @@ EOT
|
|
1020
1020
|
end
|
1021
1021
|
|
1022
1022
|
def apply(args)
|
1023
|
-
default_refresh_interval =
|
1023
|
+
default_refresh_interval = 5
|
1024
1024
|
params, payload, options = {}, {}, {}
|
1025
1025
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1026
1026
|
opts.banner = subcommand_usage("[app] [options]")
|
@@ -1381,9 +1381,15 @@ EOT
|
|
1381
1381
|
opts.on( '--keep-backups', '--keep-backups', "Preserve copy of backups" ) do
|
1382
1382
|
query_params[:keepBackups] = 'on'
|
1383
1383
|
end
|
1384
|
-
opts.on('--
|
1385
|
-
query_params[:
|
1384
|
+
opts.on('--release-ips [on|off]', ['on','off'], "Release Floating IPs. Default is on. Applies to certain types only. Only applies when used with --remove-instances") do |val|
|
1385
|
+
query_params[:releaseFloatingIps] = val.nil? ? 'on' : val
|
1386
|
+
query_params[:releaseEIPs] = query_params[:releaseFloatingIps] # old parameter before 6.0
|
1386
1387
|
end
|
1388
|
+
opts.on('--releaseEIPs [on|off]', ['on','off'], "Alias for Release Floating IPs") do |val|
|
1389
|
+
query_params[:releaseFloatingIps] = val.nil? ? 'on' : val
|
1390
|
+
query_params[:releaseEIPs] = query_params[:releaseFloatingIps] # old parameter before 6.0
|
1391
|
+
end
|
1392
|
+
opts.add_hidden_option('--releaseEIPs')
|
1387
1393
|
opts.on( '-f', '--force', "Force Delete" ) do
|
1388
1394
|
query_params[:force] = 'on'
|
1389
1395
|
end
|
@@ -43,6 +43,12 @@ class Morpheus::Cli::CatalogItemTypesCommand
|
|
43
43
|
opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
|
44
44
|
add_query_parameter(params, 'allLabels', parse_labels(val))
|
45
45
|
end
|
46
|
+
opts.on('--code CODE', String, "Filter by code" ) do |val|
|
47
|
+
params[:code] = val
|
48
|
+
end
|
49
|
+
opts.on('-c', '--category CATEGORY', String, "Filter by category") do |val|
|
50
|
+
add_query_parameter(params, 'category', val)
|
51
|
+
end
|
46
52
|
build_standard_list_options(opts, options)
|
47
53
|
opts.footer = "List catalog item types."
|
48
54
|
end
|
@@ -212,6 +218,23 @@ EOT
|
|
212
218
|
print reset,"(blank)","\n",reset
|
213
219
|
end
|
214
220
|
elsif item_type_code == 'workflow' || item_type_code == 'operationalworkflow' || item_type_code == 'taskset'
|
221
|
+
print_h2 "Workflow Config"
|
222
|
+
if catalog_item_type['workflowConfig']
|
223
|
+
#print reset,(JSON.pretty_generate(config) rescue config),"\n",reset
|
224
|
+
#print reset,(as_yaml(config, options) rescue config),"\n",reset
|
225
|
+
config_string = catalog_item_type['workflowConfig'] || ""
|
226
|
+
config_lines = config_string.split("\n")
|
227
|
+
config_line_count = config_lines.size
|
228
|
+
max_lines = 10
|
229
|
+
if config_lines.size > max_lines
|
230
|
+
config_string = config_lines.first(max_lines).join("\n")
|
231
|
+
config_string << "\n\n"
|
232
|
+
config_string << "#{dark}(#{(config_line_count - max_lines)} more lines were not shown, use -c to show the config)#{reset}"
|
233
|
+
end
|
234
|
+
print reset,config_string.chomp("\n"),"\n",reset
|
235
|
+
else
|
236
|
+
print reset,"(blank)","\n",reset
|
237
|
+
end
|
215
238
|
end
|
216
239
|
end
|
217
240
|
|
@@ -227,7 +250,7 @@ EOT
|
|
227
250
|
end
|
228
251
|
|
229
252
|
def add(args)
|
230
|
-
options = {}
|
253
|
+
options = {:option_types => add_catalog_item_type_option_types}
|
231
254
|
params = {}
|
232
255
|
logo_file = nil
|
233
256
|
dark_logo_file = nil
|
@@ -657,6 +680,8 @@ EOT
|
|
657
680
|
{
|
658
681
|
"ID" => 'id',
|
659
682
|
"Name" => 'name',
|
683
|
+
"Code" => 'code',
|
684
|
+
"Category" => 'category',
|
660
685
|
"Labels" => lambda {|it| format_list(it['labels'], '', 3) },
|
661
686
|
"Description" => 'description',
|
662
687
|
"Type" => lambda {|it| format_catalog_type(it) },
|
@@ -680,6 +705,8 @@ EOT
|
|
680
705
|
"Name" => 'name',
|
681
706
|
"Labels" => lambda {|it| format_list(it['labels']) },
|
682
707
|
"Description" => 'description',
|
708
|
+
"Code" => 'code',
|
709
|
+
"Category" => 'category',
|
683
710
|
"Type" => lambda {|it| format_catalog_type(it) },
|
684
711
|
"Visibility" => 'visibility',
|
685
712
|
"Layout Code" => 'layoutCode',
|
@@ -689,6 +716,7 @@ EOT
|
|
689
716
|
# "Content" => lambda {|it| it['content'] },
|
690
717
|
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
691
718
|
"Featured" => lambda {|it| format_boolean(it['featured']) },
|
719
|
+
"Allow Quantity" => lambda {|it| format_boolean(it['allowQuantity']) },
|
692
720
|
#"Config" => lambda {|it| it['config'] },
|
693
721
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
694
722
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
@@ -725,21 +753,25 @@ EOT
|
|
725
753
|
[
|
726
754
|
{'code' => 'catalogItemType.type', 'shorthand' => '-t', 'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Instance', 'value' => 'instance'}, {'name' => 'Blueprint', 'value' => 'blueprint'}, {'name' => 'Workflow', 'value' => 'workflow'}], 'defaultValue' => 'instance', 'required' => true, 'displayOrder' => 1},
|
727
755
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 2},
|
728
|
-
{'fieldName' => '
|
729
|
-
{'fieldName' => '
|
730
|
-
{'fieldName' => '
|
731
|
-
{'fieldName' => '
|
732
|
-
{'fieldName' => '
|
733
|
-
{'fieldName' => '
|
756
|
+
{'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'displayOrder' => 3},
|
757
|
+
{'fieldName' => 'category', 'fieldLabel' => 'Category', 'type' => 'text', 'displayOrder' => 3.5},
|
758
|
+
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 4},
|
759
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => true, 'displayOrder' => 5},
|
760
|
+
{'fieldName' => 'featured', 'fieldLabel' => 'Featured', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 6},
|
761
|
+
{'fieldName' => 'allowQuantity', 'fieldLabel' => 'Allow Quantity', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 7},
|
762
|
+
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'required' => true, 'displayOrder' => 8},
|
763
|
+
{'fieldName' => 'layoutCode', 'fieldLabel' => 'Layout Code', 'type' => 'text', 'required' => false, 'displayOrder' => 9},
|
764
|
+
{'fieldName' => 'iconPath', 'fieldLabel' => 'Logo', 'type' => 'select', 'optionSource' => 'iconList', 'displayOrder' => 10},
|
734
765
|
#{'fieldName' => 'optionTypes', 'fieldLabel' => 'Option Types', 'type' => 'text', 'description' => 'Option Types to include, comma separated list of names or IDs.', 'displayOrder' => 8},
|
735
|
-
{'dependsOnCode' => 'catalogItemType.type:instance', 'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'description' => 'JSON or YAML', 'required' => true, 'displayOrder' =>
|
736
|
-
{'dependsOnCode' => 'catalogItemType.type:
|
737
|
-
{'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => '
|
738
|
-
{'dependsOnCode' => 'catalogItemType.type:
|
766
|
+
{'dependsOnCode' => 'catalogItemType.type:instance', 'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'description' => 'JSON or YAML', 'required' => true, 'displayOrder' => 11},
|
767
|
+
{'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflowConfig', 'fieldLabel' => 'Config', 'type' => 'textarea', 'description' => 'Enter configuration for the Workflow', 'required' => false, 'noParse' => true, 'displayOrder' => 11},
|
768
|
+
{'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => 'blueprint', 'fieldLabel' => 'Blueprint', 'type' => 'select', 'optionSource' => 'blueprints', 'description' => 'Choose a blueprint to apply to the catalog item.', 'required' => true, 'noParams' => true, 'displayOrder' => 12},
|
769
|
+
{'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => 'appSpec', 'fieldLabel' => 'App Spec', 'type' => 'code-editor', 'description' => 'Enter a spec in the for the App, the Scribe YAML format', 'required' => true, 'displayOrder' => 13},
|
770
|
+
{'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflow', 'fieldLabel' => 'Workflow', 'type' => 'select', 'optionSource' => 'operationWorkflows', 'description' => 'Enter a spec in the for the App, the Scribe YAML format', 'required' => true, 'noParams' => true, 'displayOrder' => 14},
|
739
771
|
{'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'context', 'fieldLabel' => 'Context Type', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
740
772
|
[{'name' => "Select", 'value' => ""}, {'name' => "None", 'value' => "appliance"}, {'name' => "Instance", 'value' => "instance"}, {'name' => "Server", 'value' => "server"}]
|
741
773
|
}, 'description' => 'Context for operational workflow, determines target type', 'defaultValue' => 'Select', 'required' => false},
|
742
|
-
{'fieldName' => 'content', 'fieldLabel' => 'Content', 'type' => 'code-editor', 'description' => 'Wiki Page Content describing the catalog item', 'displayOrder' =>
|
774
|
+
{'fieldName' => 'content', 'fieldLabel' => 'Content', 'type' => 'code-editor', 'description' => 'Wiki Page Content describing the catalog item', 'displayOrder' => 15}
|
743
775
|
]
|
744
776
|
end
|
745
777
|
|
@@ -33,6 +33,7 @@ class Morpheus::Cli::Clusters
|
|
33
33
|
@security_groups_interface = @api_client.security_groups
|
34
34
|
#@security_group_rules_interface = @api_client.security_group_rules
|
35
35
|
@cloud_resource_pools_interface = @api_client.cloud_resource_pools
|
36
|
+
@resource_pool_groups_interface = @api_client.resource_pool_groups
|
36
37
|
@clouds_interface = @api_client.clouds
|
37
38
|
@servers_interface = @api_client.servers
|
38
39
|
@server_types_interface = @api_client.server_types
|
@@ -644,6 +645,7 @@ class Morpheus::Cli::Clusters
|
|
644
645
|
!type['enabled'] || !type['creatable'] || type['fieldComponent']
|
645
646
|
} rescue []))
|
646
647
|
|
648
|
+
|
647
649
|
# remove metadata option_type , prompt manually for that field 'tags' instead of 'metadata'
|
648
650
|
metadata_option_type = option_type_list.find {|type| type['fieldName'] == 'metadata' }
|
649
651
|
option_type_list = option_type_list.reject {|type| type['fieldName'] == 'metadata' }
|
@@ -665,6 +667,14 @@ class Morpheus::Cli::Clusters
|
|
665
667
|
# Security Groups
|
666
668
|
server_payload['securityGroups'] = prompt_security_groups_by_cloud(cloud, provision_type, resource_pool, options)
|
667
669
|
|
670
|
+
# KLUDGE part 2: need to ask for hauwei floating ip option
|
671
|
+
if option_type = option_type_list.find {|type| type['code'] == 'computeServerType.openstackLinux.selectFloatingIp'}
|
672
|
+
floating_ip = load_floating_options(cluster_payload, options)
|
673
|
+
if floating_ip != nil
|
674
|
+
server_payload['config']['osExternalNetworkId'] = floating_ip
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
668
678
|
# Visibility
|
669
679
|
server_payload['visibility'] = options[:visibility] || (Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'defaultValue' => 'private', 'required' => true, 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}]}], options[:options], @api_client, {})['visibility'])
|
670
680
|
|
@@ -3785,7 +3795,7 @@ class Morpheus::Cli::Clusters
|
|
3785
3795
|
name: cluster['name'],
|
3786
3796
|
type: (cluster['type']['name'] rescue ''),
|
3787
3797
|
layout: (cluster['layout']['name'] rescue ''),
|
3788
|
-
workers: cluster['
|
3798
|
+
workers: cluster['servers'].size,
|
3789
3799
|
cloud: (cluster['zone']['name'] rescue ''),
|
3790
3800
|
status: format_cluster_status(cluster)
|
3791
3801
|
}
|
@@ -4273,7 +4283,11 @@ class Morpheus::Cli::Clusters
|
|
4273
4283
|
else
|
4274
4284
|
resource_pool_id = resource_pool_options.first['id']
|
4275
4285
|
end
|
4276
|
-
|
4286
|
+
if resource_pool_id.to_s["poolGroup-"]
|
4287
|
+
resource_pool = @resource_pool_groups_interface.get(resource_pool_id)['resourcePoolGroup']
|
4288
|
+
else
|
4289
|
+
resource_pool = @cloud_resource_pools_interface.get(cloud['id'], resource_pool_id)['resourcePool']
|
4290
|
+
end
|
4277
4291
|
end
|
4278
4292
|
end
|
4279
4293
|
end
|
@@ -4357,6 +4371,13 @@ class Morpheus::Cli::Clusters
|
|
4357
4371
|
end
|
4358
4372
|
end
|
4359
4373
|
|
4374
|
+
def load_floating_options(cluster, options)
|
4375
|
+
floating_ip_opts = @api_client.options.options_for_source('openstackFloatingIpOptions', {optionsSourceType: 'openStack', zoneId: cluster['cloud']['id']})['data']
|
4376
|
+
floating_ip_opts = floating_ip_opts.reject {|it| it['value'] == '' }
|
4377
|
+
floating_ip = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'osExternalNetworkId', 'fieldLabel' => 'Floating IP', 'type' => 'select', 'selectOptions' => floating_ip_opts, 'required' => false, 'description' => "Select Floating IP"}], options[:options])['osExternalNetworkId']
|
4378
|
+
return floating_ip
|
4379
|
+
end
|
4380
|
+
|
4360
4381
|
def available_kube_templates
|
4361
4382
|
option_results = options_interface.options_for_source('availableKubeTemplates')
|
4362
4383
|
available_templates = option_results['data'].collect {|it|
|