Commit 8f8e2333 authored by Oswaldo Ferreira's avatar Oswaldo Ferreira

Include context metadata to /jobs/:id* APIs

It includes context metadata to /jobs endpoints
that send over the :id param to the API.

If that includes the :id param, we try to fetch
the job's project and user (who triggered) and
pass it over to the application context, which
will eventually log the metadata to Sidekiq logs.
parent 8a56fa9b
......@@ -45,7 +45,7 @@ module API
end
def authenticate_job!
job = Ci::Build.find_by_id(params[:id])
job = current_job
validate_job!(job) do
forbidden! unless job_token_valid?(job)
......@@ -54,6 +54,10 @@ module API
job
end
def current_job
@current_job ||= Ci::Build.find_by_id(params[:id])
end
def job_token_valid?(job)
token = (params[JOB_TOKEN_PARAM] || env[JOB_TOKEN_HEADER]).to_s
token && job.valid_token?(token)
......
......@@ -75,6 +75,13 @@ module API
end
resource :jobs do
before do
Gitlab::ApplicationContext.push(
user: -> { current_job&.user },
project: -> { current_job&.project }
)
end
desc 'Request a job' do
success Entities::JobRequest::Response
http_codes [[201, 'Job was scheduled'],
......
......@@ -311,11 +311,33 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
describe '/api/v4/jobs' do
shared_examples 'application context metadata' do |api_route|
it 'contains correct context metadata' do
# Avoids popping the context from the thread so we can
# check its content after the request.
allow(Labkit::Context).to receive(:pop)
send_request
Labkit::Context.with_context do |context|
expected_context = {
'meta.caller_id' => api_route,
'meta.user' => job.user.username,
'meta.project' => job.project.full_path,
'meta.root_namespace' => job.project.full_path_components.first
}
expect(context.to_h).to include(expected_context)
end
end
end
let(:root_namespace) { create(:namespace) }
let(:namespace) { create(:namespace, parent: root_namespace) }
let(:project) { create(:project, namespace: namespace, shared_runners_enabled: false) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') }
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:user) { create(:user) }
let(:job) do
create(:ci_build, :artifacts, :extended_options,
pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0)
......@@ -984,12 +1006,18 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
describe 'PUT /api/v4/jobs/:id' do
let(:job) { create(:ci_build, :pending, :trace_live, pipeline: pipeline, runner_id: runner.id) }
let(:job) do
create(:ci_build, :pending, :trace_live, pipeline: pipeline, project: project, user: user, runner_id: runner.id)
end
before do
job.run!
end
it_behaves_like 'application context metadata', '/api/:version/jobs/:id' do
let(:send_request) { update_job(state: 'success') }
end
context 'when status is given' do
it 'mark job as succeeded' do
update_job(state: 'success')
......@@ -1139,7 +1167,10 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
describe 'PATCH /api/v4/jobs/:id/trace' do
let(:job) { create(:ci_build, :running, :trace_live, runner_id: runner.id, pipeline: pipeline) }
let(:job) do
create(:ci_build, :running, :trace_live,
project: project, user: user, runner_id: runner.id, pipeline: pipeline)
end
let(:headers) { { API::Helpers::Runner::JOB_TOKEN_HEADER => job.token, 'Content-Type' => 'text/plain' } }
let(:headers_with_range) { headers.merge({ 'Content-Range' => '11-20' }) }
let(:update_interval) { 10.seconds.to_i }
......@@ -1148,6 +1179,10 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
initial_patch_the_trace
end
it_behaves_like 'application context metadata', '/api/:version/jobs/:id/trace' do
let(:send_request) { patch_the_trace }
end
context 'when request is valid' do
it 'gets correct response' do
expect(response.status).to eq 202
......@@ -1399,7 +1434,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
describe 'artifacts' do
let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner_id: runner.id) }
let(:job) { create(:ci_build, :pending, user: user, project: project, pipeline: pipeline, runner_id: runner.id) }
let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
let(:headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } }
let(:headers_with_token) { headers.merge(API::Helpers::Runner::JOB_TOKEN_HEADER => job.token) }
......@@ -1418,6 +1453,10 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
authorize_artifacts_with_token_in_params
end
it_behaves_like 'application context metadata', '/api/:version/jobs/:id/artifacts/authorize' do
let(:send_request) { subject }
end
shared_examples 'authorizes local file' do
it 'succeeds' do
subject
......@@ -1571,6 +1610,12 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
describe 'POST /api/v4/jobs/:id/artifacts' do
it_behaves_like 'application context metadata', '/api/:version/jobs/:id/artifacts' do
let(:send_request) do
upload_artifacts(file_upload, headers_with_token)
end
end
context 'when artifacts are being stored inside of tmp path' do
before do
# by configuring this path we allow to pass temp file from any path
......@@ -1931,6 +1976,10 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
describe 'GET /api/v4/jobs/:id/artifacts' do
let(:token) { job.token }
it_behaves_like 'application context metadata', '/api/:version/jobs/:id/artifacts' do
let(:send_request) { download_artifact }
end
context 'when job has artifacts' do
let(:job) { create(:ci_build) }
let(:store) { JobArtifactUploader::Store::LOCAL }
......
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