Commit 4586d77c authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'feature/runner-type-filter-for-admin-view' into 'master'

Feature: Runner type filter for admin view

See merge request gitlab-org/gitlab-ce!19649
parents 779169d3 2466a514
...@@ -7,6 +7,13 @@ const tokenKeys = [{ ...@@ -7,6 +7,13 @@ const tokenKeys = [{
symbol: '', symbol: '',
icon: 'messages', icon: 'messages',
tag: 'status', tag: 'status',
}, {
key: 'type',
type: 'string',
param: 'type',
symbol: '',
icon: 'cube',
tag: 'type',
}]; }];
const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys); const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys);
......
...@@ -96,6 +96,11 @@ export default class FilteredSearchDropdownManager { ...@@ -96,6 +96,11 @@ export default class FilteredSearchDropdownManager {
gl: NullDropdown, gl: NullDropdown,
element: this.container.querySelector('#js-dropdown-admin-runner-status'), element: this.container.querySelector('#js-dropdown-admin-runner-status'),
}, },
type: {
reference: null,
gl: NullDropdown,
element: this.container.querySelector('#js-dropdown-admin-runner-type'),
},
}; };
supportedTokens.forEach((type) => { supportedTokens.forEach((type) => {
......
...@@ -10,6 +10,7 @@ class Admin::RunnersFinder < UnionFinder ...@@ -10,6 +10,7 @@ class Admin::RunnersFinder < UnionFinder
def execute def execute
search! search!
filter_by_status! filter_by_status!
filter_by_runner_type!
sort! sort!
paginate! paginate!
...@@ -36,10 +37,11 @@ class Admin::RunnersFinder < UnionFinder ...@@ -36,10 +37,11 @@ class Admin::RunnersFinder < UnionFinder
end end
def filter_by_status! def filter_by_status!
status = @params[:status_status] filter_by!(:status_status, Ci::Runner::AVAILABLE_STATUSES)
if status.present? && Ci::Runner::AVAILABLE_STATUSES.include?(status)
@runners = @runners.public_send(status) # rubocop:disable GitlabSecurity/PublicSend
end end
def filter_by_runner_type!
filter_by!(:type_type, Ci::Runner::AVAILABLE_TYPES)
end end
def sort! def sort!
...@@ -49,4 +51,12 @@ class Admin::RunnersFinder < UnionFinder ...@@ -49,4 +51,12 @@ class Admin::RunnersFinder < UnionFinder
def paginate! def paginate!
@runners = @runners.page(@params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE) @runners = @runners.page(@params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
end 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
...@@ -9,12 +9,24 @@ module Ci ...@@ -9,12 +9,24 @@ module Ci
include ChronicDurationAttribute include ChronicDurationAttribute
include FromUnion include FromUnion
enum access_level: {
not_protected: 0,
ref_protected: 1
}
enum runner_type: {
instance_type: 1,
group_type: 2,
project_type: 3
}
RUNNER_QUEUE_EXPIRY_TIME = 60.minutes RUNNER_QUEUE_EXPIRY_TIME = 60.minutes
ONLINE_CONTACT_TIMEOUT = 1.hour ONLINE_CONTACT_TIMEOUT = 1.hour
UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes
AVAILABLE_TYPES = %w[specific shared].freeze AVAILABLE_TYPES_LEGACY = %w[specific shared].freeze
AVAILABLE_TYPES = runner_types.keys.freeze
AVAILABLE_STATUSES = %w[active paused online offline].freeze AVAILABLE_STATUSES = %w[active paused online offline].freeze
AVAILABLE_SCOPES = (AVAILABLE_TYPES + AVAILABLE_STATUSES).freeze AVAILABLE_SCOPES = (AVAILABLE_TYPES_LEGACY + AVAILABLE_TYPES + AVAILABLE_STATUSES).freeze
FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze
ignore_column :is_shared ignore_column :is_shared
...@@ -97,17 +109,6 @@ module Ci ...@@ -97,17 +109,6 @@ module Ci
after_destroy :cleanup_runner_queue after_destroy :cleanup_runner_queue
enum access_level: {
not_protected: 0,
ref_protected: 1
}
enum runner_type: {
instance_type: 1,
group_type: 2,
project_type: 3
}
cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at
chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout
......
...@@ -83,12 +83,21 @@ ...@@ -83,12 +83,21 @@
{{hint}} {{hint}}
%span.js-filter-tag.dropdown-light-content %span.js-filter-tag.dropdown-light-content
{{tag}} {{tag}}
#js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_STATUSES.each do |status| - Ci::Runner::AVAILABLE_STATUSES.each do |status|
%li.filter-dropdown-item{ data: { value: status } } %li.filter-dropdown-item{ data: { value: status } }
= button_tag class: %w[btn btn-link] do = button_tag class: %w[btn btn-link] do
= status.titleize = status.titleize
#js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
%li.filter-dropdown-item{ data: { value: runner_type } }
= button_tag class: %w[btn btn-link] do
= runner_type.titleize
= button_tag class: %w[clear-search hidden] do = button_tag class: %w[clear-search hidden] do
= icon('times') = icon('times')
.filter-dropdown-container .filter-dropdown-container
......
---
title: Add a type filter to the admin runners view
merge_request: 19649
author: Alexis Reigel
type: added
...@@ -11,11 +11,15 @@ Get a list of specific runners available to the user. ...@@ -11,11 +11,15 @@ Get a list of specific runners available to the user.
``` ```
GET /runners GET /runners
GET /runners?scope=active GET /runners?scope=active
GET /runners?type=project_type
GET /runners?status=active
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `scope` | string | no | The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided | | `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
``` ```
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners" curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners"
...@@ -56,11 +60,15 @@ is restricted to users with `admin` privileges. ...@@ -56,11 +60,15 @@ is restricted to users with `admin` privileges.
``` ```
GET /runners/all GET /runners/all
GET /runners/all?scope=online GET /runners/all?scope=online
GET /runners/all?type=project_type
GET /runners/all?status=active
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------| |-----------|---------|----------|---------------------|
| `scope` | string | no | The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided | | `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided |
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
``` ```
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/all" curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/all"
...@@ -336,11 +344,17 @@ usage is enabled in the project's settings. ...@@ -336,11 +344,17 @@ usage is enabled in the project's settings.
``` ```
GET /projects/:id/runners GET /projects/:id/runners
GET /projects/:id/runners?scope=active
GET /projects/:id/runners?type=project_type
GET /projects/:id/runners?status=active
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------| |-----------|----------------|----------|---------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
``` ```
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners" curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners"
......
...@@ -11,10 +11,18 @@ module API ...@@ -11,10 +11,18 @@ module API
params do params do
optional :scope, type: String, values: Ci::Runner::AVAILABLE_STATUSES, optional :scope, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The scope of specific runners to show' desc: 'The scope of specific runners to show'
optional :type, type: String, values: Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
use :pagination use :pagination
end end
get do get do
runners = filter_runners(current_user.ci_owned_runners, params[:scope], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES) runners = current_user.ci_owned_runners
runners = filter_runners(runners, params[:scope], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
present paginate(runners), with: Entities::Runner present paginate(runners), with: Entities::Runner
end end
...@@ -24,11 +32,20 @@ module API ...@@ -24,11 +32,20 @@ module API
params do params do
optional :scope, type: String, values: Ci::Runner::AVAILABLE_SCOPES, optional :scope, type: String, values: Ci::Runner::AVAILABLE_SCOPES,
desc: 'The scope of specific runners to show' desc: 'The scope of specific runners to show'
optional :type, type: String, values: Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
use :pagination use :pagination
end end
get 'all' do get 'all' do
authenticated_as_admin! authenticated_as_admin!
runners = filter_runners(Ci::Runner.all, params[:scope])
runners = Ci::Runner.all
runners = filter_runners(runners, params[:scope])
runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
present paginate(runners), with: Entities::Runner present paginate(runners), with: Entities::Runner
end end
...@@ -116,10 +133,18 @@ module API ...@@ -116,10 +133,18 @@ module API
params do params do
optional :scope, type: String, values: Ci::Runner::AVAILABLE_SCOPES, optional :scope, type: String, values: Ci::Runner::AVAILABLE_SCOPES,
desc: 'The scope of specific runners to show' desc: 'The scope of specific runners to show'
optional :type, type: String, values: Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The status of the runners to show'
use :pagination use :pagination
end end
get ':id/runners' do get ':id/runners' do
runners = filter_runners(Ci::Runner.owned_or_instance_wide(user_project.id), params[:scope]) runners = Ci::Runner.owned_or_instance_wide(user_project.id)
runners = filter_runners(runners, params[:scope])
runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
present paginate(runners), with: Entities::Runner present paginate(runners), with: Entities::Runner
end end
......
...@@ -73,9 +73,8 @@ describe "Admin Runners" do ...@@ -73,9 +73,8 @@ describe "Admin Runners" do
expect(page).to have_text 'No runners found' expect(page).to have_text 'No runners found'
end end
end
it 'shows correct runner when status is selected and search term is entered', :js do it 'shows correct runner when status is selected and search term is entered' do
create(:ci_runner, description: 'runner-a-1', active: true) create(:ci_runner, description: 'runner-a-1', active: true)
create(:ci_runner, description: 'runner-a-2', active: false) create(:ci_runner, description: 'runner-a-2', active: false)
create(:ci_runner, description: 'runner-b-1', active: true) create(:ci_runner, description: 'runner-b-1', active: true)
...@@ -92,6 +91,55 @@ describe "Admin Runners" do ...@@ -92,6 +91,55 @@ describe "Admin Runners" do
expect(page).not_to have_content 'runner-b-1' expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2' expect(page).not_to have_content 'runner-a-2'
end end
end
describe 'filter by type', :js do
it 'shows correct runner when type matches' do
create :ci_runner, :project, description: 'runner-project'
create :ci_runner, :group, description: 'runner-group'
visit admin_runners_path
expect(page).to have_content 'runner-project'
expect(page).to have_content 'runner-group'
input_filtered_search_keys('type:project_type')
expect(page).to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
end
it 'shows no runner when type does not match' do
create :ci_runner, :project, description: 'runner-project'
create :ci_runner, :group, description: 'runner-group'
visit admin_runners_path
input_filtered_search_keys('type:instance_type')
expect(page).not_to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
expect(page).to have_text 'No runners found'
end
it 'shows correct runner when type is selected and search term is entered' do
create :ci_runner, :project, description: 'runner-a-1'
create :ci_runner, :instance, description: 'runner-a-2'
create :ci_runner, :project, description: 'runner-b-1'
visit admin_runners_path
input_filtered_search_keys('type:project_type')
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
input_filtered_search_keys('type:project_type runner-a')
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
end
end
it 'sorts by last contact date', :js do it 'sorts by last contact date', :js do
create(:ci_runner, description: 'runner-1', created_at: '2018-07-12 15:37', contacted_at: '2018-07-12 15:37') create(:ci_runner, description: 'runner-1', created_at: '2018-07-12 15:37', contacted_at: '2018-07-12 15:37')
......
...@@ -29,6 +29,14 @@ describe Admin::RunnersFinder do ...@@ -29,6 +29,14 @@ describe Admin::RunnersFinder do
end end
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 'sort' do context 'sort' do
context 'without sort param' do context 'without sort param' do
it 'sorts by created_at' do it 'sorts by created_at' do
......
...@@ -25,36 +25,71 @@ describe API::Runners do ...@@ -25,36 +25,71 @@ describe API::Runners do
describe 'GET /runners' do describe 'GET /runners' do
context 'authorized user' do context 'authorized user' do
it 'returns user available runners' do it 'returns response status and headers' do
get api('/runners', user) get api('/runners', user)
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 end
expect(json_response[0]).to have_key('ip_address')
expect(descriptions).to contain_exactly( it 'returns user available runners' do
'Project runner', 'Two projects runner', 'Group runner' get api('/runners', user)
)
expect(shared).to be_falsey expect(json_response).to match_array [
a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner'),
a_hash_including('description' => 'Group runner')
]
end end
it 'filters runners by scope' do it 'filters runners by scope' do
get api('/runners?scope=active', user) create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
get api('/runners?scope=paused', user)
shared = json_response.any? { |r| r['is_shared'] }
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[0]).to have_key('ip_address') expect(json_response).to match_array [
expect(shared).to be_falsey a_hash_including('description' => 'Inactive project runner')
]
end end
it 'avoids filtering if scope is invalid' do it 'avoids filtering if scope is invalid' do
get api('/runners?scope=unknown', user) get api('/runners?scope=unknown', user)
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
it 'filters runners by type' do
get api('/runners?type=project_type', user)
expect(json_response).to match_array [
a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner')
]
end
it 'does not filter by invalid type' do
get api('/runners?type=bogus', user)
expect(response).to have_gitlab_http_status(400)
end
it 'filters runners by status' do
create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
get api('/runners?status=paused', user)
expect(json_response).to match_array [
a_hash_including('description' => 'Inactive project runner')
]
end
it 'does not filter by invalid status' do
get api('/runners?status=bogus', user)
expect(response).to have_gitlab_http_status(400)
end
end end
context 'unauthorized user' do context 'unauthorized user' do
...@@ -69,24 +104,22 @@ describe API::Runners do ...@@ -69,24 +104,22 @@ describe API::Runners do
describe 'GET /runners/all' do describe 'GET /runners/all' do
context 'authorized user' do context 'authorized user' do
context 'with admin privileges' do context 'with admin privileges' do
it 'returns all runners' do it 'returns response status and headers' do
get api('/runners/all', admin) get api('/runners/all', admin)
shared = json_response.any? { |r| r['is_shared'] }
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[0]).to have_key('ip_address')
expect(shared).to be_truthy
end
end end
context 'without admin privileges' do it 'returns all runners' do
it 'does not return runners list' do get api('/runners/all', admin)
get api('/runners/all', user)
expect(response).to have_gitlab_http_status(403) expect(json_response).to match_array [
end a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner'),
a_hash_including('description' => 'Group runner'),
a_hash_including('description' => 'Shared runner')
]
end end
it 'filters runners by scope' do it 'filters runners by scope' do
...@@ -103,20 +136,62 @@ describe API::Runners do ...@@ -103,20 +136,62 @@ describe API::Runners do
it 'filters runners by scope' do it 'filters runners by scope' do
get api('/runners/all?scope=specific', admin) get api('/runners/all?scope=specific', admin)
shared = json_response.any? { |r| r['is_shared'] }
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[0]).to have_key('ip_address') expect(json_response).to match_array [
expect(shared).to be_falsey a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner'),
a_hash_including('description' => 'Group runner')
]
end end
it 'avoids filtering if scope is invalid' do it 'avoids filtering if scope is invalid' do
get api('/runners?scope=unknown', admin) get api('/runners/all?scope=unknown', admin)
expect(response).to have_gitlab_http_status(400)
end
it 'filters runners by type' do
get api('/runners/all?type=project_type', admin)
expect(json_response).to match_array [
a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner')
]
end
it 'does not filter by invalid type' do
get api('/runners/all?type=bogus', admin)
expect(response).to have_gitlab_http_status(400)
end
it 'filters runners by status' do
create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
get api('/runners/all?status=paused', admin)
expect(json_response).to match_array [
a_hash_including('description' => 'Inactive project runner')
]
end
it 'does not filter by invalid status' do
get api('/runners/all?status=bogus', admin)
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
end end
context 'without admin privileges' do
it 'does not return runners list' do
get api('/runners/all', user)
expect(response).to have_gitlab_http_status(403)
end
end
end
context 'unauthorized user' do context 'unauthorized user' do
it 'does not return runners' do it 'does not return runners' do
get api('/runners') get api('/runners')
...@@ -577,15 +652,69 @@ describe API::Runners do ...@@ -577,15 +652,69 @@ describe API::Runners do
describe 'GET /projects/:id/runners' do describe 'GET /projects/:id/runners' do
context 'authorized user with maintainer privileges' do context 'authorized user with maintainer privileges' do
it "returns project's runners" do it 'returns response status and headers' do
get api('/runners/all', admin)
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
end
it 'returns all runners' do
get api("/projects/#{project.id}/runners", user) get api("/projects/#{project.id}/runners", user)
shared = json_response.any? { |r| r['is_shared'] } expect(json_response).to match_array [
a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner'),
a_hash_including('description' => 'Shared runner')
]
end
it 'filters runners by scope' do
get api("/projects/#{project.id}/runners?scope=specific", 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
expect(json_response).to be_an Array
expect(json_response[0]).to have_key('ip_address') expect(json_response).to match_array [
expect(shared).to be_truthy a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner')
]
end
it 'avoids filtering if scope is invalid' do
get api("/projects/#{project.id}/runners?scope=unknown", user)
expect(response).to have_gitlab_http_status(400)
end
it 'filters runners by type' do
get api("/projects/#{project.id}/runners?type=project_type", user)
expect(json_response).to match_array [
a_hash_including('description' => 'Project runner'),
a_hash_including('description' => 'Two projects runner')
]
end
it 'does not filter by invalid type' do
get api("/projects/#{project.id}/runners?type=bogus", user)
expect(response).to have_gitlab_http_status(400)
end
it 'filters runners by status' do
create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
get api("/projects/#{project.id}/runners?status=paused", user)
expect(json_response).to match_array [
a_hash_including('description' => 'Inactive project runner')
]
end
it 'does not filter by invalid status' do
get api("/projects/#{project.id}/runners?status=bogus", user)
expect(response).to have_gitlab_http_status(400)
end end
end end
......
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