diff --git a/app/controllers/crons_controller.rb b/app/controllers/crons_controller.rb index 4e33823d4..deccdbd71 100644 --- a/app/controllers/crons_controller.rb +++ b/app/controllers/crons_controller.rb @@ -4,18 +4,6 @@ class CronsController < ApplicationController SCRIPT_PATH = Rails.root.join('cron') CRON_DEFINITIONS = Rails.root.join('cron.yaml') - def configured_job_names - YAML.load_file(CRON_DEFINITIONS)['cron'].map { |d| d['name'] } - end - - def runnable? - request.local? && configured_job_names.include?(taskname) - end - - def taskname - request.headers['X-Aws-Sqsd-Taskname'] - end - def create return head(:forbidden) unless runnable? @@ -27,4 +15,31 @@ def create render(plain: "Unable to run #{taskname}", status: 500) end end + + private + + def runnable? + request.local? && configured_job_names.include?(taskname) && !running_same_job? + end + + def configured_job_names + YAML.load_file(CRON_DEFINITIONS)['cron'].map { |d| d['name'] } + end + + def taskname + @taskname ||= request.headers['X-Aws-Sqsd-Taskname'] + end + + def running_same_job? + res = false + IO.popen('ps ax') do |io| + io.each_line do |line| + if line.chomp.split.last.end_with?(taskname) + res = true + break + end + end + end + res + end end diff --git a/spec/controllers/crons_controller_spec.rb b/spec/controllers/crons_controller_spec.rb new file mode 100644 index 000000000..37384ca68 --- /dev/null +++ b/spec/controllers/crons_controller_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +# frozen_string_literals: true + +require 'spec_helper' + +RSpec.describe CronsController, type: :controller do + describe 'GET #create' do + before do + @request.env['REMOTE_ADDR'] = '127.0.0.1' + allow(IO).to receive(:popen) + .with('ps ax') + .and_yield( + StringIO.new(<<~STRING) + PID TTY TIME CMD + 1 ? S 0:00 bash ./dump_measurements + STRING + ) + allow(controller).to receive(:system) # Not to run cron jobs + allow($?).to receive(:success?).and_return(true) # rubocop:disable Style/SpecialGlobalVars + end + + describe 'when task exists' do + before do + allow(controller).to receive(:taskname).and_return('dump_clean') + end + + it 'returns HTTP 200 OK' do + get :create + + expect(response).to have_http_status(200) + end + end + + describe 'when task exists but try to run same job' do + before do + allow(controller).to receive(:taskname).and_return('dump_measurements') + end + + it 'returns HTTP 403 Forbidden' do + get :create + + expect(response).to have_http_status(403) + end + end + end +end