diff options
Diffstat (limited to 'spec/models/ci/runner_machine_spec.rb')
-rw-r--r-- | spec/models/ci/runner_machine_spec.rb | 158 |
1 files changed, 152 insertions, 6 deletions
diff --git a/spec/models/ci/runner_machine_spec.rb b/spec/models/ci/runner_machine_spec.rb index e39f987110f..d0979d8a485 100644 --- a/spec/models/ci/runner_machine_spec.rb +++ b/spec/models/ci/runner_machine_spec.rb @@ -6,11 +6,14 @@ RSpec.describe Ci::RunnerMachine, feature_category: :runner_fleet, type: :model it_behaves_like 'having unique enum values' it { is_expected.to belong_to(:runner) } + it { is_expected.to belong_to(:runner_version).with_foreign_key(:version) } + it { is_expected.to have_many(:build_metadata) } + it { is_expected.to have_many(:builds).through(:build_metadata) } describe 'validation' do it { is_expected.to validate_presence_of(:runner) } - it { is_expected.to validate_presence_of(:machine_xid) } - it { is_expected.to validate_length_of(:machine_xid).is_at_most(64) } + it { is_expected.to validate_presence_of(:system_xid) } + it { is_expected.to validate_length_of(:system_xid).is_at_most(64) } it { is_expected.to validate_length_of(:version).is_at_most(2048) } it { is_expected.to validate_length_of(:revision).is_at_most(255) } it { is_expected.to validate_length_of(:platform).is_at_most(255) } @@ -37,10 +40,11 @@ RSpec.describe Ci::RunnerMachine, feature_category: :runner_fleet, type: :model describe '.stale', :freeze_time do subject { described_class.stale.ids } - let!(:runner_machine1) { create(:ci_runner_machine, created_at: 8.days.ago, contacted_at: 7.days.ago) } - let!(:runner_machine2) { create(:ci_runner_machine, created_at: 7.days.ago, contacted_at: nil) } - let!(:runner_machine3) { create(:ci_runner_machine, created_at: 5.days.ago, contacted_at: nil) } - let!(:runner_machine4) do + let!(:runner_machine1) { create(:ci_runner_machine, :stale) } + let!(:runner_machine2) { create(:ci_runner_machine, :stale, contacted_at: nil) } + let!(:runner_machine3) { create(:ci_runner_machine, created_at: 6.months.ago, contacted_at: Time.current) } + let!(:runner_machine4) { create(:ci_runner_machine, created_at: 5.days.ago) } + let!(:runner_machine5) do create(:ci_runner_machine, created_at: (7.days - 1.second).ago, contacted_at: (7.days - 1.second).ago) end @@ -48,4 +52,146 @@ RSpec.describe Ci::RunnerMachine, feature_category: :runner_fleet, type: :model is_expected.to match_array([runner_machine1.id, runner_machine2.id]) end end + + describe '#heartbeat', :freeze_time do + let(:runner_machine) { create(:ci_runner_machine) } + let(:executor) { 'shell' } + let(:version) { '15.0.1' } + let(:values) do + { + ip_address: '8.8.8.8', + architecture: '18-bit', + config: { gpus: "all" }, + executor: executor, + version: version + } + end + + subject(:heartbeat) do + runner_machine.heartbeat(values) + end + + context 'when database was updated recently' do + before do + runner_machine.contacted_at = Time.current + end + + it 'schedules version update' do + expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).to receive(:perform_async).with(version).once + + heartbeat + + expect(runner_machine.runner_version).to be_nil + end + + it 'updates cache' do + expect_redis_update + + heartbeat + end + + context 'with only ip_address specified' do + let(:values) do + { ip_address: '1.1.1.1' } + end + + it 'updates only ip_address' do + attrs = Gitlab::Json.dump(ip_address: '1.1.1.1', contacted_at: Time.current) + + Gitlab::Redis::Cache.with do |redis| + redis_key = runner_machine.send(:cache_attribute_key) + expect(redis).to receive(:set).with(redis_key, attrs, any_args) + end + + heartbeat + end + end + end + + context 'when database was not updated recently' do + before do + runner_machine.contacted_at = 2.hours.ago + + allow(Ci::Runners::ProcessRunnerVersionUpdateWorker).to receive(:perform_async).with(version).once + end + + context 'with invalid runner_machine' do + before do + runner_machine.runner = nil + end + + it 'still updates redis cache and database' do + expect(runner_machine).to be_invalid + + expect_redis_update + does_db_update + + expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).to have_received(:perform_async) + .with(version).once + end + end + + context 'with unchanged runner_machine version' do + let(:runner_machine) { create(:ci_runner_machine, version: version) } + + it 'does not schedule ci_runner_versions update' do + heartbeat + + expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).not_to have_received(:perform_async) + end + end + + it 'updates redis cache and database' do + expect_redis_update + does_db_update + + expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).to have_received(:perform_async) + .with(version).once + end + + Ci::Runner::EXECUTOR_NAME_TO_TYPES.each_key do |executor| + context "with #{executor} executor" do + let(:executor) { executor } + + it 'updates with expected executor type' do + expect_redis_update + + heartbeat + + expect(runner_machine.reload.read_attribute(:executor_type)).to eq(expected_executor_type) + end + + def expected_executor_type + executor.gsub(/[+-]/, '_') + end + end + end + + context "with an unknown executor type" do + let(:executor) { 'some-unknown-type' } + + it 'updates with unknown executor type' do + expect_redis_update + + heartbeat + + expect(runner_machine.reload.read_attribute(:executor_type)).to eq('unknown') + end + end + end + + def expect_redis_update + Gitlab::Redis::Cache.with do |redis| + redis_key = runner_machine.send(:cache_attribute_key) + expect(redis).to receive(:set).with(redis_key, anything, any_args).and_call_original + end + end + + def does_db_update + expect { heartbeat }.to change { runner_machine.reload.read_attribute(:contacted_at) } + .and change { runner_machine.reload.read_attribute(:architecture) } + .and change { runner_machine.reload.read_attribute(:config) } + .and change { runner_machine.reload.read_attribute(:executor_type) } + end + end end |