vcoworkflows 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +9 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +203 -0
- data/README.md +290 -0
- data/Rakefile +21 -0
- data/bin/vcoworkflows +7 -0
- data/example.rb +45 -0
- data/lib/vcoworkflows.rb +34 -0
- data/lib/vcoworkflows/cli/auth.rb +27 -0
- data/lib/vcoworkflows/cli/execute.rb +109 -0
- data/lib/vcoworkflows/cli/query.rb +106 -0
- data/lib/vcoworkflows/constants.rb +44 -0
- data/lib/vcoworkflows/runner.rb +44 -0
- data/lib/vcoworkflows/vcosession.rb +48 -0
- data/lib/vcoworkflows/version.rb +4 -0
- data/lib/vcoworkflows/workflow.rb +304 -0
- data/lib/vcoworkflows/workflowexecutionlog.rb +40 -0
- data/lib/vcoworkflows/workflowparameter.rb +145 -0
- data/lib/vcoworkflows/workflowpresentation.rb +59 -0
- data/lib/vcoworkflows/workflowservice.rb +110 -0
- data/lib/vcoworkflows/workflowtoken.rb +111 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/vcoworkflows/vcosession_spec.rb +33 -0
- data/spec/vcoworkflows/workflow_spec.rb +144 -0
- data/spec/vcoworkflows/workflowexecutionlog_spec.rb +22 -0
- data/spec/vcoworkflows/workflowparameter_spec.rb +67 -0
- data/spec/vcoworkflows/workflowpresentation_spec.rb +34 -0
- data/spec/vcoworkflows/workflowservice_spec.rb +113 -0
- data/spec/vcoworkflows/workflowtoken_spec.rb +64 -0
- data/vcoworkflows.gemspec +39 -0
- metadata +257 -0
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'cucumber/rake/task'
|
4
|
+
require 'coveralls/rake/task'
|
5
|
+
require 'yard'
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
|
+
Cucumber::Rake::Task.new(:features)
|
10
|
+
Coveralls::RakeTask.new
|
11
|
+
|
12
|
+
task :style do
|
13
|
+
sh 'rubocop'
|
14
|
+
end
|
15
|
+
|
16
|
+
task :doc do
|
17
|
+
sh 'yard'
|
18
|
+
end
|
19
|
+
|
20
|
+
# task default: [:spec, :features, :style, :doc, 'coveralls:push']
|
21
|
+
task default: [:spec, :style, :doc, 'coveralls:push']
|
data/bin/vcoworkflows
ADDED
data/example.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'vcoworkflows'
|
4
|
+
|
5
|
+
# What am I connecting to?
|
6
|
+
url = 'https://myvco.example.com:8281/vco/api'
|
7
|
+
username = 'myuser'
|
8
|
+
password = 'secret!'
|
9
|
+
|
10
|
+
# What's the workflow I want to work with?
|
11
|
+
workflow_name = 'Do Something Cool'
|
12
|
+
|
13
|
+
# Define the parameters for the workflow which we need to supply.
|
14
|
+
# The 'Do Something Cool' workflow needs a name, version, and words (an array
|
15
|
+
# of strings).
|
16
|
+
input_parameters = { 'name' => 'a string value',
|
17
|
+
'version' => '2',
|
18
|
+
'words' => %w(fe fi fo fum) }
|
19
|
+
|
20
|
+
# Fetch the workflow from vCO
|
21
|
+
workflow = VcoWorkflows::Workflow.new(workflow_name,
|
22
|
+
url: url,
|
23
|
+
username: username,
|
24
|
+
password: password,
|
25
|
+
verify_ssl: false)
|
26
|
+
|
27
|
+
# Set the parameters in the workflow
|
28
|
+
input_parameters.each { |k, v| workflow.set_parameter(k, v) }
|
29
|
+
|
30
|
+
# Execute the workflow.
|
31
|
+
workflow.execute
|
32
|
+
|
33
|
+
# We're going to wait around until the execution is done, so we'll check
|
34
|
+
# on it every 5 seconds until we see whether it completed or failed.
|
35
|
+
finished = false
|
36
|
+
until finished
|
37
|
+
sleep 5
|
38
|
+
# Fetch a new workflow token to check the status of the workflow execution
|
39
|
+
wftoken = workflow.token
|
40
|
+
# If the execution is no longer alive, exit the loop and report the results.
|
41
|
+
unless wftoken.alive?
|
42
|
+
finished = true
|
43
|
+
wftoken.output_parameters.each { |k, v| puts " #{k}: #{v}" }
|
44
|
+
end
|
45
|
+
end
|
data/lib/vcoworkflows.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/vcoworkflows/version'
|
4
|
+
require File.dirname(__FILE__) + '/vcoworkflows/constants'
|
5
|
+
require File.dirname(__FILE__) + '/vcoworkflows/vcosession'
|
6
|
+
require File.dirname(__FILE__) + '/vcoworkflows/workflowservice'
|
7
|
+
require File.dirname(__FILE__) + '/vcoworkflows/workflow'
|
8
|
+
require File.dirname(__FILE__) + '/vcoworkflows/workflowparameter'
|
9
|
+
require File.dirname(__FILE__) + '/vcoworkflows/workflowtoken'
|
10
|
+
require File.dirname(__FILE__) + '/vcoworkflows/cli/execute'
|
11
|
+
require File.dirname(__FILE__) + '/vcoworkflows/cli/query'
|
12
|
+
|
13
|
+
# rubocop:disable LineLength
|
14
|
+
|
15
|
+
# Refer to README.md for use instructions
|
16
|
+
module VcoWorkflows
|
17
|
+
# Start of main CLI processing
|
18
|
+
class CLI < Thor
|
19
|
+
package_name 'vcoworkflows'
|
20
|
+
map '--version' => :version
|
21
|
+
map '-v' => :version
|
22
|
+
|
23
|
+
desc 'version', DESC_VERSION
|
24
|
+
|
25
|
+
# Display the version of `vcoworkflows`
|
26
|
+
def version
|
27
|
+
puts VERSION
|
28
|
+
end
|
29
|
+
|
30
|
+
register(VcoWorkflows::Cli::Execute, 'execute', 'execute <WORKFLOW>', DESC_CLI_EXECUTE)
|
31
|
+
register(VcoWorkflows::Cli::Query, 'query', 'query <WORKFLOW>', DESC_CLI_QUERY)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
# rubocop:enable LineLength
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'vcoworkflows/constants'
|
2
|
+
|
3
|
+
# VcoWorkflows
|
4
|
+
module VcoWorkflows
|
5
|
+
# Cli
|
6
|
+
module Cli
|
7
|
+
# Auth
|
8
|
+
class Auth
|
9
|
+
attr_reader :username
|
10
|
+
attr_reader :password
|
11
|
+
|
12
|
+
# Initialize the Auth object
|
13
|
+
# @param [String] username
|
14
|
+
# @param [String] password
|
15
|
+
def initialize(username: nil, password: nil)
|
16
|
+
# Set username and password from parameters, if provided, or
|
17
|
+
# environment variables $VCO_USER and $VCO_PASSWD, if not.
|
18
|
+
@username = username.nil? ? ENV['VCO_USER'] : username
|
19
|
+
@password = password.nil? ? ENV['VCO_PASSWD'] : password
|
20
|
+
|
21
|
+
# Fail if we don't have both a username and a password.
|
22
|
+
fail(IOError, ERR[:username_unset]) if @username.nil?
|
23
|
+
fail(IOError, ERR[:password_unset]) if @password.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'vcoworkflows'
|
2
|
+
require_relative 'auth'
|
3
|
+
require 'thor/group'
|
4
|
+
|
5
|
+
# rubocop:disable MethodLength, LineLength
|
6
|
+
|
7
|
+
# VcoWorkflows
|
8
|
+
module VcoWorkflows
|
9
|
+
# Cli
|
10
|
+
module Cli
|
11
|
+
# Execute
|
12
|
+
class Execute < Thor::Group
|
13
|
+
include Thor::Actions
|
14
|
+
|
15
|
+
argument :workflow, type: :string, desc: DESC_CLI_WORKFLOW
|
16
|
+
class_option :server, type: :string, aliases: '-s', required: true, desc: DESC_CLI_SERVER
|
17
|
+
class_option :username, type: :string, aliases: '-u', desc: DESC_CLI_USERNAME
|
18
|
+
class_option :password, type: :string, aliases: '-p', desc: DESC_CLI_PASSWORD
|
19
|
+
class_option :id, type: :string, aliases: '-i', desc: DESC_CLI_WORKFLOW_ID
|
20
|
+
class_option :verify_ssl, type: :boolean, default: true, desc: DESC_CLI_VERIFY_SSL
|
21
|
+
class_option :dry_run, type: :boolean, default: false, desc: DESC_CLI_DRY_RUN
|
22
|
+
class_option :verbose, type: :boolean, default: true, desc: DESC_CLI_VERBOSE
|
23
|
+
class_option :watch, type: :boolean, default: true, desc: DESC_CLI_EXECUTE_WATCH
|
24
|
+
|
25
|
+
class_option :parameters, type: :string, required: true, desc: DESC_CLI_EXECUTE_PARAMETERS
|
26
|
+
|
27
|
+
def self.source_root
|
28
|
+
File.dirname(__FILE__)
|
29
|
+
end
|
30
|
+
|
31
|
+
# rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
32
|
+
def execute
|
33
|
+
auth = VcoWorkflows::Cli::Auth.new(username: options[:username], password: options[:password])
|
34
|
+
|
35
|
+
# Parse out the parameters
|
36
|
+
parameters = {}
|
37
|
+
options[:parameters].split(/,/).each do |p|
|
38
|
+
k, v = p.split(/=/)
|
39
|
+
parameters[k] = v
|
40
|
+
end
|
41
|
+
if parameters.key?('runlist')
|
42
|
+
parameters['runlist'] = parameters['runlist'].split(/:/)
|
43
|
+
end
|
44
|
+
|
45
|
+
puts "Executing against vCO REST endpoint: #{options[:server]}"
|
46
|
+
puts "Requested execution of workflow: '#{workflow}'"
|
47
|
+
puts "Will call workflow by GUID (#{options[:id]})" if options[:id]
|
48
|
+
if options[:verbose] || options[:dry_run]
|
49
|
+
puts 'Parameters:'
|
50
|
+
parameters.each do |k, v|
|
51
|
+
v = v.join(',') if v.is_a?(Array)
|
52
|
+
puts " - #{k}: #{v}"
|
53
|
+
end
|
54
|
+
puts ''
|
55
|
+
end
|
56
|
+
|
57
|
+
return if options[:dry_run]
|
58
|
+
|
59
|
+
# Get the workflow
|
60
|
+
puts "Retrieving workflow '#{workflow}' ..."
|
61
|
+
wf = VcoWorkflows::Workflow.new(workflow,
|
62
|
+
url: options[:server],
|
63
|
+
username: auth.username,
|
64
|
+
password: auth.password,
|
65
|
+
verify_ssl: options[:verify_ssl],
|
66
|
+
id: options[:id])
|
67
|
+
|
68
|
+
# List out mandatory parameters
|
69
|
+
puts "Required parameters:\n #{wf.required_parameters.keys.join(', ')}"
|
70
|
+
|
71
|
+
# Set the input parameters
|
72
|
+
puts 'Setting workflow input parameters...' if options[:verbose]
|
73
|
+
parameters.each do |k, v|
|
74
|
+
puts "setting #{k} to #{v}" if options[:verbose]
|
75
|
+
wf.set_parameter(k, v)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Execute the workflow
|
79
|
+
puts 'Executing workflow...'
|
80
|
+
wf.execute
|
81
|
+
|
82
|
+
# Fetch the results
|
83
|
+
wftoken = wf.token
|
84
|
+
puts "#{wftoken.id} started at #{Time.at(wftoken.start_date / 1000)}"
|
85
|
+
|
86
|
+
# If we don't care about the results, move on.
|
87
|
+
return unless options[:watch]
|
88
|
+
|
89
|
+
# Check for update results until we get one who's state
|
90
|
+
# is not "running" or "waiting"
|
91
|
+
puts "\nChecking status...\n"
|
92
|
+
while wftoken.alive?
|
93
|
+
sleep 10
|
94
|
+
wftoken = wf.token
|
95
|
+
puts "#{Time.now} state: #{wftoken.state}"
|
96
|
+
end
|
97
|
+
puts "\nFinal status of execution:"
|
98
|
+
puts wftoken
|
99
|
+
|
100
|
+
# Print out the execution log
|
101
|
+
puts "\nWorkflow #{wf.name} log for execution #{wftoken.id}:"
|
102
|
+
log = wf.log(wftoken.id)
|
103
|
+
puts "\n#{log}"
|
104
|
+
end
|
105
|
+
# rubocop:enable CyclomaticComplexity, PerceivedComplexity
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
# rubocop:enable MethodLength, LineLength
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'vcoworkflows'
|
2
|
+
require_relative 'auth'
|
3
|
+
require 'thor/group'
|
4
|
+
|
5
|
+
# rubocop:disable MethodLength, LineLength
|
6
|
+
|
7
|
+
# VcoWorkflows
|
8
|
+
module VcoWorkflows
|
9
|
+
# Cli
|
10
|
+
module Cli
|
11
|
+
# Query
|
12
|
+
class Query < Thor::Group
|
13
|
+
include Thor::Actions
|
14
|
+
|
15
|
+
argument :workflow, type: :string, desc: DESC_CLI_WORKFLOW
|
16
|
+
class_option :server, type: :string, aliases: '-s', required: true, desc: DESC_CLI_SERVER
|
17
|
+
class_option :username, type: :string, aliases: '-u', desc: DESC_CLI_USERNAME
|
18
|
+
class_option :password, type: :string, aliases: '-p', desc: DESC_CLI_PASSWORD
|
19
|
+
class_option :id, type: :string, aliases: '-i', desc: DESC_CLI_WORKFLOW_ID
|
20
|
+
class_option :verify_ssl, type: :boolean, default: true, desc: DESC_CLI_VERIFY_SSL
|
21
|
+
class_option :dry_run, type: :boolean, default: false, desc: DESC_CLI_DRY_RUN
|
22
|
+
|
23
|
+
class_option :executions, type: :boolean, aliases: '-e', default: false, desc: DESC_CLI_QUERY_EXECS
|
24
|
+
class_option :last, type: :numeric, aliases: '-l', default: 0, desc: DESC_CLI_QUERY_EXEC_LIM
|
25
|
+
class_option :execution_id, type: :string, aliases: ['-I', '--execution'], desc: DESC_CLI_QUERY_EXEC_ID
|
26
|
+
class_option :state, type: :boolean, aliases: '-r', desc: DESC_CLI_QUERY_EXEC_STATE
|
27
|
+
class_option :logs, type: :boolean, aliases: ['-L', '--log'], desc: DESC_CLI_QUERY_EXEC_LOG
|
28
|
+
class_option :show_json, type: :boolean, default: false, desc: DESC_CLI_QUERY_JSON
|
29
|
+
|
30
|
+
def self.source_root
|
31
|
+
File.dirname(__FILE__)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Process the subcommand
|
35
|
+
# rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
36
|
+
def query
|
37
|
+
auth = VcoWorkflows::Cli::Auth.new(username: options[:username], password: options[:password])
|
38
|
+
|
39
|
+
if options[:dry_run]
|
40
|
+
puts "\nQuerying against vCO REST endpoint:\n #{options[:server]}"
|
41
|
+
puts "Will search for workflow: '#{workflow}'"
|
42
|
+
puts "Will query workflow by GUID (#{options[:id]})" if options[:id]
|
43
|
+
return
|
44
|
+
end
|
45
|
+
|
46
|
+
# Get the workflow
|
47
|
+
puts "\nRetrieving workflow '#{workflow}' ..."
|
48
|
+
wf = VcoWorkflows::Workflow.new(workflow,
|
49
|
+
url: options[:server],
|
50
|
+
username: auth.username,
|
51
|
+
password: auth.password,
|
52
|
+
verify_ssl: options[:verify_ssl],
|
53
|
+
id: options[:id])
|
54
|
+
|
55
|
+
puts ''
|
56
|
+
if options[:execution_id]
|
57
|
+
puts "Fetching data for execution #{options[:execution_id]}..."
|
58
|
+
execution = wf.token(options[:execution_id])
|
59
|
+
if options[:state]
|
60
|
+
puts "Execution started at #{Time.at(execution.start_date / 1000)}"
|
61
|
+
puts "Execution #{execution.state} at #{Time.at(execution.end_date / 1000)}"
|
62
|
+
else
|
63
|
+
puts ''
|
64
|
+
if options[:show_json]
|
65
|
+
puts execution.to_json
|
66
|
+
else
|
67
|
+
puts execution
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if options[:logs]
|
72
|
+
puts ''
|
73
|
+
wflog = wf.log(options[:execution_id])
|
74
|
+
if options[:show_json]
|
75
|
+
puts wflog.to_json
|
76
|
+
else
|
77
|
+
puts wflog
|
78
|
+
end
|
79
|
+
end
|
80
|
+
else
|
81
|
+
puts wf unless options[:executions]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Last thing we're checking for, so if it's not wanted, just return
|
85
|
+
return unless options[:executions]
|
86
|
+
puts "\nWorkflow: #{wf.name}"
|
87
|
+
puts "ID: #{wf.id}"
|
88
|
+
puts "Description: #{wf.description}"
|
89
|
+
puts "Version: #{wf.version}"
|
90
|
+
puts "\nExecutions: "
|
91
|
+
executions = {}
|
92
|
+
wf.executions.each_value { |attrs| executions[attrs['startDate']] = attrs }
|
93
|
+
keys = executions.keys.sort
|
94
|
+
keys = keys.slice(keys.size - options[:last], keys.size) if options[:last] > 0
|
95
|
+
keys.each do |timestamp|
|
96
|
+
dataline = "#{timestamp}"
|
97
|
+
dataline << " [#{executions[timestamp]['id']}]"
|
98
|
+
dataline << " #{executions[timestamp]['state']}"
|
99
|
+
puts dataline
|
100
|
+
end
|
101
|
+
end
|
102
|
+
# rubocop:enable CyclomaticComplexity, PerceivedComplexity
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
# rubocop:enable MethodLength, LineLength
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# VcoWorkflows
|
2
|
+
module VcoWorkflows
|
3
|
+
# rubocop:disable LineLength
|
4
|
+
|
5
|
+
# Options description messages
|
6
|
+
DESC_VERSION = 'Display the installed version of the VcoWorkflows gem'
|
7
|
+
DESC_CLI_EXECUTE = 'Execute the specified workflow'
|
8
|
+
DESC_CLI_QUERY = 'Query vCO for a workflow'
|
9
|
+
DESC_CLI_WORKFLOW = 'Name of the workflow'
|
10
|
+
DESC_CLI_WORKFLOW_ID = 'GUID of the workflow'
|
11
|
+
DESC_CLI_DRY_RUN = 'Dry run; do not actually perform operations against vCO'
|
12
|
+
DESC_CLI_VERBOSE = 'Show extra information'
|
13
|
+
DESC_CLI_NAME = 'Name of the workflow to execute'
|
14
|
+
DESC_CLI_SERVER = 'VMware vCenter Orchestrator server URL'
|
15
|
+
DESC_CLI_USERNAME = 'vCO user name'
|
16
|
+
DESC_CLI_PASSWORD = 'vCO password'
|
17
|
+
DESC_CLI_VERIFY_SSL = 'Perform TSL Certificate verification'
|
18
|
+
DESC_CLI_EXECUTE_WATCH = 'Wait around for workflow results'
|
19
|
+
DESC_CLI_EXECUTE_PARAMETERS = 'Comma-separated list of key=value parameters for workflow'
|
20
|
+
DESC_CLI_QUERY_EXECS = 'Fetch a list of executions for the workflow'
|
21
|
+
DESC_CLI_QUERY_EXEC_LIM = 'Limit the number of returned executions to the most recent N'
|
22
|
+
DESC_CLI_QUERY_EXEC_ID = 'Fetch the execution data for this execution GUID'
|
23
|
+
DESC_CLI_QUERY_EXEC_STATE = 'Fetch the state of the specified workflow execution'
|
24
|
+
DESC_CLI_QUERY_EXEC_LOG = 'In addition to execution data, show the execution log'
|
25
|
+
DESC_CLI_QUERY_JSON = 'Show the JSON document for the requested information'
|
26
|
+
|
27
|
+
# What do all the vCO REST URIs start with?
|
28
|
+
API_URL_BASE = '/vco/api'
|
29
|
+
|
30
|
+
# error messages
|
31
|
+
ERR = {
|
32
|
+
wtf: 'vcoworkflows: I have no idea what just went wrong.',
|
33
|
+
no_workflow_found: 'vcoworkflows: no workflow found!',
|
34
|
+
too_many_workflows: 'vcoworkflows: more than one workflow found for given name!',
|
35
|
+
wrong_workflow_wtf: 'vcoworkflows: search returned the wrong workflow! (?)',
|
36
|
+
no_workflow_service_defined: 'vcoworkflows: Attempted to execute a workflow with a nil workflow service!',
|
37
|
+
param_verify_failed: 'vcoworkflows: Attempt to verify required parameter failed!',
|
38
|
+
no_such_parameter: 'Attempted to set a parameter that does not exist!',
|
39
|
+
username_unset: 'No username was specified, either by $VCO_USER or --username',
|
40
|
+
password_unset: 'No password was specified, either by $VCO_PASSWD or --password'
|
41
|
+
}
|
42
|
+
|
43
|
+
# rubocop:enable LineLength
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'vcoworkflows'
|
2
|
+
|
3
|
+
# rubocop:disable all
|
4
|
+
module VcoWorkflows
|
5
|
+
# wrapper to assist aruba in single process execution
|
6
|
+
class Runner
|
7
|
+
# Allow everything fun to be injected from the outside while defaulting to normal implementations.
|
8
|
+
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
|
9
|
+
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
|
10
|
+
end
|
11
|
+
|
12
|
+
# Do the things!
|
13
|
+
def execute!
|
14
|
+
exit_code = begin
|
15
|
+
# Thor accesses these streams directly rather than letting them be
|
16
|
+
# injected, so we replace them...
|
17
|
+
$stderr = @stderr
|
18
|
+
$stdin = @stdin
|
19
|
+
$stdout = @stdout
|
20
|
+
|
21
|
+
VcoWorkflows::CLI.start(@argv)
|
22
|
+
|
23
|
+
# Thor::Base#start does not have a return value, assume success if no
|
24
|
+
# exception is raised.
|
25
|
+
0
|
26
|
+
rescue StandardError => e
|
27
|
+
# The ruby interpreter would pipe this to STDERR and exit 1 in the
|
28
|
+
# case of an unhandled exception
|
29
|
+
b = e.backtrace
|
30
|
+
b.unshift("#{b.shift}: #{e.message} (#{e.class})")
|
31
|
+
@stderr.puts(b.map { |s| "\tfrom #{s}" }.join("\n"))
|
32
|
+
1
|
33
|
+
ensure
|
34
|
+
# put them back.
|
35
|
+
$stderr = STDERR
|
36
|
+
$stdin = STDIN
|
37
|
+
$stdout = STDOUT
|
38
|
+
end
|
39
|
+
# Proxy exit code back to the injected kernel.
|
40
|
+
@kernel.exit(exit_code)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop:enable all
|