Support deployment tasks history

Changes:

* send full info about task: task name, status, summary;
* support to send summary from puppet and shell agents;
* support to send skipped report for noop tasks;
* support to send status for null node (virtual_sync_node);
* convert Astute task status to Nailgun task status in report.

Change-Id: Ia81f3eb6203dceaac5208efe812e44e951c478fe
Implements: blueprint store-deployment-tasks-history
This commit is contained in:
Vladimir Sharshov (warpc) 2016-03-10 15:04:03 +03:00
parent 0a4e1ec7bc
commit 6b3f9b46a6
10 changed files with 551 additions and 97 deletions

View File

@ -30,6 +30,7 @@ module Astute
@is_hung = false
@puppet_debug = puppet_debug
@succeed_retries = succeed_retries || Astute.config.puppet_succeed_retries
@summary = {}
end
def run
@ -44,17 +45,17 @@ module Astute
def status
raise Timeout::Error unless @time_observer.enough_time?
last_run = puppet_status
status = node_status(last_run)
@summary = puppet_status
status = node_status(@summary)
Astute.logger.debug "Node #{@node['uid']}(#{@node['role']}) status: #{status}"
result = case status
when 'succeed'
processing_succeed_node(last_run)
processing_succeed_node(@summary)
when 'running'
processing_running_node
when 'error'
processing_error_node(last_run)
processing_error_node(@summary)
end
#TODO(vsharshov): Should we move it to control module?
@ -68,6 +69,10 @@ module Astute
'error'
end
def summary
@summary
end
private
def puppetd

View File

@ -15,7 +15,7 @@
module Astute
class Task
ALLOWED_STATUSES = [:successful, :failed, :running, :pending]
ALLOWED_STATUSES = [:successful, :failed, :running, :pending, :skipped]
def initialize(task, context)
# WARNING: this code expect that only one node will be send
@ -69,6 +69,11 @@ module Astute
successful?
end
# Show additional info about tasks: last run summary, sdtout etc
def summary
{}
end
private
# Run current task on node, specified in task
@ -179,7 +184,7 @@ module Astute
end
def finished?
[:successful, :failed].include? @status
[:successful, :failed, :skipped].include? @status
end
def failed!
@ -212,6 +217,15 @@ module Astute
@status == :pending
end
def skipped?
@status == :skipped
end
def skipped!
self.status = :skipped
time_summary
end
def task_name
@task['id'] || @task['diagnostic_name']
end

View File

@ -42,8 +42,9 @@ module Astute
'nodes' => [{
'uid' => id,
'status' => 'deploying',
'task' => task.name,
'progress' => current_progress_bar
'deployment_graph_task_name' => task.name,
'progress' => current_progress_bar,
'task_status' => task.status.to_s,
}]
})
else
@ -67,13 +68,15 @@ module Astute
node_status = {
'uid' => id,
'status' => deploy_status,
'task' => task.name,
'progress' => current_progress_bar,
'deployment_graph_task_name' => task.name,
'task_status' => task.status.to_s,
'progress' => current_progress_bar
'custom' => @task_engine.summary,
}
node_status.merge!('error_type' => 'deploy') if
deploy_status == 'error'
@ctx.report('nodes' => [node_status])
end

View File

