morpheus-cli 6.1.2 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,4 @@
1
+
1
2
  require 'morpheus/cli/cli_command'
2
3
 
3
4
  class Morpheus::Cli::BackupsCommand
@@ -5,17 +6,20 @@ class Morpheus::Cli::BackupsCommand
5
6
  include Morpheus::Cli::BackupsHelper
6
7
  include Morpheus::Cli::ProvisioningHelper
7
8
  include Morpheus::Cli::OptionSourceHelper
8
-
9
- set_command_hidden # hide until ready
10
9
 
10
+ set_command_description "View and manage backups"
11
11
  set_command_name :'backups'
12
+ register_subcommands :list, :get, :add, :update, :remove, :execute #, :restore
13
+ register_subcommands :list_jobs, :get_job, :add_job, :update_job, :remove_job, :execute_job
14
+ register_subcommands :list_results, :get_result, :remove_result
15
+ register_subcommands :list_restores, :get_restore, :remove_restore
12
16
 
13
- register_subcommands :list, :get, :add, :update, :remove, :run, :restore
14
-
15
17
  def connect(opts)
16
18
  @api_client = establish_remote_appliance_connection(opts)
17
19
  @backups_interface = @api_client.backups
18
20
  @backup_jobs_interface = @api_client.backup_jobs
21
+ @backup_results_interface = @api_client.backup_results
22
+ @backup_restores_interface = @api_client.backup_restores
19
23
  @instances_interface = @api_client.instances
20
24
  @servers_interface = @api_client.servers
21
25
  end
@@ -40,14 +44,9 @@ class Morpheus::Cli::BackupsCommand
40
44
  options[:phrase] = args.join(" ")
41
45
  end
42
46
  params.merge!(parse_list_options(options))
43
- @backups_interface.setopts(options)
44
- if options[:dry_run]
45
- print_dry_run @backups_interface.dry.list(params)
46
- return
47
- end
48
- json_response = @backups_interface.list(params)
49
- backups = json_response['backups']
50
- render_response(json_response, options, 'backups') do
47
+ parse_options(options, params)
48
+ execute_api(@backups_interface, :list, [], options, 'backup') do |json_response|
49
+ backups = json_response['backups']
51
50
  print_h1 "Morpheus Backups", parse_list_subtitles(options), options
52
51
  if backups.empty?
53
52
  print cyan,"No backups found.",reset,"\n"
@@ -74,6 +73,7 @@ EOT
74
73
  optparse.parse!(args)
75
74
  verify_args!(args:args, optparse:optparse, min:1)
76
75
  connect(options)
76
+ parse_options(options, params)
77
77
  id_list = parse_id_list(args)
78
78
  return run_command_for_each_arg(id_list) do |arg|
79
79
  _get(arg, params, options)
@@ -88,14 +88,10 @@ EOT
88
88
  end
89
89
  id = record['id']
90
90
  end
91
- @backups_interface.setopts(options)
92
- if options[:dry_run]
93
- print_dry_run @backups_interface.dry.get(id, params)
94
- return
95
- end
96
- json_response = @backups_interface.get(id, params)
97
- backup = json_response['backup']
98
- render_response(json_response, options, 'backup') do
91
+ options[:params] = params # parse_options(options, params)
92
+ options.delete(:payload)
93
+ execute_api(@backups_interface, :get, [id], options, 'backup') do |json_response|
94
+ backup = json_response['backup']
99
95
  print_h1 "Backup Details", [], options
100
96
  print cyan
101
97
  columns = backup_column_definitions
@@ -105,7 +101,6 @@ EOT
105
101
  print_description_list(columns, backup, options)
106
102
  print reset,"\n"
107
103
  end
108
- return 0, nil
109
104
  end
110
105
 
111
106
  def add(args)
@@ -113,7 +108,6 @@ EOT
113
108
  params = {}
114
109
  optparse = Morpheus::Cli::OptionParser.new do |opts|
115
110
  opts.banner = subcommand_usage("[name] [options]")
116
- # build_option_type_options(opts, options, add_backup_option_types)
117
111
  opts.on('--source VALUE', String, "Backup Source: instance, host or provider") do |val|
118
112
  options[:options]['source'] = val
119
113
  end
@@ -133,7 +127,8 @@ EOT
133
127
  opts.on('--name VALUE', String, "Name") do |val|
134
128
  options[:options]['name'] = val
135
129
  end
