Skip to content
Snippets Groups Projects
Commit 7f166e6d authored by Martin Weise's avatar Martin Weise
Browse files

decorate the endpoint

parent 94a450b8
No related branches found
No related tags found
No related merge requests found
Showing
with 74 additions and 59 deletions
...@@ -29,12 +29,16 @@ Everything is handled by compose, just build it by running: ...@@ -29,12 +29,16 @@ Everything is handled by compose, just build it by running:
docker-compose build docker-compose build
``` ```
## Develop
The endpoints are documented with Swagger 2.1 and OpenAPI 3.0. The current specification for the front-end is obtainable programatically from [http://fda-container-managing-service/swagger-resources](http://localhost:9091/swagger-resources).
For easy visualization use OpenAPI at [http://fda-container-managing-service/swagger-ui/](http://localhost:9091/swagger-ui/)
## Deployment ## Deployment
The pipeline is set-up to build and test all commits. A commit to dev or master branch triggers additional jobs. The pipeline is set-up to build and test all commits. A commit to dev or master branch triggers additional jobs.
### Development
A commit to `dev` triggers the following pipeline. It deploys the docker images to the docker registry hosted on the fda-runner server and deploys it also to a test server (fda-deployment) at TU Wien. A commit to `dev` triggers the following pipeline. It deploys the docker images to the docker registry hosted on the fda-runner server and deploys it also to a test server (fda-deployment) at TU Wien.
![pipeline dev](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-docs/-/raw/master/figures/fda-pipeline-dev.png) ![pipeline dev](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-docs/-/raw/master/figures/fda-pipeline-dev.png)
......
...@@ -3,20 +3,17 @@ package at.tuwien.api.dto.container; ...@@ -3,20 +3,17 @@ package at.tuwien.api.dto.container;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.net.InetAddress;
import java.time.Instant;
@Getter @Getter
@Setter @Setter
public class ContainerDto { public class ContainerDto extends DatabaseContainerBriefDto {
private String containerId;
private String created;
private String containerName;
private String databaseName; private ContainerStateDto status;
private String status; private IpAddressDto ipAddress;
private String ipAddress; private Instant created;
} }
package at.tuwien.api.dto.container;
import lombok.Getter;
@Getter
public enum ContainerStateDto {
CREATED, RESTARTING, RUNNING, PAUSED, EXITED, DEAD
}
...@@ -6,9 +6,9 @@ import lombok.Setter; ...@@ -6,9 +6,9 @@ import lombok.Setter;
@Getter @Getter
@Setter @Setter
@Builder
public class DatabaseContainerBriefDto { public class DatabaseContainerBriefDto {
private String id; private String id;
private String containerName;
} }
...@@ -5,18 +5,8 @@ import lombok.Setter; ...@@ -5,18 +5,8 @@ import lombok.Setter;
@Getter @Getter
@Setter @Setter
public class DatabaseContainerDto { public class DatabaseContainerDto extends ContainerDto {
private String containerId;
private String created;
private String containerName;
private String databaseName; private String databaseName;
private String status;
private String ipAddress;
} }
package at.tuwien.api.dto.database; package at.tuwien.api.dto.container;
import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.net.InetAddress;
@Getter @Getter
@Setter @Setter
@Builder public class IpAddressDto {
public class DatabaseContainerCreateResponseDto {
private String containerId; private String ipv4;
} }
...@@ -8,7 +8,6 @@ import springfox.documentation.service.ApiInfo; ...@@ -8,7 +8,6 @@ import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact; import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Collections; import java.util.Collections;
...@@ -22,7 +21,7 @@ public class SwaggerConfig { ...@@ -22,7 +21,7 @@ public class SwaggerConfig {
.groupName("database-api") .groupName("database-api")
.apiInfo(apiInfo()) .apiInfo(apiInfo())
.select() .select()
.paths(PathSelectors.ant("/api/database.*")) .paths(PathSelectors.ant("/api/**"))
.build(); .build();
} }
......
...@@ -3,7 +3,6 @@ package at.tuwien.endpoints; ...@@ -3,7 +3,6 @@ package at.tuwien.endpoints;
import at.tuwien.api.dto.container.ContainerChangeDto; import at.tuwien.api.dto.container.ContainerChangeDto;
import at.tuwien.api.dto.container.DatabaseContainerBriefDto; import at.tuwien.api.dto.container.DatabaseContainerBriefDto;
import at.tuwien.api.dto.container.DatabaseContainerDto; import at.tuwien.api.dto.container.DatabaseContainerDto;
import at.tuwien.api.dto.database.DatabaseContainerCreateResponseDto;
import at.tuwien.api.dto.database.DatabaseContainerCreateRequestDto; import at.tuwien.api.dto.database.DatabaseContainerCreateRequestDto;
import at.tuwien.entity.DatabaseContainer; import at.tuwien.entity.DatabaseContainer;
import at.tuwien.exception.ContainerNotFoundException; import at.tuwien.exception.ContainerNotFoundException;
...@@ -11,6 +10,7 @@ import at.tuwien.exception.DockerClientException; ...@@ -11,6 +10,7 @@ import at.tuwien.exception.DockerClientException;
import at.tuwien.exception.ImageNotFoundException; import at.tuwien.exception.ImageNotFoundException;
import at.tuwien.mapper.DatabaseContainerMapper; import at.tuwien.mapper.DatabaseContainerMapper;
import at.tuwien.service.ContainerService; import at.tuwien.service.ContainerService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -37,50 +37,57 @@ public class DatabaseContainerController { ...@@ -37,50 +37,57 @@ public class DatabaseContainerController {
} }
@GetMapping("/database") @GetMapping("/database")
public ResponseEntity<List<DatabaseContainerBriefDto>> listDatabaseContainers() { @ApiOperation(value = "List all database containers", notes = "Lists the database containers in the metadata database.")
public ResponseEntity<List<DatabaseContainerBriefDto>> findAll() {
final List<DatabaseContainer> containers = containerService.getAll(); final List<DatabaseContainer> containers = containerService.getAll();
return ResponseEntity.ok() return ResponseEntity.ok()
.body(containers.stream() .body(containers.stream()
.map(containerMapper::databaseContainerToDataBaseContainerBriefDto) .map(containerMapper::databaseContainerToDatabaseContainerBriefDto)
.collect(Collectors.toList())); .collect(Collectors.toList()));
} }
@PostMapping("/database") @PostMapping("/database")
public ResponseEntity<DatabaseContainerCreateResponseDto> create(@RequestBody DatabaseContainerCreateRequestDto data) @ApiOperation(value = "Creates a new database containers", notes = "Creates a new database container whose image is registered in the metadata database too. Currently for development there is only one image supported 'postgres:12-alpine' as for temporal tables extension requires version 12.")
public ResponseEntity<DatabaseContainerDto> create(@RequestBody DatabaseContainerCreateRequestDto data)
throws ImageNotFoundException { throws ImageNotFoundException {
final DatabaseContainer container = containerService.create(data); final DatabaseContainer container = containerService.create(data);
log.debug("Create new database {} in container {} with id {}", data.getDatabaseName(), data.getContainerName(), container.getContainerId()); log.debug("Create new database {} in container {} with id {}", data.getDatabaseName(), data.getContainerName(), container.getContainerId());
return ResponseEntity.status(HttpStatus.CREATED) return ResponseEntity.status(HttpStatus.CREATED)
.body(containerMapper.databaseContainerToCreateDatabaseResponseDto(container)); .body(containerMapper.databaseContainerToDatabaseContainerDto(container));
} }
@GetMapping("/database/{id}") @GetMapping("/database/{id}")
@ApiOperation(value = "Get all informations about a database container", notes = "Since we follow the REST-principle, this method provides more informaiton than the findAll method.")
public ResponseEntity<DatabaseContainerDto> findById(@RequestParam String id) throws ContainerNotFoundException { public ResponseEntity<DatabaseContainerDto> findById(@RequestParam String id) throws ContainerNotFoundException {
final DatabaseContainer container = containerService.getById(id); final DatabaseContainer container = containerService.getById(id);
return ResponseEntity.ok() return ResponseEntity.ok()
.body(containerMapper.databaseContainerToDataBaseContainerDto(container)); .body(containerMapper.databaseContainerToDatabaseContainerDto(container));
} }
@PutMapping("/database/{id}") @PutMapping("/database/{id}")
public ResponseEntity<DatabaseContainerBriefDto> change(@RequestParam String id, @RequestBody ContainerChangeDto changeDto) throws ContainerNotFoundException, DockerClientException { @ApiOperation(value = "Change the state of a database container", notes = "The new state can only be one of START/STOP/REMOVE.", code = 202)
final DatabaseContainer container; public ResponseEntity<?> change(@RequestParam String id, @RequestBody ContainerChangeDto changeDto) throws ContainerNotFoundException, DockerClientException {
if (changeDto.getAction().equals(START) || changeDto.getAction().equals(STOP) || changeDto.getAction().equals(REMOVE)) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.build();
}
if (changeDto.getAction().equals(START)) { if (changeDto.getAction().equals(START)) {
container = containerService.start(id); containerService.start(id);
} else if (changeDto.getAction().equals(STOP)) { } else if (changeDto.getAction().equals(STOP)) {
container = containerService.stop(id); containerService.stop(id);
} else if (changeDto.getAction().equals(REMOVE)) { } else if (changeDto.getAction().equals(REMOVE)) {
container = containerService.remove(id); containerService.remove(id);
} else {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.build();
} }
return ResponseEntity.status(HttpStatus.ACCEPTED) return ResponseEntity.status(HttpStatus.ACCEPTED)
.body(containerMapper.databaseContainerToDataBaseContainerBriefDto(container)); .build();
} }
@DeleteMapping("/database/{id}") @DeleteMapping("/database/{id}")
public ResponseEntity<DatabaseContainerBriefDto> deleteDatabaseContainer(@RequestParam String id) { @ApiOperation(value = "Delete a database container.")
return ResponseEntity.status(HttpStatus.ACCEPTED).build(); public ResponseEntity deleteDatabaseContainer(@RequestParam String id) throws ContainerNotFoundException, DockerClientException {
containerService.remove(id);
return ResponseEntity.status(HttpStatus.OK)
.build();
} }
} }
...@@ -2,11 +2,11 @@ package at.tuwien.mapper; ...@@ -2,11 +2,11 @@ package at.tuwien.mapper;
import at.tuwien.api.dto.container.DatabaseContainerBriefDto; import at.tuwien.api.dto.container.DatabaseContainerBriefDto;
import at.tuwien.api.dto.container.DatabaseContainerDto; import at.tuwien.api.dto.container.DatabaseContainerDto;
import at.tuwien.api.dto.database.DatabaseContainerCreateResponseDto; import at.tuwien.api.dto.container.IpAddressDto;
import at.tuwien.entity.ContainerImage; import at.tuwien.entity.ContainerImage;
import at.tuwien.entity.DatabaseContainer;
import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.Container;
import at.tuwien.entity.DatabaseContainer;
import com.github.dockerjava.api.model.NetworkSettings; import com.github.dockerjava.api.model.NetworkSettings;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
...@@ -20,13 +20,6 @@ public interface DatabaseContainerMapper { ...@@ -20,13 +20,6 @@ public interface DatabaseContainerMapper {
@Mapping(source = "created", target = "containerCreated"), @Mapping(source = "created", target = "containerCreated"),
}) })
DatabaseContainer inspectContainerResponseToDatabaseContainer(InspectContainerResponse containerResponse); DatabaseContainer inspectContainerResponseToDatabaseContainer(InspectContainerResponse containerResponse);
// public DatabaseContainer map(InspectContainerResponse containerResponse) {
// DatabaseContainer databaseContainer = new DatabaseContainer();
// String ipAddress = containerResponse.getNetworkSettings().getNetworks().get("bridge").getIpAddress();
// String dbName = Arrays.stream(containerResponse.getConfig().getEnv()).filter(s -> s.startsWith("POSTGRES_DB=")).findFirst().get();
// databaseContainer.setStatus(containerResponse.getState().getStatus());
// return databaseContainer;
// }
default String networkSettingsNetworksBridgeToIpAddress(NetworkSettings data) { default String networkSettingsNetworksBridgeToIpAddress(NetworkSettings data) {
return data.getNetworks().get("bridge").getIpAddress(); return data.getNetworks().get("bridge").getIpAddress();
...@@ -42,9 +35,13 @@ public interface DatabaseContainerMapper { ...@@ -42,9 +35,13 @@ public interface DatabaseContainerMapper {
DatabaseContainer containerToDatabaseContainer(Container data); DatabaseContainer containerToDatabaseContainer(Container data);
DatabaseContainerBriefDto databaseContainerToDataBaseContainerBriefDto(DatabaseContainer data); DatabaseContainerBriefDto databaseContainerToDatabaseContainerBriefDto(DatabaseContainer data);
@Mappings({
@Mapping(target = "ipAddress.ipv4", source = "containerCreated"),
})
DatabaseContainerDto databaseContainerToDatabaseContainerDto(DatabaseContainer data);
DatabaseContainerDto databaseContainerToDataBaseContainerDto(DatabaseContainer data); IpAddressDto ipAddressToIpAddressDto(String data);
DatabaseContainerCreateResponseDto databaseContainerToCreateDatabaseResponseDto(DatabaseContainer data);
} }
...@@ -92,7 +92,7 @@ public class ContainerService { ...@@ -92,7 +92,7 @@ public class ContainerService {
return container; return container;
} }
public DatabaseContainer remove(String containerId) throws ContainerNotFoundException, DockerClientException { public void remove(String containerId) throws ContainerNotFoundException, DockerClientException {
final DatabaseContainer container = containerRepository.findByContainerId(containerId); final DatabaseContainer container = containerRepository.findByContainerId(containerId);
if (container == null) { if (container == null) {
throw new ContainerNotFoundException("no container with this id in metadata database"); throw new ContainerNotFoundException("no container with this id in metadata database");
...@@ -103,7 +103,6 @@ public class ContainerService { ...@@ -103,7 +103,6 @@ public class ContainerService {
throw new DockerClientException("docker client failed", e); throw new DockerClientException("docker client failed", e);
} }
log.debug("Removed container {}", containerId); log.debug("Removed container {}", containerId);
return container;
} }
public DatabaseContainer getById(String containerId) throws ContainerNotFoundException { public DatabaseContainer getById(String containerId) throws ContainerNotFoundException {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment