Allow to pause,resume,show,edit,destroy group runners (#10244)
This commit is contained in:
parent
1ef9e9c2aa
commit
91f358942e
|
|
@ -0,0 +1,54 @@
|
||||||
|
class Groups::RunnersController < Groups::ApplicationController
|
||||||
|
before_action :authorize_admin_pipeline!
|
||||||
|
before_action :set_runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if Ci::UpdateRunnerService.new(@runner).update(runner_params)
|
||||||
|
redirect_to group_runner_path(@group, @runner), notice: 'Runner was successfully updated.'
|
||||||
|
else
|
||||||
|
render 'edit'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@runner.destroy
|
||||||
|
|
||||||
|
redirect_to group_settings_ci_cd_path(@group), status: 302
|
||||||
|
end
|
||||||
|
|
||||||
|
def resume
|
||||||
|
if Ci::UpdateRunnerService.new(@runner).update(active: true)
|
||||||
|
redirect_to group_settings_ci_cd_path(@group), notice: 'Runner was successfully updated.'
|
||||||
|
else
|
||||||
|
redirect_to group_settings_ci_cd_path(@group), alert: 'Runner was not updated.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pause
|
||||||
|
if Ci::UpdateRunnerService.new(@runner).update(active: false)
|
||||||
|
redirect_to group_settings_ci_cd_path(@group), notice: 'Runner was successfully updated.'
|
||||||
|
else
|
||||||
|
redirect_to group_settings_ci_cd_path(@group), alert: 'Runner was not updated.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_runner
|
||||||
|
@runner ||= @group.runners.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_admin_pipeline!
|
||||||
|
return render_404 unless can?(current_user, :admin_pipeline, group)
|
||||||
|
end
|
||||||
|
|
||||||
|
def runner_params
|
||||||
|
params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
= form_for runner, url: runner_form_url, html: { class: 'form-horizontal' } do |f|
|
||||||
|
= form_errors(runner)
|
||||||
|
.form-group
|
||||||
|
= label :active, "Active", class: 'control-label'
|
||||||
|
.col-sm-10
|
||||||
|
.checkbox
|
||||||
|
= f.check_box :active
|
||||||
|
%span.light Paused Runners don't accept new jobs
|
||||||
|
.form-group
|
||||||
|
= label :protected, "Protected", class: 'control-label'
|
||||||
|
.col-sm-10
|
||||||
|
.checkbox
|
||||||
|
= f.check_box :access_level, {}, 'ref_protected', 'not_protected'
|
||||||
|
%span.light This runner will only run on pipelines triggered on protected branches
|
||||||
|
.form-group
|
||||||
|
= label :run_untagged, 'Run untagged jobs', class: 'control-label'
|
||||||
|
.col-sm-10
|
||||||
|
.checkbox
|
||||||
|
= f.check_box :run_untagged
|
||||||
|
%span.light Indicates whether this runner can pick jobs without tags
|
||||||
|
.form-group
|
||||||
|
= label_tag :token, class: 'control-label' do
|
||||||
|
Token
|
||||||
|
.col-sm-10
|
||||||
|
= f.text_field :token, class: 'form-control', readonly: true
|
||||||
|
.form-group
|
||||||
|
= label_tag :description, class: 'control-label' do
|
||||||
|
Description
|
||||||
|
.col-sm-10
|
||||||
|
= f.text_field :description, class: 'form-control'
|
||||||
|
.form-group
|
||||||
|
= label_tag :tag_list, class: 'control-label' do
|
||||||
|
Tags
|
||||||
|
.col-sm-10
|
||||||
|
= f.text_field :tag_list, value: runner.tag_list.sort.join(', '), class: 'form-control'
|
||||||
|
.help-block You can setup jobs to only use Runners with specific tags. Separate tags with commas.
|
||||||
|
.form-actions
|
||||||
|
= f.submit 'Save changes', class: 'btn btn-save'
|
||||||
|
|
@ -2,9 +2,18 @@
|
||||||
%h4
|
%h4
|
||||||
= runner_status_icon(runner)
|
= runner_status_icon(runner)
|
||||||
|
|
||||||
%span.commit-sha
|
= link_to runner.short_sha, group_runner_path(@group, runner), class: 'commit-sha'
|
||||||
= runner.short_sha
|
|
||||||
|
|
||||||
|
%small.edit-runner
|
||||||
|
= link_to edit_group_runner_path(@group, runner) do
|
||||||
|
%i.fa.fa-edit.btn
|
||||||
|
|
||||||
|
.pull-right
|
||||||
|
- if runner.active?
|
||||||
|
= link_to 'Pause', pause_group_runner_path(@group, runner), method: :post, class: 'btn btn-sm btn-danger', data: { confirm: "Are you sure?" }
|
||||||
|
- else
|
||||||
|
= link_to 'Resume', resume_group_runner_path(@group, runner), method: :post, class: 'btn btn-success btn-sm'
|
||||||
|
= link_to 'Remove Runner', group_runner_path(@group, runner), data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm'
|
||||||
.pull-right
|
.pull-right
|
||||||
%small.light
|
%small.light
|
||||||
\##{runner.id}
|
\##{runner.id}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
- page_title "Edit", "#{@runner.description} ##{@runner.id}", "Runners"
|
||||||
|
|
||||||
|
%h4 Runner ##{@runner.id}
|
||||||
|
|
||||||
|
%hr
|
||||||
|
= render 'form', runner: @runner, runner_form_url: group_runner_path(@group, @runner)
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
- page_title "#{@runner.description} ##{@runner.id}", "Runners"
|
||||||
|
|
||||||
|
%h3.page-title
|
||||||
|
Runner ##{@runner.id}
|
||||||
|
|
||||||
|
.table-holder
|
||||||
|
%table.table
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th Property Name
|
||||||
|
%th Value
|
||||||
|
%tr
|
||||||
|
%td Active
|
||||||
|
%td= @runner.active? ? 'Yes' : 'No'
|
||||||
|
%tr
|
||||||
|
%td Protected
|
||||||
|
%td= @runner.ref_protected? ? 'Yes' : 'No'
|
||||||
|
%tr
|
||||||
|
%td Can run untagged jobs
|
||||||
|
%td= @runner.run_untagged? ? 'Yes' : 'No'
|
||||||
|
%tr
|
||||||
|
%td Tags
|
||||||
|
%td
|
||||||
|
- @runner.tag_list.sort.each do |tag|
|
||||||
|
%span.label.label-primary
|
||||||
|
= tag
|
||||||
|
%tr
|
||||||
|
%td Name
|
||||||
|
%td= @runner.name
|
||||||
|
%tr
|
||||||
|
%td Version
|
||||||
|
%td= @runner.version
|
||||||
|
%tr
|
||||||
|
%td Revision
|
||||||
|
%td= @runner.revision
|
||||||
|
%tr
|
||||||
|
%td Platform
|
||||||
|
%td= @runner.platform
|
||||||
|
%tr
|
||||||
|
%td Architecture
|
||||||
|
%td= @runner.architecture
|
||||||
|
%tr
|
||||||
|
%td Description
|
||||||
|
%td= @runner.description
|
||||||
|
%tr
|
||||||
|
%td Last contact
|
||||||
|
%td
|
||||||
|
- if @runner.contacted_at
|
||||||
|
#{time_ago_in_words(@runner.contacted_at)} ago
|
||||||
|
- else
|
||||||
|
Never
|
||||||
|
|
@ -58,6 +58,13 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
|
||||||
|
|
||||||
# On CE only index and show actions are needed
|
# On CE only index and show actions are needed
|
||||||
resources :boards, only: [:index, :show]
|
resources :boards, only: [:index, :show]
|
||||||
|
|
||||||
|
resources :runners, only: [:index, :edit, :update, :destroy, :show] do
|
||||||
|
member do
|
||||||
|
post :resume
|
||||||
|
post :pause
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scope(path: '*id',
|
scope(path: '*id',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Groups::RunnersController do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:group) { create(:group) }
|
||||||
|
let(:runner) { create(:ci_runner) }
|
||||||
|
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
group_id: group,
|
||||||
|
id: runner
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(user)
|
||||||
|
group.add_master(user)
|
||||||
|
group.runners << runner
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#update' do
|
||||||
|
it 'updates the runner and ticks the queue' do
|
||||||
|
new_desc = runner.description.swapcase
|
||||||
|
|
||||||
|
expect do
|
||||||
|
post :update, params.merge(runner: { description: new_desc } )
|
||||||
|
end.to change { runner.ensure_runner_queue_value }
|
||||||
|
|
||||||
|
runner.reload
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(302)
|
||||||
|
expect(runner.description).to eq(new_desc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#destroy' do
|
||||||
|
it 'destroys the runner' do
|
||||||
|
delete :destroy, params
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(302)
|
||||||
|
expect(Ci::Runner.find_by(id: runner.id)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#resume' do
|
||||||
|
it 'marks the runner as active and ticks the queue' do
|
||||||
|
runner.update(active: false)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
post :resume, params
|
||||||
|
end.to change { runner.ensure_runner_queue_value }
|
||||||
|
|
||||||
|
runner.reload
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(302)
|
||||||
|
expect(runner.active).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#pause' do
|
||||||
|
it 'marks the runner as inactive and ticks the queue' do
|
||||||
|
runner.update(active: true)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
post :pause, params
|
||||||
|
end.to change { runner.ensure_runner_queue_value }
|
||||||
|
|
||||||
|
runner.reload
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(302)
|
||||||
|
expect(runner.active).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -182,7 +182,7 @@ feature 'Runners' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'group runners' do
|
context 'group runners in project settings' do
|
||||||
background do
|
background do
|
||||||
project.add_master(user)
|
project.add_master(user)
|
||||||
end
|
end
|
||||||
|
|
@ -200,10 +200,10 @@ feature 'Runners' do
|
||||||
scenario 'group runners are not available' do
|
scenario 'group runners are not available' do
|
||||||
visit project_runners_path(project)
|
visit project_runners_path(project)
|
||||||
|
|
||||||
expect(page).to have_content 'This group does not provide any group Runners yet.'
|
expect(page).to have_content 'This group does not provide any group Runners yet'
|
||||||
|
|
||||||
expect(page).to have_content 'Setup a group Runner manually'
|
expect(page).to have_content 'Group masters can register group runners in the Group CI/CD settings'
|
||||||
expect(page).not_to have_content 'Ask your group master to setup a group Runner.'
|
expect(page).not_to have_content 'Ask your group master to setup a group Runner'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -228,7 +228,7 @@ feature 'Runners' do
|
||||||
|
|
||||||
expect(page).to have_content 'This group does not provide any group Runners yet.'
|
expect(page).to have_content 'This group does not provide any group Runners yet.'
|
||||||
|
|
||||||
expect(page).not_to have_content 'Setup a group Runner manually'
|
expect(page).not_to have_content 'Group masters can register group runners in the Group CI/CD settings'
|
||||||
expect(page).to have_content 'Ask your group master to setup a group Runner.'
|
expect(page).to have_content 'Ask your group master to setup a group Runner.'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -261,4 +261,98 @@ feature 'Runners' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'group runners in group settings' do
|
||||||
|
given(:group) { create :group }
|
||||||
|
background do
|
||||||
|
group.add_master(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'group with no runners' do
|
||||||
|
scenario 'there are no runners displayed' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
expect(page).to have_content 'This group does not provide any group Runners yet'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'group with a runner' do
|
||||||
|
let!(:runner) { create :ci_runner, groups: [group], description: 'group-runner' }
|
||||||
|
|
||||||
|
scenario 'the runner is visible' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
expect(page).not_to have_content 'This group does not provide any group Runners yet'
|
||||||
|
expect(page).to have_content 'Available group Runners : 1'
|
||||||
|
expect(page).to have_content 'group-runner'
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user can pause and resume the group runner' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
expect(page).to have_content('Pause')
|
||||||
|
expect(page).not_to have_content('Resume')
|
||||||
|
|
||||||
|
click_on 'Pause'
|
||||||
|
|
||||||
|
expect(page).not_to have_content('Pause')
|
||||||
|
expect(page).to have_content('Resume')
|
||||||
|
|
||||||
|
click_on 'Resume'
|
||||||
|
|
||||||
|
expect(page).to have_content('Pause')
|
||||||
|
expect(page).not_to have_content('Resume')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user can view runner details' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
expect(page).to have_content(runner.display_name)
|
||||||
|
|
||||||
|
click_on runner.short_sha
|
||||||
|
|
||||||
|
expect(page).to have_content(runner.platform)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user can remove a group runner' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
click_on 'Remove Runner'
|
||||||
|
|
||||||
|
expect(page).not_to have_content(runner.display_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user edits the runner to be protected' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
first('.edit-runner > a').click
|
||||||
|
|
||||||
|
expect(page.find_field('runner[access_level]')).not_to be_checked
|
||||||
|
|
||||||
|
check 'runner_access_level'
|
||||||
|
click_button 'Save changes'
|
||||||
|
|
||||||
|
expect(page).to have_content 'Protected Yes'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a runner has a tag' do
|
||||||
|
background do
|
||||||
|
runner.update(tag_list: ['tag'])
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'user edits runner not to run untagged jobs' do
|
||||||
|
visit group_settings_ci_cd_path(group)
|
||||||
|
|
||||||
|
first('.edit-runner > a').click
|
||||||
|
|
||||||
|
expect(page.find_field('runner[run_untagged]')).to be_checked
|
||||||
|
|
||||||
|
uncheck 'runner_run_untagged'
|
||||||
|
click_button 'Save changes'
|
||||||
|
|
||||||
|
expect(page).to have_content 'Can run untagged jobs No'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue