morpheus-cli 4.1.14 → 4.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/api_client.rb +4 -0
- data/lib/morpheus/api/library_container_types_interface.rb +1 -1
- data/lib/morpheus/api/library_instance_types_interface.rb +7 -7
- data/lib/morpheus/api/library_layouts_interface.rb +1 -1
- data/lib/morpheus/api/network_routers_interface.rb +101 -0
- data/lib/morpheus/api/tasks_interface.rb +12 -14
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/apps.rb +15 -12
- data/lib/morpheus/cli/cli_command.rb +40 -2
- data/lib/morpheus/cli/clusters.rb +13 -7
- data/lib/morpheus/cli/cypher_command.rb +5 -2
- data/lib/morpheus/cli/hosts.rb +1 -1
- data/lib/morpheus/cli/instances.rb +21 -5
- data/lib/morpheus/cli/jobs_command.rb +83 -27
- data/lib/morpheus/cli/library_cluster_layouts_command.rb +12 -12
- data/lib/morpheus/cli/library_container_scripts_command.rb +52 -40
- data/lib/morpheus/cli/library_container_types_command.rb +2 -60
- data/lib/morpheus/cli/library_instance_types_command.rb +22 -1
- data/lib/morpheus/cli/library_layouts_command.rb +65 -65
- data/lib/morpheus/cli/library_option_lists_command.rb +72 -59
- data/lib/morpheus/cli/library_option_types_command.rb +30 -186
- data/lib/morpheus/cli/library_spec_templates_command.rb +39 -64
- data/lib/morpheus/cli/mixins/library_helper.rb +213 -0
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +89 -37
- data/lib/morpheus/cli/mixins/whoami_helper.rb +16 -1
- data/lib/morpheus/cli/network_routers_command.rb +1281 -0
- data/lib/morpheus/cli/networks_command.rb +164 -72
- data/lib/morpheus/cli/option_types.rb +187 -73
- data/lib/morpheus/cli/price_sets_command.rb +4 -4
- data/lib/morpheus/cli/prices_command.rb +15 -15
- data/lib/morpheus/cli/remote.rb +3 -3
- data/lib/morpheus/cli/service_plans_command.rb +17 -8
- data/lib/morpheus/cli/tasks.rb +437 -169
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +8 -0
- metadata +6 -3
@@ -235,7 +235,7 @@ class Morpheus::Cli::PriceSetsCommand
|
|
235
235
|
params['code'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'code', 'type' => 'text', 'fieldLabel' => 'Price Set Code', 'required' => true, 'defaultValue' => params['name'].gsub(/[^0-9a-z ]/i, '').gsub(' ', '.').downcase, 'description' => 'Price Set Code.'}],options[:options],@api_client,{}, options[:no_prompt])['code']
|
236
236
|
|
237
237
|
# region code
|
238
|
-
params['regionCode'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
238
|
+
params['regionCode'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'regionCode', 'type' => 'text', 'fieldLabel' => 'Price Set Region Code', 'required' => false, 'description' => 'Price Set Region Code.'}],options[:options],@api_client,{}, options[:no_prompt])['regionCode']
|
239
239
|
|
240
240
|
# cloud
|
241
241
|
if options[:cloud]
|
@@ -247,7 +247,7 @@ class Morpheus::Cli::PriceSetsCommand
|
|
247
247
|
end
|
248
248
|
params['zone'] = {'id' => cloud['id']}
|
249
249
|
else
|
250
|
-
cloud_id = Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
250
|
+
cloud_id = Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'zone', 'type' => 'select', 'fieldLabel' => 'Cloud', 'required' => false, 'description' => 'Select cloud for price set', 'selectOptions' => @clouds_interface.list['zones'].collect {|it| {'name' => it['name'], 'value' => it['id']}}], options[:options], @api_client, {}, options[:no_prompt], true)['zone']
|
251
251
|
|
252
252
|
if cloud_id
|
253
253
|
params['zone'] = {'id' => cloud_id}
|
@@ -264,7 +264,7 @@ class Morpheus::Cli::PriceSetsCommand
|
|
264
264
|
end
|
265
265
|
params['zonePool'] = {'id' => resource_pool['id']}
|
266
266
|
else
|
267
|
-
resource_pool_id = Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
267
|
+
resource_pool_id = Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'zonePool', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'required' => false, 'description' => 'Select resource pool for price set', 'selectOptions' => @cloud_resource_pools_interface.list(params['zone'] ? params['zone']['id'] : nil)['resourcePools'].collect {|it| {'name' => it['name'], 'value' => it['id']}}], options[:options], @api_client, {}, options[:no_prompt], true)['zonePool']
|
268
268
|
|
269
269
|
if resource_pool_id
|
270
270
|
params['zonePool'] = {'id' => resource_pool_id}
|
@@ -308,7 +308,7 @@ class Morpheus::Cli::PriceSetsCommand
|
|
308
308
|
# additional prices
|
309
309
|
avail_price_types = (price_set_type[:requires] + price_set_type[:allows]).collect {|it| {'name' => price_type_label(it), 'value' => it}}
|
310
310
|
price_type = nil
|
311
|
-
while Morpheus::Cli::OptionTypes.confirm("Add additional prices?") do
|
311
|
+
while Morpheus::Cli::OptionTypes.confirm("Add additional prices?", {default:false}) do
|
312
312
|
price_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priceType', 'type' => 'select', 'fieldLabel' => "Price Type", 'selectOptions' => avail_price_types, 'required' => true, 'defaultValue' => price_type, 'description' => "Select Price Type"}],options[:options],@api_client,{}, options[:no_prompt], true)['priceType']
|
313
313
|
avail_prices = @prices_interface.list({'priceType' => price_type, 'priceUnit' => params['priceUnit'], 'max' => 10000})['prices'].reject {|it| params['prices'].find {|price| price['id'] == it['id']}}.collect {|it| {'name' => it['name'], 'value' => it['id']}}
|
314
314
|
|
@@ -272,10 +272,10 @@ class Morpheus::Cli::PricesCommand
|
|
272
272
|
|
273
273
|
if !payload
|
274
274
|
# name
|
275
|
-
params['name'] ||= args[0] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Price
|
275
|
+
params['name'] ||= args[0] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Price Name', 'required' => true, 'description' => 'Price Set Name.'}],options[:options],@api_client,{}, options[:no_prompt])['name']
|
276
276
|
|
277
277
|
# code
|
278
|
-
params['code'] ||= args[1] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'code', 'type' => 'text', 'fieldLabel' => 'Price
|
278
|
+
params['code'] ||= args[1] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'code', 'type' => 'text', 'fieldLabel' => 'Price Code', 'required' => true, 'defaultValue' => params['name'].gsub(/[^0-9a-z ]/i, '').gsub(' ', '.').downcase, 'description' => 'Price Set Code.'}],options[:options],@api_client,{}, options[:no_prompt])['code']
|
279
279
|
|
280
280
|
# tenant
|
281
281
|
if options[:tenant].nil?
|
@@ -293,28 +293,28 @@ class Morpheus::Cli::PricesCommand
|
|
293
293
|
end
|
294
294
|
|
295
295
|
# type (platform, software, datastore, storage)
|
296
|
-
params['priceType'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
296
|
+
params['priceType'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priceType', 'type' => 'select', 'fieldLabel' => 'Price Type', 'required' => true, 'description' => 'Select price type', 'selectOptions' => price_types.collect {|k,v| {'name' => v, 'value' => k}}}], options[:options], @api_client, {}, options[:no_prompt])['priceType']
|
297
297
|
|
298
298
|
# price type
|
299
299
|
prompt_for_price_type(params, options)
|
300
300
|
|
301
301
|
# unit
|
302
|
-
params['priceUnit'] ||= Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
302
|
+
params['priceUnit'] ||= Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'priceUnit', 'type' => 'select', 'fieldLabel' => 'Price Unit', 'required' => true, 'description' => 'Select price unit', 'defaultValue' => 'month', 'selectOptions' => price_units.collect {|it| {'name' => it.split(' ').collect {|it| it.capitalize}.join(' '), 'value' => it}}], options[:options], @api_client, {}, options[:no_prompt])['priceUnit']
|
303
303
|
|
304
304
|
# incur
|
305
|
-
params['incurCharges'] ||= Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
305
|
+
params['incurCharges'] ||= Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'incurCharges', 'type' => 'select', 'fieldLabel' => 'Incur Charges', 'required' => true, 'description' => 'Select when to incur charges', 'defaultValue' => 'running', 'selectOptions' => [{'name' => 'When Running', 'value' => 'running'}, {'name' => 'When Stopped', 'value' => 'stopped'}, {'name' => 'Always', 'value' => 'always'}]], options[:options], @api_client, {}, options[:no_prompt])['incurCharges']
|
306
306
|
|
307
307
|
# currency
|
308
|
-
params['currency'] ||= Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
308
|
+
params['currency'] ||= Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'currency', 'type' => 'select', 'fieldLabel' => 'Currency', 'required' => true, 'description' => 'Select when to incur charges', 'defaultValue' => 'USD', 'selectOptions' => avail_currencies.collect {|it| {'value' => it}}], options[:options], @api_client, {}, options[:no_prompt])['currency']
|
309
309
|
|
310
310
|
# cost
|
311
311
|
if params['cost'].nil?
|
312
|
-
params['cost'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
312
|
+
params['cost'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cost', 'type' => 'number', 'fieldLabel' => 'Cost', 'required' => true, 'description' => 'Price cost', 'defaultValue' => 0.0}],options[:options],@api_client,{}, options[:no_prompt])['cost']
|
313
313
|
end
|
314
314
|
|
315
315
|
# adjustment / markup type
|
316
316
|
if params['markupType'].nil?
|
317
|
-
markup_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
317
|
+
markup_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'markupType', 'type' => 'select', 'fieldLabel' => 'Price Adjustment', 'required' => false, 'description' => 'Price Adjustment', 'selectOptions' => [{'name' => 'None', 'value' => 'none'}, {'name' => 'Fixed Markup', 'value' => 'fixed'}, {'name' => 'Percent Markup', 'value' => 'percent'}, {'name' => 'Custom Price', 'value' => 'custom'}], 'defaultValue' => 'none'}],options[:options],@api_client,{}, options[:no_prompt])['markupType']
|
318
318
|
|
319
319
|
if markup_type && markup_type != 'none'
|
320
320
|
params['markupType'] = markup_type
|
@@ -607,9 +607,9 @@ class Morpheus::Cli::PricesCommand
|
|
607
607
|
def prompt_for_price_type(params, options, price={})
|
608
608
|
case params['priceType']
|
609
609
|
when 'platform'
|
610
|
-
params['platform'] ||= price['platform'] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
610
|
+
params['platform'] ||= price['platform'] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'platform', 'type' => 'select', 'fieldLabel' => 'Platform', 'required' => true, 'description' => 'Select platform for platform price type', 'selectOptions' => [{'name' => 'Linux', 'value' => 'linux'}, {'name' => 'Windows', 'value' => 'windows'}]}], options[:options], @api_client, {}, options[:no_prompt])['platform']
|
611
611
|
when 'software'
|
612
|
-
params['software'] ||= price['software'] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
612
|
+
params['software'] ||= price['software'] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'software', 'type' => 'text', 'fieldLabel' => 'Software', 'required' => true, 'description' => 'Set software for software price type'}], options[:options], @api_client,{}, options[:no_prompt])['software']
|
613
613
|
when 'datastore'
|
614
614
|
if options[:datastore]
|
615
615
|
datastore = find_datastore(options[:datastore])
|
@@ -620,7 +620,7 @@ class Morpheus::Cli::PricesCommand
|
|
620
620
|
exit 1
|
621
621
|
end
|
622
622
|
else
|
623
|
-
datastore_id = Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
623
|
+
datastore_id = Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'datastore', 'type' => 'select', 'fieldLabel' => 'Datastore', 'required' => true, 'description' => 'Select datastore for datastore price type', 'selectOptions' => @prices_interface.list_datastores['datastores'].collect {|it| {'name' => it['name'], 'value' => it['id']}}], options[:options], @api_client, {}, options[:no_prompt])['datastore']
|
624
624
|
params['datastore'] = {'id' => datastore_id}
|
625
625
|
end
|
626
626
|
|
@@ -641,7 +641,7 @@ class Morpheus::Cli::PricesCommand
|
|
641
641
|
exit 1
|
642
642
|
end
|
643
643
|
else
|
644
|
-
volume_type_id = (price['volumeType'] ? price['volumeType']['id'] : Morpheus::Cli::OptionTypes.prompt(['fieldName' => '
|
644
|
+
volume_type_id = (price['volumeType'] ? price['volumeType']['id'] : Morpheus::Cli::OptionTypes.prompt(['fieldName' => 'volumeType', 'type' => 'select', 'fieldLabel' => 'Volume Type', 'required' => true, 'description' => 'Select volume type for storage price type', 'selectOptions' => @prices_interface.list_volume_types['volumeTypes'].collect {|it| {'name' => it['name'], 'value' => it['id']}}], options[:options], @api_client, {}, options[:no_prompt], true)['volumeType'])
|
645
645
|
params['volumeType'] = {'id' => volume_type_id}
|
646
646
|
end
|
647
647
|
end
|
@@ -652,17 +652,17 @@ class Morpheus::Cli::PricesCommand
|
|
652
652
|
when 'percent'
|
653
653
|
params['markupPercent'] = price['markupPercent'] if params['markupPercent'].nil?
|
654
654
|
if params['markupPercent'].nil?
|
655
|
-
params['markupPercent'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
655
|
+
params['markupPercent'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'markupPercent', 'type' => 'number', 'fieldLabel' => 'Markup Percent', 'required' => true, 'description' => 'Markup Percent'}],options[:options],@api_client,{}, options[:no_prompt])['markupPercent']
|
656
656
|
end
|
657
657
|
when 'fixed'
|
658
658
|
params['markup'] = price['markup'] if params['markup'].nil?
|
659
659
|
if params['markup'].nil?
|
660
|
-
params['markup'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
660
|
+
params['markup'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'markup', 'type' => 'number', 'fieldLabel' => 'Markup Amount', 'required' => true, 'description' => 'Markup Amount'}],options[:options],@api_client,{}, options[:no_prompt])['markup']
|
661
661
|
end
|
662
662
|
when 'custom'
|
663
663
|
params['customPrice'] = price['customPrice'] if params['customPrice'].nil?
|
664
664
|
if params['customPrice'].nil?
|
665
|
-
params['customPrice'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => '
|
665
|
+
params['customPrice'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'customPrice', 'type' => 'number', 'fieldLabel' => 'Price', 'required' => true, 'description' => 'Price'}],options[:options],@api_client,{}, options[:no_prompt])['customPrice']
|
666
666
|
end
|
667
667
|
end
|
668
668
|
end
|
data/lib/morpheus/cli/remote.rb
CHANGED
@@ -1107,9 +1107,9 @@ EOT
|
|
1107
1107
|
{'fieldName' => 'password', 'fieldLabel' => 'Create Password', 'type' => 'password', 'required' => true, 'description' => 'Create a new password for the user.'},
|
1108
1108
|
{'fieldName' => 'confirmPassword', 'fieldLabel' => 'Confirm Password', 'type' => 'password', 'required' => true, 'description' => 'Confirm the new password for the user.'},
|
1109
1109
|
]
|
1110
|
-
|
1111
|
-
if
|
1112
|
-
payload
|
1110
|
+
password_prompt = Morpheus::Cli::OptionTypes.prompt(password_option_types, options[:options])
|
1111
|
+
if password_prompt['password'] == password_prompt['confirmPassword']
|
1112
|
+
payload['password'] = password_prompt['password']
|
1113
1113
|
need_password = false
|
1114
1114
|
else
|
1115
1115
|
print_error red, "Password confirmation does not match. Re-enter your new password.", reset, "\n"
|
@@ -97,7 +97,6 @@ class Morpheus::Cli::ServicePlanCommand
|
|
97
97
|
|
98
98
|
print as_pretty_table(rows, columns, options)
|
99
99
|
print_results_pagination(json_response)
|
100
|
-
print reset,"\n"
|
101
100
|
end
|
102
101
|
print reset,"\n"
|
103
102
|
return 0
|
@@ -251,6 +250,9 @@ class Morpheus::Cli::ServicePlanCommand
|
|
251
250
|
opts.on("--description [TEXT]", String, "Description") do |val|
|
252
251
|
params['description'] = val.to_s
|
253
252
|
end
|
253
|
+
opts.on('--active [on|off]', String, "Can be used to enable / disable the plan. Default is on") do |val|
|
254
|
+
params['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
255
|
+
end
|
254
256
|
opts.on('--editable [on|off]', String, "Can be used to enable / disable the editability of the service plan. Default is on") do |val|
|
255
257
|
params['editable'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
256
258
|
end
|
@@ -333,9 +335,11 @@ class Morpheus::Cli::ServicePlanCommand
|
|
333
335
|
end
|
334
336
|
|
335
337
|
begin
|
336
|
-
|
338
|
+
if options[:payload]
|
339
|
+
payload = parse_payload(options, 'servicePlan')
|
340
|
+
else
|
341
|
+
apply_options(params, options)
|
337
342
|
|
338
|
-
if !payload
|
339
343
|
# name
|
340
344
|
params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Service Plan Name', 'required' => true, 'description' => 'Service Plan Name.'}],options[:options],@api_client,{}, options[:no_prompt])['name']
|
341
345
|
|
@@ -476,6 +480,9 @@ class Morpheus::Cli::ServicePlanCommand
|
|
476
480
|
opts.on("--description [TEXT]", String, "Description") do |val|
|
477
481
|
params['description'] = val.to_s
|
478
482
|
end
|
483
|
+
opts.on('--active [on|off]', String, "Can be used to enable / disable the plan. Default is on") do |val|
|
484
|
+
params['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
485
|
+
end
|
479
486
|
opts.on('--editable [on|off]', String, "Can be used to enable / disable the editability of the service plan. Default is on") do |val|
|
480
487
|
params['editable'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
481
488
|
end
|
@@ -557,7 +564,6 @@ class Morpheus::Cli::ServicePlanCommand
|
|
557
564
|
return 1
|
558
565
|
end
|
559
566
|
|
560
|
-
print options
|
561
567
|
begin
|
562
568
|
plan = find_service_plan(args[0])
|
563
569
|
|
@@ -566,9 +572,11 @@ class Morpheus::Cli::ServicePlanCommand
|
|
566
572
|
exit 1
|
567
573
|
end
|
568
574
|
|
569
|
-
|
575
|
+
if options[:payload]
|
576
|
+
payload = parse_payload(options, 'servicePlan')
|
577
|
+
else
|
578
|
+
apply_options(params, options)
|
570
579
|
|
571
|
-
if !payload
|
572
580
|
# provision type
|
573
581
|
options[:provisionType] = options[:provisionType] || (args.count > 1 ? args[1] : nil)
|
574
582
|
|
@@ -601,8 +609,9 @@ class Morpheus::Cli::ServicePlanCommand
|
|
601
609
|
end
|
602
610
|
|
603
611
|
if payload.empty? || !payload['servicePlan'] || payload['servicePlan'].empty?
|
604
|
-
|
605
|
-
|
612
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
613
|
+
# print_green_success "Nothing to update"
|
614
|
+
# return 0
|
606
615
|
end
|
607
616
|
|
608
617
|
@service_plans_interface.setopts(options)
|
data/lib/morpheus/cli/tasks.rb
CHANGED
@@ -7,10 +7,9 @@ require 'morpheus/cli/cli_command'
|
|
7
7
|
class Morpheus::Cli::Tasks
|
8
8
|
include Morpheus::Cli::CliCommand
|
9
9
|
|
10
|
-
register_subcommands :list, :get, :add, :update, :remove, :execute
|
11
|
-
|
12
|
-
|
13
|
-
set_default_subcommand :list
|
10
|
+
register_subcommands :list, :get, :add, :update, :remove, :execute
|
11
|
+
register_subcommands :'list-types' => :list_task_types
|
12
|
+
register_subcommands :'get-type' => :get_task_type
|
14
13
|
|
15
14
|
def connect(opts)
|
16
15
|
@api_client = establish_remote_appliance_connection(opts)
|
@@ -29,46 +28,42 @@ class Morpheus::Cli::Tasks
|
|
29
28
|
options = {}
|
30
29
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
31
30
|
opts.banner = subcommand_usage()
|
32
|
-
opts.on('--
|
31
|
+
opts.on('-t', '--type x,y,z', Array, "Filter by task type code(s)") do |val|
|
33
32
|
params['taskTypeCodes'] = val
|
34
33
|
end
|
35
34
|
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
36
35
|
end
|
37
36
|
optparse.parse!(args)
|
37
|
+
if args.count > 0
|
38
|
+
raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
39
|
+
end
|
38
40
|
connect(options)
|
39
41
|
begin
|
40
42
|
params.merge!(parse_list_options(options))
|
41
43
|
@tasks_interface.setopts(options)
|
42
44
|
if options[:dry_run]
|
43
|
-
print_dry_run @tasks_interface.dry.
|
45
|
+
print_dry_run @tasks_interface.dry.list(params)
|
44
46
|
return
|
45
47
|
end
|
46
|
-
json_response = @tasks_interface.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
json_response = @tasks_interface.list(params)
|
49
|
+
|
50
|
+
render_result = render_with_format(json_response, options, 'tasks')
|
51
|
+
return 0 if render_result
|
52
|
+
|
53
|
+
title = "Morpheus Tasks"
|
54
|
+
subtitles = []
|
55
|
+
subtitles += parse_list_subtitles(options)
|
56
|
+
print_h1 title, subtitles
|
57
|
+
tasks = json_response['tasks']
|
58
|
+
if tasks.empty?
|
59
|
+
print cyan,"No tasks found.",reset,"\n"
|
57
60
|
else
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
print_h1 title, subtitles
|
62
|
-
tasks = json_response['tasks']
|
63
|
-
if tasks.empty?
|
64
|
-
print cyan,"No tasks found.",reset,"\n"
|
65
|
-
else
|
66
|
-
print cyan
|
67
|
-
print_tasks_table(tasks, options)
|
68
|
-
print_results_pagination(json_response)
|
69
|
-
end
|
70
|
-
print reset,"\n"
|
61
|
+
print cyan
|
62
|
+
print_tasks_table(tasks, options)
|
63
|
+
print_results_pagination(json_response)
|
71
64
|
end
|
65
|
+
print reset,"\n"
|
66
|
+
return 0
|
72
67
|
rescue RestClient::Exception => e
|
73
68
|
print_rest_exception(e, options)
|
74
69
|
exit 1
|
@@ -79,12 +74,14 @@ class Morpheus::Cli::Tasks
|
|
79
74
|
options = {}
|
80
75
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
81
76
|
opts.banner = subcommand_usage("[workflow]")
|
77
|
+
opts.on('--no-content', "Do not display script content." ) do
|
78
|
+
options[:no_content] = true
|
79
|
+
end
|
82
80
|
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
83
81
|
end
|
84
82
|
optparse.parse!(args)
|
85
83
|
if args.count < 1
|
86
|
-
|
87
|
-
return 1
|
84
|
+
raise_command_error "wrong number of arguments, expected 1-N and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
88
85
|
end
|
89
86
|
connect(options)
|
90
87
|
id_list = parse_id_list(args)
|
@@ -172,123 +169,72 @@ class Morpheus::Cli::Tasks
|
|
172
169
|
|
173
170
|
# JD: uhh, the api should NOT be returning passwords!!
|
174
171
|
if task_type
|
172
|
+
# task_type['optionTypes'].sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.each do |optionType|
|
173
|
+
# if optionType['fieldLabel'].to_s.downcase == 'script'
|
174
|
+
# if task['taskOptions'][optionType['fieldName']]
|
175
|
+
# print_h2 "Script"
|
176
|
+
# print reset,"#{task['taskOptions'][optionType['fieldName']]}","\n",reset
|
177
|
+
# end
|
178
|
+
# else
|
179
|
+
# print cyan,("#{optionType['fieldLabel']} : " + (optionType['type'] == 'password' ? "#{task['taskOptions'][optionType['fieldName']] ? '************' : ''}" : "#{task['taskOptions'][optionType['fieldName']] || optionType['defaultValue']}")),"\n"
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
script_content = nil
|
183
|
+
task_option_types = []
|
184
|
+
task_option_config = {}
|
185
|
+
task_option_columns = []
|
175
186
|
task_type['optionTypes'].sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.each do |optionType|
|
176
187
|
if optionType['fieldLabel'].to_s.downcase == 'script'
|
177
|
-
|
178
|
-
|
188
|
+
script_content = task['taskOptions'][optionType['fieldName']]
|
189
|
+
elsif optionType['fieldName'] == 'httpHeaders' || optionType['fieldName'] == 'webHeaders'
|
190
|
+
http_headers = task['taskOptions']['httpHeaders'] || task['taskOptions']['webHeaders']
|
191
|
+
begin
|
192
|
+
if http_headers.is_a?(String)
|
193
|
+
http_headers = JSON.parse(http_headers)
|
194
|
+
end
|
195
|
+
# API has mismatch on fieldName httpHeaders vs webHeaders, we want to format this in a particular way though anyhow..
|
196
|
+
task_option_columns << {(optionType['fieldLabel']) => lambda {|it| http_headers.collect {|h| "#{h['key']}: #{h['value']}"}.join(", ") } }
|
197
|
+
rescue => ex
|
198
|
+
Morpheus::Logging::DarkPrinter.puts("Failed to parse httpHeaders task option as JSON") if Morpheus::Logging.debug?
|
199
|
+
end
|
179
200
|
else
|
180
|
-
|
201
|
+
task_option_types << optionType
|
202
|
+
task_option_columns << {(optionType['fieldLabel']) => lambda {|it| task['taskOptions'][optionType['fieldName']] || optionType['defaultValue'] } }
|
181
203
|
end
|
182
204
|
end
|
183
205
|
else
|
184
206
|
print yellow,"Task type not found.",reset,"\n"
|
185
207
|
end
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
rescue RestClient::Exception => e
|
190
|
-
print_rest_exception(e, options)
|
191
|
-
exit 1
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def update(args)
|
196
|
-
options = {}
|
197
|
-
account_name = nil
|
198
|
-
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
199
|
-
opts.banner = subcommand_usage("[task] [options]")
|
200
|
-
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
201
|
-
end
|
202
|
-
optparse.parse!(args)
|
203
|
-
if args.count < 1
|
204
|
-
puts optparse
|
205
|
-
exit 1
|
206
|
-
end
|
207
|
-
task_name = args[0]
|
208
|
-
connect(options)
|
209
|
-
begin
|
210
|
-
|
211
|
-
|
212
|
-
task = find_task_by_name_or_id(task_name)
|
213
|
-
exit 1 if task.nil?
|
214
|
-
task_type = find_task_type_by_name(task['taskType']['name'])
|
215
|
-
|
216
|
-
#params = Morpheus::Cli::OptionTypes.prompt(add_user_option_types, options[:options], @api_client, options[:params]) # options[:params] is mysterious
|
217
|
-
params = options[:options] || {}
|
218
|
-
|
219
|
-
if params.empty?
|
220
|
-
puts optparse.banner
|
221
|
-
option_lines = update_task_option_types(task_type).collect {|it| "\t-O #{it['fieldContext'] ? (it['fieldContext'] + '.') : ''}#{it['fieldName']}=\"value\"" }.join("\n")
|
222
|
-
puts "\nAvailable Options:\n#{option_lines}\n\n"
|
223
|
-
exit 1
|
224
|
-
end
|
225
|
-
|
226
|
-
#puts "parsed params is : #{params.inspect}"
|
227
|
-
task_keys = ['name']
|
228
|
-
changes_payload = (params.select {|k,v| task_keys.include?(k) })
|
229
|
-
task_payload = task
|
230
|
-
if changes_payload
|
231
|
-
task_payload.merge!(changes_payload)
|
232
|
-
end
|
233
|
-
if params['taskOptions']
|
234
|
-
task_payload['taskOptions'].merge!(params['taskOptions'])
|
235
|
-
end
|
236
|
-
|
237
|
-
payload = {task: task_payload}
|
238
|
-
@tasks_interface.setopts(options)
|
239
|
-
if options[:dry_run]
|
240
|
-
print_dry_run @tasks_interface.dry.update(task['id'], payload)
|
241
|
-
return 0
|
242
|
-
end
|
243
|
-
response = @tasks_interface.update(task['id'], payload)
|
244
|
-
if options[:json]
|
245
|
-
print JSON.pretty_generate(json_response)
|
246
|
-
if !response['success']
|
247
|
-
return 1
|
208
|
+
if !task_option_columns.empty?
|
209
|
+
print_h2 "Task Options"
|
210
|
+
print_description_list(task_option_columns, task["taskOptions"])
|
248
211
|
end
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
@tasks_interface.setopts(options)
|
271
|
-
if options[:dry_run]
|
272
|
-
print_dry_run @tasks_interface.dry.task_types()
|
273
|
-
return
|
274
|
-
end
|
275
|
-
json_response = @tasks_interface.task_types()
|
276
|
-
if options[:json]
|
277
|
-
print JSON.pretty_generate(json_response),"\n"
|
278
|
-
else
|
279
|
-
task_types = json_response['taskTypes']
|
280
|
-
print_h1 "Morpheus Task Types"
|
281
|
-
if task_types.nil? || task_types.empty?
|
282
|
-
print yellow,"No task types currently exist on this appliance. This could be a seed issue.",reset,"\n"
|
283
|
-
else
|
284
|
-
print cyan
|
285
|
-
rows = task_types.collect do |task_type|
|
286
|
-
{name: task_type['name'], id: task_type['id'], code: task_type['code'], description: task_type['description']}
|
212
|
+
if script_content
|
213
|
+
print_h2 "Script"
|
214
|
+
print reset,script_content,"\n",reset
|
215
|
+
end
|
216
|
+
# some task types have a file (file-content) instead of taskOptions.script
|
217
|
+
file_content = task['file']
|
218
|
+
if file_content && options[:no_content] != true
|
219
|
+
print_h2 "Script Content"
|
220
|
+
if file_content['sourceType'] == 'local'
|
221
|
+
puts file_content['content']
|
222
|
+
elsif file_content['sourceType'] == 'url'
|
223
|
+
puts "URL: #{file_content['contentPath']}"
|
224
|
+
elsif file_content['sourceType'] == 'repository'
|
225
|
+
puts "Repository: #{file_content['repository']['name'] rescue 'n/a'}"
|
226
|
+
puts "Path: #{file_content['contentPath']}"
|
227
|
+
if file_content['contentRef']
|
228
|
+
puts "Ref: #{file_content['contentRef']}"
|
229
|
+
end
|
230
|
+
else
|
231
|
+
puts "Source: #{file_content['sourceType']}"
|
232
|
+
puts "Path: #{file_content['contentPath']}"
|
287
233
|
end
|
288
|
-
puts as_pretty_table(rows, [:id, :name, :code], options)
|
289
234
|
end
|
290
235
|
|
291
236
|
print reset,"\n"
|
237
|
+
return 0
|
292
238
|
end
|
293
239
|
rescue RestClient::Exception => e
|
294
240
|
print_rest_exception(e, options)
|
@@ -298,7 +244,8 @@ class Morpheus::Cli::Tasks
|
|
298
244
|
|
299
245
|
def add(args)
|
300
246
|
params = {}
|
301
|
-
|
247
|
+
file_params = {}
|
248
|
+
options = {}
|
302
249
|
task_name = nil
|
303
250
|
task_code = nil
|
304
251
|
task_type_name = nil
|
@@ -313,6 +260,32 @@ class Morpheus::Cli::Tasks
|
|
313
260
|
opts.on('--code CODE', String, "Task Code" ) do |val|
|
314
261
|
task_code = val
|
315
262
|
end
|
263
|
+
opts.on('--source VALUE', String, "Source Type. local, repository, url. Only applies to script task types.") do |val|
|
264
|
+
file_params['sourceType'] = val
|
265
|
+
end
|
266
|
+
opts.on('--content TEXT', String, "Contents of the task script. This implies source is local.") do |val|
|
267
|
+
file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
|
268
|
+
file_params['content'] = val
|
269
|
+
end
|
270
|
+
opts.on('--file FILE', "File containing the task script. This can be used instead of --content" ) do |filename|
|
271
|
+
file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
|
272
|
+
full_filename = File.expand_path(filename)
|
273
|
+
if File.exists?(full_filename)
|
274
|
+
file_params['content'] = File.read(full_filename)
|
275
|
+
else
|
276
|
+
print_red_alert "File not found: #{full_filename}"
|
277
|
+
exit 1
|
278
|
+
end
|
279
|
+
end
|
280
|
+
opts.on('--url VALUE', String, "URL, for use when source is url") do |val|
|
281
|
+
file_params['contentPath'] = val
|
282
|
+
end
|
283
|
+
opts.on('--content-path VALUE', String, "Content Path, for use when source is repository or url") do |val|
|
284
|
+
file_params['contentPath'] = val
|
285
|
+
end
|
286
|
+
opts.on('--content-ref VALUE', String, "Content Ref (Version Ref), for use when source is repository") do |val|
|
287
|
+
file_params['contentRef'] = val
|
288
|
+
end
|
316
289
|
opts.on('--result-type VALUE', String, "Result Type" ) do |val|
|
317
290
|
options[:options]['resultType'] = val
|
318
291
|
end
|
@@ -358,21 +331,6 @@ class Morpheus::Cli::Tasks
|
|
358
331
|
opts.on('--allow-custom-config [on|off]', String, "Allow Custom Config") do |val|
|
359
332
|
options[:options]['allowCustomConfig'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
360
333
|
end
|
361
|
-
opts.on('--file FILE', "File containing the script. This can be used instead of --O taskOptions.script" ) do |filename|
|
362
|
-
full_filename = File.expand_path(filename)
|
363
|
-
if File.exists?(full_filename)
|
364
|
-
options[:options]['taskOptions'] ||= {}
|
365
|
-
options[:options]['taskOptions']['script'] = File.read(full_filename)
|
366
|
-
# params['script'] = File.read(full_filename)
|
367
|
-
else
|
368
|
-
print_red_alert "File not found: #{full_filename}"
|
369
|
-
exit 1
|
370
|
-
end
|
371
|
-
# use the filename as the name by default.
|
372
|
-
if !options[:options]['name']
|
373
|
-
options[:options]['name'] = File.basename(full_filename)
|
374
|
-
end
|
375
|
-
end
|
376
334
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
377
335
|
end
|
378
336
|
optparse.parse!(args)
|
@@ -397,6 +355,7 @@ class Morpheus::Cli::Tasks
|
|
397
355
|
if options[:payload]
|
398
356
|
payload = options[:payload]
|
399
357
|
payload.deep_merge!({'task' => passed_options}) unless passed_options.empty?
|
358
|
+
payload.deep_merge!({'task' => {'file' => file_params}}) unless file_params.empty?
|
400
359
|
else
|
401
360
|
# construct payload
|
402
361
|
payload = {
|
@@ -428,7 +387,7 @@ class Morpheus::Cli::Tasks
|
|
428
387
|
end
|
429
388
|
|
430
389
|
# Task Type
|
431
|
-
@all_task_types ||= @tasks_interface.
|
390
|
+
@all_task_types ||= @tasks_interface.list_types({max:1000})['taskTypes']
|
432
391
|
task_types_dropdown = @all_task_types.collect {|it| {"name" => it["name"], "value" => it["code"]}}
|
433
392
|
|
434
393
|
if task_type_name
|
@@ -458,14 +417,32 @@ class Morpheus::Cli::Tasks
|
|
458
417
|
|
459
418
|
# Task Type Option Types
|
460
419
|
|
461
|
-
#
|
462
|
-
|
420
|
+
# correct fieldContext
|
421
|
+
has_file_content = false
|
463
422
|
task_option_types = task_type['optionTypes'] || []
|
464
423
|
task_option_types.each do |it|
|
465
|
-
if it['
|
466
|
-
|
424
|
+
if it['type'] == 'file-content'
|
425
|
+
has_file_content = true
|
426
|
+
it['fieldContext'] = nil
|
427
|
+
it['fieldName'] = 'file'
|
428
|
+
else
|
429
|
+
if it['fieldContext'].nil? || it['fieldContext'] == ''
|
430
|
+
it['fieldContext'] = 'taskOptions'
|
431
|
+
end
|
467
432
|
end
|
468
433
|
end
|
434
|
+
# inject file_params into options for file-content prompt
|
435
|
+
# or into taskOptions.script for types not yet using file-content
|
436
|
+
unless file_params.empty?
|
437
|
+
if has_file_content
|
438
|
+
options[:options]['file'] ||= {}
|
439
|
+
options[:options]['file'].merge!(file_params)
|
440
|
+
else
|
441
|
+
options[:options]['taskOptions'] ||= {}
|
442
|
+
options[:options]['taskOptions']['script'] = file_params['content'] if file_params['content']
|
443
|
+
end
|
444
|
+
end
|
445
|
+
# prompt
|
469
446
|
input_options = Morpheus::Cli::OptionTypes.prompt(task_option_types, options[:options],@api_client, options[:params])
|
470
447
|
payload.deep_merge!({'task' => input_options}) unless input_options.empty?
|
471
448
|
|
@@ -496,17 +473,19 @@ class Morpheus::Cli::Tasks
|
|
496
473
|
end
|
497
474
|
|
498
475
|
if payload['task']['executeTarget'] == 'local'
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
476
|
+
if task_type['allowLocalRepo']
|
477
|
+
# Git Repo
|
478
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'localScriptGitId', 'fieldLabel' => 'Git Repo', 'type' => 'text', 'description' => 'Git Repo ID'}], options[:options], @api_client)
|
479
|
+
if v_prompt['taskOptions'] && !v_prompt['taskOptions']['localScriptGitId'].to_s.empty?
|
480
|
+
payload['task']['taskOptions'] ||= {}
|
481
|
+
payload['task']['taskOptions']['localScriptGitId'] = v_prompt['taskOptions']['localScriptGitId']
|
482
|
+
end
|
483
|
+
# Git Ref
|
484
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'localScriptGitRef', 'fieldLabel' => 'Git Ref', 'type' => 'text', 'description' => 'Git Ref eg. master'}], options[:options], @api_client)
|
485
|
+
if v_prompt['taskOptions'] && !v_prompt['taskOptions']['localScriptGitRef'].to_s.empty?
|
486
|
+
payload['task']['taskOptions'] ||= {}
|
487
|
+
payload['task']['taskOptions']['localScriptGitRef'] = v_prompt['taskOptions']['localScriptGitRef']
|
488
|
+
end
|
510
489
|
end
|
511
490
|
|
512
491
|
elsif payload['task']['executeTarget'] == 'remote'
|
@@ -593,6 +572,166 @@ class Morpheus::Cli::Tasks
|
|
593
572
|
end
|
594
573
|
end
|
595
574
|
|
575
|
+
def update(args)
|
576
|
+
params = {}
|
577
|
+
file_params = {}
|
578
|
+
options = {}
|
579
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
580
|
+
opts.banner = subcommand_usage("[task] [options]")
|
581
|
+
opts.on('--name NAME', String, "Task Name" ) do |val|
|
582
|
+
options[:options]['name'] = val
|
583
|
+
end
|
584
|
+
opts.on('--code CODE', String, "Task Code" ) do |val|
|
585
|
+
options[:options]['code'] = val
|
586
|
+
end
|
587
|
+
opts.on('--source VALUE', String, "Source Type. local, repository, url. Only applies to script task types.") do |val|
|
588
|
+
file_params['sourceType'] = val
|
589
|
+
end
|
590
|
+
opts.on('--content TEXT', String, "Contents of the task script. This implies source is local.") do |val|
|
591
|
+
file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
|
592
|
+
file_params['content'] = val
|
593
|
+
end
|
594
|
+
opts.on('--file FILE', "File containing the task script. This can be used instead of --content" ) do |filename|
|
595
|
+
file_params['sourceType'] = 'local' if file_params['sourceType'].nil?
|
596
|
+
full_filename = File.expand_path(filename)
|
597
|
+
if File.exists?(full_filename)
|
598
|
+
file_params['content'] = File.read(full_filename)
|
599
|
+
else
|
600
|
+
print_red_alert "File not found: #{full_filename}"
|
601
|
+
exit 1
|
602
|
+
end
|
603
|
+
end
|
604
|
+
opts.on('--url VALUE', String, "URL, for use when source is url") do |val|
|
605
|
+
file_params['contentPath'] = val
|
606
|
+
end
|
607
|
+
opts.on('--content-path VALUE', String, "Content Path, for use when source is repository or url") do |val|
|
608
|
+
file_params['contentPath'] = val
|
609
|
+
end
|
610
|
+
opts.on('--content-ref VALUE', String, "Content Ref (Version Ref), for use when source is repository") do |val|
|
611
|
+
file_params['contentRef'] = val
|
612
|
+
end
|
613
|
+
opts.on('--result-type VALUE', String, "Result Type" ) do |val|
|
614
|
+
options[:options]['resultType'] = val
|
615
|
+
end
|
616
|
+
opts.on('--result-type VALUE', String, "Result Type" ) do |val|
|
617
|
+
options[:options]['executeTarget'] = val
|
618
|
+
end
|
619
|
+
opts.on('--execute-target VALUE', String, "Execute Target" ) do |val|
|
620
|
+
options[:options]['executeTarget'] = val
|
621
|
+
end
|
622
|
+
opts.on('--target-host VALUE', String, "Target Host" ) do |val|
|
623
|
+
options[:options]['taskOptions'] ||= {}
|
624
|
+
options[:options]['taskOptions']['host'] = val
|
625
|
+
end
|
626
|
+
opts.on('--target-port VALUE', String, "Target Port" ) do |val|
|
627
|
+
options[:options]['taskOptions'] ||= {}
|
628
|
+
options[:options]['taskOptions']['port'] = val
|
629
|
+
end
|
630
|
+
opts.on('--target-username VALUE', String, "Target Username" ) do |val|
|
631
|
+
options[:options]['taskOptions'] ||= {}
|
632
|
+
options[:options]['taskOptions']['username'] = val
|
633
|
+
end
|
634
|
+
opts.on('--target-password VALUE', String, "Target Password" ) do |val|
|
635
|
+
options[:options]['taskOptions'] ||= {}
|
636
|
+
options[:options]['taskOptions']['password'] = val
|
637
|
+
end
|
638
|
+
opts.on('--git-repo VALUE', String, "Git Repo ID" ) do |val|
|
639
|
+
options[:options]['taskOptions'] ||= {}
|
640
|
+
options[:options]['taskOptions']['localScriptGitId'] = val
|
641
|
+
end
|
642
|
+
opts.on('--git-ref VALUE', String, "Git Ref" ) do |val|
|
643
|
+
options[:options]['taskOptions'] ||= {}
|
644
|
+
options[:options]['taskOptions']['localScriptGitRef'] = val
|
645
|
+
end
|
646
|
+
opts.on('--retryable [on|off]', String, "Retryable" ) do |val|
|
647
|
+
options[:options]['retryable'] = val.to_s == 'on' || val.to_s == 'true' || val == '' || val.nil?
|
648
|
+
end
|
649
|
+
opts.on('--retry-count COUNT', String, "Retry Count" ) do |val|
|
650
|
+
options[:options]['retryCount'] = val.to_i
|
651
|
+
end
|
652
|
+
opts.on('--retry-delay SECONDS', String, "Retry Delay Seconds" ) do |val|
|
653
|
+
options[:options]['retryDelaySeconds'] = val.to_i
|
654
|
+
end
|
655
|
+
opts.on('--allow-custom-config [on|off]', String, "Allow Custom Config") do |val|
|
656
|
+
options[:options]['allowCustomConfig'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
657
|
+
end
|
658
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
659
|
+
end
|
660
|
+
optparse.parse!(args)
|
661
|
+
if args.count != 1
|
662
|
+
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
663
|
+
end
|
664
|
+
task_name = args[0]
|
665
|
+
connect(options)
|
666
|
+
begin
|
667
|
+
task = find_task_by_name_or_id(task_name)
|
668
|
+
return 1 if task.nil?
|
669
|
+
task_type = find_task_type_by_name(task['taskType']['name'])
|
670
|
+
return 1 if task_type.nil?
|
671
|
+
|
672
|
+
# file content param varies, heh
|
673
|
+
has_file_content = false
|
674
|
+
task_option_types = task_type['optionTypes'] || []
|
675
|
+
task_option_types.each do |it|
|
676
|
+
if it['type'] == 'file-content'
|
677
|
+
has_file_content = true
|
678
|
+
end
|
679
|
+
end
|
680
|
+
# inject file_params into options for file-content prompt
|
681
|
+
# or into taskOptions.script for types not yet using file-content
|
682
|
+
unless file_params.empty?
|
683
|
+
if has_file_content
|
684
|
+
options[:options]['file'] ||= {}
|
685
|
+
options[:options]['file'].merge!(file_params)
|
686
|
+
else
|
687
|
+
options[:options]['taskOptions'] ||= {}
|
688
|
+
options[:options]['taskOptions']['script'] = file_params['content'] if file_params['content']
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
693
|
+
payload = nil
|
694
|
+
|
695
|
+
if options[:payload]
|
696
|
+
payload = options[:payload]
|
697
|
+
payload.deep_merge!({'task' => passed_options}) unless passed_options.empty?
|
698
|
+
# payload.deep_merge!({'task' => {'file' => file_params}}) unless file_params.empty?
|
699
|
+
else
|
700
|
+
# construct payload
|
701
|
+
payload = {}
|
702
|
+
payload.deep_merge!({'task' => passed_options}) unless passed_options.empty?
|
703
|
+
# payload.deep_merge!({'task' => {'file' => file_params}}) unless file_params.empty?
|
704
|
+
|
705
|
+
if payload['task'].empty?
|
706
|
+
print_red_alert "Specify at least one option to update"
|
707
|
+
puts optparse
|
708
|
+
return 1
|
709
|
+
end
|
710
|
+
|
711
|
+
end
|
712
|
+
|
713
|
+
@tasks_interface.setopts(options)
|
714
|
+
if options[:dry_run]
|
715
|
+
print_dry_run @tasks_interface.dry.update(task['id'], payload)
|
716
|
+
return 0
|
717
|
+
end
|
718
|
+
response = @tasks_interface.update(task['id'], payload)
|
719
|
+
if options[:json]
|
720
|
+
print JSON.pretty_generate(json_response)
|
721
|
+
if !response['success']
|
722
|
+
return 1
|
723
|
+
end
|
724
|
+
else
|
725
|
+
print_green_success "Task #{response['task']['name']} updated"
|
726
|
+
get([task['id']])
|
727
|
+
end
|
728
|
+
return 0
|
729
|
+
rescue RestClient::Exception => e
|
730
|
+
print_rest_exception(e, options)
|
731
|
+
return 1
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
596
735
|
def remove(args)
|
597
736
|
params = {}
|
598
737
|
task_name = args[0]
|
@@ -761,6 +900,135 @@ class Morpheus::Cli::Tasks
|
|
761
900
|
end
|
762
901
|
end
|
763
902
|
|
903
|
+
def list_task_types(args)
|
904
|
+
params = {}
|
905
|
+
options = {}
|
906
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
907
|
+
opts.banner = subcommand_usage()
|
908
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
909
|
+
opts.footer = "List task types."
|
910
|
+
end
|
911
|
+
optparse.parse!(args)
|
912
|
+
if args.count > 0
|
913
|
+
raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
914
|
+
end
|
915
|
+
connect(options)
|
916
|
+
begin
|
917
|
+
params.merge!(parse_list_options(options))
|
918
|
+
@tasks_interface.setopts(options)
|
919
|
+
if options[:dry_run]
|
920
|
+
print_dry_run @tasks_interface.dry.list_types(params)
|
921
|
+
return
|
922
|
+
end
|
923
|
+
json_response = @tasks_interface.list_types(params)
|
924
|
+
|
925
|
+
|
926
|
+
render_result = render_with_format(json_response, options, 'taskTypes')
|
927
|
+
return 0 if render_result
|
928
|
+
|
929
|
+
title = "Morpheus Task Types"
|
930
|
+
subtitles = []
|
931
|
+
subtitles += parse_list_subtitles(options)
|
932
|
+
print_h1 title, subtitles
|
933
|
+
task_types = json_response['taskTypes']
|
934
|
+
if task_types.empty?
|
935
|
+
print cyan,"No task types found.",reset,"\n"
|
936
|
+
else
|
937
|
+
print cyan
|
938
|
+
rows = task_types.collect do |task_type|
|
939
|
+
{name: task_type['name'], id: task_type['id'], code: task_type['code'], description: task_type['description']}
|
940
|
+
end
|
941
|
+
print as_pretty_table(rows, [:id, :name, :code], options)
|
942
|
+
#print_results_pagination(json_response)
|
943
|
+
print_results_pagination({size:task_types.size,total:task_types.size})
|
944
|
+
end
|
945
|
+
print reset,"\n"
|
946
|
+
return 0
|
947
|
+
rescue RestClient::Exception => e
|
948
|
+
print_rest_exception(e, options)
|
949
|
+
exit 1
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
953
|
+
def get_task_type(args)
|
954
|
+
params = {}
|
955
|
+
options = {}
|
956
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
957
|
+
opts.banner = subcommand_usage("[type]")
|
958
|
+
build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
959
|
+
opts.footer = "Get details about a task type.\n" +
|
960
|
+
"[type] is required. This is the id or code or name of a task type."
|
961
|
+
end
|
962
|
+
optparse.parse!(args)
|
963
|
+
if args.count != 1
|
964
|
+
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
965
|
+
end
|
966
|
+
connect(options)
|
967
|
+
begin
|
968
|
+
@tasks_interface.setopts(options)
|
969
|
+
if options[:dry_run]
|
970
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
971
|
+
print_dry_run @tasks_interface.dry.get_type(args[0].to_i)
|
972
|
+
else
|
973
|
+
print_dry_run @tasks_interface.dry.list_types({name:args[0]})
|
974
|
+
end
|
975
|
+
return
|
976
|
+
end
|
977
|
+
# find_task_type_by_name actually finds by name or code id
|
978
|
+
task_type = find_task_type_by_name(args[0])
|
979
|
+
return 1 if task_type.nil?
|
980
|
+
json_response = {'taskType' => task_type} # skip redundant request
|
981
|
+
# json_response = @tasks_interface.get(task_type['id'])
|
982
|
+
|
983
|
+
render_result = render_with_format(json_response, options, 'taskType')
|
984
|
+
return 0 if render_result
|
985
|
+
|
986
|
+
task_type = json_response['taskType']
|
987
|
+
|
988
|
+
title = "Morpheus Task Type"
|
989
|
+
|
990
|
+
print_h1 "Morpheus Task Type", [], options
|
991
|
+
|
992
|
+
print cyan
|
993
|
+
description_cols = {
|
994
|
+
"ID" => 'id',
|
995
|
+
"Name" => 'name',
|
996
|
+
"Code" => 'name',
|
997
|
+
#"Description" => 'description',
|
998
|
+
"Scriptable" => lambda {|it| format_boolean(it['scriptable']) },
|
999
|
+
# lots more here
|
1000
|
+
# "enabled" => lambda {|it| format_boolean(it['enabled']) },
|
1001
|
+
# "hasResults" => lambda {|it| format_boolean(it['hasResults']) },
|
1002
|
+
# "allowRemoteKeyAuth" => lambda {|it| format_boolean(it['allowRemoteKeyAuth']) },
|
1003
|
+
# "allowExecuteLocal" => lambda {|it| format_boolean(it['allowExecuteLocal']) },
|
1004
|
+
# "allowExecuteRemote" => lambda {|it| format_boolean(it['allowExecuteRemote']) },
|
1005
|
+
# "allowExecuteResource" => lambda {|it| format_boolean(it['allowExecuteResource']) },
|
1006
|
+
# "allowLocalRepo" => lambda {|it| format_boolean(it['allowLocalRepo']) },
|
1007
|
+
# "allowRemoteKeyAuth" => lambda {|it| format_boolean(it['allowRemoteKeyAuth']) },
|
1008
|
+
}
|
1009
|
+
print_description_list(description_cols, task_type)
|
1010
|
+
|
1011
|
+
option_types = task_type['optionTypes'] || []
|
1012
|
+
option_types = option_types.sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
|
1013
|
+
if !option_types.empty?
|
1014
|
+
print_h2 "Config Option Types", [], options
|
1015
|
+
option_type_cols = {
|
1016
|
+
"Name" => lambda {|it| it['fieldContext'].to_s != '' ? "#{it['fieldContext']}.#{it['fieldName']}" : it['fieldName'] },
|
1017
|
+
"Label" => lambda {|it| it['fieldLabel'] },
|
1018
|
+
"Type" => lambda {|it| it['type'] },
|
1019
|
+
}
|
1020
|
+
print cyan
|
1021
|
+
print as_pretty_table(option_types, option_type_cols)
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
print reset,"\n"
|
1025
|
+
return 0
|
1026
|
+
rescue RestClient::Exception => e
|
1027
|
+
print_rest_exception(e, options)
|
1028
|
+
return 1
|
1029
|
+
end
|
1030
|
+
end
|
1031
|
+
|
764
1032
|
private
|
765
1033
|
|
766
1034
|
def find_task_by_name_or_id(val)
|
@@ -802,7 +1070,7 @@ class Morpheus::Cli::Tasks
|
|
802
1070
|
|
803
1071
|
def find_task_type_by_name(val)
|
804
1072
|
raise "find_task_type_by_name passed a bad name: #{val.inspect}" if val.to_s == ''
|
805
|
-
@all_task_types ||= @tasks_interface.
|
1073
|
+
@all_task_types ||= @tasks_interface.list_types({max:1000})['taskTypes']
|
806
1074
|
|
807
1075
|
if @all_task_types.nil? && !@all_task_types.empty?
|
808
1076
|
print_red_alert "No task types found"
|