Commit e8f6e910 authored by Arthur de Lapertosa Lisboa's avatar Arthur de Lapertosa Lisboa Committed by Imre Farkas

Add finder for group-level runners

parent 0a066d83
......@@ -4,7 +4,7 @@ class Admin::RunnersController < Admin::ApplicationController
before_action :runner, except: [:index, :tag_list]
def index
finder = Admin::RunnersFinder.new(params: params)
finder = Ci::RunnersFinder.new(current_user: current_user, params: params)
@runners = finder.execute
@active_runners_count = Ci::Runner.online.count
@sort = finder.sort_key
......
# frozen_string_literal: true
class Admin::RunnersFinder < UnionFinder
NUMBER_OF_RUNNERS_PER_PAGE = 30
def initialize(params:)
@params = params
end
def execute
search!
filter_by_status!
filter_by_runner_type!
filter_by_tag_list!
sort!
paginate!
@runners.with_tags
end
def sort_key
if @params[:sort] == 'contacted_asc'
'contacted_asc'
else
'created_date'
end
end
private
def search!
@runners =
if @params[:search].present?
Ci::Runner.search(@params[:search])
else
Ci::Runner.all
end
end
def filter_by_status!
filter_by!(:status_status, Ci::Runner::AVAILABLE_STATUSES)
end
def filter_by_runner_type!
filter_by!(:type_type, Ci::Runner::AVAILABLE_TYPES)
end
def filter_by_tag_list!
tag_list = @params[:tag_name].presence
if tag_list
@runners = @runners.tagged_with(tag_list)
end
end
def sort!
@runners = @runners.order_by(sort_key)
end
def paginate!
@runners = @runners.page(@params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
end
def filter_by!(scope_name, available_scopes)
scope = @params[scope_name]
if scope.present? && available_scopes.include?(scope)
@runners = @runners.public_send(scope) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
# frozen_string_literal: true
module Ci
class RunnersFinder < UnionFinder
include Gitlab::Allowable
NUMBER_OF_RUNNERS_PER_PAGE = 30
def initialize(current_user:, group: nil, params:)
@params = params
@group = group
@current_user = current_user
end
def execute
search!
filter_by_status!
filter_by_runner_type!
filter_by_tag_list!
sort!
paginate!
@runners.with_tags
rescue Gitlab::Access::AccessDeniedError
Ci::Runner.none
end
def sort_key
if @params[:sort] == 'contacted_asc'
'contacted_asc'
else
'created_date'
end
end
private
def search!
@group ? group_runners : all_runners
@runners = @runners.search(@params[:search]) if @params[:search].present?
end
def all_runners
raise Gitlab::Access::AccessDeniedError unless @current_user&.admin?
@runners = Ci::Runner.all
end
def group_runners
raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :admin_group, @group)
# Getting all runners from the group itself and all its descendants
descentant_projects = Project.for_group_and_its_subgroups(@group)
@runners = Ci::Runner.belonging_to_group_or_project(@group.self_and_descendants, descentant_projects)
end
def filter_by_status!
filter_by!(:status_status, Ci::Runner::AVAILABLE_STATUSES)
end
def filter_by_runner_type!
filter_by!(:type_type, Ci::Runner::AVAILABLE_TYPES)
end
def filter_by_tag_list!
tag_list = @params[:tag_name].presence
if tag_list
@runners = @runners.tagged_with(tag_list)
end
end
def sort!
@runners = @runners.order_by(sort_key)
end
def paginate!
@runners = @runners.page(@params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
end
def filter_by!(scope_name, available_scopes)
scope = @params[scope_name]
if scope.present? && available_scopes.include?(scope)
@runners = @runners.public_send(scope) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
end
......@@ -81,6 +81,17 @@ module Ci
joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: groups })
}
scope :belonging_to_group_or_project, -> (group_id, project_id) {
groups = ::Group.where(id: group_id)
group_runners = joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: groups })
project_runners = joins(:runner_projects).where(ci_runner_projects: { project_id: project_id })
union_sql = ::Gitlab::SQL::Union.new([group_runners, project_runners]).to_sql
from("(#{union_sql}) #{table_name}")
}
scope :belonging_to_parent_group_of_project, -> (project_id) {
project_groups = ::Group.joins(:projects).where(projects: { id: project_id })
hierarchy_groups = Gitlab::ObjectHierarchy.new(project_groups).base_and_ancestors
......
---
title: Add finder for group-level runners
merge_request: 29283
author: Arthur de Lapertosa Lisboa
type: added
# frozen_string_literal: true
require 'spec_helper'
describe Admin::RunnersFinder do
describe '#execute' do
context 'with empty params' do
it 'returns all runners' do
runner1 = create :ci_runner, active: true
runner2 = create :ci_runner, active: false
expect(described_class.new(params: {}).execute).to match_array [runner1, runner2]
end
end
context 'filter by search term' do
it 'calls Ci::Runner.search' do
expect(Ci::Runner).to receive(:search).with('term').and_call_original
described_class.new(params: { search: 'term' }).execute
end
end
context 'filter by status' do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:paused).and_call_original
described_class.new(params: { status_status: 'paused' }).execute
end
end
context 'filter by runner type' do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:project_type).and_call_original
described_class.new(params: { type_type: 'project_type' }).execute
end
end
context 'filter by tag_name' do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:tagged_with).with(%w[tag1 tag2]).and_call_original
described_class.new(params: { tag_name: %w[tag1 tag2] }).execute
end
end
context 'sort' do
context 'without sort param' do
it 'sorts by created_at' do
runner1 = create :ci_runner, created_at: '2018-07-12 07:00'
runner2 = create :ci_runner, created_at: '2018-07-12 08:00'
runner3 = create :ci_runner, created_at: '2018-07-12 09:00'
expect(described_class.new(params: {}).execute).to eq [runner3, runner2, runner1]
end
end
context 'with sort param' do
it 'sorts by specified attribute' do
runner1 = create :ci_runner, contacted_at: 1.minute.ago
runner2 = create :ci_runner, contacted_at: 3.minutes.ago
runner3 = create :ci_runner, contacted_at: 2.minutes.ago
expect(described_class.new(params: { sort: 'contacted_asc' }).execute).to eq [runner2, runner3, runner1]
end
end
end
context 'paginate' do
it 'returns the runners for the specified page' do
stub_const('Admin::RunnersFinder::NUMBER_OF_RUNNERS_PER_PAGE', 1)
runner1 = create :ci_runner, created_at: '2018-07-12 07:00'
runner2 = create :ci_runner, created_at: '2018-07-12 08:00'
expect(described_class.new(params: { page: 1 }).execute).to eq [runner2]
expect(described_class.new(params: { page: 2 }).execute).to eq [runner1]
end
end
end
end
This diff is collapsed.
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