morpheus-cli 6.0.0 → 6.0.2
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/jobs_interface.rb +2 -2
- data/lib/morpheus/api/network_services_interface.rb +16 -0
- data/lib/morpheus/cli/commands/apps.rb +1 -1
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +11 -9
- data/lib/morpheus/cli/commands/curl_command.rb +5 -1
- data/lib/morpheus/cli/commands/instances.rb +1 -1
- data/lib/morpheus/cli/commands/invoices_command.rb +1 -1
- data/lib/morpheus/cli/commands/jobs_command.rb +50 -3
- data/lib/morpheus/cli/commands/load_balancers.rb +5 -0
- data/lib/morpheus/cli/commands/network_services_command.rb +60 -1
- data/lib/morpheus/cli/commands/service_catalog_command.rb +32 -2
- data/lib/morpheus/cli/commands/service_plans_command.rb +85 -22
- data/lib/morpheus/cli/commands/shell.rb +1 -1
- data/lib/morpheus/cli/commands/tasks.rb +129 -34
- data/lib/morpheus/cli/commands/workflows.rb +108 -22
- 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 +12 -5
- data/lib/morpheus/cli/option_types.rb +4 -1
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb39926e3f31b77cdca9175335ca0260b720641e469a240618fc98816b2b98ee
|
4
|
+
data.tar.gz: ef40d39ffa3f4a6d51139524fee83dd990b082c326b528ad66a6a8e6629c43e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32d58f65d940360fdfb48ff00f88d7f2221dbe4ad1d50adbd441ee68ae79cf7fb5e1314b7d1644808a8795fa362b0e0698e0d89ef8f57187442880fc1a0fec40
|
7
|
+
data.tar.gz: 19f7a173551371d306edbbbde91ad910f96c5c77fe8c70ef09200ba85e50885e4533cfb36c1f6c26b3cacacb629d7459aabb569f03e71d07e0a5720e3134fc9c
|
data/Dockerfile
CHANGED
@@ -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
|
@@ -23,6 +23,22 @@ class Morpheus::NetworkServicesInterface < Morpheus::APIClient
|
|
23
23
|
execute(method: :get, url: url, headers: headers)
|
24
24
|
end
|
25
25
|
|
26
|
+
def get_server(server_id)
|
27
|
+
execute(method: :get, url: "#{@base_url}/api/networks/servers/#{server_id}", params: {}, headers: {})
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_servers()
|
31
|
+
execute(method: :get, url: "#{@base_url}/api/networks/servers", params: {}, headers: {})
|
32
|
+
end
|
33
|
+
|
34
|
+
def refresh(server_id)
|
35
|
+
url = "#{@base_url}/api/networks/servers/#{server_id}/refresh"
|
36
|
+
|
37
|
+
headers = { :params => {}, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
38
|
+
opts = {method: :post, url: url, headers: headers}
|
39
|
+
execute(opts)
|
40
|
+
end
|
41
|
+
|
26
42
|
# def create(payload)
|
27
43
|
# url = "#{@base_url}/api/networks/services"
|
28
44
|
# headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
@@ -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]")
|
@@ -716,6 +716,7 @@ EOT
|
|
716
716
|
# "Content" => lambda {|it| it['content'] },
|
717
717
|
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
718
718
|
"Featured" => lambda {|it| format_boolean(it['featured']) },
|
719
|
+
"Allow Quantity" => lambda {|it| format_boolean(it['allowQuantity']) },
|
719
720
|
#"Config" => lambda {|it| it['config'] },
|
720
721
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
721
722
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
@@ -757,19 +758,20 @@ EOT
|
|
757
758
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 4},
|
758
759
|
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => true, 'displayOrder' => 5},
|
759
760
|
{'fieldName' => 'featured', 'fieldLabel' => 'Featured', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 6},
|
760
|
-
{'fieldName' => '
|
761
|
-
{'fieldName' => '
|
762
|
-
{'fieldName' => '
|
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},
|
763
765
|
#{'fieldName' => 'optionTypes', 'fieldLabel' => 'Option Types', 'type' => 'text', 'description' => 'Option Types to include, comma separated list of names or IDs.', 'displayOrder' => 8},
|
764
|
-
{'dependsOnCode' => 'catalogItemType.type:instance', 'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'description' => 'JSON or YAML', 'required' => true, 'displayOrder' =>
|
765
|
-
{'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflowConfig', 'fieldLabel' => 'Config', 'type' => 'textarea', 'description' => 'Enter configuration for the Workflow', 'required' => false, 'noParse' => true, 'displayOrder' =>
|
766
|
-
{'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' =>
|
767
|
-
{'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' =>
|
768
|
-
{'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' =>
|
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},
|
769
771
|
{'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'context', 'fieldLabel' => 'Context Type', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
770
772
|
[{'name' => "Select", 'value' => ""}, {'name' => "None", 'value' => "appliance"}, {'name' => "Instance", 'value' => "instance"}, {'name' => "Server", 'value' => "server"}]
|
771
773
|
}, 'description' => 'Context for operational workflow, determines target type', 'defaultValue' => 'Select', 'required' => false},
|
772
|
-
{'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}
|
773
775
|
]
|
774
776
|
end
|
775
777
|
|
@@ -27,7 +27,11 @@ class Morpheus::Cli::CurlCommand
|
|
27
27
|
curl_method = "DELETE"
|
28
28
|
end
|
29
29
|
opts.on( '--data DATA', String, "HTTP request body for use with POST and PUT, typically JSON." ) do |val|
|
30
|
-
|
30
|
+
begin
|
31
|
+
options[:payload] = JSON.parse(val.to_s)
|
32
|
+
rescue => ex
|
33
|
+
raise ::OptionParser::InvalidOption.new("Failed to parse payload as JSON. Error: #{ex.message}")
|
34
|
+
end
|
31
35
|
end
|
32
36
|
opts.on('--absolute', "Absolute path, value can be used to prevent automatic using the automatic /api/ path prefix to the path by default.") do
|
33
37
|
options[:absolute_path] = true
|
@@ -4946,7 +4946,7 @@ EOT
|
|
4946
4946
|
end
|
4947
4947
|
|
4948
4948
|
def apply(args)
|
4949
|
-
default_refresh_interval =
|
4949
|
+
default_refresh_interval = 5
|
4950
4950
|
params, payload, options = {}, {}, {}
|
4951
4951
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
4952
4952
|
opts.banner = subcommand_usage("[instance] [options]")
|
@@ -350,7 +350,7 @@ class Morpheus::Cli::InvoicesCommand
|
|
350
350
|
if cost_rows.sum { |it| it[:extra].to_f } == 0
|
351
351
|
cost_columns.delete("Extra".upcase)
|
352
352
|
end
|
353
|
-
print as_pretty_table(cost_rows, cost_columns, options)
|
353
|
+
print as_pretty_table(cost_rows, cost_columns, options.merge(include_fields: nil))
|
354
354
|
else
|
355
355
|
print "\n"
|
356
356
|
print yellow, "No invoice totals data", reset, "\n"
|
@@ -280,17 +280,37 @@ class Morpheus::Cli::JobsCommand
|
|
280
280
|
end
|
281
281
|
options[:type] = 'morpheus.securityScan'
|
282
282
|
end
|
283
|
-
opts.on('--context-type [TYPE]', String, "Context type (instance|server|none). Default is none") do |val|
|
283
|
+
opts.on('--context-type [TYPE]', String, "Context type (instance|instance-label|server|server-label|none). Default is none") do |val|
|
284
|
+
val = val.to_s.downcase
|
284
285
|
params['targetType'] = (val == 'none' ? 'appliance' : val)
|
285
286
|
end
|
287
|
+
opts.on('--target-type [TYPE]', String, "alias for --context-type") do |val|
|
288
|
+
val = val.to_s.downcase
|
289
|
+
params['targetType'] = (val == 'none' ? 'appliance' : val)
|
290
|
+
end
|
291
|
+
opts.add_hidden_option('--target-type')
|
286
292
|
opts.on('--instances [LIST]', Array, "Context instances(s), comma separated list of instance IDs. Incompatible with --servers") do |list|
|
287
293
|
params['targetType'] = 'instance'
|
288
294
|
params['targets'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq.collect {|it| {'refId' => it.to_i}}
|
289
295
|
end
|
296
|
+
opts.on('--instance-label LABEL', String, "Instance Label") do |val|
|
297
|
+
if params['targetType'] && params['targetType'] != 'instance-label'
|
298
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
|
299
|
+
end
|
300
|
+
params['targetType'] = 'instance-label'
|
301
|
+
params['instanceLabel'] = val
|
302
|
+
end
|
290
303
|
opts.on('--servers [LIST]', Array, "Context server(s), comma separated list of server IDs. Incompatible with --instances") do |list|
|
291
304
|
params['targetType'] = 'server'
|
292
305
|
params['targets'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq.collect {|it| {'refId' => it.to_i}}
|
293
306
|
end
|
307
|
+
opts.on('--server-label LABEL', String, "Server Label") do |val|
|
308
|
+
if params['targetType'] && params['targetType'] != 'server-label'
|
309
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
|
310
|
+
end
|
311
|
+
params['targetType'] = 'server-label'
|
312
|
+
params['serverLabel'] = val
|
313
|
+
end
|
294
314
|
opts.on('-S', '--schedule [SCHEDULE]', String, "Job execution schedule type name or ID") do |val|
|
295
315
|
options[:schedule] = val
|
296
316
|
end
|
@@ -465,8 +485,15 @@ class Morpheus::Cli::JobsCommand
|
|
465
485
|
end
|
466
486
|
end
|
467
487
|
params['targets'] = targets.collect {|it| {'refId' => it}}
|
488
|
+
elsif params['targetType'] == 'instance-label'
|
489
|
+
if params['instanceLabel'].nil?
|
490
|
+
params['instanceLabel'] = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
|
491
|
+
end
|
492
|
+
elsif params['targetType'] == 'server-label'
|
493
|
+
if params['serverLabel'].nil?
|
494
|
+
params['serverLabel'] = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
|
495
|
+
end
|
468
496
|
end
|
469
|
-
|
470
497
|
# schedule
|
471
498
|
if options[:schedule].nil?
|
472
499
|
options[:schedule] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'scheduleMode', 'fieldLabel' => "Schedule", 'type' => 'select', 'required' => true, 'selectOptions' => job_options['schedules'], 'defaultValue' => job_options['schedules'].first['name']}], options[:options], @api_client, {})['scheduleMode']
|
@@ -554,17 +581,37 @@ class Morpheus::Cli::JobsCommand
|
|
554
581
|
options[:security_package] = val
|
555
582
|
end
|
556
583
|
end
|
557
|
-
opts.on('--context-type [TYPE]', String, "Context type (instance|server|none). Default is none") do |val|
|
584
|
+
opts.on('--context-type [TYPE]', String, "Context type (instance|instance-label|server|server-label|none). Default is none") do |val|
|
585
|
+
val = val.to_s.downcase
|
586
|
+
params['targetType'] = (val == 'none' ? 'appliance' : val)
|
587
|
+
end
|
588
|
+
opts.on('--target-type [TYPE]', String, "alias for --context-type") do |val|
|
589
|
+
val = val.to_s.downcase
|
558
590
|
params['targetType'] = (val == 'none' ? 'appliance' : val)
|
559
591
|
end
|
592
|
+
opts.add_hidden_option('--target-type')
|
560
593
|
opts.on('--instances [LIST]', Array, "Context instances(s), comma separated list of instance IDs. Incompatible with --servers") do |list|
|
561
594
|
params['targetType'] = 'instance'
|
562
595
|
options[:targets] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip.to_i }.compact.uniq.collect {|it| {'refId' => it.to_i}}
|
563
596
|
end
|
597
|
+
opts.on('--instance-label LABEL', String, "Instance Label") do |val|
|
598
|
+
if params['targetType'] && params['targetType'] != 'instance-label'
|
599
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
|
600
|
+
end
|
601
|
+
params['targetType'] = 'instance-label'
|
602
|
+
params['instanceLabel'] = val
|
603
|
+
end
|
564
604
|
opts.on('--servers [LIST]', Array, "Context server(s), comma separated list of server IDs. Incompatible with --instances") do |list|
|
565
605
|
params['targetType'] = 'server'
|
566
606
|
options[:targets] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip.to_i }.compact.uniq.collect {|it| {'refId' => it.to_i}}
|
567
607
|
end
|
608
|
+
opts.on('--server-label LABEL', String, "Server Label") do |val|
|
609
|
+
if params['targetType'] && params['targetType'] != 'server-label'
|
610
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
|
611
|
+
end
|
612
|
+
params['targetType'] = 'server-label'
|
613
|
+
params['serverLabel'] = val
|
614
|
+
end
|
568
615
|
opts.on('--schedule [SCHEDULE]', String, "Job execution schedule type name or ID") do |val|
|
569
616
|
options[:schedule] = val
|
570
617
|
end
|
@@ -24,6 +24,9 @@ class Morpheus::Cli::LoadBalancers
|
|
24
24
|
render_response(json_response, options, rest_object_key) do
|
25
25
|
record = json_response[rest_object_key]
|
26
26
|
options[:exclude_username] = record['username'].nil?
|
27
|
+
options[:exclude_owner] = record['owner'].nil?
|
28
|
+
options[:exclude_tenants] = record['tenants'].nil? || record['tenants'].empty?
|
29
|
+
options[:exclude_permissions] = record['resourcePermission'].nil?
|
27
30
|
print_h1 rest_label, [], options
|
28
31
|
print cyan
|
29
32
|
print_description_list(rest_column_definitions(options), record, options)
|
@@ -125,6 +128,8 @@ EOT
|
|
125
128
|
"Provider ID" => 'externalId'
|
126
129
|
}
|
127
130
|
columns.merge!({"Username" => 'username'}) if !options[:exclude_username]
|
131
|
+
columns.merge!({"Owner" => lambda { |it| it['owner']['name'] rescue '' }}) if !options[:exclude_owner]
|
132
|
+
columns.merge!({"Tenants" => lambda { |it| it['tenants'].collect {|tenant| tenant['name']}.join(', ') rescue '' }}) if !options[:exclude_tenants]
|
128
133
|
columns.merge({
|
129
134
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
130
135
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
@@ -7,7 +7,7 @@ class Morpheus::Cli::NetworkServicesCommand
|
|
7
7
|
set_command_name :'network-services'
|
8
8
|
|
9
9
|
# register_subcommands :list, :get, :add, :update, :remove
|
10
|
-
register_subcommands :list
|
10
|
+
register_subcommands :list, :refresh
|
11
11
|
|
12
12
|
# set_default_subcommand :list
|
13
13
|
|
@@ -90,6 +90,43 @@ class Morpheus::Cli::NetworkServicesCommand
|
|
90
90
|
exit 1
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
def refresh(args)
|
95
|
+
options = {}
|
96
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
97
|
+
opts.banner = subcommand_usage("[name]")
|
98
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
99
|
+
opts.footer = "Refresh a network integration/server.\n" +
|
100
|
+
"[name] is required. This is the name or id of a network server/integration."
|
101
|
+
end
|
102
|
+
optparse.parse!(args)
|
103
|
+
if args.count < 1
|
104
|
+
puts optparse
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
connect(options)
|
108
|
+
begin
|
109
|
+
server = find_network_server_by_name_or_id(args[0])
|
110
|
+
if !server
|
111
|
+
exit 1
|
112
|
+
end
|
113
|
+
@network_services_interface.setopts(options)
|
114
|
+
if options[:dry_run]
|
115
|
+
print_dry_run @network_services_interface.dry.refresh(server['id'])
|
116
|
+
return
|
117
|
+
end
|
118
|
+
json_response = @network_services_interface.refresh(server['id'])
|
119
|
+
if options[:json]
|
120
|
+
print JSON.pretty_generate(json_response)
|
121
|
+
print "\n"
|
122
|
+
elsif !options[:quiet]
|
123
|
+
print_green_success "Refreshing #{server["name"]}"
|
124
|
+
end
|
125
|
+
rescue RestClient::Exception => e
|
126
|
+
print_rest_exception(e, options)
|
127
|
+
exit 1
|
128
|
+
end
|
129
|
+
end
|
93
130
|
|
94
131
|
|
95
132
|
private
|
@@ -136,4 +173,26 @@ class Morpheus::Cli::NetworkServicesCommand
|
|
136
173
|
end
|
137
174
|
end
|
138
175
|
|
176
|
+
def find_network_server_by_name_or_id(val)
|
177
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
178
|
+
return find_network_server_by_id(val)
|
179
|
+
else
|
180
|
+
return find_network_service_by_name(val)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def find_network_server_by_id(id)
|
185
|
+
begin
|
186
|
+
json_response = @network_services_interface.get_server(id.to_i)
|
187
|
+
return json_response['networkServer']
|
188
|
+
rescue RestClient::Exception => e
|
189
|
+
if e.response && e.response.code == 404
|
190
|
+
print_red_alert "Network Service not found by id #{id}"
|
191
|
+
return nil
|
192
|
+
else
|
193
|
+
raise e
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
139
198
|
end
|
@@ -594,11 +594,15 @@ EOT
|
|
594
594
|
type_id = nil
|
595
595
|
workflow_context = nil
|
596
596
|
workflow_target = nil
|
597
|
+
quantity = nil
|
597
598
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
598
599
|
opts.banner = subcommand_usage("[type] [options]")
|
599
600
|
opts.on('-t', '--type TYPE', String, "Catalog Item Type Name or ID") do |val|
|
600
601
|
type_id = val.to_s
|
601
602
|
end
|
603
|
+
opts.on('--quantity QUANTITY', String, "Quantity for this catalog item. Will be overridden to 1 if quantity not allowed.") do |val|
|
604
|
+
quantity = val.to_s
|
605
|
+
end
|
602
606
|
opts.on('--validate','--validate', "Validate Only. Validates the configuration and skips adding the item.") do
|
603
607
|
options[:validate_only] = true
|
604
608
|
end
|
@@ -648,6 +652,16 @@ EOT
|
|
648
652
|
payload[add_item_object_key]['type'] = {'name' => catalog_item_type['name']}
|
649
653
|
#payload[add_item_object_key]['type'] = {'id' => catalog_item_type['id']}
|
650
654
|
|
655
|
+
if quantity
|
656
|
+
payload[add_item_object_key].deep_merge!({'quantity' => quantity})
|
657
|
+
else
|
658
|
+
if catalog_item_type['allowQuantity']
|
659
|
+
quantity_option_type = {'fieldName' => 'quantity', 'fieldLabel' => 'Quantity', 'type' => 'number', 'defaultValue' => 1, 'required' => true, 'displayOrder' => 1}
|
660
|
+
quantity_prompt = Morpheus::Cli::OptionTypes.prompt( [quantity_option_type], options[:options], @api_client, options[:params])['quantity']
|
661
|
+
payload[add_item_object_key].deep_merge!({'quantity' => quantity_prompt})
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
651
665
|
# this is silly, need to load by id to get optionTypes
|
652
666
|
# maybe do ?name=foo&includeOptionTypes=true
|
653
667
|
if catalog_item_type['optionTypes'].nil?
|
@@ -926,11 +940,15 @@ EOT
|
|
926
940
|
type_id = nil
|
927
941
|
workflow_context = nil
|
928
942
|
workflow_target = nil
|
943
|
+
quantity = nil
|
929
944
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
930
945
|
opts.banner = subcommand_usage("[type] [options]")
|
931
946
|
opts.on('-t', '--type TYPE', String, "Catalog Item Type Name or ID") do |val|
|
932
947
|
type_id = val.to_s
|
933
948
|
end
|
949
|
+
opts.on('--quantity QUANTITY', String, "Quantity for this catalog item. Will be overridden to 1 if quantity not allowed.") do |val|
|
950
|
+
quantity = val.to_s
|
951
|
+
end
|
934
952
|
opts.on('--validate','--validate', "Validate Only. Validates the configuration and skips creating the order.") do
|
935
953
|
options[:validate_only] = true
|
936
954
|
end
|
@@ -991,6 +1009,17 @@ EOT
|
|
991
1009
|
item_payload['type'] = {'name' => catalog_item_type['name']}
|
992
1010
|
#payload[add_item_object_key]['type'] = {'id' => catalog_item_type['id']}
|
993
1011
|
|
1012
|
+
if quantity
|
1013
|
+
item_payload.deep_merge!({'quantity' => quantity})
|
1014
|
+
else
|
1015
|
+
if catalog_item_type['allowQuantity']
|
1016
|
+
quantity_option_type = {'fieldName' => 'quantity', 'fieldLabel' => 'Quantity', 'type' => 'number', 'defaultValue' => 1, 'required' => true, 'displayOrder' => 1}
|
1017
|
+
quantity_prompt = Morpheus::Cli::OptionTypes.prompt( [quantity_option_type], options[:options], @api_client, options[:params])['quantity']
|
1018
|
+
item_payload.deep_merge!({'quantity' => quantity_prompt})
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
|
994
1023
|
# this is silly, need to load by id to get optionTypes
|
995
1024
|
# maybe do ?name=foo&includeOptionTypes=true
|
996
1025
|
if catalog_item_type['optionTypes'].nil?
|
@@ -1200,6 +1229,7 @@ EOT
|
|
1200
1229
|
# "Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : nil },
|
1201
1230
|
# "Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
1202
1231
|
"Featured" => lambda {|it| format_boolean(it['featured']) },
|
1232
|
+
"Allow Quantity" => lambda {|it| format_boolean(it['allowQuantity']) },
|
1203
1233
|
#"Config" => lambda {|it| it['config'] },
|
1204
1234
|
# "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
1205
1235
|
# "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
@@ -1408,7 +1438,7 @@ EOT
|
|
1408
1438
|
{"ID" => lambda {|it| it['id'] } },
|
1409
1439
|
#{"NAME" => lambda {|it| it['name'] } },
|
1410
1440
|
{"Type" => lambda {|it| it['type']['name'] rescue '' } },
|
1411
|
-
|
1441
|
+
{"Qty" => lambda {|it| it['quantity'] } },
|
1412
1442
|
{"Price" => lambda {|it| it['price'] ? format_money(it['price'] , it['currency'], {sigdig:options[:sigdig] || default_sigdig}) : "No pricing configured" } },
|
1413
1443
|
{"Status" => lambda {|it|
|
1414
1444
|
status_string = format_catalog_item_status(it)
|
@@ -1438,7 +1468,7 @@ EOT
|
|
1438
1468
|
{"ID" => lambda {|it| it['id'] } },
|
1439
1469
|
#{"NAME" => lambda {|it| it['name'] } },
|
1440
1470
|
{"TYPE" => lambda {|it| it['type']['name'] rescue '' } },
|
1441
|
-
|
1471
|
+
{"QTY" => lambda {|it| it['quantity'] } },
|
1442
1472
|
{"PRICE" => lambda {|it| it['price'] ? format_money(it['price'] , it['currency'], {sigdig:options[:sigdig] || default_sigdig}) : "No pricing configured" } },
|
1443
1473
|
{"STATUS" => lambda {|it|
|
1444
1474
|
status_string = format_catalog_item_status(it)
|
@@ -171,13 +171,21 @@ class Morpheus::Cli::ServicePlanCommand
|
|
171
171
|
ranges = (service_plan['config'] ? service_plan['config']['ranges'] : nil) || {}
|
172
172
|
|
173
173
|
if (ranges['minStorage'] && ranges['minStorage'] != '') || (ranges['maxStorage'] && ranges['maxStorage'] != '')
|
174
|
-
description_cols['Custom Storage Range'] = lambda {|it|
|
174
|
+
description_cols['Custom Total Storage Range'] = lambda {|it|
|
175
175
|
get_range(
|
176
176
|
ranges['minStorage'] && ranges['minStorage'] != '' ? "#{ranges['minStorage']} #{(it['config'] && it['config']['storageSizeType'] ? it['config']['storageSizeType'] : 'GB').upcase}" : nil,
|
177
177
|
ranges['maxStorage'] && ranges['maxStorage'] != '' ? "#{ranges['maxStorage']} #{(it['config'] && it['config']['storageSizeType'] ? it['config']['storageSizeType'] : 'GB').upcase}" : nil,
|
178
178
|
)
|
179
179
|
}
|
180
180
|
end
|
181
|
+
if (ranges['minPerDiskSize'] && ranges['minPerDiskSize'] != '') || (ranges['maxPerDiskSize'] && ranges['maxPerDiskSize'] != '')
|
182
|
+
description_cols['Custom Per Disk Range'] = lambda {|it|
|
183
|
+
get_range(
|
184
|
+
ranges['minPerDiskSize'] && ranges['minPerDiskSize'] != '' ? "#{ranges['minPerDiskSize']} GB" : nil,
|
185
|
+
ranges['maxPerDiskSize'] && ranges['maxPerDiskSize'] != '' ? "#{ranges['maxPerDiskSize']} GB" : nil
|
186
|
+
)
|
187
|
+
}
|
188
|
+
end
|
181
189
|
if (ranges['minMemory'] && ranges['minMemory'] != '') || (ranges['maxMemory'] && ranges['maxMemory'] != '')
|
182
190
|
description_cols['Custom Memory Range'] = lambda {|it|
|
183
191
|
get_range(
|
@@ -264,6 +272,9 @@ class Morpheus::Cli::ServicePlanCommand
|
|
264
272
|
opts.on('--disks [NUMBER]', Integer, "Max disks allowed" ) do |val|
|
265
273
|
params['maxDisks'] = val.to_i || 1
|
266
274
|
end
|
275
|
+
opts.on('--cores-per-socket [NUMBER]', Integer, "Cores Per Socket") do |val|
|
276
|
+
params['coresPerSocket'] = val.to_i || 1
|
277
|
+
end
|
267
278
|
opts.on('--custom-cores [on|off]', String, "Can be used to enable / disable customizable cores. Default is on") do |val|
|
268
279
|
params['customCores'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
269
280
|
end
|
@@ -285,17 +296,17 @@ class Morpheus::Cli::ServicePlanCommand
|
|
285
296
|
opts.on('--price-sets [LIST]', Array, 'Price set(s), comma separated list of price set IDs') do |list|
|
286
297
|
params['priceSets'] = list.collect {|it| it.to_s.strip.empty? || !it.to_i ? nil : it.to_s.strip}.compact.uniq.collect {|it| {'id' => it.to_i}}
|
287
298
|
end
|
288
|
-
opts.on('--min-storage NUMBER', String, "Min storage
|
289
|
-
|
290
|
-
bytes = parse_bytes_param(val, '--min-storage', 'GB', true)
|
291
|
-
((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = bytes[:number]
|
292
|
-
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
299
|
+
opts.on('--min-storage NUMBER', String, "Min total storage in GB.") do |val|
|
300
|
+
((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = val.to_i
|
293
301
|
end
|
294
|
-
opts.on('--max-storage NUMBER', String, "Max storage
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
(params['config'] ||= {})['
|
302
|
+
opts.on('--max-storage NUMBER', String, "Max total storage in GB.") do |val|
|
303
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = val.to_i
|
304
|
+
end
|
305
|
+
opts.on('--min-per-disk-size NUMBER', String, "Min per disk size in GB.") do |val|
|
306
|
+
((params['config'] ||= {})['ranges'] ||= {})['minPerDiskSize'] = val.to_i
|
307
|
+
end
|
308
|
+
opts.on('--max-per-disk-size NUMBER', String, "Max per disk size in GB.") do |val|
|
309
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxPerDiskSize'] = val.to_i
|
299
310
|
end
|
300
311
|
opts.on('--min-memory NUMBER', String, "Min memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
|
301
312
|
# Memory does get converted to bytes
|
@@ -315,6 +326,18 @@ class Morpheus::Cli::ServicePlanCommand
|
|
315
326
|
opts.on('--max-cores NUMBER', String, "Max cores") do |val|
|
316
327
|
((params['config'] ||= {})['ranges'] ||= {})['maxCores'] = val.to_i
|
317
328
|
end
|
329
|
+
opts.on('--min-sockets NUMBER', String, "Min sockets") do |val|
|
330
|
+
((params['config'] ||= {})['ranges'] ||= {})['minSockets'] = val.to_i
|
331
|
+
end
|
332
|
+
opts.on('--max-sockets NUMBER', String, "Max sockets") do |val|
|
333
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxSockets'] = val.to_i
|
334
|
+
end
|
335
|
+
opts.on('--min-cores-per-socket NUMBER', String, "Min cores per socket") do |val|
|
336
|
+
((params['config'] ||= {})['ranges'] ||= {})['minCoresPerSocket'] = val.to_i
|
337
|
+
end
|
338
|
+
opts.on('--max-cores-per-socket NUMBER', String, "Max cores per socket") do |val|
|
339
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxCoresPerSocket'] = val.to_i
|
340
|
+
end
|
318
341
|
add_perms_options(opts, options, ['plans', 'groupDefaults'])
|
319
342
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
320
343
|
opts.footer = "Create service plan"
|
@@ -396,13 +419,41 @@ class Morpheus::Cli::ServicePlanCommand
|
|
396
419
|
true
|
397
420
|
)
|
398
421
|
params['maxMemory'] = bytes[:bytes]
|
399
|
-
# (params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
|
400
422
|
rescue
|
401
423
|
print "Invalid Value... Please try again.\n"
|
402
424
|
end
|
425
|
+
params['customMaxMemory'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'customMaxMemory', 'type' => 'checkbox', 'fieldLabel' => 'Custom Max Memory', 'required' => false, 'description' => 'Custom Max Memory', 'defaultValue' => false}],options[:options],@api_client,{}, options[:no_prompt])['customMaxMemory']
|
403
426
|
end
|
404
427
|
end
|
405
428
|
|
429
|
+
# add'n options
|
430
|
+
addn_options = [
|
431
|
+
{'fieldName' => 'maxCores', 'fieldLabel' => 'Core Count', 'type' => 'number', 'required' => true, 'defaultValue' => 1, 'displayOrder' => 1},
|
432
|
+
{'fieldName' => 'customCores', 'fieldLabel' => 'Custom Cores', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 2},
|
433
|
+
{'fieldName' => 'coresPerSocket', 'fieldLabel' => 'Cores Per Socket', 'type' => 'number', 'required' => true, 'defaultValue' => 1, 'displayOrder' => 3},
|
434
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minStorage', 'fieldLabel' => 'Min Total Storage (GB)', 'type' => 'number', 'displayOrder' => 1},
|
435
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxStorage', 'fieldLabel' => 'Max Total Storage (GB)', 'type' => 'number', 'displayOrder' => 2},
|
436
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minPerDiskSize', 'fieldLabel' => 'Min Per Disk Size (GB)', 'type' => 'number', 'displayOrder' => 3},
|
437
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxPerDiskSize', 'fieldLabel' => 'Max Per Disk Size (GB)', 'type' => 'number', 'displayOrder' => 4},
|
438
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minMemory', 'fieldLabel' => 'Min Memory (GB)', 'type' => 'number', 'displayOrder' => 5},
|
439
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxMemory', 'fieldLabel' => 'Max Memory (GB)', 'type' => 'number', 'displayOrder' => 6},
|
440
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minCores', 'fieldLabel' => 'Min Cores', 'type' => 'number', 'displayOrder' => 7},
|
441
|
+
{'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxCores', 'fieldLabel' => 'Max Cores', 'type' => 'number', 'displayOrder' => 8}
|
442
|
+
]
|
443
|
+
|
444
|
+
if provision_type['hasSocketRange']
|
445
|
+
addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minSockets', 'fieldLabel' => 'Min Sockets', 'type' => 'number', 'displayOrder' => 9})
|
446
|
+
addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxSockets', 'fieldLabel' => 'Max Sockets', 'type' => 'number', 'displayOrder' => 10})
|
447
|
+
end
|
448
|
+
|
449
|
+
if provision_type['hasCoresPerSocketRange']
|
450
|
+
addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minCoresPerSocket', 'fieldLabel' => 'Min Cores Per Socket', 'type' => 'number', 'displayOrder' => 11})
|
451
|
+
addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxCoresPerSocket', 'fieldLabel' => 'Max Cores Per Socket', 'type' => 'number', 'displayOrder' => 12})
|
452
|
+
end
|
453
|
+
|
454
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(addn_options, options[:options], @api_client, params)
|
455
|
+
params.deep_merge!(v_prompt)
|
456
|
+
|
406
457
|
# price sets
|
407
458
|
if params['priceSets'].nil? && !options[:no_prompt]
|
408
459
|
price_sets = []
|
@@ -517,17 +568,17 @@ class Morpheus::Cli::ServicePlanCommand
|
|
517
568
|
opts.on('--price-sets [LIST]', Array, 'Price set(s), comma separated list of price set IDs') do |list|
|
518
569
|
params['priceSets'] = list.collect {|it| it.to_s.strip.empty? || !it.to_i ? nil : it.to_s.strip}.compact.uniq.collect {|it| {'id' => it.to_i}}
|
519
570
|
end
|
520
|
-
opts.on('--min-storage NUMBER', String, "Min storage
|
521
|
-
|
522
|
-
bytes = parse_bytes_param(val, '--min-storage', 'GB')
|
523
|
-
((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = bytes[:number]
|
524
|
-
(params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
|
571
|
+
opts.on('--min-storage NUMBER', String, "Min total storage in GB.") do |val|
|
572
|
+
((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = val.to_i
|
525
573
|
end
|
526
|
-
opts.on('--max-storage NUMBER', String, "Max storage
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
(params['config'] ||= {})['
|
574
|
+
opts.on('--max-storage NUMBER', String, "Max total storage in GB.") do |val|
|
575
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = val.to_i
|
576
|
+
end
|
577
|
+
opts.on('--min-per-disk-size NUMBER', String, "Min per disk size in GB.") do |val|
|
578
|
+
((params['config'] ||= {})['ranges'] ||= {})['minPerDiskSize'] = val.to_i
|
579
|
+
end
|
580
|
+
opts.on('--max-per-disk-size NUMBER', String, "Max per disk size in GB.") do |val|
|
581
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxPerDiskSize'] = val.to_i
|
531
582
|
end
|
532
583
|
opts.on('--min-memory NUMBER', String, "Min memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
|
533
584
|
# Memory does get converted to bytes
|
@@ -546,6 +597,18 @@ class Morpheus::Cli::ServicePlanCommand
|
|
546
597
|
end
|
547
598
|
opts.on('--max-cores NUMBER', String, "Max cores") do |val|
|
548
599
|
((params['config'] ||= {})['ranges'] ||= {})['maxCores'] = val.to_i
|
600
|
+
end
|
601
|
+
opts.on('--min-sockets NUMBER', String, "Min sockets") do |val|
|
602
|
+
((params['config'] ||= {})['ranges'] ||= {})['minSockets'] = val.to_i
|
603
|
+
end
|
604
|
+
opts.on('--max-sockets NUMBER', String, "Max sockets") do |val|
|
605
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxSockets'] = val.to_i
|
606
|
+
end
|
607
|
+
opts.on('--min-cores-per-socket NUMBER', String, "Min cores per socket") do |val|
|
608
|
+
((params['config'] ||= {})['ranges'] ||= {})['minCoresPerSocket'] = val.to_i
|
609
|
+
end
|
610
|
+
opts.on('--max-cores-per-socket NUMBER', String, "Max cores per socket") do |val|
|
611
|
+
((params['config'] ||= {})['ranges'] ||= {})['maxCoresPerSocket'] = val.to_i
|
549
612
|
end
|
550
613
|
add_perms_options(opts, options, ['plans', 'groupDefaults'])
|
551
614
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
@@ -359,7 +359,7 @@ class Morpheus::Cli::Shell
|
|
359
359
|
end
|
360
360
|
out << "See the available commands below.\n"
|
361
361
|
|
362
|
-
out << "\nCommands
|
362
|
+
out << "\nCommands:\n"
|
363
363
|
# commands = @morpheus_commands + @shell_commands
|
364
364
|
# @morpheus_commands.sort.each {|cmd|
|
365
365
|
# out << "\t#{cmd.to_s}\n"
|
@@ -442,7 +442,7 @@ class Morpheus::Cli::Tasks
|
|
442
442
|
# Result Type
|
443
443
|
if options[:options]['resultType']
|
444
444
|
payload['task']['resultType'] = options[:options]['resultType']
|
445
|
-
|
445
|
+
elsif task_type['hasResults']
|
446
446
|
result_types_dropdown = [{"name" => "Value", "value" => "value"}, {"name" => "Exit Code", "value" => "exitCode"}, {"name" => "Key Value", "value" => "keyValue"}, {"name" => "JSON", "value" => "json"}]
|
447
447
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'resultType', 'fieldLabel' => 'Result Type', 'type' => 'select', 'selectOptions' => result_types_dropdown}], options[:options], @api_client)
|
448
448
|
payload['task']['resultType'] = v_prompt['resultType'] unless v_prompt['resultType'].to_s.empty?
|
@@ -471,6 +471,7 @@ class Morpheus::Cli::Tasks
|
|
471
471
|
end
|
472
472
|
end
|
473
473
|
end
|
474
|
+
process_special_task_option_typeaheads(task_option_types)
|
474
475
|
# inject file_params into options for file-content prompt
|
475
476
|
# or into taskOptions.script for types not yet using file-content
|
476
477
|
unless file_params.empty?
|
@@ -859,38 +860,99 @@ class Morpheus::Cli::Tasks
|
|
859
860
|
target_type = nil
|
860
861
|
instance_ids = []
|
861
862
|
instances = []
|
863
|
+
instance_label = nil
|
862
864
|
server_ids = []
|
863
865
|
servers = []
|
864
|
-
|
866
|
+
server_label = nil
|
867
|
+
default_refresh_interval = 5
|
868
|
+
all_target_types = ['appliance', 'instance', 'instance-label', 'server', 'server-label']
|
865
869
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
866
|
-
opts.banner = subcommand_usage("[task]
|
867
|
-
opts.on('--
|
870
|
+
opts.banner = subcommand_usage("[task] [options]")
|
871
|
+
opts.on('--context-type VALUE', String, "Context Type, #{ored_list(all_target_types)}") do |val|
|
872
|
+
val = val.downcase
|
873
|
+
val = 'appliance' if val == 'none'
|
874
|
+
if target_type && target_type != val
|
875
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
876
|
+
end
|
877
|
+
if !all_target_types.include?(val)
|
878
|
+
raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
|
879
|
+
end
|
880
|
+
target_type = val
|
881
|
+
end
|
882
|
+
opts.on('--target-type VALUE', String, "alias for context-type") do |val|
|
883
|
+
val = val.downcase
|
884
|
+
val = 'appliance' if val == 'none'
|
885
|
+
if target_type && target_type != val
|
886
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
887
|
+
end
|
888
|
+
if !all_target_types.include?(val)
|
889
|
+
raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
|
890
|
+
end
|
891
|
+
target_type = val
|
892
|
+
end
|
893
|
+
opts.add_hidden_option('--target-type')
|
894
|
+
opts.on('--instance INSTANCE', String, "Instance name or id to target for execution. This option can be passed more than once.") do |val|
|
895
|
+
if target_type && target_type != 'instance'
|
896
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
897
|
+
end
|
868
898
|
target_type = 'instance'
|
869
899
|
instance_ids << val
|
870
900
|
end
|
871
|
-
opts.on('--instances
|
901
|
+
opts.on('--instances LIST', Array, "Instances, comma separated list of instance names or IDs.") do |list|
|
902
|
+
if target_type && target_type != 'instance'
|
903
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
904
|
+
end
|
872
905
|
target_type = 'instance'
|
873
906
|
instance_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
874
907
|
end
|
875
|
-
opts.on('--
|
908
|
+
opts.on('--instance-label LABEL', String, "Instance Label") do |val|
|
909
|
+
if target_type && target_type != 'instance-label'
|
910
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
911
|
+
end
|
912
|
+
target_type = 'instance-label'
|
913
|
+
instance_label = val
|
914
|
+
end
|
915
|
+
opts.on('--server SERVER', String, "Server name or id to target for execution. This option can be passed more than once.") do |val|
|
916
|
+
if target_type && target_type != 'server'
|
917
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
918
|
+
end
|
876
919
|
target_type = 'server'
|
877
920
|
server_ids << val
|
878
921
|
end
|
879
|
-
opts.on('--
|
922
|
+
opts.on('--servers LIST', Array, "Servers, comma separated list of host names or IDs.") do |list|
|
923
|
+
if target_type && target_type != 'server'
|
924
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
925
|
+
end
|
880
926
|
target_type = 'server'
|
881
927
|
server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
882
928
|
end
|
883
|
-
opts.on('--server
|
929
|
+
opts.on('--server-label LABEL', String, "Server Label") do |val|
|
930
|
+
if target_type && target_type != 'server-label'
|
931
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
932
|
+
end
|
933
|
+
target_type = 'server-label'
|
934
|
+
server_label = val
|
935
|
+
end
|
936
|
+
opts.on('--host HOST', String, "alias for --server") do |val|
|
937
|
+
if target_type && target_type != 'server'
|
938
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
939
|
+
end
|
884
940
|
target_type = 'server'
|
885
941
|
server_ids << val
|
886
942
|
end
|
887
|
-
opts.
|
943
|
+
opts.add_hidden_option('--host')
|
944
|
+
opts.on('--hosts HOSTS', Array, "alias for --servers") do |list|
|
945
|
+
if target_type && target_type != 'server'
|
946
|
+
raise ::OptionParser::InvalidOption.new("The --hosts option cannot be combined with another context (#{target_type})")
|
947
|
+
end
|
888
948
|
target_type = 'server'
|
889
949
|
server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
890
950
|
end
|
891
|
-
opts.add_hidden_option('--
|
892
|
-
opts.add_hidden_option('--servers')
|
951
|
+
opts.add_hidden_option('--hosts')
|
893
952
|
opts.on('-a', '--appliance', "Execute on the appliance, the target is the appliance itself.") do
|
953
|
+
if target_type && target_type != 'appliance'
|
954
|
+
raise ::OptionParser::InvalidOption.new("The --appliance option cannot be combined with another context (#{target_type})")
|
955
|
+
end
|
894
956
|
target_type = 'appliance'
|
895
957
|
end
|
896
958
|
opts.on('--config [TEXT]', String, "Custom config") do |val|
|
@@ -921,46 +983,59 @@ class Morpheus::Cli::Tasks
|
|
921
983
|
payload = options[:payload]
|
922
984
|
payload.deep_merge!({'job' => passed_options}) unless passed_options.empty?
|
923
985
|
else
|
924
|
-
#
|
925
|
-
if
|
926
|
-
|
927
|
-
|
986
|
+
# prompt for target type and target
|
987
|
+
if target_type.nil?
|
988
|
+
# todo: Need api to fetch available Context Types for taskId/workflowId
|
989
|
+
available_target_types = get_available_contexts_for_task(task)
|
990
|
+
default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
|
991
|
+
if !available_target_types.empty?
|
992
|
+
default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
|
993
|
+
target_type = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'context-type', 'fieldName' => 'targetType', 'fieldLabel' => 'Context Type', 'type' => 'select', 'selectOptions' => available_target_types, 'defaultValue' => default_target_type, 'required' => true, 'description' => 'Context Type determines the type of target(s) for the execution'}], options[:options], @api_client)['targetType']
|
994
|
+
end
|
995
|
+
end
|
996
|
+
if target_type
|
997
|
+
params['targetType'] = target_type
|
998
|
+
end
|
999
|
+
if target_type == 'instance'
|
1000
|
+
if instance_ids.empty?
|
1001
|
+
instance_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instances', 'fieldName' => 'instances', 'fieldLabel' => 'Instance(s)', 'type' => 'text', 'required' => true, 'description' => 'Instances, comma separated list of instance names or IDs.'}], options[:options], @api_client)['instances']
|
1002
|
+
instance_ids = parse_array(instance_ids_value)
|
1003
|
+
end
|
928
1004
|
instance_ids.each do |instance_id|
|
929
1005
|
instance = find_instance_by_name_or_id(instance_id)
|
930
1006
|
return 1 if instance.nil?
|
931
1007
|
instances << instance
|
932
1008
|
end
|
933
1009
|
params['instances'] = instances.collect {|it| it['id'] }
|
934
|
-
elsif
|
1010
|
+
elsif target_type == 'instance-label'
|
1011
|
+
if instance_label.nil?
|
1012
|
+
instance_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
|
1013
|
+
end
|
1014
|
+
# params['config'] ||= {}
|
1015
|
+
# params['config']['instanceLabel'] = instance_label
|
1016
|
+
params['instanceLabel'] = instance_label
|
1017
|
+
elsif target_type == 'server'
|
1018
|
+
if server_ids.empty?
|
1019
|
+
server_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'servers', 'fieldName' => 'servers', 'fieldLabel' => 'Server(s)', 'type' => 'text', 'required' => true, 'description' => 'Servers, comma separated list of server names or IDs.'}], options[:options], @api_client)['servers']
|
1020
|
+
server_ids = parse_array(server_ids_value)
|
1021
|
+
end
|
935
1022
|
server_ids.each do |server_id|
|
936
1023
|
server = find_server_by_name_or_id(server_id)
|
937
1024
|
return 1 if server.nil?
|
938
1025
|
servers << server
|
939
1026
|
end
|
940
1027
|
params['servers'] = servers.collect {|it| it['id'] }
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
if instance_ids.empty? && server_ids.empty?
|
945
|
-
# todo: prompt for Context: None,Instance,Server and then Instance(s) or Server(s)
|
946
|
-
raise_command_error "missing required option: --instance or --host\n#{optparse}"
|
1028
|
+
elsif target_type == 'server-label'
|
1029
|
+
if server_label.nil?
|
1030
|
+
server_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
|
947
1031
|
end
|
948
|
-
|
949
|
-
#
|
950
|
-
|
951
|
-
# not sure about this one
|
952
|
-
else
|
953
|
-
# unknown executeTarget
|
1032
|
+
# params['config'] ||= {}
|
1033
|
+
# params['config']['serverLabel'] = server_label
|
1034
|
+
params['serverLabel'] = server_label
|
954
1035
|
end
|
955
|
-
|
956
|
-
|
957
|
-
|
958
1036
|
# todo: prompt to task optionTypes for customOptions
|
959
1037
|
if task['optionTypes']
|
960
1038
|
|
961
|
-
end
|
962
|
-
if target_type
|
963
|
-
params['targetType'] = target_type
|
964
1039
|
end
|
965
1040
|
job_payload = {}
|
966
1041
|
job_payload.deep_merge!(params)
|
@@ -1293,4 +1368,24 @@ class Morpheus::Cli::Tasks
|
|
1293
1368
|
end
|
1294
1369
|
end
|
1295
1370
|
|
1371
|
+
def process_special_task_option_typeaheads(option_types)
|
1372
|
+
# massage special task typeaheads options
|
1373
|
+
# this makes us all sad
|
1374
|
+
option_types.each do |option_type|
|
1375
|
+
if option_type['type'] == 'typeahead'
|
1376
|
+
if ['operationalWorkflowName','containerScript','containerTemplate'].include?(option_type['code'])
|
1377
|
+
option_type.deep_merge!({'config' => {'valueField' => 'name'}})
|
1378
|
+
end
|
1379
|
+
elsif option_type['type'] == 'hidden'
|
1380
|
+
if ['operationalWorkflowId','containerScriptId','containerTemplateId'].include?(option_type['code'])
|
1381
|
+
option_type['processValue'] = lambda {|val|
|
1382
|
+
if val.to_s.empty?
|
1383
|
+
selected_option = Morpheus::Cli::OptionTypes.get_last_select()
|
1384
|
+
selected_option ? selected_option['value'] : nil
|
1385
|
+
end
|
1386
|
+
}
|
1387
|
+
end
|
1388
|
+
end
|
1389
|
+
end
|
1390
|
+
end
|
1296
1391
|
end
|
@@ -550,40 +550,101 @@ class Morpheus::Cli::Workflows
|
|
550
550
|
target_type = nil
|
551
551
|
instance_ids = []
|
552
552
|
instances = []
|
553
|
+
instance_label = nil
|
553
554
|
server_ids = []
|
554
555
|
servers = []
|
555
|
-
|
556
|
+
server_label = nil
|
557
|
+
default_refresh_interval = 5
|
558
|
+
all_target_types = ['appliance', 'instance', 'instance-label', 'server', 'server-label']
|
556
559
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
557
|
-
opts.banner = subcommand_usage("[workflow]
|
558
|
-
opts.on('--
|
560
|
+
opts.banner = subcommand_usage("[workflow] [options]")
|
561
|
+
opts.on('--context-type VALUE', String, "Context Type, #{ored_list(all_target_types)}") do |val|
|
562
|
+
val = val.downcase
|
563
|
+
val = 'appliance' if val == 'none'
|
564
|
+
if target_type && target_type != val
|
565
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
566
|
+
end
|
567
|
+
if !all_target_types.include?(val)
|
568
|
+
raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
|
569
|
+
end
|
570
|
+
target_type = val
|
571
|
+
end
|
572
|
+
opts.on('--target-type VALUE', String, "alias for context-type") do |val|
|
573
|
+
val = val.downcase
|
574
|
+
val = 'appliance' if val == 'none'
|
575
|
+
if target_type && target_type != val
|
576
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
577
|
+
end
|
578
|
+
if !all_target_types.include?(val)
|
579
|
+
raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
|
580
|
+
end
|
581
|
+
target_type = val
|
582
|
+
end
|
583
|
+
opts.add_hidden_option('--target-type')
|
584
|
+
opts.on('--instance INSTANCE', String, "Instance name or id to target for execution. This option can be passed more than once.") do |val|
|
585
|
+
if target_type && target_type != 'instance'
|
586
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
587
|
+
end
|
559
588
|
target_type = 'instance'
|
560
589
|
instance_ids << val
|
561
590
|
end
|
562
|
-
opts.on('--instances
|
591
|
+
opts.on('--instances LIST', Array, "Instances, comma separated list of instance names or IDs.") do |list|
|
592
|
+
if target_type && target_type != 'instance'
|
593
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
594
|
+
end
|
563
595
|
target_type = 'instance'
|
564
596
|
instance_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
565
597
|
end
|
566
|
-
opts.on('--
|
598
|
+
opts.on('--instance-label LABEL', String, "Instance Label") do |val|
|
599
|
+
if target_type && target_type != 'instance-label'
|
600
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
601
|
+
end
|
602
|
+
target_type = 'instance-label'
|
603
|
+
instance_label = val
|
604
|
+
end
|
605
|
+
opts.on('--server SERVER', String, "Server name or id to target for execution. This option can be passed more than once.") do |val|
|
606
|
+
if target_type && target_type != 'server'
|
607
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
608
|
+
end
|
567
609
|
target_type = 'server'
|
568
610
|
server_ids << val
|
569
611
|
end
|
570
|
-
opts.on('--
|
612
|
+
opts.on('--servers LIST', Array, "Servers, comma separated list of host names or IDs.") do |list|
|
613
|
+
if target_type && target_type != 'server'
|
614
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
615
|
+
end
|
571
616
|
target_type = 'server'
|
572
617
|
server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
573
618
|
end
|
574
|
-
opts.on('--server
|
619
|
+
opts.on('--server-label LABEL', String, "Server Label") do |val|
|
620
|
+
if target_type && target_type != 'server-label'
|
621
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
622
|
+
end
|
623
|
+
target_type = 'server-label'
|
624
|
+
server_label = val
|
625
|
+
end
|
626
|
+
opts.on('--host HOST', String, "alias for --server") do |val|
|
627
|
+
if target_type && target_type != 'server'
|
628
|
+
raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
|
629
|
+
end
|
575
630
|
target_type = 'server'
|
576
631
|
server_ids << val
|
577
632
|
end
|
578
|
-
opts.
|
633
|
+
opts.add_hidden_option('--host')
|
634
|
+
opts.on('--hosts HOSTS', Array, "alias for --servers") do |list|
|
635
|
+
if target_type && target_type != 'server'
|
636
|
+
raise ::OptionParser::InvalidOption.new("The --hosts option cannot be combined with another context (#{target_type})")
|
637
|
+
end
|
579
638
|
target_type = 'server'
|
580
639
|
server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
581
640
|
end
|
641
|
+
opts.add_hidden_option('--hosts')
|
582
642
|
opts.on('-a', '--appliance', "Execute on the appliance, the target is the appliance itself.") do
|
643
|
+
if target_type && target_type != 'appliance'
|
644
|
+
raise ::OptionParser::InvalidOption.new("The --appliance option cannot be combined with another context (#{target_type})")
|
645
|
+
end
|
583
646
|
target_type = 'appliance'
|
584
647
|
end
|
585
|
-
opts.add_hidden_option('--server')
|
586
|
-
opts.add_hidden_option('--servers')
|
587
648
|
opts.on('--config [TEXT]', String, "Custom config") do |val|
|
588
649
|
params['customConfig'] = val.to_s
|
589
650
|
end
|
@@ -611,27 +672,55 @@ class Morpheus::Cli::Workflows
|
|
611
672
|
payload = options[:payload]
|
612
673
|
payload.deep_merge!({'job' => passed_options}) unless passed_options.empty?
|
613
674
|
else
|
614
|
-
|
615
|
-
|
616
|
-
|
675
|
+
# prompt for target type and target
|
676
|
+
if target_type.nil?
|
677
|
+
# todo: Need api to fetch available Context Types for taskId/workflowId
|
678
|
+
available_target_types = get_available_contexts_for_workflow(workflow)
|
679
|
+
default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
|
680
|
+
if !available_target_types.empty?
|
681
|
+
default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
|
682
|
+
target_type = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'context-type', 'fieldName' => 'targetType', 'fieldLabel' => 'Context Type', 'type' => 'select', 'selectOptions' => available_target_types, 'defaultValue' => default_target_type, 'required' => true, 'description' => 'Context Type determines the type of target(s) for the execution'}], options[:options], @api_client)['targetType']
|
683
|
+
end
|
684
|
+
end
|
685
|
+
if target_type
|
686
|
+
params['targetType'] = target_type
|
687
|
+
end
|
688
|
+
if target_type == 'instance'
|
689
|
+
if instance_ids.empty?
|
690
|
+
instance_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instances', 'fieldName' => 'instances', 'fieldLabel' => 'Instance(s)', 'type' => 'text', 'required' => true, 'description' => 'Instances, comma separated list of instance names or IDs.'}], options[:options], @api_client)['instances']
|
691
|
+
instance_ids = parse_array(instance_ids_value)
|
692
|
+
end
|
617
693
|
instance_ids.each do |instance_id|
|
618
694
|
instance = find_instance_by_name_or_id(instance_id)
|
619
695
|
return 1 if instance.nil?
|
620
696
|
instances << instance
|
621
697
|
end
|
622
698
|
params['instances'] = instances.collect {|it| it['id'] }
|
623
|
-
elsif
|
699
|
+
elsif target_type == 'instance-label'
|
700
|
+
if instance_label.nil?
|
701
|
+
instance_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
|
702
|
+
end
|
703
|
+
# params['config'] ||= {}
|
704
|
+
# params['config']['instanceLabel'] = instance_label
|
705
|
+
params['instanceLabel'] = instance_label
|
706
|
+
elsif target_type == 'server'
|
707
|
+
if server_ids.empty?
|
708
|
+
server_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'servers', 'fieldName' => 'servers', 'fieldLabel' => 'Server(s)', 'type' => 'text', 'required' => true, 'description' => 'Servers, comma separated list of server names or IDs.'}], options[:options], @api_client)['servers']
|
709
|
+
server_ids = parse_array(server_ids_value)
|
710
|
+
end
|
624
711
|
server_ids.each do |server_id|
|
625
712
|
server = find_server_by_name_or_id(server_id)
|
626
713
|
return 1 if server.nil?
|
627
714
|
servers << server
|
628
715
|
end
|
629
716
|
params['servers'] = servers.collect {|it| it['id'] }
|
630
|
-
elsif target_type == '
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
#
|
717
|
+
elsif target_type == 'server-label'
|
718
|
+
if server_label.nil?
|
719
|
+
server_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
|
720
|
+
end
|
721
|
+
# params['config'] ||= {}
|
722
|
+
# params['config']['serverLabel'] = server_label
|
723
|
+
params['serverLabel'] = server_label
|
635
724
|
end
|
636
725
|
|
637
726
|
# prompt to workflow optionTypes for customOptions
|
@@ -643,9 +732,6 @@ class Morpheus::Cli::Workflows
|
|
643
732
|
}
|
644
733
|
custom_options = Morpheus::Cli::OptionTypes.prompt(custom_option_types, options[:options], @api_client, {})
|
645
734
|
end
|
646
|
-
if target_type
|
647
|
-
params['targetType'] = target_type
|
648
|
-
end
|
649
735
|
job_payload = {}
|
650
736
|
job_payload.deep_merge!(params)
|
651
737
|
passed_options.delete('customOptions')
|
@@ -41,8 +41,8 @@ module Morpheus::Cli::JobsHelper
|
|
41
41
|
"Created By" => lambda {|it| it[:created_by]},
|
42
42
|
"Duration" => lambda {|it| it[:duration]},
|
43
43
|
"Status" => lambda {|it| it[:status]},
|
44
|
-
"Error" => lambda {|it| options[:details] ? it[:error] : truncate_string(it[:error], 32) },
|
45
|
-
"Output" => lambda {|it| options[:details] ? it[:output] : truncate_string(it[:output], 32) }
|
44
|
+
"Error" => lambda {|it| options[:details] ? it[:error].to_s.strip : truncate_string(it[:error], 32).to_s.strip.gsub("\n", ' ') },
|
45
|
+
"Output" => lambda {|it| options[:details] ? it[:output].to_s.strip : truncate_string(it[:output], 32).to_s.strip.gsub("\n", ' ') }
|
46
46
|
}
|
47
47
|
print as_pretty_table(events.collect {|it| get_process_event_data(it)}, event_columns.upcase_keys!, options)
|
48
48
|
end
|
@@ -147,7 +147,7 @@ module Morpheus::Cli::JobsHelper
|
|
147
147
|
# refresh execution request until it is finished
|
148
148
|
# returns json response data of the last execution request when status reached 'completed' or 'failed'
|
149
149
|
def wait_for_job_execution(job_execution_id, options={}, print_output = true)
|
150
|
-
refresh_interval =
|
150
|
+
refresh_interval = 5
|
151
151
|
if options[:refresh_interval].to_i > 0
|
152
152
|
refresh_interval = options[:refresh_interval]
|
153
153
|
end
|
@@ -168,5 +168,32 @@ module Morpheus::Cli::JobsHelper
|
|
168
168
|
end
|
169
169
|
|
170
170
|
|
171
|
+
def get_available_contexts_for_task(task)
|
172
|
+
#If task has target of resource, then CAN NOT run it local
|
173
|
+
targets = []
|
174
|
+
has_resource = task['executeTarget'] == 'resource'
|
175
|
+
if !has_resource
|
176
|
+
targets << {'name' => 'None', 'value' => 'appliance'}
|
177
|
+
end
|
178
|
+
targets << {'name' => 'Instance', 'value' => 'instance'}
|
179
|
+
targets << {'name' => 'Instance Label', 'value' => 'instance-label'}
|
180
|
+
targets << {'name' => 'Server', 'value' => 'server'}
|
181
|
+
targets << {'name' => 'Server Label', 'value' => 'server-label'}
|
182
|
+
return targets
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_available_contexts_for_workflow(workflow)
|
186
|
+
#If any task has target of resource, then CAN NOT run it local
|
187
|
+
targets = []
|
188
|
+
has_resource = workflow['taskSetTasks'].find {|task| task['executeTarget'] == 'resource' }
|
189
|
+
if !has_resource
|
190
|
+
targets << {'name' => 'None', 'value' => 'appliance'}
|
191
|
+
end
|
192
|
+
targets << {'name' => 'Instance', 'value' => 'instance'}
|
193
|
+
targets << {'name' => 'Instance Label', 'value' => 'instance-label'}
|
194
|
+
targets << {'name' => 'Server', 'value' => 'server'}
|
195
|
+
targets << {'name' => 'Server Label', 'value' => 'server-label'}
|
196
|
+
return targets
|
197
|
+
end
|
171
198
|
|
172
199
|
end
|
@@ -88,36 +88,12 @@ module Morpheus::Cli::ProcessesHelper
|
|
88
88
|
|
89
89
|
# decolorize, remove newlines and truncate for table cell
|
90
90
|
def format_process_error(process, max_length=20, return_color=cyan)
|
91
|
-
|
92
|
-
out = ""
|
93
|
-
if process['error']
|
94
|
-
# lines = process['error'].split("\n").collect {|line| reset + "#{line.to_s.strip}" }
|
95
|
-
# lines = process['error'].split("\n").collect {|line| "#{line.to_s.strip}" }
|
96
|
-
lines = [process['error']]
|
97
|
-
out = lines.join(" ")
|
98
|
-
if max_length
|
99
|
-
out = truncate_string(out, max_length)
|
100
|
-
end
|
101
|
-
out << return_color if return_color
|
102
|
-
end
|
103
|
-
out
|
91
|
+
truncate_string(process['error'].to_s.strip.gsub("\n", " "), max_length)
|
104
92
|
end
|
105
93
|
|
106
94
|
# decolorize, remove newlines and truncate for table cell
|
107
95
|
def format_process_output(process, max_length=20, return_color=cyan)
|
108
|
-
|
109
|
-
out = ""
|
110
|
-
if process['output']
|
111
|
-
# lines = process['output'].split("\n").collect {|line| reset + "#{line.to_s.strip}" }
|
112
|
-
# lines = process['error'].split("\n").collect {|line| "#{line.to_s.strip}" }
|
113
|
-
lines = [process['output']]
|
114
|
-
out = lines.join(" ")
|
115
|
-
if max_length
|
116
|
-
out = truncate_string(out, max_length)
|
117
|
-
end
|
118
|
-
out << return_color if return_color
|
119
|
-
end
|
120
|
-
out
|
96
|
+
truncate_string(process['output'].to_s.strip.gsub("\n", " "), max_length)
|
121
97
|
end
|
122
98
|
|
123
99
|
# format for either ETA/Duration
|
@@ -777,15 +777,22 @@ module Morpheus::Cli::ProvisioningHelper
|
|
777
777
|
option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
778
778
|
|
779
779
|
resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], layoutId: layout["id"]}.merge(service_plan.nil? ? {} : {planId: service_plan["id"]}))['data']
|
780
|
-
|
781
|
-
|
780
|
+
if options[:resource_pool]
|
781
|
+
resource_pool = resource_pool_options.find {|opt| opt['value'] == options[:resource_pool].to_s || opt['value'] == "pool-#{options[:resource_pool]}"}
|
782
|
+
end
|
783
|
+
pool_required = provision_type["zonePoolRequired"]
|
784
|
+
# Should pool_id have the pool-,poolGroup- prefix or not?
|
785
|
+
use_pool_prefix = resource_pool_options.find {|opt| opt['value'].to_s.include?("pool") }
|
782
786
|
if resource_pool
|
783
|
-
pool_id = resource_pool['id']
|
787
|
+
pool_id = resource_pool['id'] # id or value?
|
784
788
|
else
|
785
789
|
if options[:default_resource_pool]
|
786
790
|
default_resource_pool = resource_pool_options.find {|rp| rp['id'] == options[:default_resource_pool]}
|
787
791
|
end
|
788
|
-
|
792
|
+
if use_pool_prefix && options[:options]['config'] && options[:options]['config']['resourcePoolId'] && !options[:options]['config']['resourcePoolId'].to_s.include?("pool")
|
793
|
+
options[:options]['config']['resourcePoolId'] = "pool-" + options[:options]['config']['resourcePoolId'].to_s
|
794
|
+
end
|
795
|
+
resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => pool_required, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
|
789
796
|
resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{}, no_prompt, true)
|
790
797
|
resource_pool_prompt.deep_compact!
|
791
798
|
payload.deep_merge!(resource_pool_prompt)
|
@@ -795,7 +802,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
795
802
|
elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
|
796
803
|
pool_id = resource_pool_prompt[resource_pool_option_type['fieldName']]
|
797
804
|
end
|
798
|
-
resource_pool ||= resource_pool_options.find {|it| it['
|
805
|
+
resource_pool ||= resource_pool_options.find {|it| it['value'].to_s == pool_id.to_s}
|
799
806
|
end
|
800
807
|
end
|
801
808
|
end
|
@@ -582,6 +582,9 @@ module Morpheus
|
|
582
582
|
|
583
583
|
if no_prompt
|
584
584
|
if !value_found
|
585
|
+
if default_value == ""
|
586
|
+
default_value = nil
|
587
|
+
end
|
585
588
|
if !default_value.nil? && !select_options.nil?
|
586
589
|
matched_option = select_options.find {|it| it[value_field].to_s == default_value.to_s }
|
587
590
|
if matched_option.nil?
|
@@ -814,7 +817,7 @@ module Morpheus
|
|
814
817
|
api_params ||= {}
|
815
818
|
api_params['query'] = query_value
|
816
819
|
# skip refresh if you just hit enter
|
817
|
-
if !query_value.empty?
|
820
|
+
if !query_value.empty? || (select_options.nil? || select_options.empty?)
|
818
821
|
select_options = load_options(option_type, api_client, api_params, query_value)
|
819
822
|
end
|
820
823
|
|
data/lib/morpheus/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morpheus-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Estes
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-04-14 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|