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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +4 -0
  4. data/lib/morpheus/api/library_container_types_interface.rb +1 -1
  5. data/lib/morpheus/api/library_instance_types_interface.rb +7 -7
  6. data/lib/morpheus/api/library_layouts_interface.rb +1 -1
  7. data/lib/morpheus/api/network_routers_interface.rb +101 -0
  8. data/lib/morpheus/api/tasks_interface.rb +12 -14
  9. data/lib/morpheus/cli.rb +1 -0
  10. data/lib/morpheus/cli/apps.rb +15 -12
  11. data/lib/morpheus/cli/cli_command.rb +40 -2
  12. data/lib/morpheus/cli/clusters.rb +13 -7
  13. data/lib/morpheus/cli/cypher_command.rb +5 -2
  14. data/lib/morpheus/cli/hosts.rb +1 -1
  15. data/lib/morpheus/cli/instances.rb +21 -5
  16. data/lib/morpheus/cli/jobs_command.rb +83 -27
  17. data/lib/morpheus/cli/library_cluster_layouts_command.rb +12 -12
  18. data/lib/morpheus/cli/library_container_scripts_command.rb +52 -40
  19. data/lib/morpheus/cli/library_container_types_command.rb +2 -60
  20. data/lib/morpheus/cli/library_instance_types_command.rb +22 -1
  21. data/lib/morpheus/cli/library_layouts_command.rb +65 -65
  22. data/lib/morpheus/cli/library_option_lists_command.rb +72 -59
  23. data/lib/morpheus/cli/library_option_types_command.rb +30 -186
  24. data/lib/morpheus/cli/library_spec_templates_command.rb +39 -64
  25. data/lib/morpheus/cli/mixins/library_helper.rb +213 -0
  26. data/lib/morpheus/cli/mixins/provisioning_helper.rb +89 -37
  27. data/lib/morpheus/cli/mixins/whoami_helper.rb +16 -1
  28. data/lib/morpheus/cli/network_routers_command.rb +1281 -0
  29. data/lib/morpheus/cli/networks_command.rb +164 -72
  30. data/lib/morpheus/cli/option_types.rb +187 -73
  31. data/lib/morpheus/cli/price_sets_command.rb +4 -4
  32. data/lib/morpheus/cli/prices_command.rb +15 -15
  33. data/lib/morpheus/cli/remote.rb +3 -3
  34. data/lib/morpheus/cli/service_plans_command.rb +17 -8
  35. data/lib/morpheus/cli/tasks.rb +437 -169
  36. data/lib/morpheus/cli/version.rb +1 -1
  37. data/lib/morpheus/formatters.rb +8 -0
  38. 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' => 'code', 'type' => 'text', 'fieldLabel' => 'Price Set Region Code', 'required' => false, 'description' => 'Price Set Region Code.'}],options[:options],@api_client,{}, options[:no_prompt])['code']
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' => 'value', '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)['value']
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' => 'value', '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)['value']
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 Set Name', 'required' => true, 'description' => 'Price Set Name.'}],options[:options],@api_client,{}, options[:no_prompt])['name']
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 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']
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' => 'value', '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])['value']
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' => 'value', '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])['value']
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' => 'value', '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])['value']
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' => 'value', '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])['value']
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' => 'value', 'type' => 'number', 'fieldLabel' => 'Cost', 'required' => true, 'description' => 'Price cost', 'defaultValue' => 0.0}],options[:options],@api_client,{}, options[:no_prompt])['value']
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' => 'value', '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])['value']
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' => 'value', '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])['value']
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' => 'value', 'type' => 'text', 'fieldLabel' => 'Software', 'required' => true, 'description' => 'Set software for software price type'}], options[:options], @api_client,{}, options[:no_prompt])['value']
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' => 'value', '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])['value']
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' => 'value', '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)['value'])
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' => 'value', 'type' => 'number', 'fieldLabel' => 'Markup Percent', 'required' => true, 'description' => 'Markup Percent'}],options[:options],@api_client,{}, options[:no_prompt])['value']
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' => 'value', 'type' => 'number', 'fieldLabel' => 'Markup Amount', 'required' => true, 'description' => 'Markup Amount'}],options[:options],@api_client,{}, options[:no_prompt])['value']
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' => 'value', 'type' => 'number', 'fieldLabel' => 'Price', 'required' => true, 'description' => 'Price'}],options[:options],@api_client,{}, options[:no_prompt])['value']
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
@@ -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
- v_prompt = Morpheus::Cli::OptionTypes.prompt(password_option_types, options[:options])
1111
- if v_prompt['password'] == v_prompt['confirmPassword']
1112
- payload.deep_merge!(v_prompt)
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
- payload = parse_payload(options)
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
- payload = parse_payload(options)
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
- print_green_success "Nothing to update"
605
- exit 1
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)
@@ -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, :types => :task_types
11
- alias_subcommand :details, :get
12
- alias_subcommand :'task-types', :task_types
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('--types x,y,z', Array, "Filter by task type code(s)") do |val|
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.get(params)
45
+ print_dry_run @tasks_interface.dry.list(params)
44
46
  return
