support group runners in existing API endpoints

This commit is contained in:
Alexis Reigel 2017-09-12 11:34:34 +02:00 committed by Alexis Reigel
parent 7fbdd17cbc
commit b55c3a7bc4
No known key found for this signature in database
GPG key ID: 55ADA7C7B683B329
7 changed files with 239 additions and 77 deletions

View file

@ -242,13 +242,18 @@ module API
expose :requested_at expose :requested_at
end end
class Group < Grape::Entity class BasicGroupDetails < Grape::Entity
expose :id, :name, :path, :description, :visibility expose :id
expose :web_url
expose :name
end
class Group < BasicGroupDetails
expose :path, :description, :visibility
expose :lfs_enabled?, as: :lfs_enabled expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url do |group, options| expose :avatar_url do |group, options|
group.avatar_url(only_path: false) group.avatar_url(only_path: false)
end end
expose :web_url
expose :request_access_enabled expose :request_access_enabled
expose :full_name, :full_path expose :full_name, :full_path
@ -965,6 +970,13 @@ module API
options[:current_user].authorized_projects.where(id: runner.projects) options[:current_user].authorized_projects.where(id: runner.projects)
end end
end end
expose :groups, with: Entities::BasicGroupDetails do |runner, options|
if options[:current_user].admin?
runner.groups
else
options[:current_user].authorized_groups.where(id: runner.groups)
end
end
end end
class RunnerRegistrationDetails < Grape::Entity class RunnerRegistrationDetails < Grape::Entity

View file

@ -25,8 +25,11 @@ module API
# Create shared runner. Requires admin access # Create shared runner. Requires admin access
Ci::Runner.create(attributes.merge(is_shared: true)) Ci::Runner.create(attributes.merge(is_shared: true))
elsif project = Project.find_by(runners_token: params[:token]) elsif project = Project.find_by(runners_token: params[:token])
# Create a specific runner for project. # Create a specific runner for the project
project.runners.create(attributes) project.runners.create(attributes)
elsif group = Group.find_by(runners_token: params[:token])
# Create a specific runner for the group
group.runners.create(attributes)
end end
break forbidden! unless runner break forbidden! unless runner

View file

@ -199,6 +199,7 @@ module API
forbidden!("Runner is shared") if runner.is_shared? forbidden!("Runner is shared") if runner.is_shared?
forbidden!("Runner associated with more than one project") if runner.projects.count > 1 forbidden!("Runner associated with more than one project") if runner.projects.count > 1
forbidden!("Runner associated with more that one group") if runner.groups.count > 1
forbidden!("No access granted") unless user_can_access_runner?(runner) forbidden!("No access granted") unless user_can_access_runner?(runner)
end end

View file

@ -54,6 +54,7 @@ module API
forbidden!("Runner is shared") if runner.is_shared? forbidden!("Runner is shared") if runner.is_shared?
forbidden!("Runner associated with more than one project") if runner.projects.count > 1 forbidden!("Runner associated with more than one project") if runner.projects.count > 1
forbidden!("Runner associated with more that one group") if runner.groups.count > 1
forbidden!("No access granted") unless user_can_access_runner?(runner) forbidden!("No access granted") unless user_can_access_runner?(runner)
end end

View file

@ -45,7 +45,7 @@ describe API::Runner do
context 'when project token is used' do context 'when project token is used' do
let(:project) { create(:project) } let(:project) { create(:project) }
it 'creates runner' do it 'creates project runner' do
post api('/runners'), token: project.runners_token post api('/runners'), token: project.runners_token
expect(response).to have_gitlab_http_status 201 expect(response).to have_gitlab_http_status 201
@ -54,6 +54,19 @@ describe API::Runner do
expect(Ci::Runner.first.token).not_to eq(project.runners_token) expect(Ci::Runner.first.token).not_to eq(project.runners_token)
end end
end end
context 'when group token is used' do
let(:group) { create(:group) }
it 'creates a group runner' do
post api('/runners'), token: group.runners_token
expect(response).to have_http_status 201
expect(group.runners.size).to eq(1)
expect(Ci::Runner.first.token).not_to eq(registration_token)
expect(Ci::Runner.first.token).not_to eq(group.runners_token)
end
end
end end
context 'when runner description is provided' do context 'when runner description is provided' do

View file

@ -8,22 +8,29 @@ describe API::Runners do
let(:project) { create(:project, creator_id: user.id) } let(:project) { create(:project, creator_id: user.id) }
let(:project2) { create(:project, creator_id: user.id) } let(:project2) { create(:project, creator_id: user.id) }
let!(:shared_runner) { create(:ci_runner, :shared) } let(:group) { create(:group).tap { |group| group.add_owner(user) } }
let!(:unused_specific_runner) { create(:ci_runner) } let(:group2) { create(:group).tap { |group| group.add_owner(user) } }
let!(:specific_runner) do let!(:shared_runner) { create(:ci_runner, :shared, description: 'Shared runner') }
create(:ci_runner).tap do |runner| let!(:unused_project_runner) { create(:ci_runner) }
let!(:project_runner) do
create(:ci_runner, description: 'Project runner').tap do |runner|
create(:ci_runner_project, runner: runner, project: project) create(:ci_runner_project, runner: runner, project: project)
end end
end end
let!(:two_projects_runner) do let!(:two_projects_runner) do
create(:ci_runner).tap do |runner| create(:ci_runner, description: 'Two projects runner').tap do |runner|
create(:ci_runner_project, runner: runner, project: project) create(:ci_runner_project, runner: runner, project: project)
create(:ci_runner_project, runner: runner, project: project2) create(:ci_runner_project, runner: runner, project: project2)
end end
end end
let!(:group_runner) { create(:ci_runner, description: 'Group runner', groups: [group]) }
let!(:two_groups_runner) { create(:ci_runner, description: 'Two groups runner', groups: [group, group2]) }
before do before do
# Set project access for users # Set project access for users
create(:project_member, :master, user: user, project: project) create(:project_member, :master, user: user, project: project)
@ -37,9 +44,13 @@ describe API::Runners do
get api('/runners', user) get api('/runners', user)
shared = json_response.any? { |r| r['is_shared'] } shared = json_response.any? { |r| r['is_shared'] }
descriptions = json_response.map { |runner| runner['description'] }
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(descriptions).to contain_exactly(
'Project runner', 'Group runner', 'Two projects runner', 'Two groups runner'
)
expect(shared).to be_falsey expect(shared).to be_falsey
end end
@ -129,10 +140,26 @@ describe API::Runners do
context 'when runner is not shared' do context 'when runner is not shared' do
it "returns runner's details" do it "returns runner's details" do
get api("/runners/#{specific_runner.id}", admin) get api("/runners/#{project_runner.id}", admin)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response['description']).to eq(specific_runner.description) expect(json_response['description']).to eq(project_runner.description)
end
it "returns the project's details for a project runner" do
get api("/runners/#{project_runner.id}", admin)
expect(json_response['projects'].first['id']).to eq(project.id)
end
it "returns the group's details for a group runner" do
get api("/runners/#{group_runner.id}", admin)
expect(json_response['groups'].first).to eq(
'id' => group.id,
'web_url' => group.web_url,
'name' => group.name
)
end end
end end
@ -146,10 +173,10 @@ describe API::Runners do
context "runner project's administrative user" do context "runner project's administrative user" do
context 'when runner is not shared' do context 'when runner is not shared' do
it "returns runner's details" do it "returns runner's details" do
get api("/runners/#{specific_runner.id}", user) get api("/runners/#{project_runner.id}", user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response['description']).to eq(specific_runner.description) expect(json_response['description']).to eq(project_runner.description)
end end
end end
@ -163,17 +190,40 @@ describe API::Runners do
end end
end end
context "runner group's administrative user" do
context 'when runner is not shared' do
it "returns runner's details" do
get api("/runners/#{group_runner.id}", user)
expect(response).to have_http_status(200)
expect(json_response['id']).to eq(group_runner.id)
end
end
end
context 'other authorized user' do context 'other authorized user' do
it "does not return runner's details" do it "does not return project runner's details" do
get api("/runners/#{specific_runner.id}", user2) get api("/runners/#{project_runner.id}", user2)
expect(response).to have_http_status(403)
end
it "does not return group runner's details" do
get api("/runners/#{group_runner.id}", user2)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
end end
context 'unauthorized user' do context 'unauthorized user' do
it "does not return runner's details" do it "does not return project runner's details" do
get api("/runners/#{specific_runner.id}") get api("/runners/#{project_runner.id}")
expect(response).to have_http_status(401)
end
it "does not return group runner's details" do
get api("/runners/#{group_runner.id}")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end
@ -212,16 +262,16 @@ describe API::Runners do
context 'when runner is not shared' do context 'when runner is not shared' do
it 'updates runner' do it 'updates runner' do
description = specific_runner.description description = project_runner.description
runner_queue_value = specific_runner.ensure_runner_queue_value runner_queue_value = project_runner.ensure_runner_queue_value
update_runner(specific_runner.id, admin, description: 'test') update_runner(project_runner.id, admin, description: 'test')
specific_runner.reload project_runner.reload
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(specific_runner.description).to eq('test') expect(project_runner.description).to eq('test')
expect(specific_runner.description).not_to eq(description) expect(project_runner.description).not_to eq(description)
expect(specific_runner.ensure_runner_queue_value) expect(project_runner.ensure_runner_queue_value)
.not_to eq(runner_queue_value) .not_to eq(runner_queue_value)
end end
end end
@ -247,27 +297,49 @@ describe API::Runners do
end end
context 'when runner is not shared' do context 'when runner is not shared' do
it 'does not update runner without access to it' do it 'does not update project runner without access to it' do
put api("/runners/#{specific_runner.id}", user2), description: 'test' put api("/runners/#{project_runner.id}", user2), description: 'test'
expect(response).to have_http_status(403)
end
it 'does not update group runner without access to it' do
put api("/runners/#{group_runner.id}", user2), description: 'test'
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'updates runner with access to it' do it 'updates project runner with access to it' do
description = specific_runner.description description = project_runner.description
put api("/runners/#{specific_runner.id}", admin), description: 'test' put api("/runners/#{project_runner.id}", admin), description: 'test'
specific_runner.reload project_runner.reload
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(specific_runner.description).to eq('test') expect(project_runner.description).to eq('test')
expect(specific_runner.description).not_to eq(description) expect(project_runner.description).not_to eq(description)
end
it 'updates group runner with access to it' do
description = group_runner.description
put api("/runners/#{group_runner.id}", admin), description: 'test'
group_runner.reload
expect(response).to have_gitlab_http_status(200)
expect(group_runner.description).to eq('test')
expect(group_runner.description).not_to eq(description)
end end
end end
end end
context 'unauthorized user' do context 'unauthorized user' do
it 'does not delete runner' do it 'does not delete project runner' do
put api("/runners/#{specific_runner.id}") put api("/runners/#{project_runner.id}")
expect(response).to have_http_status(401)
end
it 'does not delete group runner' do
put api("/runners/#{group_runner.id}")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end
@ -293,15 +365,23 @@ describe API::Runners do
context 'when runner is not shared' do context 'when runner is not shared' do
it 'deletes unused runner' do it 'deletes unused runner' do
expect do expect do
delete api("/runners/#{unused_specific_runner.id}", admin) delete api("/runners/#{unused_project_runner.id}", admin)
expect(response).to have_gitlab_http_status(204) expect(response).to have_gitlab_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1) end.to change { Ci::Runner.specific.count }.by(-1)
end end
it 'deletes used runner' do it 'deletes used project runner' do
expect do expect do
delete api("/runners/#{specific_runner.id}", admin) delete api("/runners/#{project_runner.id}", admin)
expect(response).to have_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1)
end
it 'deletes used group runner' do
expect do
delete api("/runners/#{group_runner.id}", admin)
expect(response).to have_gitlab_http_status(204) expect(response).to have_gitlab_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1) end.to change { Ci::Runner.specific.count }.by(-1)
@ -325,32 +405,51 @@ describe API::Runners do
context 'when runner is not shared' do context 'when runner is not shared' do
it 'does not delete runner without access to it' do it 'does not delete runner without access to it' do
delete api("/runners/#{specific_runner.id}", user2) delete api("/runners/#{project_runner.id}", user2)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'does not delete runner with more than one associated project' do it 'does not delete project runner with more than one associated project' do
delete api("/runners/#{two_projects_runner.id}", user) delete api("/runners/#{two_projects_runner.id}", user)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'deletes runner for one owned project' do it 'deletes project runner for one owned project' do
expect do expect do
delete api("/runners/#{specific_runner.id}", user) delete api("/runners/#{project_runner.id}", user)
expect(response).to have_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1)
end
it 'does not delete group runner with more than one associated group' do
delete api("/runners/#{two_groups_runner.id}", user)
expect(response).to have_http_status(403)
end
it 'deletes group runner for one owned group' do
expect do
delete api("/runners/#{group_runner.id}", user)
expect(response).to have_gitlab_http_status(204) expect(response).to have_gitlab_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1) end.to change { Ci::Runner.specific.count }.by(-1)
end end
it_behaves_like '412 response' do it_behaves_like '412 response' do
let(:request) { api("/runners/#{specific_runner.id}", user) } let(:request) { api("/runners/#{project_runner.id}", user) }
end end
end end
end end
context 'unauthorized user' do context 'unauthorized user' do
it 'does not delete runner' do it 'does not delete project runner' do
delete api("/runners/#{specific_runner.id}") delete api("/runners/#{project_runner.id}")
expect(response).to have_http_status(401)
end
it 'does not delete group runner' do
delete api("/runners/#{group_runner.id}")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end
@ -361,8 +460,8 @@ describe API::Runners do
set(:job_1) { create(:ci_build) } set(:job_1) { create(:ci_build) }
let!(:job_2) { create(:ci_build, :running, runner: shared_runner, project: project) } let!(:job_2) { create(:ci_build, :running, runner: shared_runner, project: project) }
let!(:job_3) { create(:ci_build, :failed, runner: shared_runner, project: project) } let!(:job_3) { create(:ci_build, :failed, runner: shared_runner, project: project) }
let!(:job_4) { create(:ci_build, :running, runner: specific_runner, project: project) } let!(:job_4) { create(:ci_build, :running, runner: project_runner, project: project) }
let!(:job_5) { create(:ci_build, :failed, runner: specific_runner, project: project) } let!(:job_5) { create(:ci_build, :failed, runner: project_runner, project: project) }
context 'admin user' do context 'admin user' do
context 'when runner exists' do context 'when runner exists' do
@ -380,7 +479,7 @@ describe API::Runners do
context 'when runner is specific' do context 'when runner is specific' do
it 'return jobs' do it 'return jobs' do
get api("/runners/#{specific_runner.id}/jobs", admin) get api("/runners/#{project_runner.id}/jobs", admin)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
@ -392,7 +491,7 @@ describe API::Runners do
context 'when valid status is provided' do context 'when valid status is provided' do
it 'return filtered jobs' do it 'return filtered jobs' do
get api("/runners/#{specific_runner.id}/jobs?status=failed", admin) get api("/runners/#{project_runner.id}/jobs?status=failed", admin)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
@ -405,7 +504,7 @@ describe API::Runners do
context 'when invalid status is provided' do context 'when invalid status is provided' do
it 'return 400' do it 'return 400' do
get api("/runners/#{specific_runner.id}/jobs?status=non-existing", admin) get api("/runners/#{project_runner.id}/jobs?status=non-existing", admin)
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
@ -433,7 +532,7 @@ describe API::Runners do
context 'when runner is specific' do context 'when runner is specific' do
it 'return jobs' do it 'return jobs' do
get api("/runners/#{specific_runner.id}/jobs", user) get api("/runners/#{project_runner.id}/jobs", user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
@ -445,7 +544,7 @@ describe API::Runners do
context 'when valid status is provided' do context 'when valid status is provided' do
it 'return filtered jobs' do it 'return filtered jobs' do
get api("/runners/#{specific_runner.id}/jobs?status=failed", user) get api("/runners/#{project_runner.id}/jobs?status=failed", user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
@ -458,7 +557,7 @@ describe API::Runners do
context 'when invalid status is provided' do context 'when invalid status is provided' do
it 'return 400' do it 'return 400' do
get api("/runners/#{specific_runner.id}/jobs?status=non-existing", user) get api("/runners/#{project_runner.id}/jobs?status=non-existing", user)
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
@ -476,7 +575,7 @@ describe API::Runners do
context 'other authorized user' do context 'other authorized user' do
it 'does not return jobs' do it 'does not return jobs' do
get api("/runners/#{specific_runner.id}/jobs", user2) get api("/runners/#{project_runner.id}/jobs", user2)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
@ -484,7 +583,7 @@ describe API::Runners do
context 'unauthorized user' do context 'unauthorized user' do
it 'does not return jobs' do it 'does not return jobs' do
get api("/runners/#{specific_runner.id}/jobs") get api("/runners/#{project_runner.id}/jobs")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end
@ -523,7 +622,7 @@ describe API::Runners do
describe 'POST /projects/:id/runners' do describe 'POST /projects/:id/runners' do
context 'authorized user' do context 'authorized user' do
let(:specific_runner2) do let(:project_runner2) do
create(:ci_runner).tap do |runner| create(:ci_runner).tap do |runner|
create(:ci_runner_project, runner: runner, project: project2) create(:ci_runner_project, runner: runner, project: project2)
end end
@ -531,23 +630,23 @@ describe API::Runners do
it 'enables specific runner' do it 'enables specific runner' do
expect do expect do
post api("/projects/#{project.id}/runners", user), runner_id: specific_runner2.id post api("/projects/#{project.id}/runners", user), runner_id: project_runner2.id
end.to change { project.runners.count }.by(+1) end.to change { project.runners.count }.by(+1)
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
end end
it 'avoids changes when enabling already enabled runner' do it 'avoids changes when enabling already enabled runner' do
expect do expect do
post api("/projects/#{project.id}/runners", user), runner_id: specific_runner.id post api("/projects/#{project.id}/runners", user), runner_id: project_runner.id
end.to change { project.runners.count }.by(0) end.to change { project.runners.count }.by(0)
expect(response).to have_gitlab_http_status(409) expect(response).to have_gitlab_http_status(409)
end end
it 'does not enable locked runner' do it 'does not enable locked runner' do
specific_runner2.update(locked: true) project_runner2.update(locked: true)
expect do expect do
post api("/projects/#{project.id}/runners", user), runner_id: specific_runner2.id post api("/projects/#{project.id}/runners", user), runner_id: project_runner2.id
end.to change { project.runners.count }.by(0) end.to change { project.runners.count }.by(0)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
@ -562,7 +661,7 @@ describe API::Runners do
context 'user is admin' do context 'user is admin' do
it 'enables any specific runner' do it 'enables any specific runner' do
expect do expect do
post api("/projects/#{project.id}/runners", admin), runner_id: unused_specific_runner.id post api("/projects/#{project.id}/runners", admin), runner_id: unused_project_runner.id
end.to change { project.runners.count }.by(+1) end.to change { project.runners.count }.by(+1)
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
end end
@ -570,7 +669,7 @@ describe API::Runners do
context 'user is not admin' do context 'user is not admin' do
it 'does not enable runner without access to' do it 'does not enable runner without access to' do
post api("/projects/#{project.id}/runners", user), runner_id: unused_specific_runner.id post api("/projects/#{project.id}/runners", user), runner_id: unused_project_runner.id
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
@ -619,7 +718,7 @@ describe API::Runners do
context 'when runner have one associated projects' do context 'when runner have one associated projects' do
it "does not disable project's runner" do it "does not disable project's runner" do
expect do expect do
delete api("/projects/#{project.id}/runners/#{specific_runner.id}", user) delete api("/projects/#{project.id}/runners/#{project_runner.id}", user)
end.to change { project.runners.count }.by(0) end.to change { project.runners.count }.by(0)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
@ -634,7 +733,7 @@ describe API::Runners do
context 'authorized user without permissions' do context 'authorized user without permissions' do
it "does not disable project's runner" do it "does not disable project's runner" do
delete api("/projects/#{project.id}/runners/#{specific_runner.id}", user2) delete api("/projects/#{project.id}/runners/#{project_runner.id}", user2)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
@ -642,7 +741,7 @@ describe API::Runners do
context 'unauthorized user' do context 'unauthorized user' do
it "does not disable project's runner" do it "does not disable project's runner" do
delete api("/projects/#{project.id}/runners/#{specific_runner.id}") delete api("/projects/#{project.id}/runners/#{project_runner.id}")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end

View file

@ -8,10 +8,16 @@ describe API::V3::Runners do
let(:project) { create(:project, creator_id: user.id) } let(:project) { create(:project, creator_id: user.id) }
let(:project2) { create(:project, creator_id: user.id) } let(:project2) { create(:project, creator_id: user.id) }
let(:group) { create(:group).tap { |group| group.add_owner(user) } }
let(:group2) { create(:group).tap { |group| group.add_owner(user) } }
let!(:group_runner) { create(:ci_runner, description: 'Group runner', groups: [group]) }
let!(:two_groups_runner) { create(:ci_runner, description: 'Two groups runner', groups: [group, group2]) }
let!(:shared_runner) { create(:ci_runner, :shared) } let!(:shared_runner) { create(:ci_runner, :shared) }
let!(:unused_specific_runner) { create(:ci_runner) } let!(:unused_specific_runner) { create(:ci_runner) }
let!(:specific_runner) do let!(:project_runner) do
create(:ci_runner).tap do |runner| create(:ci_runner).tap do |runner|
create(:ci_runner_project, runner: runner, project: project) create(:ci_runner_project, runner: runner, project: project)
end end
@ -51,9 +57,17 @@ describe API::V3::Runners do
end.to change { Ci::Runner.specific.count }.by(-1) end.to change { Ci::Runner.specific.count }.by(-1)
end end
it 'deletes used runner' do it 'deletes used project runner' do
expect do expect do
delete v3_api("/runners/#{specific_runner.id}", admin) delete v3_api("/runners/#{project_runner.id}", admin)
expect(response).to have_http_status(200)
end.to change { Ci::Runner.specific.count }.by(-1)
end
it 'deletes used group runner' do
expect do
delete v3_api("/runners/#{group_runner.id}", admin)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
end.to change { Ci::Runner.specific.count }.by(-1) end.to change { Ci::Runner.specific.count }.by(-1)
@ -77,18 +91,31 @@ describe API::V3::Runners do
context 'when runner is not shared' do context 'when runner is not shared' do
it 'does not delete runner without access to it' do it 'does not delete runner without access to it' do
delete v3_api("/runners/#{specific_runner.id}", user2) delete v3_api("/runners/#{project_runner.id}", user2)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'does not delete runner with more than one associated project' do it 'does not delete project runner with more than one associated project' do
delete v3_api("/runners/#{two_projects_runner.id}", user) delete v3_api("/runners/#{two_projects_runner.id}", user)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'deletes runner for one owned project' do it 'deletes project runner for one owned project' do
expect do expect do
delete v3_api("/runners/#{specific_runner.id}", user) delete v3_api("/runners/#{group_runner.id}", user)
expect(response).to have_http_status(200)
end.to change { Ci::Runner.specific.count }.by(-1)
end
it 'does not delete group runner with more than one associated project' do
delete v3_api("/runners/#{two_groups_runner.id}", user)
expect(response).to have_http_status(403)
end
it 'deletes group runner for one owned project' do
expect do
delete v3_api("/runners/#{project_runner.id}", user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
end.to change { Ci::Runner.specific.count }.by(-1) end.to change { Ci::Runner.specific.count }.by(-1)
@ -97,8 +124,14 @@ describe API::V3::Runners do
end end
context 'unauthorized user' do context 'unauthorized user' do
it 'does not delete runner' do it 'does not delete project runner' do
delete v3_api("/runners/#{specific_runner.id}") delete v3_api("/runners/#{project_runner.id}")
expect(response).to have_http_status(401)
end
it 'does not delete group runner' do
delete v3_api("/runners/#{group_runner.id}")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end
@ -120,7 +153,7 @@ describe API::V3::Runners do
context 'when runner have one associated projects' do context 'when runner have one associated projects' do
it "does not disable project's runner" do it "does not disable project's runner" do
expect do expect do
delete v3_api("/projects/#{project.id}/runners/#{specific_runner.id}", user) delete v3_api("/projects/#{project.id}/runners/#{project_runner.id}", user)
end.to change { project.runners.count }.by(0) end.to change { project.runners.count }.by(0)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
@ -135,7 +168,7 @@ describe API::V3::Runners do
context 'authorized user without permissions' do context 'authorized user without permissions' do
it "does not disable project's runner" do it "does not disable project's runner" do
delete v3_api("/projects/#{project.id}/runners/#{specific_runner.id}", user2) delete v3_api("/projects/#{project.id}/runners/#{project_runner.id}", user2)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
@ -143,7 +176,7 @@ describe API::V3::Runners do
context 'unauthorized user' do context 'unauthorized user' do
it "does not disable project's runner" do it "does not disable project's runner" do
delete v3_api("/projects/#{project.id}/runners/#{specific_runner.id}") delete v3_api("/projects/#{project.id}/runners/#{project_runner.id}")
expect(response).to have_gitlab_http_status(401) expect(response).to have_gitlab_http_status(401)
end end