Commit cd9e3a23 authored by Alex Buijs's avatar Alex Buijs

Add root_namespace and project metadata for APi

This adds meta.project and meta.root_namespace
data when available for the /api/:version/runners and
/api/:version/jobs/request API endpoints
parent ff21bade
---
title: Add runners api context metadata
merge_request: 55089
author:
type: changed
......@@ -34,12 +34,12 @@ module API
if runner_registration_token_valid?
# Create shared runner. Requires admin access
attributes.merge(runner_type: :instance_type)
elsif project = Project.find_by_runners_token(params[:token])
elsif @project = Project.find_by_runners_token(params[:token])
# Create a specific runner for the project
attributes.merge(runner_type: :project_type, projects: [project])
elsif group = Group.find_by_runners_token(params[:token])
attributes.merge(runner_type: :project_type, projects: [@project])
elsif @group = Group.find_by_runners_token(params[:token])
# Create a specific runner for the group
attributes.merge(runner_type: :group_type, groups: [group])
attributes.merge(runner_type: :group_type, groups: [@group])
else
forbidden!
end
......@@ -81,12 +81,7 @@ module API
end
resource :jobs do
before do
Gitlab::ApplicationContext.push(
user: -> { current_job&.user },
project: -> { current_job&.project }
)
end
before { set_application_context }
desc 'Request a job' do
success Entities::JobRequest::Response
......
......@@ -71,6 +71,26 @@ module API
header 'Job-Status', job.status
forbidden!(reason)
end
def set_application_context
if current_job
Gitlab::ApplicationContext.push(
user: -> { current_job.user },
project: -> { current_job.project }
)
elsif current_runner&.project_type?
Gitlab::ApplicationContext.push(
project: -> do
projects = current_runner.projects.limit(2) # rubocop: disable CodeReuse/ActiveRecord
projects.first if projects.length == 1
end
)
elsif current_runner&.group_type?
Gitlab::ApplicationContext.push(
namespace: -> { current_runner.groups.first }
)
end
end
end
end
end
......@@ -798,6 +798,50 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
describe 'setting the application context' do
subject { request_job }
context 'when triggered by a user' do
let(:job) { create(:ci_build, user: user, project: project) }
subject { request_job(id: job.id) }
it_behaves_like 'storing arguments in the application context' do
let(:expected_params) { { user: user.username, project: project.full_path } }
end
it_behaves_like 'not executing any extra queries for the application context', 3 do
# Extra queries: User, Project, Route
let(:subject_proc) { proc { request_job(id: job.id) } }
end
end
context 'when the runner is of project type' do
it_behaves_like 'storing arguments in the application context' do
let(:expected_params) { { project: project.full_path } }
end
it_behaves_like 'not executing any extra queries for the application context', 2 do
# Extra queries: Project, Route
let(:subject_proc) { proc { request_job } }
end
end
context 'when the runner is of group type' do
let(:group) { create(:group) }
let(:runner) { create(:ci_runner, :group, groups: [group]) }
it_behaves_like 'storing arguments in the application context' do
let(:expected_params) { { root_namespace: group.full_path_components.first } }
end
it_behaves_like 'not executing any extra queries for the application context', 2 do
# Extra queries: Group, Route
let(:subject_proc) { proc { request_job } }
end
end
end
def request_job(token = runner.token, **params)
new_params = params.merge(token: token, last_update: last_update)
post api('/jobs/request'), params: new_params.to_json, headers: { 'User-Agent' => user_agent, 'Content-Type': 'application/json' }
......
......@@ -35,6 +35,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when valid token is provided' do
def request
post api('/runners'), params: { token: token }
end
it 'creates runner with default values' do
post api('/runners'), params: { token: registration_token }
......@@ -51,9 +55,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when project token is used' do
let(:project) { create(:project) }
let(:token) { project.runners_token }
it 'creates project runner' do
post api('/runners'), params: { token: project.runners_token }
request
expect(response).to have_gitlab_http_status(:created)
expect(project.runners.size).to eq(1)
......@@ -62,13 +67,24 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(runner.token).not_to eq(project.runners_token)
expect(runner).to be_project_type
end
it_behaves_like 'storing arguments in the application context' do
subject { request }
let(:expected_params) { { project: project.full_path } }
end
it_behaves_like 'not executing any extra queries for the application context' do
let(:subject_proc) { proc { request } }
end
end
context 'when group token is used' do
let(:group) { create(:group) }
let(:token) { group.runners_token }
it 'creates a group runner' do
post api('/runners'), params: { token: group.runners_token }
request
expect(response).to have_gitlab_http_status(:created)
expect(group.runners.reload.size).to eq(1)
......@@ -77,6 +93,16 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(runner.token).not_to eq(group.runners_token)
expect(runner).to be_group_type
end
it_behaves_like 'storing arguments in the application context' do
subject { request }
let(:expected_params) { { root_namespace: group.full_path_components.first } }
end
it_behaves_like 'not executing any extra queries for the application context' do
let(:subject_proc) { proc { request } }
end
end
end
......
......@@ -22,3 +22,19 @@ RSpec.shared_examples 'storing arguments in the application context' do
hash.transform_keys! { |key| "meta.#{key}" }
end
end
RSpec.shared_examples 'not executing any extra queries for the application context' do |expected_extra_queries = 0|
it 'does not execute more queries than without adding anything to the application context' do
# Call the subject once to memoize all factories being used for the spec, so they won't
# add any queries to the expectation.
subject_proc.call
expect do
allow(Gitlab::ApplicationContext).to receive(:push).and_call_original
subject_proc.call
end.to issue_same_number_of_queries_as {
allow(Gitlab::ApplicationContext).to receive(:push)
subject_proc.call
}.with_threshold(expected_extra_queries).ignoring_cached_queries
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment