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.
@@ -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