1//
2// Copyright 2017, Sander van Harmelen
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17package gitlab
18
19import (
20 "fmt"
21 "time"
22)
23
24// RunnersService handles communication with the runner related methods of the
25// GitLab API.
26//
27// GitLab API docs: https://docs.gitlab.com/ce/api/runners.html
28type RunnersService struct {
29 client *Client
30}
31
32// Runner represents a GitLab CI Runner.
33//
34// GitLab API docs: https://docs.gitlab.com/ce/api/runners.html
35type Runner struct {
36 ID int `json:"id"`
37 Description string `json:"description"`
38 Active bool `json:"active"`
39 IsShared bool `json:"is_shared"`
40 IPAddress string `json:"ip_address"`
41 Name string `json:"name"`
42 Online bool `json:"online"`
43 Status string `json:"status"`
44 Token string `json:"token"`
45}
46
47// RunnerDetails represents the GitLab CI runner details.
48//
49// GitLab API docs: https://docs.gitlab.com/ce/api/runners.html
50type RunnerDetails struct {
51 Active bool `json:"active"`
52 Architecture string `json:"architecture"`
53 Description string `json:"description"`
54 ID int `json:"id"`
55 IPAddress string `json:"ip_address"`
56 IsShared bool `json:"is_shared"`
57 ContactedAt *time.Time `json:"contacted_at"`
58 Name string `json:"name"`
59 Online bool `json:"online"`
60 Status string `json:"status"`
61 Platform string `json:"platform"`
62 Projects []struct {
63 ID int `json:"id"`
64 Name string `json:"name"`
65 NameWithNamespace string `json:"name_with_namespace"`
66 Path string `json:"path"`
67 PathWithNamespace string `json:"path_with_namespace"`
68 } `json:"projects"`
69 Token string `json:"token"`
70 Revision string `json:"revision"`
71 TagList []string `json:"tag_list"`
72 Version string `json:"version"`
73 AccessLevel string `json:"access_level"`
74 MaximumTimeout int `json:"maximum_timeout"`
75 Groups []struct {
76 ID int `json:"id"`
77 Name string `json:"name"`
78 WebURL string `json:"web_url"`
79 } `json:"groups"`
80}
81
82// ListRunnersOptions represents the available ListRunners() options.
83//
84// GitLab API docs:
85// https://docs.gitlab.com/ce/api/runners.html#list-owned-runners
86type ListRunnersOptions struct {
87 ListOptions
88 Scope *string `url:"scope,omitempty" json:"scope,omitempty"`
89 Type *string `url:"type,omitempty" json:"type,omitempty"`
90 Status *string `url:"status,omitempty" json:"status,omitempty"`
91 TagList []string `url:"tag_list,comma,omitempty" json:"tag_list,omitempty"`
92}
93
94// ListRunners gets a list of runners accessible by the authenticated user.
95//
96// GitLab API docs:
97// https://docs.gitlab.com/ce/api/runners.html#list-owned-runners
98func (s *RunnersService) ListRunners(opt *ListRunnersOptions, options ...OptionFunc) ([]*Runner, *Response, error) {
99 req, err := s.client.NewRequest("GET", "runners", opt, options)
100 if err != nil {
101 return nil, nil, err
102 }
103
104 var rs []*Runner
105 resp, err := s.client.Do(req, &rs)
106 if err != nil {
107 return nil, resp, err
108 }
109
110 return rs, resp, err
111}
112
113// ListAllRunners gets a list of all runners in the GitLab instance. Access is
114// restricted to users with admin privileges.
115//
116// GitLab API docs:
117// https://docs.gitlab.com/ce/api/runners.html#list-all-runners
118func (s *RunnersService) ListAllRunners(opt *ListRunnersOptions, options ...OptionFunc) ([]*Runner, *Response, error) {
119 req, err := s.client.NewRequest("GET", "runners/all", opt, options)
120 if err != nil {
121 return nil, nil, err
122 }
123
124 var rs []*Runner
125 resp, err := s.client.Do(req, &rs)
126 if err != nil {
127 return nil, resp, err
128 }
129
130 return rs, resp, err
131}
132
133// GetRunnerDetails returns details for given runner.
134//
135// GitLab API docs:
136// https://docs.gitlab.com/ce/api/runners.html#get-runner-39-s-details
137func (s *RunnersService) GetRunnerDetails(rid interface{}, options ...OptionFunc) (*RunnerDetails, *Response, error) {
138 runner, err := parseID(rid)
139 if err != nil {
140 return nil, nil, err
141 }
142 u := fmt.Sprintf("runners/%s", runner)
143
144 req, err := s.client.NewRequest("GET", u, nil, options)
145 if err != nil {
146 return nil, nil, err
147 }
148
149 var rs *RunnerDetails
150 resp, err := s.client.Do(req, &rs)
151 if err != nil {
152 return nil, resp, err
153 }
154
155 return rs, resp, err
156}
157
158// UpdateRunnerDetailsOptions represents the available UpdateRunnerDetails() options.
159//
160// GitLab API docs:
161// https://docs.gitlab.com/ce/api/runners.html#update-runner-39-s-details
162type UpdateRunnerDetailsOptions struct {
163 Description *string `url:"description,omitempty" json:"description,omitempty"`
164 Active *bool `url:"active,omitempty" json:"active,omitempty"`
165 TagList []string `url:"tag_list[],omitempty" json:"tag_list,omitempty"`
166 RunUntagged *bool `url:"run_untagged,omitempty" json:"run_untagged,omitempty"`
167 Locked *bool `url:"locked,omitempty" json:"locked,omitempty"`
168 AccessLevel *string `url:"access_level,omitempty" json:"access_level,omitempty"`
169 MaximumTimeout *int `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"`
170}
171
172// UpdateRunnerDetails updates details for a given runner.
173//
174// GitLab API docs:
175// https://docs.gitlab.com/ce/api/runners.html#update-runner-39-s-details
176func (s *RunnersService) UpdateRunnerDetails(rid interface{}, opt *UpdateRunnerDetailsOptions, options ...OptionFunc) (*RunnerDetails, *Response, error) {
177 runner, err := parseID(rid)
178 if err != nil {
179 return nil, nil, err
180 }
181 u := fmt.Sprintf("runners/%s", runner)
182
183 req, err := s.client.NewRequest("PUT", u, opt, options)
184 if err != nil {
185 return nil, nil, err
186 }
187
188 var rs *RunnerDetails
189 resp, err := s.client.Do(req, &rs)
190 if err != nil {
191 return nil, resp, err
192 }
193
194 return rs, resp, err
195}
196
197// RemoveRunner removes a runner.
198//
199// GitLab API docs:
200// https://docs.gitlab.com/ce/api/runners.html#remove-a-runner
201func (s *RunnersService) RemoveRunner(rid interface{}, options ...OptionFunc) (*Response, error) {
202 runner, err := parseID(rid)
203 if err != nil {
204 return nil, err
205 }
206 u := fmt.Sprintf("runners/%s", runner)
207
208 req, err := s.client.NewRequest("DELETE", u, nil, options)
209 if err != nil {
210 return nil, err
211 }
212
213 return s.client.Do(req, nil)
214}
215
216// ListRunnerJobsOptions represents the available ListRunnerJobs()
217// options. Status can be one of: running, success, failed, canceled.
218//
219// GitLab API docs:
220// https://docs.gitlab.com/ce/api/runners.html#list-runners-jobs
221type ListRunnerJobsOptions struct {
222 ListOptions
223 Status *string `url:"status,omitempty" json:"status,omitempty"`
224 OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
225 Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
226}
227
228// ListRunnerJobs gets a list of jobs that are being processed or were processed by specified Runner.
229//
230// GitLab API docs:
231// https://docs.gitlab.com/ce/api/runners.html#list-runner-39-s-jobs
232func (s *RunnersService) ListRunnerJobs(rid interface{}, opt *ListRunnerJobsOptions, options ...OptionFunc) ([]*Job, *Response, error) {
233 runner, err := parseID(rid)
234 if err != nil {
235 return nil, nil, err
236 }
237 u := fmt.Sprintf("runners/%s/jobs", runner)
238
239 req, err := s.client.NewRequest("GET", u, opt, options)
240 if err != nil {
241 return nil, nil, err
242 }
243
244 var rs []*Job
245 resp, err := s.client.Do(req, &rs)
246 if err != nil {
247 return nil, resp, err
248 }
249
250 return rs, resp, err
251}
252
253// ListProjectRunnersOptions represents the available ListProjectRunners()
254// options.
255//
256// GitLab API docs:
257// https://docs.gitlab.com/ce/api/runners.html#list-project-s-runners
258type ListProjectRunnersOptions ListRunnersOptions
259
260// ListProjectRunners gets a list of runners accessible by the authenticated user.
261//
262// GitLab API docs:
263// https://docs.gitlab.com/ce/api/runners.html#list-project-s-runners
264func (s *RunnersService) ListProjectRunners(pid interface{}, opt *ListProjectRunnersOptions, options ...OptionFunc) ([]*Runner, *Response, error) {
265 project, err := parseID(pid)
266 if err != nil {
267 return nil, nil, err
268 }
269 u := fmt.Sprintf("projects/%s/runners", pathEscape(project))
270
271 req, err := s.client.NewRequest("GET", u, opt, options)
272 if err != nil {
273 return nil, nil, err
274 }
275
276 var rs []*Runner
277 resp, err := s.client.Do(req, &rs)
278 if err != nil {
279 return nil, resp, err
280 }
281
282 return rs, resp, err
283}
284
285// EnableProjectRunnerOptions represents the available EnableProjectRunner()
286// options.
287//
288// GitLab API docs:
289// https://docs.gitlab.com/ce/api/runners.html#enable-a-runner-in-project
290type EnableProjectRunnerOptions struct {
291 RunnerID int `json:"runner_id"`
292}
293
294// EnableProjectRunner enables an available specific runner in the project.
295//
296// GitLab API docs:
297// https://docs.gitlab.com/ce/api/runners.html#enable-a-runner-in-project
298func (s *RunnersService) EnableProjectRunner(pid interface{}, opt *EnableProjectRunnerOptions, options ...OptionFunc) (*Runner, *Response, error) {
299 project, err := parseID(pid)
300 if err != nil {
301 return nil, nil, err
302 }
303 u := fmt.Sprintf("projects/%s/runners", pathEscape(project))
304
305 req, err := s.client.NewRequest("POST", u, opt, options)
306 if err != nil {
307 return nil, nil, err
308 }
309
310 var r *Runner
311 resp, err := s.client.Do(req, &r)
312 if err != nil {
313 return nil, resp, err
314 }
315
316 return r, resp, err
317}
318
319// DisableProjectRunner disables a specific runner from project.
320//
321// GitLab API docs:
322// https://docs.gitlab.com/ce/api/runners.html#disable-a-runner-from-project
323func (s *RunnersService) DisableProjectRunner(pid interface{}, runner int, options ...OptionFunc) (*Response, error) {
324 project, err := parseID(pid)
325 if err != nil {
326 return nil, err
327 }
328 u := fmt.Sprintf("projects/%s/runners/%d", pathEscape(project), runner)
329
330 req, err := s.client.NewRequest("DELETE", u, nil, options)
331 if err != nil {
332 return nil, err
333 }
334
335 return s.client.Do(req, nil)
336}
337
338// RegisterNewRunnerOptions represents the available RegisterNewRunner()
339// options.
340//
341// GitLab API docs:
342// https://docs.gitlab.com/ce/api/runners.html#register-a-new-runner
343type RegisterNewRunnerOptions struct {
344 Token *string `url:"token" json:"token"`
345 Description *string `url:"description,omitempty" json:"description,omitempty"`
346 Info *string `url:"info,omitempty" json:"info,omitempty"`
347 Active *bool `url:"active,omitempty" json:"active,omitempty"`
348 Locked *bool `url:"locked,omitempty" json:"locked,omitempty"`
349 RunUntagged *bool `url:"run_untagged,omitempty" json:"run_untagged,omitempty"`
350 TagList []string `url:"tag_list[],omitempty" json:"tag_list,omitempty"`
351 MaximumTimeout *int `url:"maximum_timeout,omitempty" json:"maximum_timeout,omitempty"`
352}
353
354// RegisterNewRunner registers a new Runner for the instance.
355//
356// GitLab API docs:
357// https://docs.gitlab.com/ce/api/runners.html#register-a-new-runner
358func (s *RunnersService) RegisterNewRunner(opt *RegisterNewRunnerOptions, options ...OptionFunc) (*Runner, *Response, error) {
359 req, err := s.client.NewRequest("POST", "runners", opt, options)
360 if err != nil {
361 return nil, nil, err
362 }
363
364 var r *Runner
365 resp, err := s.client.Do(req, &r)
366 if err != nil {
367 return nil, resp, err
368 }
369
370 return r, resp, err
371}
372
373// DeleteRegisteredRunnerOptions represents the available
374// DeleteRegisteredRunner() options.
375//
376// GitLab API docs:
377// https://docs.gitlab.com/ce/api/runners.html#delete-a-registered-runner
378type DeleteRegisteredRunnerOptions struct {
379 Token *string `url:"token" json:"token"`
380}
381
382// DeleteRegisteredRunner registers a new Runner for the instance.
383//
384// GitLab API docs:
385// https://docs.gitlab.com/ce/api/runners.html#delete-a-registered-runner
386func (s *RunnersService) DeleteRegisteredRunner(opt *DeleteRegisteredRunnerOptions, options ...OptionFunc) (*Response, error) {
387 req, err := s.client.NewRequest("DELETE", "runners", opt, options)
388 if err != nil {
389 return nil, err
390 }
391
392 return s.client.Do(req, nil)
393}
394
395// VerifyRegisteredRunnerOptions represents the available
396// VerifyRegisteredRunner() options.
397//
398// GitLab API docs:
399// https://docs.gitlab.com/ce/api/runners.html#verify-authentication-for-a-registered-runner
400type VerifyRegisteredRunnerOptions struct {
401 Token *string `url:"token" json:"token"`
402}
403
404// VerifyRegisteredRunner registers a new Runner for the instance.
405//
406// GitLab API docs:
407// https://docs.gitlab.com/ce/api/runners.html#verify-authentication-for-a-registered-runner
408func (s *RunnersService) VerifyRegisteredRunner(opt *VerifyRegisteredRunnerOptions, options ...OptionFunc) (*Response, error) {
409 req, err := s.client.NewRequest("POST", "runners/verify", opt, options)
410 if err != nil {
411 return nil, err
412 }
413
414 return s.client.Do(req, nil)
415}