136
- build_standard_add_options(opts, options)
130
+ # build_option_type_options(opts, options, add_backup_option_types)
131
+ build_standard_add_many_options(opts, options)
137
132
  opts.footer = <<-EOT
138
133
  Create a new backup.
139
134
  EOT
@@ -142,13 +137,10 @@ EOT
142
137
  verify_args!(args:args, optparse:optparse, min:0, max:1)
143
138
  options[:options]['name'] = args[0] if args[0]
144
139
  connect(options)
145
- payload = {}
146
- if options[:payload]
147
- payload = options[:payload]
148
- payload.deep_merge!({'backup' => parse_passed_options(options)})
149
- else
150
- payload.deep_merge!({'backup' => parse_passed_options(options)})
151
-
140
+ parse_payload(options, 'backup') do |payload|
141
+ # v_prompt = Morpheus::Cli::OptionTypes.no_prompt(add_backup_option_types, options[:options], @api_client)
142
+ # v_prompt.deep_compact!.booleanize! # remove empty values and convert checkbox "on" and "off" to true and false
143
+ # params.deep_merge!(v_prompt)
152
144
  location_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'fieldLabel' => 'Source', 'type' => 'select', 'selectOptions' => [{'name' => 'Instance', 'value' => 'instance'}, {'name' => 'Host', 'value' => 'server'}, {'name' => 'Provider', 'value' => 'provider'}], 'defaultValue' => 'instance', 'required' => true, 'description' => 'Where is the backup located?'}], options[:options], @api_client)['source']
153
145
  params['locationType'] = location_type
154
146
  if location_type == 'instance'
@@ -183,7 +175,6 @@ EOT
183
175
  end
184
176
  elsif location_type == 'server'
185
177
 
186
-
187
178
  end
188
179
  # Backup Type
189
180
  avail_backup_types = (create_results['backupTypes'] || []).collect {|it| {'name' => it['name'], 'value' => it['code']} }
@@ -197,9 +188,15 @@ EOT
197
188
  params['jobAction'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobAction', 'fieldLabel' => 'Backup Job Type', 'type' => 'select', 'optionSource' => 'backupJobActions', 'required' => true, 'defaultValue' => 'new'}], options[:options], @api_client)['jobAction']
198
189
  if params['jobAction'] == 'new'
199
190
  params['jobName'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobName', 'fieldLabel' => 'Job Name', 'type' => 'text', 'required' => false, 'defaultValue' => nil}], options[:options], @api_client)['jobName']
200
- default_retention_count = create_results['backup'] ? create_results['backup']['retentionCount'] : nil
191
+ default_retention_count = (create_results['backup'] && create_results['backup']['retentionCount']) ? create_results['backup']['retentionCount'] : ((create_results['backupSettings'] && create_results['backupSettings']['retentionCount']) ? create_results['backupSettings']['retentionCount'] : nil)
201
192
  params['retentionCount'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retentionCount', 'fieldLabel' => 'Retention Count', 'type' => 'number', 'required' => false, 'defaultValue' => default_retention_count}], options[:options], @api_client)['retentionCount']
202
- params['jobSchedule'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobSchedule', 'fieldLabel' => 'Backup Schedule', 'type' => 'select', 'optionSource' => 'executeSchedules', 'required' => true}], options[:options], @api_client)['jobSchedule']
193
+ params['jobSchedule'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobSchedule', 'fieldLabel' => 'Backup Schedule', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
194
+ schedules = api_client.options.options_for_source('executeSchedules',{})['data']
195
+ [{"name" => "Manual", "value" => "manual"}] + schedules
196
+ }, 'required' => false}], options[:options], @api_client)['jobSchedule']
197
+ if params['jobSchedule'] == 'manual' || params['jobSchedule'] == ''
198
+ params.delete('jobSchedule')
199
+ end
203
200
  elsif params['jobAction'] == 'clone'
204
201
  params['jobId'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobId', 'fieldLabel' => 'Backup Job', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
205
202
  @backup_jobs_interface.list({max:10000})['jobs'].collect {|backup_job|
@@ -215,21 +212,13 @@ EOT
215
212
  }, 'required' => true}], options[:options], @api_client)['jobId']
216
213
  end
217
214
  end
218
-
219
215
  payload['backup'].deep_merge!(params)
220
216
  end
221
- @backups_interface.setopts(options)
222
- if options[:dry_run]
223
- print_dry_run @backups_interface.dry.create(payload)
224
- return 0, nil
225
- end
226
- json_response = @backups_interface.create(payload)
227
- backup = json_response['backup']
228
- render_response(json_response, options, 'backup') do
217
+ execute_api(@backups_interface, :create, [], options, 'backup') do |json_response|
218
+ backup = json_response['backup']
229
219
  print_green_success "Added backup #{backup['name']}"
230
- return _get(backup["id"], {}, options)
220
+ _get(backup["id"], {}, options)
231
221
  end
232
- return 0, nil
233
222
  end
234
223
 
235
224
  def update(args)
@@ -238,8 +227,16 @@ EOT
238
227
  payload = {}
239
228
  optparse = Morpheus::Cli::OptionParser.new do |opts|
240
229
  opts.banner = subcommand_usage("[backup] [options]")
230
+ # opts.on('--name NAME', String, "Name") do |val|
231
+ # options[:options]['name'] = val
232
+ # end
233
+ # opts.on('--job JOB', String, "Name or ID of the Backup Job to associate this backup with") do |val|
234
+ # options[:options]['jobId'] = val
235
+ # end
236
+ # opts.on('--enabled [on|off]', String, "Can be used to disable") do |val|
237
+ # options[:options]['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s.empty?
238
+ # end
241
239
  build_option_type_options(opts, options, update_backup_option_types)
242
- build_option_type_options(opts, options, update_backup_advanced_option_types)
243
240
  build_standard_update_options(opts, options)
244
241
  opts.footer = <<-EOT
245
242
  Update a backup.
@@ -251,36 +248,21 @@ EOT
251
248
  connect(options)
252
249
  backup = find_backup_by_name_or_id(args[0])
253
250
  return 1 if backup.nil?
254
- payload = {}
255
- if options[:payload]
256
- payload = options[:payload]
257
- payload.deep_merge!({'backup' => parse_passed_options(options)})
258
- else
259
- payload.deep_merge!({'backup' => parse_passed_options(options)})
251
+ parse_payload(options, 'backup') do |payload|
260
252
  # do not prompt on update
261
- v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_backup_option_types, options[:options], @api_client, options[:params])
262
- v_prompt.deep_compact!
253
+ v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_backup_option_types, options[:options], @api_client)
254
+ v_prompt.deep_compact!.booleanize! # remove empty values and convert checkbox "on" and "off" to true and false
263
255
  params.deep_merge!(v_prompt)
264
- advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_backup_advanced_option_types, options[:options], @api_client, options[:params])
265
- advanced_config.deep_compact!
266
- params.deep_merge!(advanced_config)
267
256
  payload.deep_merge!({'backup' => params})
268
257
  if payload['backup'].empty? # || options[:no_prompt]
269
258
  raise_command_error "Specify at least one option to update.\n#{optparse}"
270
259
  end
271
260
  end
272
- @backups_interface.setopts(options)
273
- if options[:dry_run]
274
- print_dry_run @backups_interface.dry.update(backup['id'], payload)
275
- return
276
- end
277
- json_response = @backups_interface.update(backup['id'], payload)
278
- backup = json_response['backup']
279
- render_response(json_response, options, 'backup') do
261
+ execute_api(@backups_interface, :update, [backup['id']], options, 'backup') do |json_response|
262
+ backup = json_response['backup']
280
263
  print_green_success "Updated backup #{backup['name']}"
281
264
  return _get(backup["id"], {}, options)
282
265
  end
283
- return 0, nil
284
266
  end
285
267
 
286
268
  def remove(args)
@@ -299,23 +281,169 @@ EOT
299
281
  connect(options)
300
282
  backup = find_backup_by_name_or_id(args[0])
301
283
  return 1 if backup.nil?
302
- @backups_interface.setopts(options)
303
- if options[:dry_run]
304
- print_dry_run @backups_interface.dry.destroy(backup['id'], params)
305
- return
284
+ parse_options(options, params)
285
+ confirm!("Are you sure you want to delete the backup #{backup['name']}?", options)
286
+ execute_api(@backups_interface, :destroy, [backup['id']], options, 'backup') do |json_response|
287
+ print_green_success "Removed backup #{backup['name']}"
306
288
  end
307
- unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the backup #{backup['name']}?")
308
- return 9, "aborted command"
289
+ end
290
+
291
+ def execute(args)
292
+ options = {}
293
+ params = {}
294
+ payload = {}
295
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
296
+ opts.banner = subcommand_usage("[backup] [options]")
297
+ build_standard_post_options(opts, options)
298
+ opts.footer = <<-EOT
299
+ Execute a backup to create a new backup result.
300
+ [backup] is required. This is the name or id of a backup.
301
+ EOT
309
302
  end
310
- json_response = @backups_interface.destroy(backup['id'], params)
311
- render_response(json_response, options) do
312
- print_green_success "Removed backup #{backup['name']}"
303
+ optparse.parse!(args)
304
+ verify_args!(args:args, optparse:optparse, count:1)
305
+ connect(options)
306
+ backup = find_backup_by_name_or_id(args[0])
307
+ return 1 if backup.nil?
308
+ parse_payload(options)
309
+ execute_api(@backups_interface, :execute_backup, [backup['id']], options, 'backup') do |json_response|
310
+ print_green_success "Executing backup #{backup['name']}"
311
+ # should get the result maybe, or could even support refreshing until it is complete...
312
+ # return _get(backup["id"], {}, options)
313
+ end
314
+ end
315
+
316
+ def restore(args)
317
+ raise "Not Yet Implemented"
318
+ options = {}
319
+ params = {}
320
+ payload = {}
321
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
322
+ opts.banner = subcommand_usage("[backup] [result] [options]")
323
+ build_standard_post_options(opts, options)
324
+ opts.on('--result ID', String, "Backup Result ID that is being restored") do |val|
325
+ options[:options]['backupResultId'] = val
326
+ end
327
+ opts.on('--restore-instance existing|new', String, "Instance being targeted for the restore, existing to restore the current instance or new to create a new instance. The current instance is targeted by default.") do |val|
328
+ # restoreInstanceSelect=current|new and the flag on the restore object is called 'restoreToNew'
329
+ options[:options]['restoreInstanceSelect'] = val
330
+ end
331
+ opts.footer = <<-EOT
332
+ Restore a backup, replacing the existing target with the specified backup result.
333
+ [backup] is required. This is the name or id of a backup.
334
+ --result ID is required. This is the id of a backup result being restored.
335
+ EOT
336
+ end
337
+ optparse.parse!(args)
338
+ verify_args!(args:args, optparse:optparse, max:1)
339
+ connect(options)
340
+ backup = nil
341
+ backup_result = nil
342
+ if args[0]
343
+ backup = find_backup_by_name_or_id(args[0])
344
+ return 1 if backup.nil?
345
+ else
346
+ # Prompt for backup
347
+ if backup.nil?
348
+ # Backup
349
+ available_backups = @backups_interface.list({max:10000})['backups'].collect {|it| {'name' => it['name'], 'value' => it['id']}}
350
+ backup_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'backupId', 'fieldLabel' => 'Backup', 'type' => 'select', 'selectOptions' => available_backups, 'required' => true}], options[:options], @api_client)['backupId']
351
+ backup = find_backup_by_name_or_id(backup_id)
352
+ return 1 if backup.nil?
353
+ end
354
+ end
355
+ # Prompt for backup result
356
+ if backup_result.nil?
357
+
358
+ # Instance
359
+ available_backup_results = @backups_interface.list({backupId: backup['id'], max:10000})['results'].collect {|it| {'name' => it['name'], 'value' => it['id']}}
360
+ params['backupResultId'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'backupResultId', 'fieldLabel' => 'Backup Result', 'type' => 'select', 'selectOptions' => available_backup_results, 'required' => true}], options[:options], @api_client)['backupResultId']
361
+ # Name
362
+ params['name'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Backup Name'}], options[:options], @api_client)['name']
363
+ end
364
+
365
+ parse_payload(options, 'restore') do |payload|
366
+ # Prompt for restore configuration
367
+ # We should probably require identifying the instance by name or id too, just to be safe.
368
+ # Target Instance
369
+ if backup_result['instance']
370
+ params['restoreInstanceSelect'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Instance being targeted for the restore, existing to restore the current instance or new to create a new instance. By default the existing instance is restored.'}], options[:options], @api_client)['restoreInstanceSelect']
371
+ end
372
+ payload['backup'].deep_merge!(params)
373
+ end
374
+
375
+ print cyan,"#{bold}WARNING!#{reset}#{cyan} Restoring a backup will erase all data when restored to an existing instance.",reset,"\n"
376
+ confirm!("Are you sure you want to restore the backup result ID: #{backup_result['id']} Name: #{backup_result['backup']['name'] rescue ''} Date: (#{format_local_dt(backup_result['dateCreated'])})?", options)
377
+ execute_api(@backups_interface, :restore, [backup['id']], options, 'backup') do |json_response|
378
+ print_green_success "Restoring backup result ID: #{backup_result['id']} Name: #{backup_result['backup']['name'] rescue ''} Date: (#{format_local_dt(backup_result['dateCreated'])}"
379
+ # should get the restore maybe, or could even support refreshing until it is complete...
380
+ # restore = json_response["restore"]
381
+ # return _get_restore(restore["id"], {}, options)
313
382
  end
314
- return 0, nil
383
+ end
384
+
385
+ # Delegate jobs, results and restores
386
+ # to backup-jobs, backup-results and backup-restores
387
+ # which are hidden in the docs
388
+
389
+ ## Backup Jobs
390
+
391
+ def list_jobs(args)
392
+ Morpheus::Cli::BackupJobsCommand.new.list(args)
393
+ end
394
+
395
+ def get_job(args)
396
+ Morpheus::Cli::BackupJobsCommand.new.get(args)
397
+ end
398
+
399
+ def add_job(args)
400
+ Morpheus::Cli::BackupJobsCommand.new.add(args)
401
+ end
402
+
403
+ def update_job(args)
404
+ Morpheus::Cli::BackupJobsCommand.new.update(args)
405
+ end
406
+
407
+ def remove_job(args)
408
+ Morpheus::Cli::BackupJobsCommand.new.remove(args)
409
+ end
410
+
411
+ def execute_job(args)
412
+ Morpheus::Cli::BackupJobsCommand.new.execute(args)
413
+ end
414
+
415
+ ## Backup Results
416
+
417
+ def list_results(args)
418
+ Morpheus::Cli::BackupResultsCommand.new.list(args)
419
+ end
420
+
421
+ def get_result(args)
422
+ Morpheus::Cli::BackupResultsCommand.new.get(args)
423
+ end
424
+
425
+ def remove_result(args)
426
+ Morpheus::Cli::BackupResultsCommand.new.remove(args)
427
+ end
428
+
429
+ ## Backup Restores
430
+
431
+ def list_restores(args)
432
+ Morpheus::Cli::BackupRestoresCommand.new.list(args)
433
+ end
434
+
435
+ def get_restore(args)
436
+ Morpheus::Cli::BackupRestoresCommand.new.get(args)
437
+ end
438
+
439
+ def remove_restore(args)
440
+ Morpheus::Cli::BackupRestoresCommand.new.remove(args)
315
441
  end
316
442
 
317
443
  private
318
444
 
445
+ ## Backups
446
+
319
447
  def backup_list_column_definitions()
320
448
  {
321
449
  "ID" => 'id',
@@ -345,12 +473,13 @@ EOT
345
473
  "Host" => lambda {|it| it['server']['name'] rescue '' },
346
474
  "Schedule" => lambda {|it| it['schedule']['name'] rescue '' },
347
475
  "Backup Job" => lambda {|it| it['job']['name'] rescue '' },
476
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
348
477
  "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
349
478
  "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
350
479
  }
351
480
  end
352
481
 
353
- # this is not so simple, need to first choose select instance, host or provider
482
+ # not used atm, this is not so simple, need to first choose select instance, host or provider
354
483
  def add_backup_option_types
355
484
  [
356
485
  {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
@@ -364,24 +493,16 @@ EOT
364
493
  ]
365
494
  end
366
495
 
367
- def add_backup_advanced_option_types
368
- []
369
- end
370
-
371
496
  def update_backup_option_types
372
- add_backup_option_types.collect {|it|
373
- it.delete('required')
374
- it.delete('defaultValue')
375
- it
376
- }
377
- end
378
-
379
- def update_backup_advanced_option_types
380
- add_backup_advanced_option_types.collect {|it|
381
- it.delete('required')
382
- it.delete('defaultValue')
383
- it
384
- }
497
+ [
498
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text'},
499
+ {'fieldName' => 'jobId', 'fieldLabel' => 'Backup Job', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
500
+ @backup_jobs_interface.list({max:10000})['jobs'].collect {|backup_job|
501
+ {'name' => backup_job['name'], 'value' => backup_job['id'], 'id' => backup_job['id']}
502
+ }
503
+ } },
504
+ {'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox'},
505
+ ]
385
506
  end
386
507
 
387
508
  end
@@ -1500,8 +1500,19 @@ class Morpheus::Cli::Hosts
1500
1500
  params = {}
1501
1501
  options = {}
1502
1502
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1503
- opts.banner = subcommand_usage("[name] [workflow] [options]")
1503
+ opts.banner = subcommand_usage("[host] [workflow] [options]")
1504
+ opts.on("--phase PHASE", String, "Task Phase to run for Provisioning workflows. The default is provision.") do |val|
1505
+ options[:phase] = val
1506
+ end
1504
1507
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
1508
+ opts.footer = <<-EOT
1509
+ Run workflow for a host.
1510
+ [host] is required. This is the name or id of a host
1511
+ [workflow] is required. This is the name or id of a workflow
1512
+ By default the provision phase is executed.
1513
+ Use the --phase option to execute a different phase.
1514
+ The available phases are start, stop, preProvision, provision, postProvision, preDeploy, deploy, reconfigure, teardown, startup and shutdown.
1515
+ EOT
1505
1516
  end
1506
1517
  optparse.parse!(args)
1507
1518
  if args.count != 2
@@ -1555,7 +1566,9 @@ class Morpheus::Cli::Hosts
1555
1566
  payload['taskSet']["#{workflow['id']}"] ||= {}
1556
1567
  payload['taskSet']["#{workflow['id']}"].deep_merge!(params)
1557
1568
  end
1558
-
1569
+ if options[:phase]
1570
+ payload['taskPhase'] = options[:phase]
1571
+ end
1559
1572
  begin
1560
1573
  @servers_interface.setopts(options)
1561
1574
  if options[:dry_run]
@@ -258,7 +258,7 @@ class Morpheus::Cli::Instances
258
258
  end
259
259
  row = {
260
260
  id: instance['id'],
261
- name: instance['name'],
261
+ name: instance['displayName'] ? instance['displayName'] : instance['name'],
262
262
  labels: format_list(instance['labels'], '', 3),
263
263
  connection: format_instance_connection_string(instance),
264
264
  environment: instance['instanceContext'],
@@ -3357,7 +3357,18 @@ EOT
3357
3357
  options = {}
3358
3358
  optparse = Morpheus::Cli::OptionParser.new do |opts|
3359
3359
  opts.banner = subcommand_usage("[instance] [workflow] [options]")
3360
+ opts.on("--phase PHASE", String, "Task Phase to run for Provisioning workflows. The default is provision.") do |val|
3361
+ options[:phase] = val
3362
+ end
3360
3363
  build_common_options(opts, options, [:options, :json, :dry_run, :remote])
3364
+ opts.footer = <<-EOT
3365
+ Run workflow for an instance.
3366
+ [instance] is required. This is the name or id of an instance
3367
+ [workflow] is required. This is the name or id of a workflow
3368
+ By default the provision phase is executed.
3369
+ Use the --phase option to execute a different phase.
3370
+ The available phases are start, stop, preProvision, provision, postProvision, preDeploy, deploy, reconfigure, teardown, startup and shutdown.
3371
+ EOT
3361
3372
  end
3362
3373
  optparse.parse!(args)
3363
3374
  if args.count != 2
@@ -3391,6 +3402,9 @@ EOT
3391
3402
  # end
3392
3403
 
3393
3404
  workflow_payload = {taskSet: {"#{workflow['id']}" => params }}
3405
+ if options[:phase]
3406
+ workflow_payload['taskPhase'] = options[:phase]
3407
+ end
3394
3408
  begin
3395
3409
  @instances_interface.setopts(options)
3396
3410
  if options[:dry_run]
@@ -5298,6 +5312,7 @@ private
5298
5312
  rescue RestClient::Exception => e
5299
5313
  if e.response && e.response.code == 404
5300
5314
  print_red_alert "Workflow not found by id #{id}"
5315
+ exit 1
5301
5316
  else
5302
5317
  raise e
5303
5318
  end
@@ -5308,12 +5323,12 @@ private
5308
5323
  workflows = @task_sets_interface.list({name: name.to_s})['taskSets']
5309
5324
  if workflows.empty?
5310
5325
  print_red_alert "Workflow not found by name #{name}"
5311
- return nil
5326
+ exit 1
5312
5327
  elsif workflows.size > 1
5313
5328
  print_red_alert "#{workflows.size} workflows by name #{name}"
5314
5329
  print_workflows_table(workflows, {color: red})
5315
5330
  print reset,"\n\n"
5316
- return nil
5331
+ exit 1
5317
5332
  else
5318
5333
  return workflows[0]
5319
5334
  end