441 lines
12 KiB
Ruby
441 lines
12 KiB
Ruby
# Copyright 2015 Mirantis, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
require File.join(File.dirname(__FILE__), '../spec_helper')
|
|
|
|
describe Astute::TaskNode do
|
|
include SpecHelpers
|
|
|
|
let(:cluster) do
|
|
Astute::TaskCluster.new
|
|
end
|
|
|
|
let(:ctx) do
|
|
ctx = mock('context')
|
|
ctx.stubs(:task_id)
|
|
ctx.stubs(:report)
|
|
ctx
|
|
end
|
|
|
|
let(:task_node) do
|
|
node = Astute::TaskNode.new('node_id', cluster)
|
|
node.context = ctx
|
|
node
|
|
end
|
|
|
|
let(:task) do
|
|
task_node.graph.create_task(
|
|
task_data['id'],
|
|
task_data.merge({'node_id' => 'node_id'})
|
|
)
|
|
end
|
|
|
|
context '#run' 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" => "/"
|
|
},
|
|
"type" => "puppet",
|
|
"fail_on_error" => true,
|
|
"required_for" => [],
|
|
"requires" => [],
|
|
"id" => "openstack-haproxy-mysqld",
|
|
}
|
|
end
|
|
|
|
it 'should run task' do
|
|
Astute::Puppet.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'should run noop puppet task' do
|
|
cluster_new = Astute::TaskCluster.new
|
|
cluster_new.uid = 'test2'
|
|
cluster_new.noop_run = true
|
|
task_node_new = Astute::TaskNode.new('node_id', cluster_new)
|
|
task_node_new.context = ctx
|
|
task_node_new.graph.create_task(
|
|
task_data['id'],
|
|
task_data.merge({'node_id' => 'node_id'})
|
|
)
|
|
Astute::NoopPuppet.any_instance.expects(:run)
|
|
task_node_new.run(task)
|
|
end
|
|
|
|
it 'should mark node as busy' do
|
|
Astute::Puppet.any_instance.stubs(:run)
|
|
task_node.run(task)
|
|
expect(task_node.status).to eql(:busy)
|
|
end
|
|
|
|
it 'should mark task as running' do
|
|
Astute::Puppet.any_instance.stubs(:run)
|
|
task_node.run(task)
|
|
expect(task.status).to eql(:running)
|
|
end
|
|
|
|
it 'should report about task as running' do
|
|
Astute::Puppet.any_instance.stubs(:run)
|
|
ctx.expects(:report).with('nodes' => [{
|
|
'uid' => 'node_id',
|
|
'progress' => 0,
|
|
'deployment_graph_task_name' => 'openstack-haproxy-mysqld',
|
|
'task_status' => 'running',
|
|
'summary' => {}
|
|
}])
|
|
task_node.run(task)
|
|
end
|
|
|
|
context 'should not report about task as running' do
|
|
let(:task_data_wo_type) do
|
|
{
|
|
"type" => "noop",
|
|
"fail_on_error" => true,
|
|
"required_for" => [],
|
|
"requires" => [],
|
|
"id" => "openstack-haproxy"
|
|
}
|
|
end
|
|
|
|
shared_examples 'disable running report' do
|
|
it 'task should not report running status' do
|
|
ctx.unstub(:report)
|
|
ctx.expects(:report).never
|
|
task_node.run(task)
|
|
end
|
|
end
|
|
|
|
context 'noop' do
|
|
let(:task_data) { task_data_wo_type.merge!('type'=> 'noop') }
|
|
it_behaves_like 'disable running report'
|
|
end
|
|
|
|
context 'stage' do
|
|
let(:task_data) { task_data_wo_type.merge!('type'=> 'stage') }
|
|
it_behaves_like 'disable running report'
|
|
end
|
|
|
|
context 'skipped' do
|
|
let(:task_data) { task_data_wo_type.merge!('type'=> 'skipped') }
|
|
it_behaves_like 'disable running report'
|
|
end
|
|
end
|
|
|
|
context 'support different task type' do
|
|
|
|
let(:task_data) do
|
|
{
|
|
"parameters" => {},
|
|
"type" => "noop",
|
|
"fail_on_error" => false,
|
|
"required_for" => [],
|
|
"requires" => [],
|
|
"id" => "test-task",
|
|
}
|
|
end
|
|
|
|
it 'shell' do
|
|
task_data['type'] = "shell"
|
|
Astute::Shell.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'puppet' do
|
|
task_data['type'] = "puppet"
|
|
Astute::Puppet.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'sync' do
|
|
task_data['type'] = "sync"
|
|
Astute::Sync.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'cobbler_sync' do
|
|
task_data['type'] = "cobbler_sync"
|
|
Astute::CobblerSync.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'noop' do
|
|
task_data['type'] = "noop"
|
|
Astute::Noop.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'skipped' do
|
|
task_data['type'] = "skipped"
|
|
Astute::Skipped.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'stage' do
|
|
task_data['type'] = "stage"
|
|
Astute::Stage.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'reboot' do
|
|
task_data['type'] = "reboot"
|
|
Astute::Reboot.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'upload_file' do
|
|
task_data['type'] = "upload_file"
|
|
Astute::UploadFile.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'upload_files' do
|
|
task_data['type'] = "upload_files"
|
|
task_data['parameters']['nodes'] = []
|
|
Astute::UploadFiles.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'copy_files' do
|
|
task_data['type'] = "copy_files"
|
|
task_data['parameters']['files'] = []
|
|
Astute::CopyFiles.any_instance.expects(:run)
|
|
task_node.run(task)
|
|
end
|
|
|
|
it 'unkown type' do
|
|
task_data['type'] = "unknown"
|
|
expect{task_node.run(task)}.to raise_error(
|
|
Astute::TaskValidationError,
|
|
"Unknown task type 'unknown'. Detailed: uninitialized constant Astute::Unknown")
|
|
end
|
|
end # support task type
|
|
end
|
|
|
|
|
|
context '#poll' do
|
|
|
|
context 'not busy' do
|
|
it 'should not raise any error' do
|
|
expect{task_node.poll}.not_to raise_error
|
|
end
|
|
|
|
it 'should not change node status' do
|
|
old_status = task_node.status
|
|
task_node.poll
|
|
expect(task_node.status).to eql(old_status)
|
|
end
|
|
end
|
|
|
|
context 'busy' do
|
|
let(:task_data) do
|
|
{
|
|
"parameters" => {},
|
|
"type" => "puppet",
|
|
"fail_on_error" => false,
|
|
"required_for" => [],
|
|
"requires" => [],
|
|
"id" => "test-task",
|
|
}
|
|
end
|
|
|
|
before(:each) do
|
|
Astute::Puppet.any_instance.stubs(:run)
|
|
end
|
|
|
|
context 'mark failed' do
|
|
it 'if task failed' do
|
|
Astute::Puppet.any_instance.stubs(:status).returns(:failed)
|
|
ctx.stubs(:report)
|
|
task_node.run(task)
|
|
task_node.poll
|
|
expect(task_node.status).to eql(:failed)
|
|
end
|
|
end
|
|
|
|
context 'mark online' do
|
|
it 'if task successful' do
|
|
Astute::Puppet.any_instance.stubs(:status).returns(:successful)
|
|
ctx.stubs(:report)
|
|
task_node.run(task)
|
|
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
|
|
Astute::Puppet.any_instance.expects(:status).returns(:running)
|
|
task_node.run(task)
|
|
ctx.expects(:report).with({
|
|
'nodes' => [{
|
|
'uid' => 'node_id',
|
|
'deployment_graph_task_name' => task.name,
|
|
'task_status' => 'running',
|
|
'progress' => 0}]
|
|
})
|
|
task_node.poll
|
|
end
|
|
|
|
it 'should report ready if task successful and no more task' do
|
|
cluster.node_statuses_transitions['successful'] = {
|
|
'status' => 'ready'
|
|
}
|
|
|
|
Astute::Puppet.any_instance.expects(:status).returns(:successful)
|
|
task_node.run(task)
|
|
ctx.expects(:report).with({
|
|
'nodes' => [{
|
|
'uid' => 'node_id',
|
|
'status' => 'ready',
|
|
'deployment_graph_task_name' => task.name,
|
|
'summary' => {},
|
|
'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
|
|
cluster.node_statuses_transitions['successful'] = {
|
|
'status' => 'ready'
|
|
}
|
|
task_node.run(task)
|
|
ctx.expects(:report).with({
|
|
'nodes' => [{
|
|
'uid' => 'node_id',
|
|
'deployment_graph_task_name' => task.name,
|
|
'status' => 'ready',
|
|
'summary' => {},
|
|
'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',
|
|
'deployment_graph_task_name' => task.name,
|
|
'summary' => {},
|
|
'task_status' => 'skipped',
|
|
'progress' => 50}]
|
|
})
|
|
task_node.poll
|
|
end
|
|
end
|
|
|
|
it 'should report error if task failed and no more task' do
|
|
cluster.node_statuses_transitions['failed'] = {
|
|
'status' => 'error',
|
|
'error_type' => 'deploy'
|
|
}
|
|
|
|
Astute::Puppet.any_instance.expects(:status).returns(:failed)
|
|
|
|
task_node.run(task)
|
|
ctx.expects(:report).with({
|
|
'nodes' => [{
|
|
'uid' => 'node_id',
|
|
'status' => 'error',
|
|
'deployment_graph_task_name' => task.name,
|
|
'summary' => {},
|
|
'task_status' => 'failed',
|
|
'error_type' => 'deploy',
|
|
'error_msg' => "Task #{task.name} failed on node node_id",
|
|
'progress' => 100}]
|
|
})
|
|
task_node.poll
|
|
end
|
|
|
|
it 'should report deploy progress if task successful and another tasks exists' do
|
|
Astute::Puppet.any_instance.expects(:status).returns(:successful)
|
|
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',
|
|
'deployment_graph_task_name' => task.name,
|
|
'summary' => {},
|
|
'task_status' => 'successful',
|
|
'progress' => 50}]
|
|
})
|
|
task_node.poll
|
|
end
|
|
|
|
it 'should not report deploy progress if task failed and another tasks exists' do
|
|
Astute::Puppet.any_instance.expects(:status).returns(:failed)
|
|
task_node.graph.create_task(
|
|
'second_task',
|
|
task_data.merge({'node_id' => 'node_id'})
|
|
)
|
|
|
|
task_node.run(task)
|
|
ctx.expects(:report).never
|
|
task_node.poll
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
|
|
end
|