morpheus-cli 4.2.18 → 5.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 +14 -0
- data/lib/morpheus/api/billing_interface.rb +33 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
- data/lib/morpheus/api/rest_interface.rb +0 -6
- data/lib/morpheus/api/roles_interface.rb +14 -0
- data/lib/morpheus/cli.rb +2 -2
- data/lib/morpheus/cli/apps.rb +3 -4
- data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
- data/lib/morpheus/cli/backups_command.rb +3 -0
- data/lib/morpheus/cli/blueprints_command.rb +27 -61
- data/lib/morpheus/cli/budgets_command.rb +4 -4
- data/lib/morpheus/cli/catalog_command.rb +507 -0
- data/lib/morpheus/cli/cli_command.rb +30 -15
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +16 -0
- data/lib/morpheus/cli/clouds.rb +7 -10
- data/lib/morpheus/cli/commands/standard/curl_command.rb +23 -7
- data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
- data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
- data/lib/morpheus/cli/containers_command.rb +14 -0
- data/lib/morpheus/cli/deployments.rb +1 -1
- data/lib/morpheus/cli/hosts.rb +30 -2
- data/lib/morpheus/cli/instances.rb +19 -1
- data/lib/morpheus/cli/invoices_command.rb +8 -9
- data/lib/morpheus/cli/jobs_command.rb +30 -8
- data/lib/morpheus/cli/library_instance_types_command.rb +17 -3
- data/lib/morpheus/cli/library_option_lists_command.rb +14 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +7 -6
- data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
- data/lib/morpheus/cli/mixins/catalog_helper.rb +66 -0
- data/lib/morpheus/cli/mixins/deployments_helper.rb +0 -1
- data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +46 -0
- data/lib/morpheus/cli/network_pools_command.rb +14 -6
- data/lib/morpheus/cli/ping.rb +0 -1
- data/lib/morpheus/cli/projects_command.rb +7 -7
- data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
- data/lib/morpheus/cli/remote.rb +0 -2
- data/lib/morpheus/cli/roles.rb +305 -3
- data/lib/morpheus/cli/service_plans_command.rb +2 -2
- data/lib/morpheus/cli/storage_providers_command.rb +40 -56
- data/lib/morpheus/cli/tasks.rb +24 -10
- data/lib/morpheus/cli/tenants_command.rb +1 -1
- data/lib/morpheus/cli/usage_command.rb +150 -0
- data/lib/morpheus/cli/user_settings_command.rb +1 -0
- data/lib/morpheus/cli/users.rb +12 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/workflows.rb +12 -9
- data/lib/morpheus/formatters.rb +26 -5
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7e5399fa687da8ee714dc1bfe80cd72c2f01bf15cb465f1e6e576df53aa0a84
|
4
|
+
data.tar.gz: d5fe9c71d49308c5f7f92e47b134647712c302f833d7e77a55431bcec2e3036f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0904e36c4240d638d87862cefffd681241868a8cd06730eef6ddac921d4fb288a27043d365b4ba94b3223fa6be41b783f2b9aaa570e490b731528c6b282b5ff
|
7
|
+
data.tar.gz: b05b484d490e4829e20bba8d942acef387346cc03e214cd1c04d96a2cfca603d971d20054cb3bb9f9024d5bf977864b543d3c6d599089765f55426aa317a4f0e
|
data/Dockerfile
CHANGED
@@ -764,6 +764,20 @@ class Morpheus::APIClient
|
|
764
764
|
Morpheus::BackupJobsInterface.new(common_interface_options).setopts(@options)
|
765
765
|
end
|
766
766
|
|
767
|
+
def catalog_item_types
|
768
|
+
Morpheus::CatalogItemTypesInterface.new(common_interface_options).setopts(@options)
|
769
|
+
end
|
770
|
+
|
771
|
+
def billing
|
772
|
+
Morpheus::BillingInterface.new(common_interface_options).setopts(@options)
|
773
|
+
end
|
774
|
+
|
767
775
|
# add new interfaces here
|
768
776
|
|
777
|
+
protected
|
778
|
+
|
779
|
+
def validate_id!(id)
|
780
|
+
raise "#{self.class} passed a blank id!" if id.to_s.strip.empty?
|
781
|
+
end
|
782
|
+
|
769
783
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'morpheus/api/api_client'
|
2
|
+
|
3
|
+
class Morpheus::BillingInterface < Morpheus::APIClient
|
4
|
+
|
5
|
+
def base_path
|
6
|
+
"/api/billing"
|
7
|
+
end
|
8
|
+
|
9
|
+
def list(params={})
|
10
|
+
execute(method: :get, url: "#{base_path}", params: params)
|
11
|
+
end
|
12
|
+
|
13
|
+
def list_account(params={})
|
14
|
+
execute(method: :get, url: "#{base_path}/account", params: params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def list_zones(params={})
|
18
|
+
execute(method: :get, url: "#{base_path}/zones", params: params)
|
19
|
+
end
|
20
|
+
|
21
|
+
def list_instances(params={})
|
22
|
+
execute(method: :get, url: "#{base_path}/instances", params: params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def list_servers(params={})
|
26
|
+
execute(method: :get, url: "#{base_path}/servers", params: params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def list_discovered_servers(params={})
|
30
|
+
execute(method: :get, url: "#{base_path}/discoveredServers", params: params)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -31,10 +31,4 @@ class Morpheus::RestInterface < Morpheus::APIClient
|
|
31
31
|
execute(method: :delete, url: "#{base_path}/#{id}", params: params)
|
32
32
|
end
|
33
33
|
|
34
|
-
protected
|
35
|
-
|
36
|
-
def validate_id!(id)
|
37
|
-
raise "#{self.class} passed a blank id!" if id.to_s.strip.empty?
|
38
|
-
end
|
39
|
-
|
40
34
|
end
|
@@ -77,6 +77,20 @@ class Morpheus::RolesInterface < Morpheus::APIClient
|
|
77
77
|
execute(method: :put, url: url, headers: headers, payload: payload.to_json)
|
78
78
|
end
|
79
79
|
|
80
|
+
def update_catalog_item_type(account_id, id, options)
|
81
|
+
url = build_url(account_id, id) + "/update-catalog-item-type"
|
82
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
83
|
+
payload = options
|
84
|
+
execute(method: :put, url: url, headers: headers, payload: payload.to_json)
|
85
|
+
end
|
86
|
+
|
87
|
+
def update_persona(account_id, id, options)
|
88
|
+
url = build_url(account_id, id) + "/update-persona"
|
89
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
90
|
+
payload = options
|
91
|
+
execute(method: :put, url: url, headers: headers, payload: payload.to_json)
|
92
|
+
end
|
93
|
+
|
80
94
|
private
|
81
95
|
|
82
96
|
def build_url(account_id=nil, role_id=nil)
|
data/lib/morpheus/cli.rb
CHANGED
@@ -67,8 +67,6 @@ module Morpheus
|
|
67
67
|
# all standard commands
|
68
68
|
Dir[File.dirname(__FILE__) + "/cli/commands/standard/**/*.rb"].each {|file| load file }
|
69
69
|
|
70
|
-
# shell scripting commands
|
71
|
-
|
72
70
|
# all the known commands
|
73
71
|
load 'morpheus/cli/remote.rb'
|
74
72
|
load 'morpheus/cli/doc.rb'
|
@@ -174,6 +172,8 @@ module Morpheus
|
|
174
172
|
load 'morpheus/cli/projects_command.rb'
|
175
173
|
load 'morpheus/cli/backups_command.rb'
|
176
174
|
load 'morpheus/cli/backup_jobs_command.rb'
|
175
|
+
load 'morpheus/cli/catalog_command.rb'
|
176
|
+
load 'morpheus/cli/usage_command.rb'
|
177
177
|
# add new commands here...
|
178
178
|
|
179
179
|
end
|
data/lib/morpheus/cli/apps.rb
CHANGED
@@ -92,10 +92,9 @@ class Morpheus::Cli::Apps
|
|
92
92
|
opts.footer = "List apps."
|
93
93
|
end
|
94
94
|
optparse.parse!(args)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
return 1
|
95
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
96
|
+
if args.count > 0
|
97
|
+
options[:phrase] = args.join(" ")
|
99
98
|
end
|
100
99
|
connect(options)
|
101
100
|
begin
|
@@ -225,6 +225,9 @@ EOT
|
|
225
225
|
print_dry_run @backup_jobs_interface.dry.destroy(backup_job['id'], params)
|
226
226
|
return
|
227
227
|
end
|
228
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the backup #{backup['name']}?")
|
229
|
+
return 9, "aborted command"
|
230
|
+
end
|
228
231
|
json_response = @backup_jobs_interface.destroy(backup_job['id'], params)
|
229
232
|
render_response(json_response, options) do
|
230
233
|
print_green_success "Removed backup job #{backup_job['name']}"
|
@@ -215,6 +215,9 @@ EOT
|
|
215
215
|
print_dry_run @backups_interface.dry.destroy(backup['id'], params)
|
216
216
|
return
|
217
217
|
end
|
218
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the backup #{backup['name']}?")
|
219
|
+
return 9, "aborted command"
|
220
|
+
end
|
218
221
|
json_response = @backups_interface.destroy(backup['id'], params)
|
219
222
|
render_response(json_response, options) do
|
220
223
|
print_green_success "Removed backup #{backup['name']}"
|
@@ -62,11 +62,15 @@ class Morpheus::Cli::BlueprintsCommand
|
|
62
62
|
params['ownerId'] << val
|
63
63
|
end
|
64
64
|
opts.add_hidden_option('--created-by')
|
65
|
-
|
65
|
+
build_standard_list_options(opts, options)
|
66
66
|
opts.footer = "List blueprints."
|
67
67
|
end
|
68
68
|
optparse.parse!(args)
|
69
69
|
connect(options)
|
70
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
71
|
+
if args.count > 0
|
72
|
+
options[:phrase] = args.join(" ")
|
73
|
+
end
|
70
74
|
begin
|
71
75
|
if params['ownerId']
|
72
76
|
params['ownerId'] = params['ownerId'].collect do |owner_id|
|
@@ -125,7 +129,7 @@ class Morpheus::Cli::BlueprintsCommand
|
|
125
129
|
opts.on( '-c', '--config', "Display raw config only. Default is YAML. Combine with -j for JSON instead." ) do
|
126
130
|
options[:show_config] = true
|
127
131
|
end
|
128
|
-
|
132
|
+
build_standard_get_options(opts, options)
|
129
133
|
opts.footer = "Get details about a blueprint.\n" +
|
130
134
|
"[blueprint] is required. This is the name or id of a blueprint. Supports 1-N [instance] arguments."
|
131
135
|
end
|
@@ -154,8 +158,9 @@ class Morpheus::Cli::BlueprintsCommand
|
|
154
158
|
end
|
155
159
|
@blueprints_interface.setopts(options)
|
156
160
|
blueprint = find_blueprint_by_name_or_id(arg)
|
157
|
-
|
158
|
-
|
161
|
+
if blueprint.nil?
|
162
|
+
return 1, "blueprint not found"
|
163
|
+
end
|
159
164
|
json_response = {'blueprint' => blueprint} # skip redundant request
|
160
165
|
#json_response = @blueprints_interface.get(blueprint['id'])
|
161
166
|
blueprint = json_response['blueprint']
|
@@ -165,43 +170,13 @@ class Morpheus::Cli::BlueprintsCommand
|
|
165
170
|
unless options[:json] || options[:yaml] || options[:csv]
|
166
171
|
options[:yaml] = true
|
167
172
|
end
|
168
|
-
|
169
|
-
render_result = render_with_format(blueprint_config, options)
|
170
|
-
return 0 if render_result
|
173
|
+
return render_with_format(blueprint['config'], options)
|
171
174
|
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
print_blueprint_details(blueprint)
|
179
|
-
|
180
|
-
if blueprint['resourcePermission'].nil?
|
181
|
-
#print "\n", "No group access found", "\n"
|
182
|
-
else
|
183
|
-
# print_h2 "Group Access"
|
184
|
-
# rows = []
|
185
|
-
# if blueprint['resourcePermission']['allSites'] || blueprint['resourcePermission']['all']
|
186
|
-
# rows.push({"name" => 'All'})
|
187
|
-
# end
|
188
|
-
# if blueprint['resourcePermission']['sites']
|
189
|
-
# blueprint['resourcePermission']['sites'].each do |site|
|
190
|
-
# rows.push(site)
|
191
|
-
# end
|
192
|
-
# end
|
193
|
-
# rows = rows.collect do |site|
|
194
|
-
# {group: site['name'], default: site['default'] ? 'Yes' : ''}
|
195
|
-
# end
|
196
|
-
# # columns = [:group, :default]
|
197
|
-
# columns = [:group]
|
198
|
-
# print cyan
|
199
|
-
# print as_pretty_table(rows, columns)
|
200
|
-
# print reset,"\n"
|
201
|
-
end
|
202
|
-
|
203
|
-
#print reset,"\n"
|
204
|
-
return 0
|
175
|
+
render_response(json_response, options, 'blueprint') do
|
176
|
+
print_h1 "Blueprint Details"
|
177
|
+
print_blueprint_details(blueprint)
|
178
|
+
end
|
179
|
+
return 0, nil
|
205
180
|
rescue RestClient::Exception => e
|
206
181
|
print_rest_exception(e, options)
|
207
182
|
exit 1
|
@@ -216,17 +191,12 @@ class Morpheus::Cli::BlueprintsCommand
|
|
216
191
|
opts.on('-t', '--type TYPE', String, "Blueprint Type. Default is morpheus.") do |val|
|
217
192
|
options[:blueprint_type] = parse_blueprint_type(val.to_s)
|
218
193
|
end
|
219
|
-
|
194
|
+
build_standard_add_options(opts, options)
|
220
195
|
opts.footer = "Create a new blueprint.\n" +
|
221
196
|
"[name] is required. This is the name of the new blueprint."
|
222
197
|
end
|
223
198
|
optparse.parse!(args)
|
224
|
-
|
225
|
-
print_error Morpheus::Terminal.angry_prompt
|
226
|
-
puts_error "#{command_name} add expects 0-1 arguments and received #{args.count}: #{args}\n#{optparse}"
|
227
|
-
return 1
|
228
|
-
end
|
229
|
-
options[:options] ||= {}
|
199
|
+
verify_args!(args:args, optparse:optparse, min:0, max:1)
|
230
200
|
if args[0]
|
231
201
|
options[:options]['name'] = args[0]
|
232
202
|
end
|
@@ -248,9 +218,7 @@ class Morpheus::Cli::BlueprintsCommand
|
|
248
218
|
end
|
249
219
|
params = Morpheus::Cli::OptionTypes.prompt(add_blueprint_option_types, options[:options], @api_client, options[:params])
|
250
220
|
params.deep_compact!
|
251
|
-
#blueprint_payload = params.select {|k,v| ['name', 'description', 'category'].include?(k) }
|
252
221
|
# expects no namespace, just the config
|
253
|
-
#payload = blueprint_payload
|
254
222
|
payload.deep_merge!(params)
|
255
223
|
end
|
256
224
|
@blueprints_interface.setopts(options)
|
@@ -260,12 +228,8 @@ class Morpheus::Cli::BlueprintsCommand
|
|
260
228
|
end
|
261
229
|
|
262
230
|
json_response = @blueprints_interface.create(payload)
|
263
|
-
|
264
|
-
|
265
|
-
print JSON.pretty_generate(json_response)
|
266
|
-
print "\n"
|
267
|
-
elsif !options[:quiet]
|
268
|
-
blueprint = json_response["blueprint"]
|
231
|
+
blueprint = json_response['blueprint']
|
232
|
+
render_response(json_response, options, 'blueprint') do
|
269
233
|
print_green_success "Added blueprint #{blueprint['name']}"
|
270
234
|
if !options[:no_prompt]
|
271
235
|
if options[:payload].nil? && ::Morpheus::Cli::OptionTypes::confirm("Would you like to add a tier now?", options.merge({default: false}))
|
@@ -275,11 +239,11 @@ class Morpheus::Cli::BlueprintsCommand
|
|
275
239
|
end
|
276
240
|
else
|
277
241
|
# print details
|
278
|
-
|
242
|
+
return _get(blueprint["id"], options)
|
279
243
|
end
|
280
244
|
end
|
281
245
|
end
|
282
|
-
return 0
|
246
|
+
return 0, nil
|
283
247
|
rescue RestClient::Exception => e
|
284
248
|
print_rest_exception(e, options)
|
285
249
|
exit 1
|
@@ -294,7 +258,7 @@ class Morpheus::Cli::BlueprintsCommand
|
|
294
258
|
opts.on( '--owner USER', "Owner Username or ID" ) do |val|
|
295
259
|
options[:owner] = val == 'null' ? nil : val
|
296
260
|
end
|
297
|
-
|
261
|
+
build_standard_update_options(opts, options)
|
298
262
|
opts.footer = "Update a blueprint.\n" +
|
299
263
|
"[blueprint] is required. This is the name or id of a blueprint."
|
300
264
|
end
|
@@ -388,7 +352,7 @@ class Morpheus::Cli::BlueprintsCommand
|
|
388
352
|
options[:owner] = val == 'null' ? nil : val
|
389
353
|
end
|
390
354
|
build_option_type_options(opts, options, update_blueprint_option_types(false))
|
391
|
-
|
355
|
+
build_standard_update_options(opts, options)
|
392
356
|
opts.footer = "Update a blueprint permissions.\n" +
|
393
357
|
"[blueprint] is required. This is the name or id of a blueprint."
|
394
358
|
end
|
@@ -586,7 +550,7 @@ class Morpheus::Cli::BlueprintsCommand
|
|
586
550
|
options = {}
|
587
551
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
588
552
|
opts.banner = subcommand_usage("[blueprint]")
|
589
|
-
|
553
|
+
build_standard_remove_options(opts, options)
|
590
554
|
opts.footer = "Delete a blueprint." + "\n" +
|
591
555
|
"[blueprint] is required. This is the name or id of a blueprint."
|
592
556
|
end
|
@@ -2123,6 +2087,7 @@ class Morpheus::Cli::BlueprintsCommand
|
|
2123
2087
|
}
|
2124
2088
|
|
2125
2089
|
print_description_list(description_cols, blueprint)
|
2090
|
+
print reset,"\n"
|
2126
2091
|
# print_h2 "Tiers"
|
2127
2092
|
if blueprint["config"] && blueprint["config"]["tiers"] && blueprint["config"]["tiers"].keys.size != 0
|
2128
2093
|
print cyan
|
@@ -2213,7 +2178,8 @@ class Morpheus::Cli::BlueprintsCommand
|
|
2213
2178
|
else
|
2214
2179
|
#print white,"\nTemplate is empty, use `blueprints add-tier \"#{blueprint['name']}\"`",reset,"\n"
|
2215
2180
|
end
|
2216
|
-
print reset,"\n"
|
2181
|
+
# print reset,"\n"
|
2182
|
+
print reset
|
2217
2183
|
end
|
2218
2184
|
|
2219
2185
|
# this parses the environments => groups => clouds tree structure
|
@@ -570,16 +570,16 @@ class Morpheus::Cli::BudgetsCommand
|
|
570
570
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 1},
|
571
571
|
# {'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => true},
|
572
572
|
{'fieldName' => 'scope', 'fieldLabel' => 'Scope', 'code' => 'budget.scope', 'type' => 'select', 'selectOptions' => [{'name'=>'Account','value'=>'account'},{'name'=>'Tenant','value'=>'tenant'},{'name'=>'Cloud','value'=>'cloud'},{'name'=>'Group','value'=>'group'},{'name'=>'User','value'=>'user'}], 'defaultValue' => 'account', 'required' => true, 'displayOrder' => 3},
|
573
|
-
{'fieldName' => 'tenant', 'fieldLabel' => 'Tenant', 'type' => 'select', 'optionSource' => lambda {
|
573
|
+
{'fieldName' => 'tenant', 'fieldLabel' => 'Tenant', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
|
574
574
|
@options_interface.options_for_source("tenants", {})['data']
|
575
575
|
}, 'required' => true, 'dependsOnCode' => 'budget.scope:tenant', 'displayOrder' => 4},
|
576
|
-
{'fieldName' => 'user', 'fieldLabel' => 'User', 'type' => 'select', 'optionSource' => lambda {
|
576
|
+
{'fieldName' => 'user', 'fieldLabel' => 'User', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
|
577
577
|
@options_interface.options_for_source("users", {})['data']
|
578
578
|
}, 'required' => true, 'dependsOnCode' => 'budget.scope:user', 'displayOrder' => 5},
|
579
|
-
{'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'optionSource' => lambda {
|
579
|
+
{'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
|
580
580
|
@options_interface.options_for_source("groups", {})['data']
|
581
581
|
}, 'required' => true, 'dependsOnCode' => 'budget.scope:group', 'displayOrder' => 6},
|
582
|
-
{'fieldName' => 'cloud', 'fieldLabel' => 'Cloud', 'type' => 'select', 'optionSource' => lambda {
|
582
|
+
{'fieldName' => 'cloud', 'fieldLabel' => 'Cloud', 'type' => 'select', 'optionSource' => lambda {|api_client, api_params|
|
583
583
|
@options_interface.options_for_source("clouds", {})['data']
|
584
584
|
}, 'required' => true, 'dependsOnCode' => 'budget.scope:cloud', 'displayOrder' => 7},
|
585
585
|
{'fieldName' => 'year', 'fieldLabel' => 'Period', 'type' => 'text', 'required' => true, 'defaultValue' => Time.now.year, 'description' => "The period (year) the budget applies to. Default is the current year.", 'displayOrder' => 8},
|
@@ -0,0 +1,507 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
# CLI command self service
|
4
|
+
# UI is Tools: Self Service - Catalog Items
|
5
|
+
# API is /catalog-item-types and returns catalogItemTypes
|
6
|
+
class Morpheus::Cli::CatalogCommand
|
7
|
+
include Morpheus::Cli::CliCommand
|
8
|
+
include Morpheus::Cli::CatalogHelper
|
9
|
+
include Morpheus::Cli::LibraryHelper
|
10
|
+
include Morpheus::Cli::OptionSourceHelper
|
11
|
+
|
12
|
+
# hide until 5.1 when update api is fixed and service-catalog endpoints are available
|
13
|
+
set_command_hidden
|
14
|
+
set_command_name :'catalog'
|
15
|
+
|
16
|
+
register_subcommands :list, :get, :add, :update, :remove
|
17
|
+
|
18
|
+
def connect(opts)
|
19
|
+
@api_client = establish_remote_appliance_connection(opts)
|
20
|
+
@catalog_item_types_interface = @api_client.catalog_item_types
|
21
|
+
@option_types_interface = @api_client.option_types
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle(args)
|
25
|
+
handle_subcommand(args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def list(args)
|
29
|
+
options = {}
|
30
|
+
params = {}
|
31
|
+
ref_ids = []
|
32
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
33
|
+
opts.banner = subcommand_usage("[search]")
|
34
|
+
opts.on( '--enabled [on|off]', String, "Filter by enabled" ) do |val|
|
35
|
+
params['enabled'] = (val.to_s != 'false' && val.to_s != 'off')
|
36
|
+
end
|
37
|
+
opts.on( '--featured [on|off]', String, "Filter by featured" ) do |val|
|
38
|
+
params['featured'] = (val.to_s != 'false' && val.to_s != 'off')
|
39
|
+
end
|
40
|
+
build_standard_list_options(opts, options)
|
41
|
+
opts.footer = "List catalog items."
|
42
|
+
end
|
43
|
+
optparse.parse!(args)
|
44
|
+
connect(options)
|
45
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
46
|
+
if args.count > 0
|
47
|
+
options[:phrase] = args.join(" ")
|
48
|
+
end
|
49
|
+
params.merge!(parse_list_options(options))
|
50
|
+
@catalog_item_types_interface.setopts(options)
|
51
|
+
if options[:dry_run]
|
52
|
+
print_dry_run @catalog_item_types_interface.dry.list(params)
|
53
|
+
return
|
54
|
+
end
|
55
|
+
json_response = @catalog_item_types_interface.list(params)
|
56
|
+
catalog_item_types = json_response[catalog_item_type_list_key]
|
57
|
+
render_response(json_response, options, catalog_item_type_list_key) do
|
58
|
+
print_h1 "Morpheus Catalog Items", parse_list_subtitles(options), options
|
59
|
+
if catalog_item_types.empty?
|
60
|
+
print cyan,"No catalog items found.",reset,"\n"
|
61
|
+
else
|
62
|
+
list_columns = catalog_item_type_column_definitions.upcase_keys!
|
63
|
+
#list_columns["Config"] = lambda {|it| truncate_string(it['config'], 100) }
|
64
|
+
print as_pretty_table(catalog_item_types, list_columns.upcase_keys!, options)
|
65
|
+
print_results_pagination(json_response)
|
66
|
+
end
|
67
|
+
print reset,"\n"
|
68
|
+
end
|
69
|
+
if catalog_item_types.empty?
|
70
|
+
return 1, "no catalog items found"
|
71
|
+
else
|
72
|
+
return 0, nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get(args)
|
77
|
+
params = {}
|
78
|
+
options = {}
|
79
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
80
|
+
opts.banner = subcommand_usage("[catalog item type]")
|
81
|
+
opts.on( '-c', '--config', "Display raw config only. Default is YAML. Combine with -j for JSON instead." ) do
|
82
|
+
options[:show_config] = true
|
83
|
+
end
|
84
|
+
# opts.on('--no-config', "Do not display config content." ) do
|
85
|
+
# options[:no_config] = true
|
86
|
+
# end
|
87
|
+
build_standard_get_options(opts, options)
|
88
|
+
opts.footer = <<-EOT
|
89
|
+
Get details about a specific catalog item type.
|
90
|
+
[catalog item type] is required. This is the name or id of a catalog item type.
|
91
|
+
EOT
|
92
|
+
end
|
93
|
+
optparse.parse!(args)
|
94
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
95
|
+
connect(options)
|
96
|
+
id_list = parse_id_list(args)
|
97
|
+
return run_command_for_each_arg(id_list) do |arg|
|
98
|
+
_get(arg, params, options)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _get(id, params, options)
|
103
|
+
catalog_item_type = nil
|
104
|
+
if id.to_s !~ /\A\d{1,}\Z/
|
105
|
+
catalog_item_type = find_catalog_item_type_by_name(id)
|
106
|
+
return 1, "catalog item type not found for #{id}" if catalog_item_type.nil?
|
107
|
+
id = catalog_item_type['id']
|
108
|
+
end
|
109
|
+
@catalog_item_types_interface.setopts(options)
|
110
|
+
if options[:dry_run]
|
111
|
+
print_dry_run @catalog_item_types_interface.dry.get(id, params)
|
112
|
+
return
|
113
|
+
end
|
114
|
+
# skip extra query, list has same data as show right now
|
115
|
+
if catalog_item_type
|
116
|
+
json_response = {catalog_item_type_object_key => catalog_item_type}
|
117
|
+
else
|
118
|
+
json_response = @catalog_item_types_interface.get(id, params)
|
119
|
+
end
|
120
|
+
catalog_item_type = json_response[catalog_item_type_object_key]
|
121
|
+
config = catalog_item_type['config'] || {}
|
122
|
+
# export just the config as json or yaml (default)
|
123
|
+
if options[:show_config]
|
124
|
+
unless options[:json] || options[:yaml] || options[:csv]
|
125
|
+
options[:yaml] = true
|
126
|
+
end
|
127
|
+
return render_with_format(config, options)
|
128
|
+
end
|
129
|
+
render_response(json_response, options, catalog_item_type_object_key) do
|
130
|
+
print_h1 "Catalog Item Type Details", [], options
|
131
|
+
print cyan
|
132
|
+
show_columns = catalog_item_type_column_definitions
|
133
|
+
show_columns.delete("Blueprint") unless catalog_item_type['blueprint']
|
134
|
+
print_description_list(show_columns, catalog_item_type)
|
135
|
+
|
136
|
+
if catalog_item_type['optionTypes'] && catalog_item_type['optionTypes'].size > 0
|
137
|
+
print_h2 "Option Types"
|
138
|
+
opt_columns = [
|
139
|
+
{"ID" => lambda {|it| it['id'] } },
|
140
|
+
{"NAME" => lambda {|it| it['name'] } },
|
141
|
+
{"TYPE" => lambda {|it| it['type'] } },
|
142
|
+
{"FIELD NAME" => lambda {|it| it['fieldName'] } },
|
143
|
+
{"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
|
144
|
+
{"DEFAULT" => lambda {|it| it['defaultValue'] } },
|
145
|
+
{"REQUIRED" => lambda {|it| format_boolean it['required'] } },
|
146
|
+
]
|
147
|
+
print as_pretty_table(catalog_item_type['optionTypes'], opt_columns)
|
148
|
+
else
|
149
|
+
# print cyan,"No option types found for this catalog item.","\n",reset
|
150
|
+
end
|
151
|
+
|
152
|
+
if config && options[:no_config] != true
|
153
|
+
print_h2 "Config YAML"
|
154
|
+
#print reset,(JSON.pretty_generate(config) rescue config),"\n",reset
|
155
|
+
#print reset,(as_yaml(config, options) rescue config),"\n",reset
|
156
|
+
config_string = as_yaml(config, options) rescue config
|
157
|
+
config_lines = config_string.split("\n")
|
158
|
+
config_line_count = config_lines.size
|
159
|
+
max_lines = 10
|
160
|
+
if config_lines.size > max_lines
|
161
|
+
config_string = config_lines.first(max_lines).join("\n")
|
162
|
+
config_string << "\n\n"
|
163
|
+
config_string << "(#{(config_line_count - max_lines)} more lines were not shown, use -c to show the config)"
|
164
|
+
#config_string << "\n"
|
165
|
+
end
|
166
|
+
# strip --- yaml header
|
167
|
+
if config_string[0..3] == "---\n"
|
168
|
+
config_string = config_string[4..-1]
|
169
|
+
end
|
170
|
+
print reset,config_string.chomp("\n"),"\n",reset
|
171
|
+
end
|
172
|
+
|
173
|
+
print reset,"\n"
|
174
|
+
end
|
175
|
+
return 0, nil
|
176
|
+
end
|
177
|
+
|
178
|
+
def add(args)
|
179
|
+
options = {}
|
180
|
+
params = {}
|
181
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
182
|
+
opts.banner = subcommand_usage("[name] [options]")
|
183
|
+
build_option_type_options(opts, options, add_catalog_item_type_option_types)
|
184
|
+
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
185
|
+
options[:config_file] = val.to_s
|
186
|
+
file_content = nil
|
187
|
+
full_filename = File.expand_path(options[:config_file])
|
188
|
+
if File.exists?(full_filename)
|
189
|
+
file_content = File.read(full_filename)
|
190
|
+
else
|
191
|
+
print_red_alert "File not found: #{full_filename}"
|
192
|
+
return 1
|
193
|
+
end
|
194
|
+
parse_result = parse_json_or_yaml(file_content)
|
195
|
+
config_map = parse_result[:data]
|
196
|
+
if config_map.nil?
|
197
|
+
# todo: bubble up JSON.parse error message
|
198
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
199
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
200
|
+
else
|
201
|
+
params['config'] = config_map
|
202
|
+
options[:options]['config'] = params['config'] # or file_content
|
203
|
+
end
|
204
|
+
end
|
205
|
+
opts.on('--option-types [x,y,z]', Array, "List of Option Type IDs") do |list|
|
206
|
+
if list.nil?
|
207
|
+
params['optionTypes'] = []
|
208
|
+
else
|
209
|
+
params['optionTypes'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
210
|
+
end
|
211
|
+
end
|
212
|
+
opts.on('--optionTypes [x,y,z]', Array, "List of Option Type IDs") do |list|
|
213
|
+
if list.nil?
|
214
|
+
params['optionTypes'] = []
|
215
|
+
else
|
216
|
+
params['optionTypes'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
217
|
+
end
|
218
|
+
end
|
219
|
+
opts.add_hidden_option('--optionTypes')
|
220
|
+
build_option_type_options(opts, options, add_catalog_item_type_advanced_option_types)
|
221
|
+
build_standard_add_options(opts, options)
|
222
|
+
opts.footer = <<-EOT
|
223
|
+
Create a new catalog item type.
|
224
|
+
EOT
|
225
|
+
end
|
226
|
+
optparse.parse!(args)
|
227
|
+
verify_args!(args:args, optparse:optparse, min:0, max:1)
|
228
|
+
options[:options]['name'] = args[0] if args[0]
|
229
|
+
connect(options)
|
230
|
+
payload = {}
|
231
|
+
if options[:payload]
|
232
|
+
payload = options[:payload]
|
233
|
+
payload.deep_merge!({catalog_item_type_object_key => parse_passed_options(options)})
|
234
|
+
else
|
235
|
+
payload.deep_merge!({catalog_item_type_object_key => parse_passed_options(options)})
|
236
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(add_catalog_item_type_option_types(), options[:options], @api_client, options[:params])
|
237
|
+
params.deep_merge!(v_prompt)
|
238
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_catalog_item_type_advanced_option_types, options[:options], @api_client, options[:params])
|
239
|
+
advanced_config.deep_compact!
|
240
|
+
params.deep_merge!(advanced_config)
|
241
|
+
# convert checkbox "on" and "off" to true and false
|
242
|
+
params.booleanize!
|
243
|
+
# convert type to refType until api accepts type
|
244
|
+
if params['type'] && !params['refType']
|
245
|
+
if params['type'].to_s.downcase == 'blueprint'
|
246
|
+
params['refType'] = 'AppTemplate'
|
247
|
+
else
|
248
|
+
params['refType'] = 'InstanceType'
|
249
|
+
end
|
250
|
+
end
|
251
|
+
# convert config string to a map
|
252
|
+
config = params['config']
|
253
|
+
if config && config.is_a?(String)
|
254
|
+
parse_result = parse_json_or_yaml(config)
|
255
|
+
config_map = parse_result[:data]
|
256
|
+
if config_map.nil?
|
257
|
+
# todo: bubble up JSON.parse error message
|
258
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
259
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
260
|
+
else
|
261
|
+
params['config'] = config_map
|
262
|
+
end
|
263
|
+
end
|
264
|
+
if params['optionTypes']
|
265
|
+
# todo: move to optionSource, so it will be /api/options/optionTypes lol
|
266
|
+
prompt_results = prompt_for_option_types(params, options, @api_client)
|
267
|
+
if prompt_results[:success]
|
268
|
+
params['optionTypes'] = prompt_results[:data] unless prompt_results[:data].nil?
|
269
|
+
else
|
270
|
+
return 1
|
271
|
+
end
|
272
|
+
end
|
273
|
+
payload[catalog_item_type_object_key].deep_merge!(params)
|
274
|
+
end
|
275
|
+
@catalog_item_types_interface.setopts(options)
|
276
|
+
if options[:dry_run]
|
277
|
+
print_dry_run @catalog_item_types_interface.dry.create(payload)
|
278
|
+
return 0, nil
|
279
|
+
end
|
280
|
+
json_response = @catalog_item_types_interface.create(payload)
|
281
|
+
catalog_item_type = json_response[catalog_item_type_object_key]
|
282
|
+
render_response(json_response, options, catalog_item_type_object_key) do
|
283
|
+
print_green_success "Added catalog item #{catalog_item_type['name']}"
|
284
|
+
return _get(catalog_item_type["id"], {}, options)
|
285
|
+
end
|
286
|
+
return 0, nil
|
287
|
+
end
|
288
|
+
|
289
|
+
def update(args)
|
290
|
+
options = {}
|
291
|
+
params = {}
|
292
|
+
payload = {}
|
293
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
294
|
+
opts.banner = subcommand_usage("[catalog item type] [options]")
|
295
|
+
build_option_type_options(opts, options, update_catalog_item_type_option_types)
|
296
|
+
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
297
|
+
options[:config_file] = val.to_s
|
298
|
+
file_content = nil
|
299
|
+
full_filename = File.expand_path(options[:config_file])
|
300
|
+
if File.exists?(full_filename)
|
301
|
+
file_content = File.read(full_filename)
|
302
|
+
else
|
303
|
+
print_red_alert "File not found: #{full_filename}"
|
304
|
+
return 1
|
305
|
+
end
|
306
|
+
parse_result = parse_json_or_yaml(file_content)
|
307
|
+
config_map = parse_result[:data]
|
308
|
+
if config_map.nil?
|
309
|
+
# todo: bubble up JSON.parse error message
|
310
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
311
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
312
|
+
else
|
313
|
+
params['config'] = config_map
|
314
|
+
options[:options]['config'] = params['config'] # or file_content
|
315
|
+
end
|
316
|
+
end
|
317
|
+
opts.on('--option-types [x,y,z]', Array, "List of Option Type IDs") do |list|
|
318
|
+
if list.nil?
|
319
|
+
params['optionTypes'] = []
|
320
|
+
else
|
321
|
+
params['optionTypes'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
322
|
+
end
|
323
|
+
end
|
324
|
+
opts.on('--optionTypes [x,y,z]', Array, "List of Option Type IDs") do |list|
|
325
|
+
if list.nil?
|
326
|
+
params['optionTypes'] = []
|
327
|
+
else
|
328
|
+
params['optionTypes'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
329
|
+
end
|
330
|
+
end
|
331
|
+
opts.add_hidden_option('--optionTypes')
|
332
|
+
build_option_type_options(opts, options, update_catalog_item_type_advanced_option_types)
|
333
|
+
build_standard_update_options(opts, options)
|
334
|
+
opts.footer = <<-EOT
|
335
|
+
Update a catalog item type.
|
336
|
+
[catalog item type] is required. This is the name or id of a catalog item type.
|
337
|
+
EOT
|
338
|
+
end
|
339
|
+
optparse.parse!(args)
|
340
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
341
|
+
connect(options)
|
342
|
+
catalog_item_type = find_catalog_item_type_by_name_or_id(args[0])
|
343
|
+
return 1 if catalog_item_type.nil?
|
344
|
+
payload = {}
|
345
|
+
if options[:payload]
|
346
|
+
payload = options[:payload]
|
347
|
+
payload.deep_merge!({catalog_item_type_object_key => parse_passed_options(options)})
|
348
|
+
else
|
349
|
+
payload.deep_merge!({catalog_item_type_object_key => parse_passed_options(options)})
|
350
|
+
# do not prompt on update
|
351
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_catalog_item_type_option_types, options[:options], @api_client, options[:params])
|
352
|
+
v_prompt.deep_compact!
|
353
|
+
params.deep_merge!(v_prompt)
|
354
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_catalog_item_type_advanced_option_types, options[:options], @api_client, options[:params])
|
355
|
+
advanced_config.deep_compact!
|
356
|
+
params.deep_merge!(advanced_config)
|
357
|
+
# convert checkbox "on" and "off" to true and false
|
358
|
+
params.booleanize!
|
359
|
+
# convert type to refType until api accepts type
|
360
|
+
if params['type'] && !params['refType']
|
361
|
+
if params['type'].to_s.downcase == 'blueprint'
|
362
|
+
params['refType'] = 'AppTemplate'
|
363
|
+
else
|
364
|
+
params['refType'] = 'InstanceType'
|
365
|
+
end
|
366
|
+
end
|
367
|
+
# convert config string to a map
|
368
|
+
config = params['config']
|
369
|
+
if config && config.is_a?(String)
|
370
|
+
parse_result = parse_json_or_yaml(config)
|
371
|
+
config_map = parse_result[:data]
|
372
|
+
if config_map.nil?
|
373
|
+
# todo: bubble up JSON.parse error message
|
374
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
375
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
376
|
+
else
|
377
|
+
params['config'] = config_map
|
378
|
+
end
|
379
|
+
end
|
380
|
+
payload.deep_merge!({catalog_item_type_object_key => params})
|
381
|
+
if payload[catalog_item_type_object_key].empty? # || options[:no_prompt]
|
382
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
383
|
+
end
|
384
|
+
end
|
385
|
+
@catalog_item_types_interface.setopts(options)
|
386
|
+
if options[:dry_run]
|
387
|
+
print_dry_run @catalog_item_types_interface.dry.update(catalog_item_type['id'], payload)
|
388
|
+
return
|
389
|
+
end
|
390
|
+
json_response = @catalog_item_types_interface.update(catalog_item_type['id'], payload)
|
391
|
+
catalog_item_type = json_response[catalog_item_type_object_key]
|
392
|
+
render_response(json_response, options, catalog_item_type_object_key) do
|
393
|
+
print_green_success "Updated catalog item #{catalog_item_type['name']}"
|
394
|
+
return _get(catalog_item_type["id"], {}, options)
|
395
|
+
end
|
396
|
+
return 0, nil
|
397
|
+
end
|
398
|
+
|
399
|
+
def remove(args)
|
400
|
+
options = {}
|
401
|
+
params = {}
|
402
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
403
|
+
opts.banner = subcommand_usage("[catalog item type] [options]")
|
404
|
+
build_standard_remove_options(opts, options)
|
405
|
+
opts.footer = <<-EOT
|
406
|
+
Delete a catalog_item_type.
|
407
|
+
[catalog item type] is required. This is the name or id of a catalog item type.
|
408
|
+
EOT
|
409
|
+
end
|
410
|
+
optparse.parse!(args)
|
411
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
412
|
+
connect(options)
|
413
|
+
catalog_item_type = find_catalog_item_type_by_name_or_id(args[0])
|
414
|
+
return 1 if catalog_item_type.nil?
|
415
|
+
@catalog_item_types_interface.setopts(options)
|
416
|
+
if options[:dry_run]
|
417
|
+
print_dry_run @catalog_item_types_interface.dry.destroy(catalog_item_type['id'], params)
|
418
|
+
return
|
419
|
+
end
|
420
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the catalog item #{catalog_item_type['name']}?")
|
421
|
+
return 9, "aborted command"
|
422
|
+
end
|
423
|
+
json_response = @catalog_item_types_interface.destroy(catalog_item_type['id'], params)
|
424
|
+
render_response(json_response, options) do
|
425
|
+
print_green_success "Removed catalog item #{catalog_item_type['name']}"
|
426
|
+
end
|
427
|
+
return 0, nil
|
428
|
+
end
|
429
|
+
|
430
|
+
private
|
431
|
+
|
432
|
+
def catalog_item_type_column_definitions()
|
433
|
+
{
|
434
|
+
"ID" => 'id',
|
435
|
+
"Name" => 'name',
|
436
|
+
"Description" => 'description',
|
437
|
+
"Type" => lambda {|it| format_catalog_type(it) },
|
438
|
+
"Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : nil },
|
439
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
440
|
+
"Featured" => lambda {|it| format_boolean(it['featured']) },
|
441
|
+
#"Config" => lambda {|it| it['config'] },
|
442
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
443
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
444
|
+
}
|
445
|
+
end
|
446
|
+
|
447
|
+
def format_catalog_type(catalog_item_type)
|
448
|
+
out = ""
|
449
|
+
# api "blueprint": {"name":my blueprint"} }
|
450
|
+
# instead of cryptic refType
|
451
|
+
if catalog_item_type['type']
|
452
|
+
if catalog_item_type['type'].is_a?(String)
|
453
|
+
out << catalog_item_type['type'].to_s.capitalize
|
454
|
+
else
|
455
|
+
out << (catalog_item_type['type']['name'] || catalog_item_type['type']['code']) rescue catalog_item_type['type'].to_s
|
456
|
+
end
|
457
|
+
else
|
458
|
+
ref_type = catalog_item_type['refType']
|
459
|
+
if ref_type == 'InstanceType'
|
460
|
+
out << "Instance"
|
461
|
+
elsif ref_type == 'AppTemplate'
|
462
|
+
out << "Blueprint"
|
463
|
+
elsif ref_type
|
464
|
+
out << ref_type
|
465
|
+
else
|
466
|
+
"(none)"
|
467
|
+
end
|
468
|
+
end
|
469
|
+
out
|
470
|
+
end
|
471
|
+
|
472
|
+
# this is not so simple, need to first choose select instance, host or provider
|
473
|
+
def add_catalog_item_type_option_types
|
474
|
+
[
|
475
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
476
|
+
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
|
477
|
+
{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Instance', 'value' => 'instance'}, {'name' => 'Blueprint', 'value' => 'blueprint'}], 'defaultValue' => 'instance'},
|
478
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => true},
|
479
|
+
{'fieldName' => 'featured', 'fieldLabel' => 'Featured', 'type' => 'checkbox', 'defaultValue' => false},
|
480
|
+
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'required' => true},
|
481
|
+
{'fieldName' => 'iconPath', 'fieldLabel' => 'Logo', 'type' => 'select', 'optionSource' => 'iconList'},
|
482
|
+
#{'fieldName' => 'optionTypes', 'fieldLabel' => 'Option Types', 'type' => 'text', 'description' => 'Option Types to include, comma separated list of names or IDs.'},
|
483
|
+
{'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'required' => true, 'description' => 'JSON or YAML'}
|
484
|
+
]
|
485
|
+
end
|
486
|
+
|
487
|
+
def add_catalog_item_type_advanced_option_types
|
488
|
+
[]
|
489
|
+
end
|
490
|
+
|
491
|
+
def update_catalog_item_type_option_types
|
492
|
+
add_catalog_item_type_option_types.collect {|it|
|
493
|
+
it.delete('required')
|
494
|
+
it.delete('defaultValue')
|
495
|
+
it
|
496
|
+
}
|
497
|
+
end
|
498
|
+
|
499
|
+
def update_catalog_item_type_advanced_option_types
|
500
|
+
add_catalog_item_type_advanced_option_types.collect {|it|
|
501
|
+
it.delete('required')
|
502
|
+
it.delete('defaultValue')
|
503
|
+
it
|
504
|
+
}
|
505
|
+
end
|
506
|
+
|
507
|
+
end
|