Commit 800bf64e authored by Kyle Edwards's avatar Kyle Edwards

GraphQL: Expose token_expires_at property and sorting

With the addition of the token_expires_at property, it can now
be exposed by the GraphQL API, and queries can sort by it.

Changelog: added
Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/30942
parent 3488a9c8
...@@ -4,7 +4,7 @@ module Ci ...@@ -4,7 +4,7 @@ module Ci
class RunnersFinder < UnionFinder class RunnersFinder < UnionFinder
include Gitlab::Allowable include Gitlab::Allowable
ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date].freeze ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date token_expires_at_asc token_expires_at_desc].freeze
DEFAULT_SORT = 'created_at_desc' DEFAULT_SORT = 'created_at_desc'
def initialize(current_user:, params:) def initialize(current_user:, params:)
......
...@@ -10,6 +10,8 @@ module Types ...@@ -10,6 +10,8 @@ module Types
value 'CONTACTED_DESC', 'Ordered by contacted_at in descending order.', value: :contacted_desc value 'CONTACTED_DESC', 'Ordered by contacted_at in descending order.', value: :contacted_desc
value 'CREATED_ASC', 'Ordered by created_at in ascending order.', value: :created_at_asc value 'CREATED_ASC', 'Ordered by created_at in ascending order.', value: :created_at_asc
value 'CREATED_DESC', 'Ordered by created_at in descending order.', value: :created_at_desc value 'CREATED_DESC', 'Ordered by created_at in descending order.', value: :created_at_desc
value 'TOKEN_EXPIRES_AT_ASC', 'Ordered by token_expires_at in ascending order.', value: :token_expires_at_asc
value 'TOKEN_EXPIRES_AT_DESC', 'Ordered by token_expires_at in descending order.', value: :token_expires_at_desc
end end
end end
end end
...@@ -25,6 +25,9 @@ module Types ...@@ -25,6 +25,9 @@ module Types
field :contacted_at, Types::TimeType, null: true, field :contacted_at, Types::TimeType, null: true,
description: 'Timestamp of last contact from this runner.', description: 'Timestamp of last contact from this runner.',
method: :contacted_at method: :contacted_at
field :token_expires_at, Types::TimeType, null: true,
description: 'Runner token expiration time.',
method: :token_expires_at
field :maximum_timeout, GraphQL::Types::Int, null: true, field :maximum_timeout, GraphQL::Types::Int, null: true,
description: 'Maximum timeout (in seconds) for jobs processed by the runner.' description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false, field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false,
......
...@@ -9201,6 +9201,7 @@ Represents the total number of issues and their weights for a particular day. ...@@ -9201,6 +9201,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunnerrunnertype"></a>`runnerType` | [`CiRunnerType!`](#cirunnertype) | Type of the runner. | | <a id="cirunnerrunnertype"></a>`runnerType` | [`CiRunnerType!`](#cirunnertype) | Type of the runner. |
| <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. | | <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
| <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. | | <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
| <a id="cirunnertokenexpiresat"></a>`tokenExpiresAt` | [`Time`](#time) | Runner token expiration time. |
| <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. | | <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. |
| <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. | | <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. |
...@@ -16796,6 +16797,8 @@ Values for sorting runners. ...@@ -16796,6 +16797,8 @@ Values for sorting runners.
| <a id="cirunnersortcontacted_desc"></a>`CONTACTED_DESC` | Ordered by contacted_at in descending order. | | <a id="cirunnersortcontacted_desc"></a>`CONTACTED_DESC` | Ordered by contacted_at in descending order. |
| <a id="cirunnersortcreated_asc"></a>`CREATED_ASC` | Ordered by created_at in ascending order. | | <a id="cirunnersortcreated_asc"></a>`CREATED_ASC` | Ordered by created_at in ascending order. |
| <a id="cirunnersortcreated_desc"></a>`CREATED_DESC` | Ordered by created_at in descending order. | | <a id="cirunnersortcreated_desc"></a>`CREATED_DESC` | Ordered by created_at in descending order. |
| <a id="cirunnersorttoken_expires_at_asc"></a>`TOKEN_EXPIRES_AT_ASC` | Ordered by token_expires_at in ascending order. |
| <a id="cirunnersorttoken_expires_at_desc"></a>`TOKEN_EXPIRES_AT_DESC` | Ordered by token_expires_at in descending order. |
### `CiRunnerStatus` ### `CiRunnerStatus`
...@@ -13,6 +13,7 @@ FactoryBot.define do ...@@ -13,6 +13,7 @@ FactoryBot.define do
transient do transient do
groups { [] } groups { [] }
projects { [] } projects { [] }
token_expires_at { nil }
end end
after(:build) do |runner, evaluator| after(:build) do |runner, evaluator|
...@@ -25,6 +26,10 @@ FactoryBot.define do ...@@ -25,6 +26,10 @@ FactoryBot.define do
end end
end end
after(:create) do |runner, evaluator|
runner.update!(token_expires_at: evaluator.token_expires_at) if evaluator.token_expires_at
end
trait :online do trait :online do
contacted_at { Time.now } contacted_at { Time.now }
end end
......
...@@ -91,8 +91,8 @@ RSpec.describe Ci::RunnersFinder do ...@@ -91,8 +91,8 @@ RSpec.describe Ci::RunnersFinder do
end end
context 'sorting' do context 'sorting' do
let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago } let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago, token_expires_at: '2022-02-15 07:00' }
let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago } let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago, token_expires_at: '2022-02-15 06:00' }
let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago } let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago }
subject do subject do
...@@ -142,6 +142,22 @@ RSpec.describe Ci::RunnersFinder do ...@@ -142,6 +142,22 @@ RSpec.describe Ci::RunnersFinder do
is_expected.to eq [runner1, runner3, runner2] is_expected.to eq [runner1, runner3, runner2]
end end
end end
context 'with sort param equal to token_expires_at_asc' do
let(:params) { { sort: 'token_expires_at_asc' } }
it 'sorts by contacted_at ascending' do
is_expected.to eq [runner2, runner1, runner3]
end
end
context 'with sort param equal to token_expires_at_desc' do
let(:params) { { sort: 'token_expires_at_desc' } }
it 'sorts by contacted_at descending' do
is_expected.to eq [runner3, runner1, runner2]
end
end
end end
context 'by non admin user' do context 'by non admin user' do
......
...@@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do ...@@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
id description created_at contacted_at maximum_timeout access_level active paused status id description created_at contacted_at maximum_timeout access_level active paused status
version short_sha revision locked run_untagged ip_address runner_type tag_list version short_sha revision locked run_untagged ip_address runner_type tag_list
project_count job_count admin_url edit_admin_url user_permissions executor_name project_count job_count admin_url edit_admin_url user_permissions executor_name
groups projects jobs groups projects jobs token_expires_at
] ]
expect(described_class).to include_graphql_fields(*expected_fields) expect(described_class).to include_graphql_fields(*expected_fields)
......
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