diff --git a/README.md b/README.md index d9d76944c45174245f14c4f8ec8642050b630b57..caadd4a9c6d27684898274a2291f7b612af97abf 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,16 @@ Everything is handled by compose, just build it by running: 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 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.  diff --git a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerDto.java b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerDto.java index 6e23c906f485073458a00e6b9ec3dcdef4a96b80..5d3bad43a9609a49a902d44c66c8f0fd7209fce6 100644 --- a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerDto.java +++ b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerDto.java @@ -3,20 +3,17 @@ package at.tuwien.api.dto.container; import lombok.Getter; import lombok.Setter; +import java.net.InetAddress; +import java.time.Instant; + @Getter @Setter -public class ContainerDto { - - private String containerId; - - private String created; - - private String containerName; +public class ContainerDto extends DatabaseContainerBriefDto { - private String databaseName; + private ContainerStateDto status; - private String status; + private IpAddressDto ipAddress; - private String ipAddress; + private Instant created; } diff --git a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerStateDto.java b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerStateDto.java new file mode 100644 index 0000000000000000000000000000000000000000..acd2aeab93c545277af3185d725fc628a73f10d9 --- /dev/null +++ b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/ContainerStateDto.java @@ -0,0 +1,8 @@ +package at.tuwien.api.dto.container; + +import lombok.Getter; + +@Getter +public enum ContainerStateDto { + CREATED, RESTARTING, RUNNING, PAUSED, EXITED, DEAD +} diff --git a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerBriefDto.java b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerBriefDto.java index e8afd33ce8c35a4d9972df8f6d39ea600afcebde..76f18c7c2928ef9bc047117b0b4fa3ae2fc41591 100644 --- a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerBriefDto.java +++ b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerBriefDto.java @@ -6,9 +6,9 @@ import lombok.Setter; @Getter @Setter -@Builder public class DatabaseContainerBriefDto { private String id; + private String containerName; } diff --git a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerDto.java b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerDto.java index 50461db0da1d735dc90c310a78cc4ac166b7f498..be67da83a8c7bf2c588a6903b666da88d01290d8 100644 --- a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerDto.java +++ b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/DatabaseContainerDto.java @@ -5,18 +5,8 @@ import lombok.Setter; @Getter @Setter -public class DatabaseContainerDto { - - private String containerId; - - private String created; - - private String containerName; +public class DatabaseContainerDto extends ContainerDto { private String databaseName; - private String status; - - private String ipAddress; - } diff --git a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/IpAddressDto.java b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/IpAddressDto.java new file mode 100644 index 0000000000000000000000000000000000000000..e98b708ca05ad1937d9ebfa63d004adb592220e6 --- /dev/null +++ b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/container/IpAddressDto.java @@ -0,0 +1,14 @@ +package at.tuwien.api.dto.container; + +import lombok.Getter; +import lombok.Setter; + +import java.net.InetAddress; + +@Getter +@Setter +public class IpAddressDto { + + private String ipv4; + +} diff --git a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/database/DatabaseContainerCreateResponseDto.java b/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/database/DatabaseContainerCreateResponseDto.java deleted file mode 100644 index b168e9cbdf3745448ac045bde1200f1a8d50ee0f..0000000000000000000000000000000000000000 --- a/fda-container-managing-service/api/src/main/java/at/tuwien/api/dto/database/DatabaseContainerCreateResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package at.tuwien.api.dto.database; - -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Builder -public class DatabaseContainerCreateResponseDto { - - private String containerId; - -} diff --git a/fda-container-managing-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java b/fda-container-managing-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java index 797c4569723028b32547144ee1afb58a371cd4e6..af8b3f514a4800354d9330007a62d790172a7621 100644 --- a/fda-container-managing-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java +++ b/fda-container-managing-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java @@ -8,7 +8,6 @@ import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.Collections; @@ -22,7 +21,7 @@ public class SwaggerConfig { .groupName("database-api") .apiInfo(apiInfo()) .select() - .paths(PathSelectors.ant("/api/database.*")) + .paths(PathSelectors.ant("/api/**")) .build(); } diff --git a/fda-container-managing-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseContainerController.java b/fda-container-managing-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseContainerController.java index 749d270731ba45d91743fed6c2e4be67b4ffb226..b49d8739c949c76efbc8eaaef8ab5ae45a4757a1 100644 --- a/fda-container-managing-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseContainerController.java +++ b/fda-container-managing-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseContainerController.java @@ -3,7 +3,6 @@ package at.tuwien.endpoints; import at.tuwien.api.dto.container.ContainerChangeDto; import at.tuwien.api.dto.container.DatabaseContainerBriefDto; import at.tuwien.api.dto.container.DatabaseContainerDto; -import at.tuwien.api.dto.database.DatabaseContainerCreateResponseDto; import at.tuwien.api.dto.database.DatabaseContainerCreateRequestDto; import at.tuwien.entity.DatabaseContainer; import at.tuwien.exception.ContainerNotFoundException; @@ -11,6 +10,7 @@ import at.tuwien.exception.DockerClientException; import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.DatabaseContainerMapper; import at.tuwien.service.ContainerService; +import io.swagger.annotations.ApiOperation; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -37,50 +37,57 @@ public class DatabaseContainerController { } @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(); return ResponseEntity.ok() .body(containers.stream() - .map(containerMapper::databaseContainerToDataBaseContainerBriefDto) + .map(containerMapper::databaseContainerToDatabaseContainerBriefDto) .collect(Collectors.toList())); } @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 { final DatabaseContainer container = containerService.create(data); log.debug("Create new database {} in container {} with id {}", data.getDatabaseName(), data.getContainerName(), container.getContainerId()); return ResponseEntity.status(HttpStatus.CREATED) - .body(containerMapper.databaseContainerToCreateDatabaseResponseDto(container)); + .body(containerMapper.databaseContainerToDatabaseContainerDto(container)); } @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 { final DatabaseContainer container = containerService.getById(id); return ResponseEntity.ok() - .body(containerMapper.databaseContainerToDataBaseContainerDto(container)); + .body(containerMapper.databaseContainerToDatabaseContainerDto(container)); } @PutMapping("/database/{id}") - public ResponseEntity<DatabaseContainerBriefDto> change(@RequestParam String id, @RequestBody ContainerChangeDto changeDto) throws ContainerNotFoundException, DockerClientException { - final DatabaseContainer container; + @ApiOperation(value = "Change the state of a database container", notes = "The new state can only be one of START/STOP/REMOVE.", code = 202) + 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)) { - container = containerService.start(id); + containerService.start(id); } else if (changeDto.getAction().equals(STOP)) { - container = containerService.stop(id); + containerService.stop(id); } else if (changeDto.getAction().equals(REMOVE)) { - container = containerService.remove(id); - } else { - return ResponseEntity.status(HttpStatus.BAD_REQUEST) - .build(); + containerService.remove(id); } return ResponseEntity.status(HttpStatus.ACCEPTED) - .body(containerMapper.databaseContainerToDataBaseContainerBriefDto(container)); + .build(); } @DeleteMapping("/database/{id}") - public ResponseEntity<DatabaseContainerBriefDto> deleteDatabaseContainer(@RequestParam String id) { - return ResponseEntity.status(HttpStatus.ACCEPTED).build(); + @ApiOperation(value = "Delete a database container.") + public ResponseEntity deleteDatabaseContainer(@RequestParam String id) throws ContainerNotFoundException, DockerClientException { + containerService.remove(id); + return ResponseEntity.status(HttpStatus.OK) + .build(); } } diff --git a/fda-container-managing-service/services/src/main/java/at/tuwien/mapper/DatabaseContainerMapper.java b/fda-container-managing-service/services/src/main/java/at/tuwien/mapper/DatabaseContainerMapper.java index 279119f7f59da3cda24dc4925716fcb64a302f86..4519a0094bade5de908e4e5b0463e25a0edbb678 100644 --- a/fda-container-managing-service/services/src/main/java/at/tuwien/mapper/DatabaseContainerMapper.java +++ b/fda-container-managing-service/services/src/main/java/at/tuwien/mapper/DatabaseContainerMapper.java @@ -2,11 +2,11 @@ package at.tuwien.mapper; import at.tuwien.api.dto.container.DatabaseContainerBriefDto; 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.DatabaseContainer; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.model.Container; -import at.tuwien.entity.DatabaseContainer; import com.github.dockerjava.api.model.NetworkSettings; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -20,13 +20,6 @@ public interface DatabaseContainerMapper { @Mapping(source = "created", target = "containerCreated"), }) 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) { return data.getNetworks().get("bridge").getIpAddress(); @@ -35,16 +28,20 @@ public interface DatabaseContainerMapper { default ContainerImage imageToContainerImage(String image) { int index = image.indexOf(":"); return new ContainerImage().builder() - .repository(image.substring(0,index)) - .tag(image.substring(index+1)) + .repository(image.substring(0, index)) + .tag(image.substring(index + 1)) .build(); } 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); } diff --git a/fda-container-managing-service/services/src/main/java/at/tuwien/service/ContainerService.java b/fda-container-managing-service/services/src/main/java/at/tuwien/service/ContainerService.java index cd248e60cb17ca4dc0731e0422831f18069329fc..9db0810567fbeb90702d4de1934fe7459990f009 100644 --- a/fda-container-managing-service/services/src/main/java/at/tuwien/service/ContainerService.java +++ b/fda-container-managing-service/services/src/main/java/at/tuwien/service/ContainerService.java @@ -92,7 +92,7 @@ public class ContainerService { return container; } - public DatabaseContainer remove(String containerId) throws ContainerNotFoundException, DockerClientException { + public void remove(String containerId) throws ContainerNotFoundException, DockerClientException { final DatabaseContainer container = containerRepository.findByContainerId(containerId); if (container == null) { throw new ContainerNotFoundException("no container with this id in metadata database"); @@ -103,7 +103,6 @@ public class ContainerService { throw new DockerClientException("docker client failed", e); } log.debug("Removed container {}", containerId); - return container; } public DatabaseContainer getById(String containerId) throws ContainerNotFoundException {