registration and unregister work
This commit is contained in:
parent
6e7a6055b4
commit
2ec8fb5411
@ -5,6 +5,99 @@ command used to register new runner
|
||||
```shell script
|
||||
$ docker run -d --name gitlab-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock -v gitlab-runner-config:/etc/gitlab-runner gitlab/gitlab-runner:latest
|
||||
|
||||
$ gitlab-runner register -non-interactive --description "manualy registered gitlab runner" --url "http://172.17.0.1
|
||||
:8080/" --registration-token "registration_token" --tag-list "docker,manual"
|
||||
$ gitlab-runner register -non-interactive --description "manualy registered gitlab runner" --url "http://172.17.0.1:8080/" --registration-token "3b79eb1f-32f3-4db2-ad1b-6
|
||||
702e476d839" --tag-list "docker,manual" --executor shell
|
||||
```
|
||||
|
||||
same with curl
|
||||
|
||||
```shell script
|
||||
$ curl --request POST -H 'Content-Type: application/json' "http://localhost:8080/api/v4/runners" -d '{"description":"manualy registered gitlab runner","tag_list":"docker,manual","run_untagged":false,"locked":true,"active":true,"info":{"name":"gitlab-runner","version":"13.3.1","revision":"738bbe5a","platform":"linux","architecture":"amd64","features":{"variables":false,"image":false,"services":false,"artifacts":false,"cache":false,"shared":false,"upload_multiple_artifacts":false,"upload_raw_artifacts":false,"session":false,"terminal":false,"refspecs":false,"masking":false,"proxy":false,"raw_variables":false,"artifacts_exclude":false,"multi_build_steps":false}},"token":"registration_token"}'
|
||||
```
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
```json
|
||||
{
|
||||
"description":"manualy registered gitlab runner",
|
||||
"tag_list":"docker,manual",
|
||||
"run_untagged":false,
|
||||
"locked":true,
|
||||
"active":true,
|
||||
"info":{
|
||||
"name":"gitlab-runner",
|
||||
"version":"13.3.1",
|
||||
"revision":"738bbe5a",
|
||||
"platform":"linux",
|
||||
"architecture":"amd64",
|
||||
"features":{
|
||||
"variables":false,
|
||||
"image":false,
|
||||
"services":false,
|
||||
"artifacts":false,
|
||||
"cache":false,
|
||||
"shared":false,
|
||||
"upload_multiple_artifacts":false,
|
||||
"upload_raw_artifacts":false,
|
||||
"session":false,
|
||||
"terminal":false,
|
||||
"refspecs":false,
|
||||
"masking":false,
|
||||
"proxy":false,
|
||||
"raw_variables":false,
|
||||
"artifacts_exclude":false,
|
||||
"multi_build_steps":false
|
||||
}
|
||||
},
|
||||
"token":"registration_token"
|
||||
}
|
||||
```
|
||||
|
||||
## http call use when job is run
|
||||
|
||||
```
|
||||
[POST /api/v4/jobs/request HTTP/1.1
|
||||
Host: 172.17.0.1:8080
|
||||
User-Agent: gitlab-runner 13.3.1 (13-3-stable; go1.13.8; linux/amd64)
|
||||
Content-Length: 510
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Accept-Encoding: gzip
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"info":{
|
||||
"name":"gitlab-runner",
|
||||
"version":"13.3.1",
|
||||
"revision":"738bbe5a",
|
||||
"platform":"linux",
|
||||
"architecture":"amd64",
|
||||
"executor":"shell",
|
||||
"shell":"bash",
|
||||
"features":{
|
||||
"variables":true,
|
||||
"image":false,
|
||||
"services":false,
|
||||
"artifacts":true,
|
||||
"cache":true,
|
||||
"shared":true,
|
||||
"upload_multiple_artifacts":true,
|
||||
"upload_raw_artifacts":true,
|
||||
"session":true,
|
||||
"terminal":true,
|
||||
"refspecs":true,
|
||||
"masking":true,
|
||||
"proxy":false,
|
||||
"raw_variables":true,
|
||||
"artifacts_exclude":true,
|
||||
"multi_build_steps":true
|
||||
}
|
||||
},
|
||||
"token":"76a79b73-b211-48c6-a3da-6b99fb8b0612"
|
||||
}
|
||||
```
|
||||
|
||||
...
|
||||
|
1
pom.xml
1
pom.xml
@ -9,6 +9,7 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.4.0-M2</version>
|
||||
<!-- <version>2.3.2.RELEASE</version>-->
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
@ -1,42 +1,39 @@
|
||||
package tk.antoine_roux.wiki;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import tk.antoine_roux.wiki.annotation.ApiPrefix;
|
||||
import tk.antoine_roux.wiki.annotation.ApiVersion;
|
||||
import tk.antoine_roux.wiki.configuration.Exception.DeleteRunnerException;
|
||||
import tk.antoine_roux.wiki.model.Runner;
|
||||
import tk.antoine_roux.wiki.model.request.AddRunner;
|
||||
import tk.antoine_roux.wiki.model.request.DeleteRunner;
|
||||
import tk.antoine_roux.wiki.model.response.RegisterResponse;
|
||||
import tk.antoine_roux.wiki.utilitary.Boolean;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
import static tk.antoine_roux.wiki.Constant.*;
|
||||
|
||||
@RestController
|
||||
@ApiPrefix(API_PREFIX)
|
||||
public class ControllerHandlers {
|
||||
|
||||
private RunnerRegistrar runnerRegistrar;
|
||||
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private final RunnerRegistrar runnerRegistrar;
|
||||
|
||||
@Autowired
|
||||
public ControllerHandlers(RunnerRegistrar runnerRegistrar) {
|
||||
this.runnerRegistrar = runnerRegistrar;
|
||||
}
|
||||
|
||||
/**
|
||||
* add register new runners
|
||||
*
|
||||
* @param body
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@ApiVersion({API_VERSION})
|
||||
@PostMapping(value = "/runners", produces = APPLICATION_JSON_VALUE)
|
||||
public static ResponseEntity<String> addRunner(@RequestBody String body) {
|
||||
System.out.println(body);
|
||||
return ResponseEntity.ok(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* hello test endpoint
|
||||
*
|
||||
@ -44,7 +41,7 @@ public class ControllerHandlers {
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/info")
|
||||
public static ResponseEntity<TreeMap<String, String>> info() {
|
||||
public ResponseEntity<TreeMap<String, String>> info() {
|
||||
return ResponseEntity.ok(
|
||||
// sort attribute by key name
|
||||
new TreeMap<>(
|
||||
@ -55,4 +52,32 @@ public class ControllerHandlers {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* add register new runners
|
||||
*
|
||||
* @param body
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@ApiVersion({API_VERSION})
|
||||
@PostMapping("/runners")
|
||||
public ResponseEntity<RegisterResponse> addRunner(@RequestBody AddRunner body) {
|
||||
|
||||
logger.debug("Receive register runner request " + body);
|
||||
Runner createdRunner = this.runnerRegistrar.addRunner(body);
|
||||
|
||||
RegisterResponse response = createdRunner.toRegisterResponse();
|
||||
logger.debug("Response register runner " + response);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(response);
|
||||
}
|
||||
|
||||
@ApiVersion(API_VERSION)
|
||||
@DeleteMapping("/runners")
|
||||
public ResponseEntity<Void> deleteRunner(@RequestBody DeleteRunner body) throws Exception {
|
||||
logger.debug("Receive delete runner request " + body);
|
||||
Boolean.trueOrElseThrow(this.runnerRegistrar.removeRunnerByRegistrationToken(body), DeleteRunnerException::new);
|
||||
logger.debug("Successfully delete runner ");
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,14 @@
|
||||
package tk.antoine_roux.wiki;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import tk.antoine_roux.wiki.model.Runner;
|
||||
import tk.antoine_roux.wiki.model.request.AddRunner;
|
||||
import tk.antoine_roux.wiki.model.request.DeleteRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Class use to perist registered gitlab runner
|
||||
@ -12,30 +17,24 @@ import java.util.List;
|
||||
public class RunnerRegistrar {
|
||||
private final List<Runner> runners = new ArrayList<>();
|
||||
|
||||
AtomicInteger idIncrementer = new AtomicInteger();
|
||||
|
||||
public List<Runner> getRunners() {
|
||||
return this.runners;
|
||||
}
|
||||
|
||||
public void addRunner(Runner r) {
|
||||
public Runner addRunner(AddRunner addRunner) {
|
||||
Runner r = new Runner();
|
||||
r.id = this.idIncrementer.getAndIncrement();
|
||||
r.authenticationToken = UUID.randomUUID();
|
||||
r.registrationToken = addRunner.token;
|
||||
r.tags = addRunner.tags;
|
||||
r.description = addRunner.description;
|
||||
this.runners.add(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* in memory representation of gitlab runner
|
||||
*/
|
||||
public static class Runner {
|
||||
private static final String TAG_SEPARATOR = ",";
|
||||
|
||||
public String id;
|
||||
public String description;
|
||||
public String[] tags;
|
||||
public String registrationToken;
|
||||
|
||||
public Runner(String id, String description, String tags, String registrationToken) {
|
||||
this.id = id;
|
||||
this.description = description;
|
||||
this.tags = tags.split(TAG_SEPARATOR);
|
||||
this.registrationToken = registrationToken;
|
||||
}
|
||||
public boolean removeRunnerByRegistrationToken(DeleteRunner r) {
|
||||
return this.runners.removeIf(runner -> runner.authenticationToken.equals(r.token));
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandle
|
||||
RequestMappingInfo requestMappingInfo = new RequestMappingInfo(
|
||||
new PatternsRequestCondition(
|
||||
new String[]{annotationApiPrefix.value()},
|
||||
false,
|
||||
this.getPathMatcher()
|
||||
this.getUrlPathHelper(), this.getPathMatcher(),
|
||||
false
|
||||
),
|
||||
new RequestMethodsRequestCondition(),
|
||||
new ParamsRequestCondition(),
|
||||
@ -76,7 +76,11 @@ public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandle
|
||||
}
|
||||
|
||||
return new RequestMappingInfo(
|
||||
new PatternsRequestCondition(patterns, false, this.getPathMatcher()),
|
||||
new PatternsRequestCondition(
|
||||
patterns, this.getUrlPathHelper(), this.getPathMatcher(),
|
||||
false
|
||||
// , this.useTrailingSlashMatch(), this.getFileExtensions()
|
||||
),
|
||||
new RequestMethodsRequestCondition(),
|
||||
new ParamsRequestCondition(),
|
||||
new HeadersRequestCondition(),
|
||||
|
@ -0,0 +1,39 @@
|
||||
package tk.antoine_roux.wiki.configuration;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
import tk.antoine_roux.wiki.configuration.Exception.DeleteRunnerException;
|
||||
import tk.antoine_roux.wiki.configuration.Exception.NoIdException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Custom http handler for dealing with {@link Exception}
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
|
||||
@ExceptionHandler({NoIdException.class})
|
||||
public ResponseEntity<Object> handleInternalException(NoIdException ex, WebRequest request) {
|
||||
Map<String, Object> body = new LinkedHashMap<>();
|
||||
body.put("timestamp", LocalDateTime.now());
|
||||
body.put("message", ex.getMessage());
|
||||
|
||||
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@ExceptionHandler({DeleteRunnerException.class})
|
||||
public ResponseEntity<Object> handleNotFoundException(NoIdException ex, WebRequest request) {
|
||||
Map<String, Object> body = new LinkedHashMap<>();
|
||||
body.put("timestamp", LocalDateTime.now());
|
||||
body.put("message", ex.getMessage());
|
||||
|
||||
return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package tk.antoine_roux.wiki.configuration.Exception;
|
||||
|
||||
public class DeleteRunnerException extends RuntimeException {
|
||||
private static final long serialVersionUID = 559919382888691526L;
|
||||
|
||||
public DeleteRunnerException() {
|
||||
super("Fail to delete runner");
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package tk.antoine_roux.wiki.configuration.Exception;
|
||||
|
||||
public class NoIdException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1470945508482780554L;
|
||||
|
||||
public NoIdException() {
|
||||
super("Invalid id value");
|
||||
}
|
||||
}
|
@ -1,25 +1,20 @@
|
||||
package tk.antoine_roux.wiki.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.resource.ResourceUrlProvider;
|
||||
import tk.antoine_roux.wiki.Constant;
|
||||
|
||||
/**
|
||||
* spring web configuration
|
||||
*
|
||||
* @see org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class WebConfiguration extends WebMvcConfigurationSupport {
|
||||
public class WebConfiguration implements WebMvcRegistrations {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public RequestMappingHandlerMapping requestMappingHandlerMapping(ContentNegotiationManager contentNegotiationManager,
|
||||
FormattingConversionService conversionService,
|
||||
ResourceUrlProvider resourceUrlProvider) {
|
||||
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
|
||||
return new ApiVersionRequestMappingHandlerMapping(Constant.VERSION_PREFIX);
|
||||
}
|
||||
}
|
||||
|
21
src/main/java/tk/antoine_roux/wiki/model/Runner.java
Normal file
21
src/main/java/tk/antoine_roux/wiki/model/Runner.java
Normal file
@ -0,0 +1,21 @@
|
||||
package tk.antoine_roux.wiki.model;
|
||||
|
||||
import tk.antoine_roux.wiki.model.response.RegisterResponse;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* in memory representation of gitlab runner
|
||||
*/
|
||||
public class Runner {
|
||||
public String description;
|
||||
public List<String> tags;
|
||||
public UUID registrationToken;
|
||||
public UUID authenticationToken;
|
||||
public Integer id;
|
||||
|
||||
public RegisterResponse toRegisterResponse() {
|
||||
return new RegisterResponse(String.valueOf(this.id), this.authenticationToken.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package tk.antoine_roux.wiki.model.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Model use to add runner instance
|
||||
*/
|
||||
public class AddRunner {
|
||||
private static final String TAG_SEPARATOR = ",";
|
||||
|
||||
public String description;
|
||||
public List<String> tags;
|
||||
public UUID token;
|
||||
|
||||
@JsonProperty("tag_list")
|
||||
public void setTags(String tags) {
|
||||
this.tags = Arrays.asList(tags.split(TAG_SEPARATOR).clone());
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package tk.antoine_roux.wiki.model.request;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Model use to remove runner instance
|
||||
*/
|
||||
public class DeleteRunner {
|
||||
public UUID token;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package tk.antoine_roux.wiki.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Json response object for register endpoint
|
||||
*/
|
||||
public class RegisterResponse {
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
String id;
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
String token;
|
||||
|
||||
public RegisterResponse(String id, String token) {
|
||||
this.id = id;
|
||||
this.token = token;
|
||||
}
|
||||
}
|
19
src/main/java/tk/antoine_roux/wiki/utilitary/Boolean.java
Normal file
19
src/main/java/tk/antoine_roux/wiki/utilitary/Boolean.java
Normal file
@ -0,0 +1,19 @@
|
||||
package tk.antoine_roux.wiki.utilitary;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class Boolean {
|
||||
|
||||
/**
|
||||
* utility method throw ex if in is false, else follow in value
|
||||
*
|
||||
* @param in
|
||||
* @param ex
|
||||
* @throws Exception exception thrown when in param is false
|
||||
*/
|
||||
public static <T extends Exception> void trueOrElseThrow(boolean in, Supplier<T> ex) throws Exception {
|
||||
if (!in) {
|
||||
throw ex.get();
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,9 @@ server.port=^application.port^
|
||||
|
||||
logging.level.root=INFO
|
||||
|
||||
# this log print request content
|
||||
logging.level.org.apache.coyote.http11.Http11InputBuffer=DEBUG
|
||||
|
||||
# spring boot actuator
|
||||
management.server.port=8080
|
||||
info.name=gitlab-runner-gateway
|
||||
|
Loading…
Reference in New Issue
Block a user