require 'test_plugin_helper' module ForemanRemoteExecution class RunHostsJobTest < ActiveSupport::TestCase include Dynflow::Testing let(:host) { FactoryGirl.create(:host, :with_execution) } let(:proxy) { host.remote_execution_proxies('SSH')[:subnet].first } let(:targeting) { FactoryGirl.create(:targeting, :search_query => "name = #{host.name}", :user => User.current) } let(:job_invocation) do FactoryGirl.build(:job_invocation, :with_template).tap do |invocation| invocation.targeting = targeting invocation.save end end let(:task) do OpenStruct.new(:id => '123').tap do |o| o.stubs(:add_missing_task_groups) o.stubs(:task_groups).returns([]) end end let(:action) do create_action(Actions::RemoteExecution::RunHostsJob).tap do |action| action.expects(:action_subject).with(job_invocation) ForemanTasks::Task::DynflowTask.stubs(:where).returns(mock.tap { |m| m.stubs(:first! => task) }) end end let(:planned) do plan_action action, job_invocation end before do ProxyAPI::ForemanDynflow::DynflowProxy.any_instance.stubs(:tasks_count).returns(0) User.current = users :admin action end it 'resolves the hosts on targeting in plan phase' do planned targeting.hosts.must_include(host) end it 'triggers the RunHostJob actions on the resolved hosts in run phase' do planned.expects(:trigger).with() { |*args| args[0] == Actions::RemoteExecution::RunHostJob } planned.create_sub_plans end it 'uses the BindJobInvocation middleware' do planned job_invocation.task_id.must_equal '123' end describe 'concurrency control' do let(:level) { 5 } let(:span) { 60 } it 'can be disabled' do job_invocation.expects(:concurrency_level) job_invocation.expects(:time_span) action.expects(:limit_concurrency_level).never action.expects(:distribute_over_time).never planned end it 'can limit concurrency level' do job_invocation.expects(:concurrency_level).returns(level).twice job_invocation.expects(:time_span) action.expects(:limit_concurrency_level).with(level) action.expects(:distribute_over_time).never planned end it 'can distribute tasks over time' do job_invocation.expects(:time_span).returns(span).twice job_invocation.expects(:concurrency_level) action.expects(:distribute_over_time).with(span) action.expects(:distribute_over_time).never planned end it 'can use both' do job_invocation.expects(:time_span).returns(span).twice action.expects(:distribute_over_time).with(span) job_invocation.expects(:concurrency_level).returns(level).twice action.expects(:limit_concurrency_level).with(level) planned end end end end