@ -19,6 +19,17 @@ module Astute
STATES = ['deploying', 'ready', 'error', 'stopped']
FINAL_STATES = ['ready', 'error', 'stopped']
REPORT_REAL_TASK_STATE_MAP = {
'running' => 'running',
'successful' => 'ready',
'failed' => 'error',
'skipped' => 'skipped'
}
REPORT_REAL_NODE_MAP = {
'virtual_sync_node' => 'null'
}
def initialize(up_reporter, nodes_uids=[])
@up_reporter = up_reporter
@nodes = nodes_uids.inject({}) do |nodes, node_uid|
@ -26,7 +37,8 @@ module Astute
end
end
def report(data)
def report(original_data)
data = deep_copy(original_data)
if data['nodes']
nodes_to_report = get_nodes_to_report(data['nodes'])
return if nodes_to_report.empty? # Let's report only if nodes updated
@ -44,27 +56,36 @@ module Astute
nodes.map{ |node| node_validate(node) }.compact
end
def node_validate(node)
return if node_should_exclude?(node)
validates_basic_fields(node)
def node_validate(original_node)
node = deep_copy(original_node)
return unless node_should_include?(node)
validates_node_basic_fields(node)
validates_task_basic_fields(node)
conver_node_name_to_original(node)
conver_task_status_to_status(node)
normalization_progress(node)
compare_with_previous_state(node)
end
def node_should_exclude?(node)
node['uid'].to_i == 0 && node['uid'] != 'master'
def node_should_include?(node)
is_num?(node['uid']) ||
['master', 'virtual_sync_node'].include?(node['uid'])
end
def valid_status?(status)
STATES.include? status.to_s
end
def valid_task_status?(status)
REPORT_REAL_TASK_STATE_MAP.keys.include? status.to_s
end
def final_status?(status)
FINAL_STATES.include? status.to_s
end
# Validate of basic fields in message about nodes
def validates_basic_fields(node)
# Validate of basic fields in message about node
def validates_node_basic_fields(node)
err = []
err << "Status provided '#{node['status']}' is not supported" if
@ -73,12 +94,23 @@ module Astute
!node['status'] && node['progress']
err << "Node uid is not provided" unless node['uid']
if err.any?
msg = "Validation of node:\n#{node.pretty_inspect} for " \
"report failed: #{err.join('; ')}"
Astute.logger.error(msg)
raise msg
end
fail_validation(node, err) if err.any?
end
# Validate of basic fields in message about task
def validates_task_basic_fields(node)
err = []
err << "Task status provided '#{node['task_status']}' is not supported" if
!valid_task_status?(node['task_status'])
err << "Task name is not provided" if node['deployment_graph_task_name'].blank?
fail_validation(node, err) if err.any?
end
def conver_task_status_to_status(node)
node['task_status'] = REPORT_REAL_TASK_STATE_MAP.fetch(node['task_status'])
end
# Normalization of progress field: ensures that the scaling progress was
@ -105,7 +137,8 @@ module Astute
!final_status?(node['status'])
# Allow to send only node progress/status update
return if node_progress.to_i <= saved_node['progress'].to_i &&
node['status'] == saved_node['status']
node['status'] == saved_node['status'] &&
node['deployment_graph_task_name'] == saved_node['deployment_graph_task_name']
node
end
@ -121,6 +154,29 @@ module Astute
end
end
def fail_validation(node, err)
msg = "Validation of node:\n#{node.pretty_inspect} for " \
"report failed: #{err.join('; ')}"
Astute.logger.error(msg)
raise Astute::AstuteError, msg
end
def conver_node_name_to_original(node)
if REPORT_REAL_NODE_MAP.keys.include?(node['uid'])
node['uid'] = REPORT_REAL_NODE_MAP.fetch(node['uid'])
end
end
def deep_copy(data)
data.deep_dup
end
def is_num?(str)
Integer(str)
rescue ArgumentError, TypeError
false
end
end
end
end

View File

@ -22,7 +22,7 @@ module Astute
end
def calculate_status
succeed!
skipped!
end
end

View File

@ -17,6 +17,12 @@ require 'timeout'
module Astute
class Puppet < Task
def summary
@puppet_task.summary
rescue
{}
end
private
def process

View File

@ -25,6 +25,12 @@ module Astute
@puppet_task = nil
end
def summary
@puppet_task.summary
rescue
{}
end
private
SHELL_MANIFEST_DIR = '/etc/puppet/shell_manifests'

View File

@ -217,7 +217,7 @@ module Deployment
return true if @tasks_are_successful
return false if @tasks_have_failed
successful = all? do |task|
task.successful?
task.successful? || task.skipped?
end
if successful
debug 'All tasks are successful'

View File

