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.
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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # require 'vcoworkflows'
4
+ require 'vcoworkflows/runner'
5
+
6
+ VcoWorkflows::Runner.new(ARGV.dup).execute!
7
+ # VcoWorkflows::CLI.start(ARGV.dup)
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
@@ -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