summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Maczukin <tomasz@maczukin.pl>2017-11-16 17:12:33 +0100
committerTomasz Maczukin <tomasz@maczukin.pl>2017-11-28 00:36:48 +0100
commit623eb68195d51ea50e09970771442d992ff19a4a (patch)
treeb8778abd2aabd5a80867f9250884f39b506fa861
parent8e7e2aeb4f0f9e1e61366a62e41fd15936593cfd (diff)
downloadgitlab-ce-623eb68195d51ea50e09970771442d992ff19a4a.tar.gz
Add new API endpoint - list jobs of a specified runner
-rw-r--r--doc/api/runners.md51
-rw-r--r--lib/api/runners.rb18
-rw-r--r--spec/requests/api/runners_spec.rb92
3 files changed, 161 insertions, 0 deletions
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 6304a496f94..171857ef49e 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -215,6 +215,57 @@ DELETE /runners/:id
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/6"
```
+## List runner's running jobs
+
+List running jobs assigned to the specified Runner.
+
+```
+GET /runners/:id/jobs
+```
+
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer | yes | The ID of a runner |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/1/jobs"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 2,
+ "status": "running",
+ "stage": "test",
+ "name": "test",
+ "ref": "master",
+ "tag": false,
+ "coverage": null,
+ "created_at": "2017-11-16T08:50:29.000Z",
+ "started_at": "2017-11-16T08:51:29.000Z",
+ "finished_at": "2017-11-16T08:53:29.000Z",
+ "duration": 120,
+ "user": null,
+ "commit": null,
+ "runner": {
+ "id": 1,
+ "description": "My runner1",
+ "active": true,
+ "is_shared": true,
+ "name": null
+ },
+ "pipeline": {
+ "id": 2,
+ "sha": "97de212e80737a608d939f648d959671fb0a0142",
+ "ref": "master",
+ "status": "pending"
+ }
+ }
+]
+```
+
## List project's runners
List all runners (specific and shared) available in the project. Shared runners
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index e816fcdd928..56b70681852 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -84,6 +84,18 @@ module API
destroy_conditionally!(runner)
end
+
+ desc 'List jobs running on a runner'
+ params do
+ requires :id, type: Integer, desc: 'The ID of the runner'
+ use :pagination
+ end
+ get ':id/jobs' do
+ runner = get_runner(params[:id])
+ authenticate_list_runners_jobs!(runner)
+
+ present paginate(runner.builds.running), with: Entities::Job
+ end
end
params do
@@ -192,6 +204,12 @@ module API
forbidden!("No access granted") unless user_can_access_runner?(runner)
end
+ def authenticate_list_runners_jobs!(runner)
+ return if current_user.admin?
+
+ forbidden!("No access granted") unless user_can_access_runner?(runner)
+ end
+
def user_can_access_runner?(runner)
current_user.ci_authorized_runners.exists?(runner.id)
end
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index fe38a7b3251..95e5dd91c12 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -354,6 +354,98 @@ describe API::Runners do
end
end
+ describe 'GET /runners/:id/jobs' do
+ let!(:job_1) { create(:ci_build) }
+ let!(:job_2) { create(:ci_build, :running, runner: shared_runner) }
+ let!(:job_3) { create(:ci_build, :failed, runner: shared_runner) }
+ let!(:job_4) { create(:ci_build, :running, runner: specific_runner) }
+ let!(:job_5) { create(:ci_build, :failed, runner: specific_runner) }
+
+ context 'admin user' do
+ context 'when runner exists' do
+ context 'when runner is shared' do
+ it 'return jobs' do
+ get api("/runners/#{shared_runner.id}/jobs", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+
+ expect(json_response.length).to eq(1)
+ expect(json_response[0]).to include('id' => job_2.id)
+ end
+ end
+
+ context 'when runner is specific' do
+ it 'return jobs' do
+ get api("/runners/#{specific_runner.id}/jobs", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+
+ expect(json_response.length).to eq(1)
+ expect(json_response[0]).to include('id' => job_4.id)
+ end
+ end
+ end
+
+ context "when runner doesn't exist" do
+ it 'returns 404' do
+ get api('/runners/9999/jobs', admin)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ context "runner project's administrative user" do
+ context 'when runner exists' do
+ context 'when runner is shared' do
+ it 'returns 403' do
+ get api("/runners/#{shared_runner.id}/jobs", user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'when runner is specific' do
+ it 'return jobs' do
+ get api("/runners/#{specific_runner.id}/jobs", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+
+ expect(json_response.length).to eq(1)
+ expect(json_response[0]).to include('id' => job_4.id)
+ end
+ end
+ end
+
+ context "when runner doesn't exist" do
+ it 'returns 404' do
+ get api('/runners/9999/jobs', user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ context 'other authorized user' do
+ it 'does not return jobs' do
+ get api("/runners/#{specific_runner.id}/jobs", user2)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not return jobs' do
+ get api("/runners/#{specific_runner.id}/jobs")
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+ end
+
describe 'GET /projects/:id/runners' do
context 'authorized user with master privileges' do
it "returns project's runners" do