@ -46,17 +46,17 @@ describe Astute::TaskNode do
let(:task_data) do
{
"parameters" => {
"puppet_modules" => "/etc/puppet/modules",
"puppet_manifest" => "/etc/puppet/modules/osnailyfacter/modular" \
"/openstack-haproxy/openstack-haproxy-mysqld.pp",
"timeout" => 300,
"cwd" => "/"
"puppet_modules" => "/etc/puppet/modules",
"puppet_manifest" => "/etc/puppet/modules/osnailyfacter/modular" \
"/openstack-haproxy/openstack-haproxy-mysqld.pp",
"timeout" => 300,
"cwd" => "/"
},
"type" => "puppet",
"fail_on_error" => true,
"required_for" => [],
"requires" => [],
"id" => "openstack-haproxy-mysqld"
"id" => "openstack-haproxy-mysqld",
}
end
@ -86,7 +86,7 @@ describe Astute::TaskNode do
"fail_on_error" => false,
"required_for" => [],
"requires" => [],
"id" => "test-task"
"id" => "test-task",
}
end
@ -190,7 +190,7 @@ describe Astute::TaskNode do
"fail_on_error" => false,
"required_for" => [],
"requires" => [],
"id" => "test-task"
"id" => "test-task",
}
end
@ -214,6 +214,26 @@ describe Astute::TaskNode do
task_node.poll
expect(task_node.status).to eql(:online)
end
context "skipped" do
let(:task_data) do
{
"parameters" => {},
"type" => "noop",
"fail_on_error" => false,
"required_for" => [],
"requires" => [],
"id" => "test-task",
}
end
it 'if task skipped' do
ctx.stubs(:report)
task_node.run(task)
task_node.poll
expect(task_node.status).to eql(:online)
end
end
end
it 'should report progress if task running' do
@ -223,7 +243,8 @@ describe Astute::TaskNode do
'nodes' => [{
'uid' => 'node_id',
'status' => 'deploying',
'task' => task.name,
'deployment_graph_task_name' => task.name,
'task_status' => 'running',
'progress' => 0}]
})
task_node.poll
@ -236,13 +257,60 @@ describe Astute::TaskNode do
'nodes' => [{
'uid' => 'node_id',
'status' => 'ready',
'task' => task.name,
'deployment_graph_task_name' => task.name,
'custom' => {},
'task_status' => 'successful',
'progress' => 100}]
})
task_node.poll
end
context 'skipped' do
let(:task_data) do
{
"parameters" => {},
"type" => "noop",
"fail_on_error" => false,
"required_for" => [],
"requires" => [],
"id" => "test-task",
}
end
it 'should report ready if task skipped and no more task' do
task_node.run(task)
ctx.expects(:report).with({
'nodes' => [{
'uid' => 'node_id',
'status' => 'ready',
'deployment_graph_task_name' => task.name,
'custom' => {},
'task_status' => 'skipped',
'progress' => 100}]
})
task_node.poll
end
it 'should report deploy progress if task skipped and another tasks exists' do
task_node.graph.create_task(
'second_task',
task_data.merge({'node_id' => 'node_id'})
)
task_node.run(task)
ctx.expects(:report).with({
'nodes' => [{
'uid' => 'node_id',
'status' => 'deploying',
'deployment_graph_task_name' => task.name,
'custom' => {},
'task_status' => 'skipped',
'progress' => 50}]
})
task_node.poll
end
end
it 'should report error if task failed and no more task' do
Astute::Puppet.any_instance.expects(:status).returns(:failed)
task_node.run(task)
@ -250,7 +318,8 @@ describe Astute::TaskNode do
'nodes' => [{
'uid' => 'node_id',
'status' => 'error',
'task' => task.name,
'deployment_graph_task_name' => task.name,
'custom' => {},
'task_status' => 'failed',
'error_type' => 'deploy',
'progress' => 100}]
@ -270,7 +339,8 @@ describe Astute::TaskNode do
'nodes' => [{
'uid' => 'node_id',
'status' => 'deploying',
'task' => task.name,
'deployment_graph_task_name' => task.name,
'custom' => {},
'task_status' => 'successful',
'progress' => 50}]
})
@ -289,13 +359,13 @@ describe Astute::TaskNode do
'nodes' => [{
'uid' => 'node_id',
'status' => 'deploying',
'task' => task.name,
'deployment_graph_task_name' => task.name,
'custom' => {},
'task_status' => 'failed',
'progress' => 50}]
})
task_node.poll
end
end
end

View File

@ -19,11 +19,37 @@ include Astute
describe "TaskProxyReporter" do
context "Instance of ProxyReporter class" do
let(:msg) { {'nodes' => [{'status' => 'ready', 'uid' => '1'}]} }
let(:msg) do
{'nodes' => [{
'status' => 'ready',
'uid' => '1',
'deployment_graph_task_name' => 'test_1',
'task_status' => 'successful'}
]
}
end
let(:expected_msg) do
{'nodes' => [{
'status' => 'ready',
'uid' => '1',
'deployment_graph_task_name' => 'test_1',
'task_status' => 'ready',
'progress' => 100}
]
}
end
let(:msg_pr) do
{'nodes' => [
msg['nodes'][0],
{'status' => 'deploying', 'uid' => '2', 'progress' => 54}
{
'status' => 'deploying',
'uid' => '2',
'progress' => 54,
'task_status' => 'running',
'deployment_graph_task_name' => 'test_1'
}
]}
end
@ -31,27 +57,34 @@ describe "TaskProxyReporter" do
let(:reporter) { ProxyReporter::TaskProxyReporter.new(up_reporter) }
it "reports first-come data" do
up_reporter.expects(:report).with(msg)
up_reporter.expects(:report).with(expected_msg)
reporter.report(msg)
end
it "does not report the same message" do
up_reporter.expects(:report).with(msg).once
up_reporter.expects(:report).with(expected_msg).once
5.times { reporter.report(msg) }
end
it "reports only updated node" do
updated_node = msg_pr['nodes'][1]
expected_msg = {'nodes' => [updated_node]}
up_reporter.expects(:report).with(msg)
expected_msg_2 = {'nodes' => [{
'status' => 'deploying',
'uid' => '2',
'deployment_graph_task_name' => 'test_1',
'task_status' => 'running',
'progress' => 54}]
}
up_reporter.expects(:report).with(expected_msg)
up_reporter.expects(:report).with(expected_msg_2)
reporter.report(msg)
reporter.report(msg_pr)
end
it "reports only if progress value is greater" do
msg1 = {'nodes' => [{'status' => 'deploying', 'uid' => '1', 'progress' => 54},
{'status' => 'deploying', 'uid' => '2', 'progress' => 54}]}
msg1 = {'nodes' => [{'status' => 'deploying', 'uid' => '1', 'progress' => 54,
'deployment_graph_task_name' => 'test_1', 'task_status' => 'running'},
{'status' => 'deploying', 'uid' => '2', 'progress' => 54,
'deployment_graph_task_name' => 'test_1', 'task_status' => 'running'}]}
msg2 = Marshal.load(Marshal.dump(msg1))
msg2['nodes'][1]['progress'] = 100
msg2['nodes'][1]['status'] = 'ready'
@ -64,14 +97,46 @@ describe "TaskProxyReporter" do
reporter.report(msg2)
end
it "should report only nodes with integer > 0 or master uid" do
it "reports if progress value same, but deployment graph task name different" do
msg1 = {'nodes' => [{'status' => 'deploying', 'uid' => '1', 'progress' => 54,
'deployment_graph_task_name' => 'test_1', 'task_status' => 'running'}]}
msg2 = {'nodes' => [{'status' => 'deploying', 'uid' => '1', 'progress' => 54,
'deployment_graph_task_name' => 'test_2', 'task_status' => 'running'}]}
up_reporter.expects(:report).with(msg1)
up_reporter.expects(:report).with(msg2)
reporter.report(msg1)
reporter.report(msg2)
end
it "should report only nodes with integer or master uid or virtual node" do
input_msg = {'nodes' => [
{'uid' => '0', 'status' => 'deploying', 'progress' => 10},
{'uid' => 'virtual_sync_node', 'status' => 'deploying', 'progress' => 10},
{'uid' => '1', 'status' => 'deploying', 'progress' => 10}
{'uid' => 'master', 'status' => 'deploying', 'progress' => 10,
'deployment_graph_task_name' => 'test_2', 'task_status' => 'running'},
{'uid' => 'virtual_sync_node', 'status' => 'deploying', 'progress' => 10,
'deployment_graph_task_name' => 'test_2', 'task_status' => 'running'},
{'uid' => '0', 'status' => 'deploying', 'progress' => 10,
'deployment_graph_task_name' => 'test_2', 'task_status' => 'running'},
{'uid' => 'unknown', 'status' => 'deploying', 'progress' => 10,
'deployment_graph_task_name' => 'test_2', 'task_status' => 'running'}
]}
expected_msg = {'nodes' => [{'uid' => '1', 'status' => 'deploying', 'progress' => 10}]}
expected_msg = {'nodes' => [
{'uid' => 'master',
'status' => 'deploying',
'progress' => 10,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'},
{'uid' => 'null',
'status' => 'deploying',
'progress' => 10,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'},
{'uid' => '0',
'status' => 'deploying',
'progress' => 10,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
up_reporter.expects(:report).with(expected_msg).once
reporter.report(input_msg)
end
@ -82,39 +147,90 @@ describe "TaskProxyReporter" do
end
it "adjusts progress to 100 if passed greater" do
input_msg = {'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 120}]}
expected_msg = {'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 100}]}
input_msg = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'progress' => 120,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
expected_msg = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
up_reporter.expects(:report).with(expected_msg)
reporter.report(input_msg)
end
it "adjusts progress to 0 if passed less" do
input_msg = {'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => -20}]}
expected_msg = {'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 0}]}
input_msg = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'progress' => -20,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
expected_msg = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'progress' => 0,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
up_reporter.expects(:report).with(expected_msg)
reporter.report(input_msg)
end
it "adjusts progress to 100 if status ready and no progress given" do
input_msg = {'nodes' => [{'uid' => 1, 'status' => 'ready'}]}
expected_msg = {'nodes' => [{'uid' => 1, 'status' => 'ready', 'progress' => 100}]}
input_msg = {'nodes' => [{'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]}
expected_msg = {'nodes' => [{'uid' => 1,
'status' => 'ready',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready'}]}
up_reporter.expects(:report).with(expected_msg)
reporter.report(input_msg)
end
it "adjusts progress to 100 if status ready with progress" do
input_msg = {'nodes' => [{'uid' => 1, 'status' => 'ready', 'progress' => 50}]}
expected_msg = {'nodes' => [{'uid' => 1, 'status' => 'ready', 'progress' => 100}]}
input_msg = {'nodes' => [{'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful',
'progress' => 50}]}
expected_msg = {'nodes' => [{'uid' => 1,
'status' => 'ready',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready'}]}
up_reporter.expects(:report).with(expected_msg)
reporter.report(input_msg)
end
it "does not report if node was in ready, and trying to set is deploying" do
msg1 = {'nodes' => [{'uid' => 1, 'status' => 'ready'}]}
msg2 = {'nodes' => [{'uid' => 2, 'status' => 'ready'}]}
msg3 = {'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 100}]}
up_reporter.expects(:report).with(msg1)
up_reporter.expects(:report).with(msg2)
msg1 = {'nodes' => [{'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]}
msg2 = {'nodes' => [{'uid' => 2,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]}
msg3 = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]}
expected_msg_1 = {'nodes' => [{'uid' => 1,
'status' => 'ready',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready'}]}
expected_msg_2 = {'nodes' => [{'uid' => 2,
'status' => 'ready',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready'}]}
up_reporter.expects(:report).with(expected_msg_1)
up_reporter.expects(:report).with(expected_msg_2)
up_reporter.expects(:report).never
reporter.report(msg1)
reporter.report(msg2)
@ -122,21 +238,35 @@ describe "TaskProxyReporter" do
end
it "reports even not all keys provided" do
msg1 = {'nodes' => [{'uid' => 1, 'status' => 'deploying'}]}
msg2 = {'nodes' => [{'uid' => 2, 'status' => 'ready'}]}
msg1 = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
msg2 = {'nodes' => [{'uid' => 2,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]}
expected_msg2 = {'nodes' => [{'uid' => 2,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready',
'progress' => 100}]}
up_reporter.expects(:report).with(msg1)
up_reporter.expects(:report).with(msg2)
up_reporter.expects(:report).with(expected_msg2)
reporter.report(msg1)
reporter.report(msg2)
end
it "raises exception if progress provided and no status" do
msg1 = {'nodes' => [{'uid' => 1, 'status' => 'ready'}]}
msg1 = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
msg2 = {'nodes' => [{'uid' => 1, 'progress' => 100}]}
up_reporter.expects(:report).with(msg1)
up_reporter.expects(:report).never
reporter.report(msg1)
lambda {reporter.report(msg2)}.should raise_error
expect{ reporter.report(msg2) }.to raise_error
end
it "raises exception if status of node is not supported" do
@ -146,43 +276,112 @@ describe "TaskProxyReporter" do
end
it "some other attrs are valid and passed" do
msg1 = {'nodes' => [{'uid' => 1, 'status' => 'deploying'}]}
msg2 = {'status' => 'error', 'error_type' => 'deploy',
'nodes' => [{'uid' => 2, 'status' => 'error', 'message' => 'deploy'}]}
msg1 = {'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]}
msg2 = {'status' => 'error',
'error_type' => 'deploy',
'nodes' => [{'uid' => 2,
'status' => 'error',
'message' => 'deploy',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'failed'}]}
expected_msg2 = {
'status' => 'error',
'error_type' => 'deploy',
'nodes' => [{
'uid' => 2,
'status' => 'error',
'message' => 'deploy',
'progress' => 100,
'deployment_graph_task_name' => 'test_2',
'task_status' => 'error'}]}
up_reporter.expects(:report).with(msg1)
up_reporter.expects(:report).with(msg2)
up_reporter.expects(:report).with(expected_msg2)
reporter.report(msg1)
reporter.report(msg2)
end
it "reports if status is greater" do
msgs = [
{'nodes' => [{'uid' => 1, 'status' => 'deploying'}]},
{'nodes' => [{'uid' => 1, 'status' => 'ready'}]},
{'nodes' => [{'uid' => 1, 'status' => 'deploying'}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]},
{'nodes' => [{'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]},
]
expected_msg2 = {'nodes' => [{
'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready',
'progress' => 100}]}
up_reporter.expects(:report).with(msgs[0])
up_reporter.expects(:report).with(msgs[1])
up_reporter.expects(:report).with(expected_msg2)
msgs.each {|msg| reporter.report(msg)}
end
it "report if final status changed" do
msgs = [
{'nodes' => [{'uid' => 1, 'status' => 'deploying'}]},
{'nodes' => [{'uid' => 1, 'status' => 'ready'}]},
{'nodes' => [{'uid' => 1, 'status' => 'deploying'}]},
{'nodes' => [{'uid' => 1, 'status' => 'error'}]}
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]},
{'nodes' => [{'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'successful'}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]},
{'nodes' => [{'uid' => 1,
'status' => 'error',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'failed'}]},
]
expected_msg2 = {'nodes' => [{
'uid' => 1,
'status' => 'ready',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'ready',
'progress' => 100}]}
expected_msg3 = {'nodes' => [{
'uid' => 1,
'status' => 'error',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'error',
'progress' => 100}]}
up_reporter.expects(:report).with(msgs[0])
up_reporter.expects(:report).with(msgs[1])
up_reporter.expects(:report).with(msgs[3])
up_reporter.expects(:report).with(expected_msg2)
up_reporter.expects(:report).with(expected_msg3)
msgs.each {|msg| reporter.report(msg)}
end
it "doesn't update progress if it less than previous progress with same status" do
msgs = [
{'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 50}]},
{'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 10}]}
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running',
'progress' => 50}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running',
'progress' => 10 }]},
]
up_reporter.expects(:report).with(msgs[0])
up_reporter.expects(:report).never
@ -190,11 +389,28 @@ describe "TaskProxyReporter" do
end
it "doesn't forget previously reported attributes" do
msgs = [{'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 50}]},
{'nodes' => [{'uid' => 1, 'status' => 'deploying'}]},
{'nodes' => [{'uid' => 1, 'status' => 'deploying', 'key' => 'value', 'progress' => 60}]},
{'nodes' => [{'uid' => 1, 'status' => 'deploying', 'progress' => 0}]},
]
msgs = [
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running',
'progress' => 50}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running'}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running',
'key' => 'value',
'progress' => 60 }]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_2',
'task_status' => 'running',
'progress' => 0 }]},
]
up_reporter.expects(:report).with(msgs[0])
up_reporter.expects(:report).with(msgs[2])
up_reporter.expects(:report).never
@ -203,13 +419,91 @@ describe "TaskProxyReporter" do
it "report stopped status" do
msgs = [
{'nodes' => [{'uid' => 1, 'status' => 'deploying'}]},
{'nodes' => [{'uid' => 1, 'status' => 'stopped'}]},
{'nodes' => [{'uid' => 1,
'status' => 'deploying',
'deployment_graph_task_name' => 'test_1',
'task_status' => 'running'}]},
{'nodes' => [{'uid' => 1,
'status' => 'stopped',
'deployment_graph_task_name' => 'test_1',
'task_status' => 'successful'}]},
]
expected_msg_1 = {
'nodes' => [{
'uid' => 1,
'status' => 'stopped',
'deployment_graph_task_name' => 'test_1',
'task_status' => 'ready',
'progress' => 100}]}
up_reporter.expects(:report).with(msgs[0])
up_reporter.expects(:report).with(msgs[1])
up_reporter.expects(:report).with(expected_msg_1)
msgs.each {|msg| reporter.report(msg)}
end
context 'tasks' do
let(:msg) do
{'nodes' => [{'status' => 'deploying', 'uid' => '1', 'progress' => 54}.merge(task_part_msg)]
}
end
let(:task_part_msg) do
{'deployment_graph_task_name' => 'test_1', 'task_status' => 'running'}
end
context 'validation' do
it 'should validate deployment graph task name' do
msg['nodes'].first.delete('deployment_graph_task_name')
up_reporter.expects(:report).never
expect { reporter.report(msg) }.to raise_error(
Astute::AstuteError,
/Task name is not provided/
)
end
it 'should validate task status absent' do
msg['nodes'].first.delete('task_status')
up_reporter.expects(:report).never
expect { reporter.report(msg) }.to raise_error(
Astute::AstuteError,
/Task status provided '' is not supported/
)
end
end
context 'task status convertation' do
it 'should convert task running status to running' do
up_reporter.expects(:report).with(msg)
reporter.report(msg)
end
it 'should convert task failed status to error' do
task_part_msg['task_status'] = 'failed'
expected_msg = msg.deep_dup
expected_msg['nodes'].first['task_status'] = 'error'
up_reporter.expects(:report).with(expected_msg)
reporter.report(msg)
end
it 'should convert task successful status to ready' do
task_part_msg['task_status'] = 'successful'
expected_msg = msg.deep_dup
expected_msg['nodes'].first['task_status'] = 'ready'
up_reporter.expects(:report).with(expected_msg)
reporter.report(msg)
end
it 'should failed if task has inccorect status' do
task_part_msg['task_status'] = 'unknown'
up_reporter.expects(:report).never
expect { reporter.report(msg) }.to raise_error(
Astute::AstuteError,
/Task status provided 'unknown' is not supported/
)
end
end
end
end
end