support group runners in existing API endpoints
This commit is contained in:
parent
7fbdd17cbc
commit
b55c3a7bc4
7 changed files with 239 additions and 77 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue