vcoworkflows 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ require_relative 'constants'
2
+ require_relative 'workflowservice'
3
+ require_relative 'workflow'
4
+ require_relative 'workflowtoken'
5
+ require_relative 'workflowparameter'
6
+ require 'json'
7
+
8
+ # VcoWorkflows
9
+ module VcoWorkflows
10
+ # rubocop:disable ClassLength
11
+
12
+ # WorkflowPresentation is a helper class for Workflow and is primarily used
13
+ # internally to apply additional constraints to WorkflowParameters. Currently
14
+ # WorkflowPresentation examines the presentation JSON from vCO to determine
15
+ # whether input parameters for the workflow are required or not.
16
+ class WorkflowPresentation
17
+ attr_reader :presentation_data
18
+ attr_reader :required
19
+
20
+ # rubocop:disable LineLength, MethodLength
21
+
22
+ # Create a new WorkflowPresentation
23
+ # @param [VcoWorkflows::WorkflowService] workflow_service workflow service to use
24
+ # @param [String] workflow_id workflow GUID
25
+ # @return [VcoWorkflows::WorkflowPresentation]
26
+ def initialize(workflow_service, workflow_id)
27
+ @required = []
28
+ @presentation_data = JSON.parse(workflow_service.get_presentation(workflow_id))
29
+
30
+ # Determine if there are any required input parameters
31
+ # We're parsing this because we specifically want to know if any of
32
+ # the input parameters are marked as required. This is very specifically
33
+ # in the array of hashes in:
34
+ # presentation_data[:steps][0][:step][:elements][0][:fields]
35
+ fields = @presentation_data['steps'][0]['step']['elements'][0]['fields']
36
+ fields.each do |attribute|
37
+ next unless attribute.key?('constraints')
38
+ attribute['constraints'].each do |const|
39
+ if const.key?('@type') && const['@type'].eql?('mandatory')
40
+ @required << attribute['id']
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ # String representation of the presentation
47
+ # @return [String]
48
+ def to_s
49
+ @presentation_data.to_s
50
+ end
51
+
52
+ # JSON document
53
+ # @return [String] JSON Document
54
+ def to_json
55
+ JSON.pretty_generate(@presentation_data)
56
+ end
57
+ end
58
+ # rubocop:enable ClassLength
59
+ end
@@ -0,0 +1,110 @@
1
+ require_relative 'constants'
2
+ require_relative 'vcosession'
3
+ require_relative 'workflow'
4
+ require_relative 'workflowexecutionlog'
5
+ require 'json'
6
+ require 'erb'
7
+
8
+ include ERB::Util
9
+
10
+ module VcoWorkflows
11
+ # WorkflowService is the object which acts as the interface to the vCO
12
+ # API, and is loosely modeled from the vCO API documentation.
13
+ class WorkflowService
14
+ # Return the VcoSession
15
+ attr_reader :session
16
+
17
+ # rubocop:disable LineLength
18
+
19
+ # Create a new WorkflowService
20
+ # @param [VcoWorkflows::VcoSession] session Session object for the API endpoint
21
+ # @return [VcoWorkflows::WorkflowService]
22
+ def initialize(session)
23
+ @session = session
24
+ end
25
+ # rubocop:enable LineLength
26
+
27
+ # Get a workflow by GUID
28
+ # @param [String] id Workflow GUID
29
+ # @return [VcoWorkflows::Workflow] the requested workflow
30
+ def get_workflow_for_id(id)
31
+ @session.get("/workflows/#{id}").body
32
+ end
33
+
34
+ # Get the presentation for the given workflow GUID
35
+ # @param [String] workflow_id workflow GUID
36
+ # @return [String] JSON document representation of Workflow Presentation
37
+ def get_presentation(workflow_id)
38
+ @session.get("/workflows/#{workflow_id}/presentation/").body
39
+ end
40
+
41
+ # Get one workflow with a specified name.
42
+ # @param [String] name Name of the workflow
43
+ # @return [VcoWorkflows::Workflow] the requested workflow
44
+ def get_workflow_for_name(name)
45
+ path = "/workflows?conditions=name=#{url_encode(name)}"
46
+ response = JSON.parse(@session.get(path).body)
47
+
48
+ # barf if we got anything other than a single workflow
49
+ fail(IOError, ERR[:too_many_workflows]) if response['total'] > 1
50
+ fail(IOError, ERR[:no_workflow_found]) if response['total'] == 0
51
+
52
+ # yank out the workflow id and name from the result attributes
53
+ workflow_id = nil
54
+ response['link'][0]['attributes'].each do |a|
55
+ workflow_id = a['value'] if a['name'].eql?('id')
56
+ end
57
+
58
+ # Get the workflow by GUID
59
+ get_workflow_for_id(workflow_id)
60
+ end
61
+
62
+ # Get a WorkflowToken for the requested workflow_id and execution_id
63
+ # @param [String] workflow_id Workflow GUID
64
+ # @param [String] execution_id Execution GUID
65
+ # @return [String] JSON document for workflow token
66
+ def get_execution(workflow_id, execution_id)
67
+ path = "/workflows/#{workflow_id}/executions/#{execution_id}"
68
+ @session.get(path).body
69
+ end
70
+
71
+ # Get a list of executions for the given workflow GUID
72
+ # @param [String] workflow_id Workflow GUID
73
+ # @return [Hash]
74
+ def get_execution_list(workflow_id)
75
+ path = "/workflows/#{workflow_id}/executions/"
76
+ relations = JSON.parse(@session.get(path).body)['relations']
77
+ # The first two elements of the relations['link'] array are URLS,
78
+ # so scrap them. Everything else is an execution.
79
+ executions = {}
80
+ relations['link'].each do |link|
81
+ next unless link.key?('attributes')
82
+ attributes = {}
83
+ link['attributes'].each { |a| attributes[a['name']] = a['value'] }
84
+ executions[attributes['id']] = attributes
85
+ end
86
+ executions
87
+ end
88
+
89
+ # Get the log for a specific execution
90
+ # @param [String] workflow_id
91
+ # @param [String] execution_id
92
+ # @return [String] JSON log document
93
+ def get_log(workflow_id, execution_id)
94
+ path = "/workflows/#{workflow_id}/executions/#{execution_id}/logs/"
95
+ @session.get(path).body
96
+ end
97
+
98
+ # Submit the given workflow for execution
99
+ # @param [String] id Workflow GUID for the workflow we want to execute
100
+ # @param [String] parameter_json JSON document of input parameters
101
+ # @return [String] Execution ID
102
+ def execute_workflow(id, parameter_json)
103
+ path = "/workflows/#{id}/executions/"
104
+ response = @session.post(path, parameter_json)
105
+ # Execution ID is the final component in the Location header URL, so
106
+ # chop off the front, then pull off any trailing /
107
+ response.headers[:location].gsub(%r{^.*/executions/}, '').gsub(/\/$/, '')
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,111 @@
1
+ require_relative 'constants'
2
+ require_relative 'workflow'
3
+ require_relative 'workflowservice'
4
+ require 'json'
5
+
6
+ module VcoWorkflows
7
+ # WorkflowToken is used for workflow execution results, and contains as much
8
+ # data on the given workflow execution instance as vCO can provide.
9
+ class WorkflowToken
10
+ attr_reader :id
11
+ attr_reader :workflow_id
12
+ attr_reader :name
13
+ attr_reader :state
14
+ attr_reader :href
15
+ attr_reader :start_date
16
+ attr_reader :end_date
17
+ attr_reader :started_by
18
+ attr_reader :current_item_name
19
+ attr_reader :current_item_state
20
+ attr_reader :content_exception
21
+ attr_reader :global_state
22
+ attr_reader :input_parameters
23
+ attr_reader :output_parameters
24
+ attr_reader :json_content
25
+
26
+ # rubocop:disable CyclomaticComplexity, PerceivedComplexity, MethodLength, LineLength
27
+
28
+ # Create a new workflow token
29
+ # @param [VcoWorkflows::WorkflowService] workflow_service Workflow service to use
30
+ # @param [String] workflow_id GUID of the workflow
31
+ # @param [String] execution_id GUID of execution
32
+ # @return [VcoWorkflows::WorkflowToken]
33
+ def initialize(workflow_service, workflow_id, execution_id)
34
+ @service = workflow_service
35
+ @workflow_id = workflow_id
36
+ @json_content = @service.get_execution(workflow_id, execution_id)
37
+
38
+ token = JSON.parse(@json_content)
39
+
40
+ @id = token.key?('id') ? token['id'] : nil
41
+ @name = token.key?('name') ? token['name'] : nil
42
+ @state = token.key?('state') ? token['state'] : nil
43
+ @href = token.key?('href') ? token['href'] : nil
44
+ @start_date = token.key?('start-date') ? token['start-date'] : nil
45
+ @end_date = token.key?('end-date') ? token['end-date'] : nil
46
+ @started_by = token.key?('started-by') ? token['started-by'] : nil
47
+ @current_item_name = token.key?('current-item-display-name') ? token['current-item-display-name'] : nil
48
+ @current_item_state = token.key?('current-item-state') ? token['current-item-state'] : nil
49
+ @global_state = token.key?('global-state') ? token['global-state'] : nil
50
+ @content_exception = token.key?('content-exeption') ? token['content-exception'] : nil
51
+
52
+ if token.key?('input-parameters')
53
+ @input_parameters = VcoWorkflows::Workflow.parse_parameters(token['input-parameters'])
54
+ else
55
+ @input_parameters = {}
56
+ end
57
+
58
+ if token.key?('output-parameters')
59
+ @output_parameters = VcoWorkflows::Workflow.parse_parameters(token['output-parameters'])
60
+ else
61
+ @output_parameters = {}
62
+ end
63
+ end
64
+ # rubocop:enable CyclomaticComplexity, PerceivedComplexity, MethodLength, LineLength
65
+
66
+ # Is the workflow execution still alive?
67
+ # @return [Boolean]
68
+ def alive?
69
+ running? || waiting?
70
+ end
71
+
72
+ # Is the workflow actively running?
73
+ # @return [Boolean]
74
+ def running?
75
+ state.eql?('running')
76
+ end
77
+
78
+ # Is the workflow in a waiting state?
79
+ # @return [Boolean]
80
+ def waiting?
81
+ state.match(/waiting/).nil? ? false : true
82
+ end
83
+
84
+ # rubocop:disable MethodLength, LineLength
85
+
86
+ # Convert this object to a string representation
87
+ # @return [String]
88
+ def to_s
89
+ string = "Execution ID: #{@id}\n"
90
+ string << "Name: #{@name}\n"
91
+ string << "Workflow ID: #{@workflow_id}\n"
92
+ string << "State: #{@state}\n"
93
+ string << "Start Date: #{Time.at(@start_date / 1000)}\n"
94
+ string << "End Date: #{end_date.nil? ? '' : Time.at(@end_date / 1000)}\n"
95
+ string << "Started By: #{@started_by}\n"
96
+ string << "Content Exception: #{@content_exception}\n" unless @content_exception.nil?
97
+ string << "\nInput Parameters:\n"
98
+ @input_parameters.each_value { |wf_param| string << " #{wf_param}" if wf_param.set? } if @input_parameters.size > 0
99
+ string << "\nOutput Parameters:" << "\n"
100
+ @output_parameters.each_value { |wf_param| string << " #{wf_param}" } if @output_parameters.size > 0
101
+ string
102
+ end
103
+ # rubocop:enable MethodLength, LineLength
104
+
105
+ # Convert this object to a JSON document (string)
106
+ # @return [String] JSON representation of the workflow token
107
+ def to_json
108
+ JSON.pretty_generate(JSON.parse(@json_content))
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH << '../../lib'
2
+
3
+ # require 'coveralls'
4
+ # Coveralls.wear!
@@ -0,0 +1,33 @@
1
+ require_relative '../spec_helper.rb'
2
+ require 'vcoworkflows'
3
+
4
+ # rubocop:disable LineLength
5
+
6
+ describe VcoWorkflows::VcoSession, 'VcoSession' do
7
+ before(:each) do
8
+ @uri = 'https://vcoserver.example.com:8281'
9
+ @username = 'johndoe'
10
+ @password = 's3cr3t'
11
+ end
12
+
13
+ it 'should set the URL' do
14
+ vs = VcoWorkflows::VcoSession.new(@uri, user: @username, password: @password)
15
+ api_url = '/vco/api'
16
+
17
+ expect(vs.rest_resource.url).to eql(@uri << api_url)
18
+ end
19
+
20
+ it 'should set the username' do
21
+ vs = VcoWorkflows::VcoSession.new(@uri, user: @username, password: @password)
22
+
23
+ expect(vs.rest_resource.user).to eql(@username)
24
+ end
25
+
26
+ it 'should set the password' do
27
+ vs = VcoWorkflows::VcoSession.new(@uri, user: @username, password: @password)
28
+
29
+ expect(vs.rest_resource.password).to eql(@password)
30
+ end
31
+ end
32
+
33
+ # rubocop:enable LineLength
@@ -0,0 +1,144 @@
1
+ require_relative '../spec_helper.rb'
2
+ require 'vcoworkflows'
3
+
4
+ # rubocop:disable LineLength
5
+
6
+ describe VcoWorkflows::Workflow, 'Workflow' do
7
+ before(:each) do
8
+ # Set up some basic starting data
9
+ @workflow_name = 'Request Component'
10
+ @workflow_id = '6e04a460-4a45-4e16-9603-db2922c24462'
11
+ @execution_id = 'ff8080814a1cb55c014a6481a9927a78'
12
+ @workflow_json = '''{"output-parameters":[{"name":"result","type":"string","description":"Catalog item request state"},{"name":"requestNumber","type":"number"},{"name":"requestCompletionDetails","type":"string"}],"relations":{"link":[{"rel":"up","href":"https://vco.example.com:8281/vco/api/inventory/System/Workflows/dlinsley%2540vmware.com/vCAC/"},{"rel":"executions","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/executions/"},{"rel":"presentation","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/presentation/"},{"rel":"tasks","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/tasks/"},{"rel":"icon","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/icon/"},{"rel":"schema","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/schema/"},{"rel":"permissions","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/permissions/"},{"rel":"interactions","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/interactions/"}]},"id":"6e04a460-4a45-4e16-9603-db2922c24462","name":"Request Component","version":"0.0.33","description":"","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/","customized-icon":false,"input-parameters":[{"name":"coreCount","type":"string"},{"name":"ramMB","type":"string"},{"name":"onBehalfOf","type":"string"},{"name":"machineCount","type":"string"},{"name":"businessUnit","type":"string"},{"name":"reservation","type":"string"},{"name":"location","type":"string"},{"name":"environment","type":"string"},{"name":"image","type":"string","description":"vCenter template name"},{"name":"runlist","type":"Array/string","description":"Chef Runlist for first run. Leave empty for no Chef"},{"name":"nodename","type":"string","description":"Chef Nodename"},{"name":"component","type":"string"},{"name":"attributesJS","type":"string","description":"JSON object of vCenter Attributes to apply to VM(s)"}]}'''
13
+ @presentation_json = '''{"output-parameters":[{"name":"machineCount","type":"string"},{"name":"location","type":"string"},{"name":"image","type":"string","description":"vCenter template name"},{"name":"coreCount","type":"string"},{"name":"ramMB","type":"string"},{"name":"onBehalfOf","type":"string"},{"name":"businessUnit","type":"string"},{"name":"environment","type":"string"},{"name":"component","type":"string"},{"name":"reservation","type":"string"},{"name":"runlist","type":"Array/string","description":"Chef Runlist for first run. Leave empty for no Chef"},{"name":"nodename","type":"string","description":"Chef Nodename"},{"name":"attributesJS","type":"string","description":"JSON object of vCenter Attributes to apply to VM(s)"}],"input-parameters":[{"name":"businessUnit","type":"string","description":"businessUnit"},{"name":"environment","type":"string","description":"environment"},{"name":"component","type":"string","description":"component"},{"name":"onBehalfOf","type":"string","description":"On Behalf of User: (user@domain format)"},{"name":"machineCount","type":"string","description":"machineCount"},{"name":"image","type":"string","description":"image"},{"name":"coreCount","type":"string","description":"coreCount"},{"name":"ramMB","type":"string","description":"ramSizeMB"},{"name":"runlist","type":"Array/string","description":"runlist"},{"name":"reservation","type":"string","description":"reservation"},{"name":"location","type":"string","description":"location"},{"name":"attributesJS","type":"string","description":"JSON object of vCenter Attributes to apply to VM(s)"},{"name":"nodename","type":"string","description":"Chef Nodename"}],"href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/presentation/","name":"Request Component","id":"6e04a460-4a45-4e16-9603-db2922c24462","steps":[{"step":{"messages":[],"hidden":false,"elements":[{"fields":[{"display-name":"businessUnit","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"businessUnit","description":"businessUnit","hidden":false,"messages":[],"decorators":[{"array":{"elements":[{"string":{"value":"an"}},{"string":{"value":"aw"}},{"string":{"value":"soi"}}]},"@type":"drop-down"}],"type":"string"},{"display-name":"environment","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"environment","description":"environment","hidden":false,"messages":[],"decorators":[],"type":"string"},{"display-name":"component","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"component","description":"component","hidden":false,"messages":[],"decorators":[],"type":"string"},{"display-name":"On Behalf of User: (user@domain format)","constraints":[],"@type":"field","fields":[],"id":"onBehalfOf","description":"On Behalf of User: (user@domain format)","hidden":false,"messages":[],"decorators":[],"type":"string"},{"display-name":"machineCount","constraints":[],"@type":"field","fields":[],"id":"machineCount","description":"machineCount","hidden":false,"messages":[],"decorators":[{"array":{"elements":[{"string":{"value":"1"}},{"string":{"value":"2"}},{"string":{"value":"3"}},{"string":{"value":"4"}},{"string":{"value":"5"}},{"string":{"value":"6"}},{"string":{"value":"7"}},{"string":{"value":"8"}},{"string":{"value":"9"}},{"string":{"value":"10"}}]},"@type":"drop-down"}],"type":"string"},{"display-name":"image","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"image","description":"image","hidden":false,"messages":[],"decorators":[{"array":{"elements":[{"string":{"value":"vcaccentos65v8-agent"}},{"string":{"value":"win2012std"}},{"string":{"value":"vcac2012std"}},{"string":{"value":"centos-6.6-x86_64-20141203-1"}},{"string":{"value":"v8-centos65-agent"}},{"string":{"value":"vcac2008r2std"}},{"string":{"value":"oracle-6.5-x86_64-20141203-1"}},{"string":{"value":"centos65v8"}},{"string":{"value":"w2012r2std_coreservices"}},{"string":{"value":"2008r2std"}}]},"@type":"drop-down"}],"type":"string"},{"display-name":"coreCount","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"coreCount","description":"coreCount","hidden":false,"messages":[],"decorators":[{"@type":"refresh-on-change"},{"array":{"elements":[{"string":{"value":"1"}},{"string":{"value":"2"}},{"string":{"value":"4"}},{"string":{"value":"8"}}]},"@type":"drop-down"}],"type":"string"},{"display-name":"ramSizeMB","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"ramMB","description":"ramSizeMB","hidden":false,"messages":[],"decorators":[{"array":{"elements":[null]},"@type":"drop-down"}],"type":"string"},{"display-name":"runlist","constraints":[],"@type":"field","fields":[],"id":"runlist","description":"runlist","hidden":false,"messages":[],"decorators":[],"type":"Array/string"},{"display-name":"reservation","constraints":[{"@type":"mandatory"}],"@type":"field","fields":[],"id":"reservation","description":"reservation","hidden":false,"messages":[],"decorators":[],"type":"string"},{"display-name":"location","constraints":[],"@type":"field","fields":[],"id":"location","description":"location","hidden":false,"messages":[],"decorators":[],"type":"string"},{"display-name":"JSON object of vCenter Attributes to apply to VM(s)","constraints":[],"@type":"field","fields":[],"id":"attributesJS","description":"JSON object of vCenter Attributes to apply to VM(s)","hidden":false,"messages":[],"decorators":[{"@type":"multiline"}],"type":"string"},{"display-name":"Chef Nodename","constraints":[],"@type":"field","fields":[],"id":"nodename","description":"Chef Nodename","hidden":false,"messages":[],"decorators":[],"type":"string"}],"messages":[],"hidden":false,"@type":"group"}]}}],"relations":{"link":[{"rel":"up","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/"},{"rel":"instances","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/presentation/instances/"},{"rel":"add","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/presentation/instances/"}]}}'''
14
+ @param_string_json = '''{"type":"string","name":"stringparam","scope":"local","value":{"string":{"value":"squirrel!"}}}'''
15
+ @param_array_json = '''{"type":"Array/string","name":"arrayparam","scope":"local","value":{"array":{"elements":[{"string":{"value":"a"}},{"string":{"value":"b"}},{"string":{"value":"c"}}]}}}'''
16
+
17
+ # Mock the WorkflowService
18
+ @service = double('service')
19
+ allow(@service).to receive(:get_workflow_for_id) { @workflow_json }
20
+ allow(@service).to receive(:get_workflow_for_name) { @workflow_json }
21
+ allow(@service).to receive(:get_presentation) { @presentation_json }
22
+ end
23
+
24
+ it 'should parse a single string parameter' do
25
+ param_data = []
26
+ param_data << JSON.parse(@param_string_json)
27
+ wfparams = VcoWorkflows::Workflow.parse_parameters(param_data)
28
+
29
+ expect(wfparams).to_not eq(nil)
30
+ expect(wfparams.size).to eq(1)
31
+ expect(wfparams.key?('stringparam')).to eq(true)
32
+ expect(wfparams['stringparam'].type).to eql('string')
33
+ expect(wfparams['stringparam'].subtype).to eq(nil)
34
+ expect(wfparams['stringparam'].value).to eql('squirrel!')
35
+ end
36
+
37
+ it 'should parse a single Array parameter' do
38
+ param_data = []
39
+ param_data << JSON.parse(@param_array_json)
40
+ wfparams = VcoWorkflows::Workflow.parse_parameters(param_data)
41
+
42
+ expect(wfparams).to_not eq(nil)
43
+ expect(wfparams.size).to eq(1)
44
+ expect(wfparams.key?('arrayparam')).to eq(true)
45
+ expect(wfparams['arrayparam'].type).to eql('Array')
46
+ expect(wfparams['arrayparam'].subtype).to eql('string')
47
+ expect(wfparams['arrayparam'].value).to eql(%w(a b c))
48
+ end
49
+
50
+ it 'should parse an array of mixed parameters' do
51
+ param_data = []
52
+ param_data << JSON.parse(@param_string_json)
53
+ param_data << JSON.parse(@param_array_json)
54
+ wfparams = VcoWorkflows::Workflow.parse_parameters(param_data)
55
+
56
+ expect(wfparams).to_not eq(nil)
57
+ expect(wfparams.size).to eq(2)
58
+ expect(wfparams.key?('stringparam')).to eq(true)
59
+ expect(wfparams['stringparam'].type).to eql('string')
60
+ expect(wfparams['stringparam'].subtype).to eq(nil)
61
+ expect(wfparams['stringparam'].value).to eql('squirrel!')
62
+ expect(wfparams.key?('arrayparam')).to eq(true)
63
+ expect(wfparams['arrayparam'].type).to eql('Array')
64
+ expect(wfparams['arrayparam'].subtype).to eql('string')
65
+ expect(wfparams['arrayparam'].value).to eql(%w(a b c))
66
+ end
67
+
68
+ it 'should not explode' do
69
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
70
+
71
+ expect(wf).to_not eq(nil)
72
+ end
73
+
74
+ it 'should have input and output parameters' do
75
+ input_param_count = 13
76
+ output_param_count = 3
77
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
78
+
79
+ expect(wf.input_parameters.size).to eq(input_param_count)
80
+ expect(wf.output_parameters.size).to eq(output_param_count)
81
+ end
82
+
83
+ it 'should have required parameters' do
84
+ required_param_count = 7
85
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
86
+
87
+ expect(wf.required_parameters.size).to eq(required_param_count)
88
+ end
89
+
90
+ it 'should set and return a parameter value' do
91
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
92
+
93
+ expect(wf.set_parameter('coreCount', 4)).to eq(4)
94
+ expect(wf.input_parameters['coreCount'].value).to eq(4)
95
+ expect(wf.get_parameter('coreCount')).to eql(4)
96
+ end
97
+
98
+ it 'should execute' do
99
+ allow(@service).to receive(:execute_workflow) { @execution_id }
100
+ target_parameters = {
101
+ 'coreCount' => 2,
102
+ 'ramMB' => 2048,
103
+ 'businessUnit' => 'aw',
104
+ 'reservation' => 'nonprodlinux',
105
+ 'environment' => 'dev1',
106
+ 'image' => 'centos-6.6-x86_64-20141203-1',
107
+ 'component' => 'api',
108
+ 'onBehalfOf' => 'svcacct@example.com',
109
+ 'location' => 'us_east',
110
+ 'runlist' => %w(role[loc_uswest] role[base] role[api]),
111
+ 'machineCount' => 1
112
+ }
113
+
114
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
115
+ target_parameters.each { |k, v| wf.set_parameter(k, v) }
116
+
117
+ expect(wf.execute).to eql(@execution_id)
118
+ end
119
+
120
+ it 'should provide a WorkflowToken' do
121
+ token_json = '''{"relations":{"link":[{"href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/executions/","rel":"up"},{"href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/executions/ff8080814a1cb55c014a6481a9927a78/","rel":"remove"},{"href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/executions/ff8080814a1cb55c014a6481a9927a78/logs/","rel":"logs"},{"href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/executions/ff8080814a1cb55c014a6481a9927a78/state/","rel":"state"}]},"id":"ff8080814a1cb55c014a6481a9927a78","state":"completed","name":"Request Component","href":"https://vco.example.com:8281/vco/api/workflows/6e04a460-4a45-4e16-9603-db2922c24462/executions/ff8080814a1cb55c014a6481a9927a78/","start-date":1419025426833,"end-date":1419026124320,"started-by":"someuser@EXAMPLE.COM","input-parameters":[{"value":{"string":{"value":"2"}},"type":"string","name":"coreCount","scope":"local"},{"value":{"string":{"value":"2048"}},"type":"string","name":"ramMB","scope":"local"},{"value":{"string":{"value":"svcacct@example.com"}},"type":"string","name":"onBehalfOf","scope":"local"},{"value":{"string":{"value":"1"}},"type":"string","name":"machineCount","scope":"local"},{"value":{"string":{"value":"aw"}},"type":"string","name":"businessUnit","scope":"local"},{"value":{"string":{"value":"nonprodlinux"}},"type":"string","name":"reservation","scope":"local"},{"value":{"string":{"value":"us_east"}},"type":"string","name":"location","scope":"local"},{"value":{"string":{"value":"dev1"}},"type":"string","name":"environment","scope":"local"},{"value":{"string":{"value":"centos-6.6-x86_64-20141203-1"}},"type":"string","name":"image","scope":"local"},{"value":{"array":{"elements":[{"string":{"value":"role[loc_uswest]"}},{"string":{"value":"role[base]"}},{"string":{"value":"role[api]"}}]}},"type":"Array/string","name":"runlist","scope":"local"},{"value":{"string":{"value":""}},"type":"string","name":"nodename","scope":"local"},{"value":{"string":{"value":"api"}},"type":"string","name":"component","scope":"local"},{"value":{"string":{"value":""}},"type":"string","name":"attributesJS","scope":"local"}],"output-parameters":[{"value":{"string":{"value":"SUCCESSFUL"}},"type":"string","name":"result","scope":"local"},{"value":{"number":{"value":326.0}},"type":"number","name":"requestNumber","scope":"local"},{"value":{"string":{"value":"Request succeeded. Created vm00378."}},"type":"string","name":"requestCompletionDetails","scope":"local"}]}'''
122
+ allow(@service).to receive(:get_execution) { token_json }
123
+
124
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
125
+ wftoken = wf.token(@execution_id)
126
+
127
+ expect(wftoken).to_not eq(nil)
128
+ expect(wftoken.workflow_id).to eq(wf.id)
129
+ expect(wftoken.id).to eq(@execution_id)
130
+ expect(wftoken.alive?).to eq(false)
131
+ expect(wftoken.state).to eql('completed')
132
+ end
133
+
134
+ it 'should provide a WorkflowExectionLog' do
135
+ log_json = '''{"logs":[{"entry":{"severity":"info","time-stamp":1419026124333,"user":"gruiz-ade","short-description":"Workflow \'Request Component\' has completed","long-description":"Workflow \'Request Component\' has completed"}},{"entry":{"severity":"info","time-stamp":1419026123927,"user":"gruiz-ade","short-description":"Workflow \'Request Component\' has resumed","long-description":"Workflow \'Request Component\' has resumed"}},{"entry":{"severity":"info","time-stamp":1419025439183,"user":"gruiz-ade","short-description":"Workflow is paused","long-description":"Workflow \'Request Component\' has paused while waiting on signal"}},{"entry":{"severity":"info","time-stamp":1419025426870,"user":"gruiz-ade","short-description":"Workflow \'Request Component\' has started","long-description":"Workflow \'Request Component\' has started"}}]}'''
136
+ allow(@service).to receive(:get_log) { log_json }
137
+
138
+ wf = VcoWorkflows::Workflow.new(@workflow_name, service: @service)
139
+ wflog = wf.log(@execution_id)
140
+
141
+ expect(wflog).to_not eq(nil)
142
+ end
143
+ end
144
+ # rubocop:enable LineLength