morpheus-cli 6.2.3 → 6.3.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/README.md +4 -1
- data/lib/morpheus/api/api_client.rb +8 -0
- data/lib/morpheus/api/library_cluster_packages_interface.rb +41 -0
- data/lib/morpheus/api/option_type_forms_interface.rb +9 -0
- data/lib/morpheus/cli/cli_command.rb +3 -1
- data/lib/morpheus/cli/cli_registry.rb +2 -4
- data/lib/morpheus/cli/commands/backups_command.rb +1 -1
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +54 -12
- data/lib/morpheus/cli/commands/certificates_command.rb +1 -1
- data/lib/morpheus/cli/commands/clusters.rb +1 -2
- data/lib/morpheus/cli/commands/library_cluster_packages_command.rb +485 -0
- data/lib/morpheus/cli/commands/library_forms_command.rb +625 -0
- data/lib/morpheus/cli/commands/network_servers_command.rb +19 -9
- data/lib/morpheus/cli/commands/policies_command.rb +112 -128
- data/lib/morpheus/cli/commands/roles.rb +3 -0
- data/lib/morpheus/cli/commands/self_service_command.rb +17 -0
- data/lib/morpheus/cli/commands/service_catalog_command.rb +70 -30
- data/lib/morpheus/cli/commands/virtual_images.rb +1 -1
- data/lib/morpheus/cli/error_handler.rb +18 -3
- data/lib/morpheus/cli/mixins/accounts_helper.rb +2 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +20 -6
- data/lib/morpheus/cli/mixins/prompt_helper.rb +132 -11
- data/lib/morpheus/cli/option_types.rb +104 -7
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/routes.rb +9 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8acef874a37276edc6d53f64e243ca01c0e0d30e49dea166502058da2f01350d
|
4
|
+
data.tar.gz: f0f9022abbb5b04c526cf992c95cacee2927ce5fb2e27027b19dc624abe454be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab4f224e431ff217ea24591b385d76f1a6370626770e8eb9f8ae8291c6d6681e3a29c58c6c220fea85510819da0df901e3816e37f4937ad2b04c4322a5eae0b2
|
7
|
+
data.tar.gz: 27976146b5f086f41968860c7eb210fdbc7cf8ac6667b55e1318e88f9fae938c33699b05a14a1cdba91bfcde0635b01113bc61c3c1e21ade5e2a7bea719cee66
|
data/Dockerfile
CHANGED
data/README.md
CHANGED
@@ -55,7 +55,7 @@ New CLI commands get added under the library directory: `lib/morpheus/cli/comman
|
|
55
55
|
While developing, you can quickly reload your code changes in a morpheus shell while developing:
|
56
56
|
|
57
57
|
```shell
|
58
|
-
morpheus shell
|
58
|
+
bundle exec morpheus shell —debug
|
59
59
|
```
|
60
60
|
|
61
61
|
Then to reload changes without restarting the morpheus shell (and the ruby process), use:
|
@@ -66,6 +66,9 @@ reload
|
|
66
66
|
|
67
67
|
Don't forget to add unit tests for your new commands under the directory: `test/`.
|
68
68
|
|
69
|
+
|
70
|
+
|
71
|
+
|
69
72
|
## Testing
|
70
73
|
|
71
74
|
To run the CLI unit tests, first create a `test_config.yaml` and then run `rake test`.
|
@@ -600,6 +600,10 @@ class Morpheus::APIClient
|
|
600
600
|
Morpheus::OptionTypeListsInterface.new(common_interface_options).setopts(@options)
|
601
601
|
end
|
602
602
|
|
603
|
+
def option_type_forms
|
604
|
+
Morpheus::OptionTypeFormsInterface.new(common_interface_options).setopts(@options)
|
605
|
+
end
|
606
|
+
|
603
607
|
def scale_thresholds
|
604
608
|
Morpheus::ScaleThresholdsInterface.new(common_interface_options).setopts(@options)
|
605
609
|
end
|
@@ -766,6 +770,10 @@ class Morpheus::APIClient
|
|
766
770
|
Morpheus::LibraryClusterLayoutsInterface.new(common_interface_options).setopts(@options)
|
767
771
|
end
|
768
772
|
|
773
|
+
def library_cluster_packages
|
774
|
+
Morpheus::LibraryClusterPackagesInterface.new(common_interface_options).setopts(@options)
|
775
|
+
end
|
776
|
+
|
769
777
|
def library_spec_templates
|
770
778
|
Morpheus::LibrarySpecTemplatesInterface.new(common_interface_options).setopts(@options)
|
771
779
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'morpheus/api/api_client'
|
2
|
+
|
3
|
+
class Morpheus::LibraryClusterPackagesInterface < Morpheus::APIClient
|
4
|
+
|
5
|
+
def list(params={})
|
6
|
+
url = "#{@base_url}/api/library/cluster-packages"
|
7
|
+
params['sort'] = 'name'
|
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(id, params={})
|
14
|
+
raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
|
15
|
+
url = "#{@base_url}/api/library/cluster-packages/#{id}"
|
16
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
17
|
+
opts = {method: :get, url: url, headers: headers}
|
18
|
+
execute(opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create(payload)
|
22
|
+
url = "#{@base_url}/api/library/cluster-packages"
|
23
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
24
|
+
opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
|
25
|
+
execute(opts)
|
26
|
+
end
|
27
|
+
|
28
|
+
def update(id, payload)
|
29
|
+
url = "#{@base_url}/api/library/cluster-packages/#{id}"
|
30
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
31
|
+
opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
|
32
|
+
execute(opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
def destroy(id, payload={})
|
36
|
+
url = "#{@base_url}/api/library/cluster-packages/#{id}"
|
37
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
38
|
+
opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
|
39
|
+
execute(opts)
|
40
|
+
end
|
41
|
+
end
|
@@ -268,7 +268,6 @@ module Morpheus
|
|
268
268
|
build_standard_post_options(opts, options, includes, excludes)
|
269
269
|
end
|
270
270
|
|
271
|
-
# todo: this can go away once every command is using execute_api()
|
272
271
|
def build_standard_add_many_options(opts, options, includes=[], excludes=[])
|
273
272
|
build_standard_post_options(opts, options, includes + [:payloads], excludes)
|
274
273
|
end
|
@@ -1579,6 +1578,9 @@ module Morpheus
|
|
1579
1578
|
# could use parse_passed_options() here to support exclusion of certain options
|
1580
1579
|
#passed_options = parse_passed_options(options, options[:apply_options] || {})
|
1581
1580
|
passed_options = options[:options].reject {|k,v| k.is_a?(Symbol)}
|
1581
|
+
if options[:apply_options_exclude]
|
1582
|
+
passed_options = options[:options].reject {|k,v| options[:skip_apply_options].include?(k.to_s) || options[:skip_apply_options].include?(k.to_sym) }
|
1583
|
+
end
|
1582
1584
|
if object_key
|
1583
1585
|
payload.deep_merge!({object_key => passed_options})
|
1584
1586
|
else
|
@@ -95,12 +95,10 @@ module Morpheus
|
|
95
95
|
suggestions = find_command_suggestions(command_name)
|
96
96
|
if suggestions && suggestions.size == 1
|
97
97
|
msg += "\nThe most similar command is:\n"
|
98
|
-
suggestions.first
|
99
|
-
msg += "\t" + suggestion + "\n"
|
100
|
-
end
|
98
|
+
msg += "\t" + suggestions.first + "\n"
|
101
99
|
elsif suggestions && suggestions.size > 1
|
102
100
|
msg += "\nThe most similar commands are:\n"
|
103
|
-
suggestions.first(
|
101
|
+
suggestions.first(50).each do |suggestion|
|
104
102
|
msg += "\t" + suggestion + "\n"
|
105
103
|
end
|
106
104
|
end
|
@@ -283,7 +283,7 @@ EOT
|
|
283
283
|
return 1 if backup.nil?
|
284
284
|
parse_options(options, params)
|
285
285
|
confirm!("Are you sure you want to delete the backup #{backup['name']}?", options)
|
286
|
-
execute_api(@backups_interface, :destroy, [backup['id']], options
|
286
|
+
execute_api(@backups_interface, :destroy, [backup['id']], options) do |json_response|
|
287
287
|
print_green_success "Removed backup #{backup['name']}"
|
288
288
|
end
|
289
289
|
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'morpheus/cli/cli_command'
|
2
2
|
|
3
|
-
# CLI command
|
4
|
-
# UI is
|
5
|
-
# API is /catalog-item-types and returns catalogItemTypes
|
3
|
+
# CLI command Catalog Item Types
|
4
|
+
# UI is Library > Blueprints > Catalog Items
|
5
|
+
# API is /api/catalog-item-types and returns catalogItemTypes
|
6
6
|
class Morpheus::Cli::CatalogItemTypesCommand
|
7
7
|
include Morpheus::Cli::CliCommand
|
8
8
|
include Morpheus::Cli::LibraryHelper
|
9
9
|
include Morpheus::Cli::OptionSourceHelper
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
set_command_description "Self Service: View and manage catalog item types"
|
11
|
+
set_command_name :'catalog-item-types'
|
12
|
+
set_command_description "View and manage catalog item types"
|
14
13
|
|
15
14
|
register_subcommands :list, :get, :add, :update, :remove
|
16
15
|
register_subcommands({:'update-logo' => :update_logo, :'update-dark-logo' => :update_dark_logo})
|
@@ -152,13 +151,28 @@ EOT
|
|
152
151
|
print_h1 "Catalog Item Type Details", [], options
|
153
152
|
print cyan
|
154
153
|
show_columns = catalog_item_type_column_definitions
|
154
|
+
show_columns.delete("Form") unless catalog_item_type['form']
|
155
155
|
show_columns.delete("Blueprint") unless catalog_item_type['blueprint']
|
156
156
|
show_columns.delete("Workflow") unless catalog_item_type['workflow']
|
157
157
|
show_columns.delete("Context") unless catalog_item_type['context'] # workflow context
|
158
158
|
print_description_list(show_columns, catalog_item_type)
|
159
159
|
|
160
|
+
option_type_form = catalog_item_type['form']
|
161
|
+
if option_type_form
|
162
|
+
print_h2 "Form Inputs"
|
163
|
+
form_inputs = (option_type_form['options'] || [])
|
164
|
+
if option_type_form['fieldGroups']
|
165
|
+
option_type_form['fieldGroups'].each { |field_group| form_inputs += (field_group['options'] || []) }
|
166
|
+
end
|
167
|
+
# print format_simple_option_types_table(form_inputs, options)
|
168
|
+
print format_option_types_table(form_inputs, options, 'config.customOptions')
|
169
|
+
print reset,"\n"
|
170
|
+
else
|
171
|
+
# print cyan,"No form inputs found for this catalog item.","\n",reset
|
172
|
+
end
|
173
|
+
|
160
174
|
if catalog_item_type['optionTypes'] && catalog_item_type['optionTypes'].size > 0
|
161
|
-
print_h2 "
|
175
|
+
print_h2 "Inputs"
|
162
176
|
opt_columns = [
|
163
177
|
{"ID" => lambda {|it| it['id'] } },
|
164
178
|
{"NAME" => lambda {|it| it['name'] } },
|
@@ -313,7 +327,13 @@ EOT
|
|
313
327
|
options[:options]['config'] = params['config'] # or file_content
|
314
328
|
end
|
315
329
|
end
|
316
|
-
opts.on('--
|
330
|
+
opts.on('--form-type form|optionTypes', String, "Form Type determines if input comes from a Form or list of Option Types") do |val|
|
331
|
+
params['formType'] = val
|
332
|
+
end
|
333
|
+
opts.on('--form FORM', String, "Form Name or ID") do |val|
|
334
|
+
params['form'] = val
|
335
|
+
end
|
336
|
+
opts.on('--option-types [x,y,z]', Array, "List of Option Type IDs") do |val|
|
317
337
|
if list.nil?
|
318
338
|
params['optionTypes'] = []
|
319
339
|
else
|
@@ -379,11 +399,24 @@ EOT
|
|
379
399
|
# massage association params a bit
|
380
400
|
params['workflow'] = {'id' => params['workflow']} if params['workflow'] && !params['workflow'].is_a?(Hash)
|
381
401
|
params['blueprint'] = {'id' => params['blueprint']} if params['blueprint'] && !params['blueprint'].is_a?(Hash)
|
382
|
-
|
383
|
-
|
384
|
-
|
402
|
+
if params['formType'].to_s.empty?
|
403
|
+
params['formType'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'formType', 'fieldLabel' => 'Form Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Form', 'value' => 'form'}, {'name' => 'Inputs', 'value' => 'optionTypes'}], 'defaultValue' => 'optionTypes', 'required' => true}], options[:options], @api_client, options[:params])['formType']
|
404
|
+
end
|
405
|
+
if params['formType'] == 'form'
|
406
|
+
# using formType = 'form'
|
407
|
+
# prompt for Form
|
408
|
+
options[:options]['form'] = params['form'] if params['form']
|
409
|
+
form_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'form', 'fieldLabel' => 'Form', 'type' => 'select', 'optionSource' => 'forms', 'required' => true}], options[:options], @api_client, options[:params])['form']
|
410
|
+
params['form'] = {'id' => form_id}
|
385
411
|
else
|
386
|
-
|
412
|
+
# using formType = 'optionTypes'
|
413
|
+
# prompt for Option Types
|
414
|
+
prompt_results = prompt_for_option_types(params, options, @api_client)
|
415
|
+
if prompt_results[:success]
|
416
|
+
params['optionTypes'] = prompt_results[:data] unless prompt_results[:data].nil?
|
417
|
+
else
|
418
|
+
return 1, "failed to parse optionTypes"
|
419
|
+
end
|
387
420
|
end
|
388
421
|
payload[catalog_item_type_object_key].deep_merge!(params)
|
389
422
|
end
|
@@ -470,6 +503,12 @@ EOT
|
|
470
503
|
options[:options]['config'] = params['config'] # or file_content
|
471
504
|
end
|
472
505
|
end
|
506
|
+
opts.on('--form-type form|optionTypes', String, "Form Type determines if input comes from a Form or list of Option Types") do |val|
|
507
|
+
params['formType'] = val
|
508
|
+
end
|
509
|
+
opts.on('--form FORM', String, "Form Name or ID") do |val|
|
510
|
+
params['form'] = val
|
511
|
+
end
|
473
512
|
opts.on('--option-types [x,y,z]', Array, "List of Option Type IDs") do |list|
|
474
513
|
if list.nil?
|
475
514
|
params['optionTypes'] = []
|
@@ -693,6 +732,7 @@ EOT
|
|
693
732
|
"Workflow" => lambda {|it| it['workflow'] ? it['workflow']['name'] : nil },
|
694
733
|
"Context" => lambda {|it| it['context'] },
|
695
734
|
# "Content" => lambda {|it| it['content'] },
|
735
|
+
"Form Type" => lambda {|it| it['formType'] == 'form' ? "Form" : "Inputs" },
|
696
736
|
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
697
737
|
"Featured" => lambda {|it| format_boolean(it['featured']) },
|
698
738
|
#"Config" => lambda {|it| it['config'] },
|
@@ -716,6 +756,8 @@ EOT
|
|
716
756
|
"Workflow" => lambda {|it| it['workflow'] ? it['workflow']['name'] : nil },
|
717
757
|
"Context" => lambda {|it| it['context'] },
|
718
758
|
# "Content" => lambda {|it| it['content'] },
|
759
|
+
"Form Type" => lambda {|it| it['formType'] == 'form' ? "Form" : "Inputs" },
|
760
|
+
"Form" => lambda {|it| it['form'] ? it['form']['name'] : nil },
|
719
761
|
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
720
762
|
"Featured" => lambda {|it| format_boolean(it['featured']) },
|
721
763
|
"Allow Quantity" => lambda {|it| format_boolean(it['allowQuantity']) },
|
@@ -175,7 +175,7 @@ EOT
|
|
175
175
|
end
|
176
176
|
# reject hardcoded optionTypes
|
177
177
|
config_option_types = config_option_types.reject {|it| it['fieldName'] == 'name' || it['fieldName'] == 'description' || it['fieldName'] == 'domainName' }
|
178
|
-
config_prompt = Morpheus::Cli::OptionTypes.prompt(config_option_types, options[:options], @api_client,
|
178
|
+
config_prompt = Morpheus::Cli::OptionTypes.prompt(config_option_types, options[:options], @api_client, {certType: certificate_type['id']})
|
179
179
|
config_prompt.deep_compact!
|
180
180
|
params.deep_merge!(config_prompt)
|
181
181
|
end
|
@@ -730,14 +730,13 @@ class Morpheus::Cli::Clusters
|
|
730
730
|
server_payload['hostname'] = options[:hostname] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'hostname', 'fieldLabel' => 'Hostname', 'type' => 'text', 'required' => true, 'description' => 'Hostname', 'defaultValue' => resourceName}], options[:options], @api_client, api_params)['hostname']
|
731
731
|
|
732
732
|
# Kube Default Repo
|
733
|
-
if cluster_payload['type'] == 'kubernetes-cluster'
|
733
|
+
if cluster_payload['type'] == 'kubernetes-cluster'
|
734
734
|
default_repo = options[:default_repo] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultRepoAccount', 'fieldLabel' => 'Cluster Repo Account', 'type' => 'select', 'required' => false, 'optionSource' => 'dockerHubRegistries'}], options[:options], @api_client, api_params)['defaultRepoAccount']
|
735
735
|
if default_repo != ""
|
736
736
|
server_payload['config']['defaultRepoAccount'] = default_repo
|
737
737
|
end
|
738
738
|
end
|
739
739
|
|
740
|
-
|
741
740
|
# Workflow / Automation
|
742
741
|
if provision_type['code'] != 'manual' && controller_type && controller_type['hasAutomation']
|
743
742
|
task_set_id = options[:taskSetId] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'taskSet', 'fieldLabel' => 'Workflow', 'type' => 'select', 'required' => false, 'optionSource' => 'taskSets'}], options[:options], @api_client, api_params.merge({'phase' => 'postProvision'}))['taskSet']
|