45
47
  end
46
- json_response = @tasks_interface.get(params)
47
- # print result and return output
48
- if options[:json]
49
- puts as_json(json_response, options, "tasks")
50
- return 0
51
- elsif options[:csv]
52
- puts records_as_csv(json_response['tasks'], options)
53
- return 0
54
- elsif options[:yaml]
55
- puts as_yaml(json_response, options, "tasks")
56
- return 0
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
- title = "Morpheus Tasks"
59
- subtitles = []
60
- subtitles += parse_list_subtitles(options)
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
- puts optparse
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
- print_h2 "Script"
178
- print reset,bright_black,"#{task['taskOptions'][optionType['fieldName']]}","\n",reset
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
- print cyan,("#{optionType['fieldLabel']} : " + (optionType['type'] == 'password' ? "#{task['taskOptions'][optionType['fieldName']] ? '************' : ''}" : "#{task['taskOptions'][optionType['fieldName']] || optionType['defaultValue']}")),"\n"
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
- print reset,"\n"
187
- return 0
188
- end
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
- else
250
- print_green_success "Task #{response['task']['name']} updated"
251
- get([task['id']])
252
- end
253
- return 0
254
- rescue RestClient::Exception => e
255
- print_rest_exception(e, options)
256
- return 1
257
- end
258
- end
259
-
260
-
261
- def task_types(args)
262
- options = {}
263
- optparse = Morpheus::Cli::OptionParser.new do |opts|
264
- opts.banner = subcommand_usage()
265
- build_common_options(opts, options, [:json, :dry_run, :remote])
266
- end
267
- optparse.parse!(args)
268
- connect(options)
269
- begin
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
- options = {:options => {}}
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.task_types({max:1000})['taskTypes']
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
- # JD: uhh some of these are missing a fieldContext?
462
- # containerScript just points to a library script via Id now??
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['fieldContext'].nil? || it['fieldContext'] == ''
466
- it['fieldContext'] = 'taskOptions'
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
- # Git Repo
500
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'localScriptGitId', 'fieldLabel' => 'Git Repo', 'type' => 'text', 'description' => 'Git Repo ID'}], options[:options], @api_client)
501
- if v_prompt['taskOptions'] && !v_prompt['taskOptions']['localScriptGitId'].to_s.empty?
502
- payload['task']['taskOptions'] ||= {}
503
- payload['task']['taskOptions']['localScriptGitId'] = v_prompt['taskOptions']['localScriptGitId']
504
- end
505
- # Git Ref
506
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'taskOptions', 'fieldName' => 'localScriptGitRef', 'fieldLabel' => 'Git Ref', 'type' => 'text', 'description' => 'Git Ref eg. master'}], options[:options], @api_client)
507
- if v_prompt['taskOptions'] && !v_prompt['taskOptions']['localScriptGitRef'].to_s.empty?
508
- payload['task']['taskOptions'] ||= {}
509
- payload['task']['taskOptions']['localScriptGitRef'] = v_prompt['taskOptions']['localScriptGitRef']
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.task_types({max:1000})['taskTypes']
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"