diff --git a/dbrepo-container-service/pom.xml b/dbrepo-container-service/pom.xml index 8c4c65ef615f46ca8d19fcf3d980e91f23016a65..f29838b4df8d9597be18594a9ea65f9ff0370e47 100644 --- a/dbrepo-container-service/pom.xml +++ b/dbrepo-container-service/pom.xml @@ -25,11 +25,11 @@ <java.version>17</java.version> <spring-cloud.version>4.0.2</spring-cloud.version> <mapstruct.version>1.5.5.Final</mapstruct.version> - <docker.version>3.3.0</docker.version> <swagger.version>2.2.9</swagger.version> <jacoco.version>0.8.10</jacoco.version> <jwt.version>4.3.0</jwt.version> <springdoc-openapi.version>2.1.0</springdoc-openapi.version> + <hsqldb.version>2.7.2</hsqldb.version> <opensearch-client.version>1.1.0</opensearch-client.version> </properties> @@ -137,8 +137,9 @@ </exclusions> </dependency> <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> + <groupId>org.hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <version>${hsqldb.version}</version> <scope>test</scope> </dependency> <dependency> @@ -156,23 +157,6 @@ <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> - <!-- Docker --> - <dependency> - <groupId>com.github.docker-java</groupId> - <artifactId>docker-java</artifactId> - <version>${docker.version}</version> - <exclusions> - <exclusion> - <groupId>javax.ws.rs</groupId> - <artifactId>jsr311-api</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>com.github.docker-java</groupId> - <artifactId>docker-java-transport-httpclient5</artifactId> - <version>${docker.version}</version> - </dependency> <!-- Mapping --> <dependency> <groupId>org.mapstruct</groupId> diff --git a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java index 687af47485679ffd7553165cb88bf2e794cf0736..08cd6928682d379b3de45cdcb344072027780f83 100644 --- a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java @@ -1,11 +1,13 @@ package at.tuwien.endpoints; -import at.tuwien.api.container.*; +import at.tuwien.api.container.ContainerBriefDto; +import at.tuwien.api.container.ContainerCreateRequestDto; +import at.tuwien.api.container.ContainerDto; import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.semantics.OntologyDto; import at.tuwien.entities.container.Container; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; +import at.tuwien.exception.ContainerAlreadyExistsException; +import at.tuwien.exception.ContainerNotFoundException; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.ContainerMapper; import at.tuwien.service.UserService; import at.tuwien.service.impl.ContainerServiceImpl; @@ -17,21 +19,18 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; - import java.security.Principal; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; @@ -68,19 +67,8 @@ public class ContainerEndpoint { @RequestParam(required = false) Integer limit) { log.debug("endpoint find all containers, principal={}, limit={}", principal, limit); final List<Container> containers = containerService.getAll(limit); - final List<com.github.dockerjava.api.model.Container> list = containerService.list(); final List<ContainerBriefDto> dtos = containers.stream() .map(containerMapper::containerToDatabaseContainerBriefDto) - .peek(container -> { - final Optional<com.github.dockerjava.api.model.Container> optional = list.stream() - .filter(c -> c.getId().equals(container.getHash())) - .findFirst(); - optional.ifPresent(value -> { - final String state = value.getState(); - log.trace("container {} has status {}", container.getId(), state); - container.setRunning(state.equals("running")); - }); - }) .collect(Collectors.toList()); log.trace("find all containers resulted in containers {}", dtos); return ResponseEntity.ok() @@ -98,7 +86,7 @@ public class ContainerEndpoint { mediaType = "application/json", schema = @Schema(implementation = ContainerBriefDto.class))}), @ApiResponse(responseCode = "502", - description = "Docker client failed to connect", + description = "Failed to connect", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -120,8 +108,7 @@ public class ContainerEndpoint { }) public ResponseEntity<ContainerBriefDto> create(@Valid @RequestBody ContainerCreateRequestDto data, @NotNull Principal principal) - throws ImageNotFoundException, DockerClientException, ContainerAlreadyExistsException, - UserNotFoundException { + throws ImageNotFoundException, ContainerAlreadyExistsException { log.debug("endpoint create container, data={}, principal={}", data, principal); final Container container = containerService.create(data, principal); final ContainerBriefDto dto = containerMapper.containerToDatabaseContainerBriefDto(container); @@ -140,7 +127,7 @@ public class ContainerEndpoint { mediaType = "application/json", schema = @Schema(implementation = ContainerDto.class))}), @ApiResponse(responseCode = "502", - description = "Docker client failed to connect", + description = "Failed to connect", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -156,80 +143,15 @@ public class ContainerEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<ContainerDto> findById(@NotNull @PathVariable("id") Long containerId) - throws DockerClientException, ContainerNotFoundException { + throws ContainerNotFoundException { log.debug("endpoint find container, id={}", containerId); - ContainerDto dto; - try { - dto = containerService.inspect(containerId); - } catch (ContainerNotRunningException e) { - /* ignore */ - dto = containerMapper.containerToContainerDto(containerService.find(containerId)); - dto.setRunning(false); - dto.setState(ContainerStateDto.EXITED); - } + final Container container = containerService.find(containerId); + final ContainerDto dto = containerMapper.containerToContainerDto(container); log.trace("find container resulted in container {}", dto); return ResponseEntity.ok() .body(dto); } - @PutMapping("/{id}") - @Transactional - @Timed(value = "container.modify", description = "Time needed to modify the container state") - @PreAuthorize("hasAuthority('modify-container-state') or hasAuthority('modify-foreign-container-state')") - @Operation(summary = "Modify some container", security = @SecurityRequirement(name = "bearerAuth")) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "Modified state of container successfully", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ContainerBriefDto.class))}), - @ApiResponse(responseCode = "404", - description = "Container or user could not be found", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "405", - description = "Modification of container state is not permitted", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "409", - description = "Container is already started/stopped", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - }) - public ResponseEntity<ContainerBriefDto> modify(@NotNull @PathVariable("id") Long containerId, - @Valid @RequestBody ContainerChangeDto changeDto, - @NotNull Principal principal) - throws ContainerNotFoundException, ContainerAlreadyRunningException, ContainerAlreadyStoppedException, - UserNotFoundException, NotAllowedException { - log.debug("endpoint modify container, containerId={}, changeDto={}, principal={}", containerId, changeDto, principal); - final User user = userService.findByUsername(principal.getName()); - final Container container = containerService.find(containerId); - final Authentication authentication = (Authentication) principal; - if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("modify-foreign-container-state")) - && !(container.getOwner().getId().equals(user.getId()))) { - log.error("Failed to modify container: not owner and no sufficient privileges"); - log.debug("relevant privileges found: {}", authentication.getAuthorities().stream() - .filter(a -> a.getAuthority().startsWith("modify-") && a.getAuthority().endsWith("container-state")) - .collect(Collectors.toList())); - throw new NotAllowedException("Failed to modify container: not owner and no sufficient privileges"); - } - final Container entity; - if (changeDto.getAction().equals(ContainerActionTypeDto.START)) { - log.trace("request attempts to start the container"); - entity = containerService.start(containerId); - } else { - log.trace("request attempts to stop the container"); - entity = containerService.stop(containerId); - } - final ContainerBriefDto dto = containerMapper.containerToDatabaseContainerBriefDto(entity); - log.trace("modify container resulted in container {}", dto); - return ResponseEntity.status(HttpStatus.ACCEPTED) - .body(dto); - } - @DeleteMapping("/{id}") @Transactional @Timed(value = "container.delete", description = "Time needed to delete the container") @@ -251,8 +173,7 @@ public class ContainerEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<?> delete(@NotNull @PathVariable("id") Long containerId, - @NotNull Principal principal) throws ContainerNotFoundException, - ContainerStillRunningException, ContainerAlreadyRemovedException { + @NotNull Principal principal) throws ContainerNotFoundException { log.debug("endpoint delete container, containerId={}, principal={}", containerId, principal); containerService.remove(containerId); return ResponseEntity.accepted() diff --git a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java index 73ca916d7296010878e66fde4bc24437573301be..6ff6958cdc302817c0ec2c871731db07d38d4f8f 100644 --- a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java +++ b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java @@ -1,13 +1,15 @@ package at.tuwien.endpoints; -import at.tuwien.api.container.ContainerBriefDto; import at.tuwien.api.container.image.ImageBriefDto; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.api.container.image.ImageDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.*; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageInvalidException; +import at.tuwien.exception.ImageNotFoundException; +import at.tuwien.exception.UserNotFoundException; import at.tuwien.mapper.ImageMapper; import at.tuwien.service.impl.ImageServiceImpl; import io.micrometer.core.annotation.Timed; @@ -18,6 +20,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -26,8 +30,6 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; import java.security.Principal; import java.util.List; import java.util.stream.Collectors; @@ -90,7 +92,7 @@ public class ImageEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "502", - description = "Docker client failed to connect", + description = "Failed to connect", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -102,7 +104,7 @@ public class ImageEndpoint { }) public ResponseEntity<ImageDto> create(@Valid @RequestBody ImageCreateDto data, @NotNull Principal principal) throws ImageNotFoundException, - ImageAlreadyExistsException, DockerClientException, UserNotFoundException, ImageInvalidException { + ImageAlreadyExistsException, UserNotFoundException, ImageInvalidException { log.debug("endpoint create image, data={}, principal={}", data, principal); if (data.getDefaultPort() == null) { log.error("Failed to create image, default port is null"); @@ -184,11 +186,11 @@ public class ImageEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<?> delete(@NotNull @PathVariable("id") Long imageId, + public ResponseEntity<?> delete(@NotNull @PathVariable("id") Long id, @NotNull Principal principal) throws ImageNotFoundException { - log.debug("endpoint delete image, id={}, principal={}", imageId, principal); - imageService.find(imageId); - imageService.delete(imageId); + log.debug("endpoint delete image, id={}, principal={}", id, principal); + imageService.find(id); + imageService.delete(id); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index 5488575f3c53ca510b8db43c5cda0d48699abf5b..c8b884f8cd7d72d1cfe6baa6e4da658b98db479f 100644 --- a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java @@ -99,18 +99,6 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return new ResponseEntity<>(response, new HttpHeaders(), response.getStatus()); } - @Hidden - @ResponseStatus(HttpStatus.BAD_GATEWAY) - @ExceptionHandler(DockerClientException.class) - public ResponseEntity<ApiErrorDto> handle(DockerClientException e, WebRequest request) { - final ApiErrorDto response = ApiErrorDto.builder() - .status(HttpStatus.BAD_GATEWAY) - .message(e.getLocalizedMessage()) - .code("error.container.dockerclient") - .build(); - return new ResponseEntity<>(response, new HttpHeaders(), response.getStatus()); - } - @Hidden @ResponseStatus(HttpStatus.CONFLICT) @ExceptionHandler(ImageAlreadyExistsException.class) diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java index acaa7b1c87fa808b6c6af90cb63d6e8a6410f82a..d33f1fbee2351201d7e297ba0398ec989cd5b3ae 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java @@ -1,11 +1,14 @@ package at.tuwien.endpoint; import at.tuwien.BaseUnitTest; -import at.tuwien.api.container.*; +import at.tuwien.api.container.ContainerBriefDto; +import at.tuwien.api.container.ContainerCreateRequestDto; +import at.tuwien.api.container.ContainerDto; import at.tuwien.config.ReadyConfig; import at.tuwien.endpoints.ContainerEndpoint; import at.tuwien.entities.container.Container; import at.tuwien.exception.*; +import at.tuwien.repository.mdb.ImageRepository; import at.tuwien.repository.mdb.UserRepository; import at.tuwien.service.impl.ContainerServiceImpl; import lombok.extern.log4j.Log4j2; @@ -26,7 +29,8 @@ import java.util.List; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; @Log4j2 @ExtendWith(SpringExtension.class) @@ -42,42 +46,42 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @MockBean private UserRepository userRepository; + @MockBean + private ImageRepository imageRepository; + @Autowired private ContainerEndpoint containerEndpoint; @Test @WithAnonymousUser - public void findById_anonymous_succeeds() throws DockerClientException, ContainerNotFoundException, - ContainerNotRunningException { + public void findById_anonymous_succeeds() throws ContainerNotFoundException { /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1_HASH, CONTAINER_1, CONTAINER_1_DTO); + findById_generic(CONTAINER_1_ID, CONTAINER_1); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-container"}) - public void findById_hasRole_succeeds() throws DockerClientException, ContainerNotFoundException, - ContainerNotRunningException { + public void findById_hasRole_succeeds() throws ContainerNotFoundException { /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) .thenReturn(Optional.of(USER_1)); /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1_HASH, CONTAINER_1, CONTAINER_1_DTO); + findById_generic(CONTAINER_1_ID, CONTAINER_1); } @Test @WithMockUser(username = USER_4_USERNAME) - public void findById_noRole_succeeds() throws DockerClientException, ContainerNotFoundException, - ContainerNotRunningException { + public void findById_noRole_succeeds() throws ContainerNotFoundException { /* mock */ when(userRepository.findByUsername(USER_4_USERNAME)) .thenReturn(Optional.of(USER_4)); /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1_HASH, CONTAINER_1, CONTAINER_1_DTO); + findById_generic(CONTAINER_1_ID, CONTAINER_1); } @Test @@ -154,8 +158,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { public void create_anonymous_fails() { final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder() .name(CONTAINER_1_NAME) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .imageId(IMAGE_1_ID) .build(); /* test */ @@ -166,12 +169,10 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-container"}) - public void create_hasRole_succeeds() throws UserNotFoundException, DockerClientException, - ContainerAlreadyExistsException, ImageNotFoundException { + public void create_hasRole_succeeds() throws ContainerAlreadyExistsException, ImageNotFoundException { final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder() .name(CONTAINER_1_NAME) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .imageId(IMAGE_1_ID) .build(); /* mock */ @@ -187,8 +188,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { public void create_noRole_fails() { final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder() .name(CONTAINER_1_NAME) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .imageId(IMAGE_1_ID) .build(); /* mock */ @@ -201,70 +201,6 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { }); } - @Test - @WithAnonymousUser - public void modify_anonymous_fails() { - - /* test */ - assertThrows(AccessDeniedException.class, () -> { - modify_generic(ContainerActionTypeDto.START, CONTAINER_1_ID, CONTAINER_1, null); - }); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-container-state"}) - public void modify_hasRole_succeeds() throws ContainerAlreadyRunningException, - ContainerAlreadyStoppedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException { - - /* mock */ - when(userRepository.findByUsername(USER_1_USERNAME)) - .thenReturn(Optional.of(USER_1)); - - /* test */ - modify_generic(ContainerActionTypeDto.START, CONTAINER_1_ID, CONTAINER_1, USER_1_PRINCIPAL); - } - - @Test - @WithMockUser(username = USER_4_USERNAME) - public void modify_noRole_fails() { - - /* mock */ - when(userRepository.findByUsername(USER_4_USERNAME)) - .thenReturn(Optional.of(USER_4)); - - /* test */ - assertThrows(AccessDeniedException.class, () -> { - modify_generic(ContainerActionTypeDto.START, CONTAINER_1_ID, CONTAINER_1, USER_4_PRINCIPAL); - }); - } - - @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-foreign-container-state"}) - public void modify_hasRoleForeign_succeeds() throws UserNotFoundException, ContainerAlreadyRunningException, - NotAllowedException, ContainerAlreadyStoppedException, ContainerNotFoundException { - - /* mock */ - when(userRepository.findByUsername(USER_2_USERNAME)) - .thenReturn(Optional.of(USER_2)); - - /* test */ - modify_generic(ContainerActionTypeDto.START, CONTAINER_1_ID, CONTAINER_1, USER_2_PRINCIPAL); - } - - @Test - @WithMockUser(username = USER_4_USERNAME) - public void modify_noRoleForeign_fails() { - - /* mock */ - when(userRepository.findByUsername(USER_4_USERNAME)) - .thenReturn(Optional.of(USER_4)); - - /* test */ - assertThrows(AccessDeniedException.class, () -> { - modify_generic(ContainerActionTypeDto.STOP, CONTAINER_1_ID, CONTAINER_1, USER_4_PRINCIPAL); - }); - } - @Test @WithAnonymousUser public void findAll_anonymousNoLimit_succeeds() { @@ -273,39 +209,21 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { findAll_generic(null, null); } - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"modify-container-state"}) - public void modify_foreign_fails() { - - /* when */ - when(userRepository.findByUsername(USER_3_USERNAME)) - .thenReturn(Optional.of(USER_3)); - - /* test */ - assertThrows(NotAllowedException.class, () -> { - modify_generic(ContainerActionTypeDto.STOP, CONTAINER_1_ID, CONTAINER_1, USER_3_PRINCIPAL); - }); - } - /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void findById_generic(Long containerId, String containerHash, Container container, ContainerDto containerDto) - throws DockerClientException, ContainerNotFoundException, ContainerNotRunningException { + public void findById_generic(Long containerId, Container container) + throws ContainerNotFoundException { /* mock */ when(containerService.find(containerId)) .thenReturn(container); - when(containerService.inspect(containerId)) - .thenReturn(containerDto); /* test */ final ResponseEntity<ContainerDto> response = containerEndpoint.findById(containerId); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); - final ContainerDto dto = response.getBody(); - assertEquals(ContainerStateDto.RUNNING, dto.getState()); } public void delete_generic(Long containerId, Container container, Principal principal) throws ContainerNotFoundException, @@ -346,8 +264,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { assertEquals(CONTAINER_2_INTERNALNAME, container2.getInternalName()); } - public void create_generic(ContainerCreateRequestDto data, Principal principal) throws UserNotFoundException, - DockerClientException, ContainerAlreadyExistsException, ImageNotFoundException { + public void create_generic(ContainerCreateRequestDto data, Principal principal) throws ContainerAlreadyExistsException, ImageNotFoundException { /* mock */ when(containerService.create(data, principal)) @@ -359,28 +276,4 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { assertNotNull(response.getBody()); } - public void modify_generic(ContainerActionTypeDto data, Long containerId, Container container, Principal principal) - throws ContainerAlreadyRunningException, ContainerNotFoundException, ContainerAlreadyStoppedException, - UserNotFoundException, NotAllowedException { - final ContainerChangeDto request = ContainerChangeDto.builder() - .action(data) - .build(); - - /* mock */ - when(containerService.find(containerId)) - .thenReturn(container); - if (data.equals(ContainerActionTypeDto.START)) { - when(containerService.start(containerId)) - .thenReturn(container); - } else if (data.equals(ContainerActionTypeDto.STOP)) { - when(containerService.stop(containerId)) - .thenReturn(container); - } - - /* test */ - final ResponseEntity<ContainerBriefDto> response = containerEndpoint.modify(containerId, request, principal); - assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); - assertNotNull(response.getBody()); - } - } diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointIntegrationTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointIntegrationTest.java index f6b05e147582fc78bbf45716dce770d375e8e2dc..092fa0d80d9577963522f7eff46bf91ed4e348d1 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointIntegrationTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointIntegrationTest.java @@ -1,14 +1,15 @@ package at.tuwien.endpoint; import at.tuwien.BaseUnitTest; -import at.tuwien.config.DockerConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.endpoints.ImageEndpoint; -import at.tuwien.exception.*; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageInvalidException; +import at.tuwien.exception.ImageNotFoundException; +import at.tuwien.exception.UserNotFoundException; import at.tuwien.repository.mdb.RealmRepository; import at.tuwien.repository.mdb.UserRepository; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -18,8 +19,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; -import static org.mockito.Mockito.any; - @Log4j2 @ExtendWith(SpringExtension.class) @SpringBootTest @@ -39,23 +38,14 @@ public class ImageEndpointIntegrationTest extends BaseUnitTest { @BeforeEach public void beforeEach() { - afterEach(); - /* networks */ - DockerConfig.createAllNetworks(); /* metadata database */ realmRepository.save(REALM_DBREPO); userRepository.save(USER_2_SIMPLE); } - @AfterEach - public void afterEach() { - DockerConfig.removeAllContainers(); - DockerConfig.removeAllNetworks(); - } - @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"create-image"}) - public void create_succeeds() throws UserNotFoundException, ImageAlreadyExistsException, DockerClientException, + public void create_succeeds() throws UserNotFoundException, ImageAlreadyExistsException, ImageNotFoundException, ImageInvalidException { diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java index 32380858b126df2d5867d13f29743790517119b1..638be02943e00cc7bfa39d11b588a76df84a49b5 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java @@ -5,8 +5,6 @@ import at.tuwien.api.container.image.ImageBriefDto; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.api.container.image.ImageDto; -import at.tuwien.config.DockerDaemonConfig; -import at.tuwien.config.ReadyConfig; import at.tuwien.endpoints.ImageEndpoint; import at.tuwien.entities.container.image.ContainerImage; import at.tuwien.exception.*; @@ -37,9 +35,6 @@ import static org.mockito.Mockito.*; @SpringBootTest public class ImageEndpointUnitTest extends BaseUnitTest { - @MockBean - private ReadyConfig readyConfig; - @MockBean private ImageServiceImpl imageService; @@ -49,9 +44,6 @@ public class ImageEndpointUnitTest extends BaseUnitTest { @Autowired private ImageEndpoint imageEndpoint; - @Autowired - private DockerDaemonConfig dockerUtil; - @Test @WithAnonymousUser public void findAll_anonymous_succeeds() { @@ -88,12 +80,11 @@ public class ImageEndpointUnitTest extends BaseUnitTest { @WithAnonymousUser public void create_anonymous_fails() { final ImageCreateDto request = ImageCreateDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .name(IMAGE_1_NAME) + .version(IMAGE_1_VERSION) .defaultPort(IMAGE_1_PORT) .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) - .environment(IMAGE_1_ENV_DTO) .build(); /* test */ @@ -106,12 +97,11 @@ public class ImageEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_1_USERNAME, roles = {"create-image"}) public void create_hasRole_fails() { final ImageCreateDto request = ImageCreateDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .name(IMAGE_1_NAME) + .version(IMAGE_1_VERSION) .defaultPort(IMAGE_1_PORT) .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) - .environment(IMAGE_1_ENV_DTO) .build(); /* mock */ @@ -128,12 +118,11 @@ public class ImageEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_4_USERNAME) public void create_noRole_fails() { final ImageCreateDto request = ImageCreateDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .name(IMAGE_1_NAME) + .version(IMAGE_1_VERSION) .defaultPort(IMAGE_1_PORT) .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) - .environment(IMAGE_1_ENV_DTO) .build(); /* mock */ @@ -150,12 +139,11 @@ public class ImageEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"create-image"}) public void create_missingEssentialInfo_fails() { final ImageCreateDto request = ImageCreateDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .name(IMAGE_1_NAME) + .version(IMAGE_1_VERSION) .defaultPort(null) .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) - .environment(IMAGE_1_ENV_DTO) .build(); /* mock */ @@ -236,7 +224,6 @@ public class ImageEndpointUnitTest extends BaseUnitTest { .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) .driverClass(IMAGE_1_DRIVER) - .environment(IMAGE_1_ENV_DTO) .build(); /* test */ @@ -253,7 +240,6 @@ public class ImageEndpointUnitTest extends BaseUnitTest { .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) .driverClass(IMAGE_1_DRIVER) - .environment(IMAGE_1_ENV_DTO) .build(); /* mock */ @@ -268,14 +254,13 @@ public class ImageEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-image"}) - public void modify_hasRole_succeeds() throws ImageNotFoundException, DockerClientException { + public void modify_hasRole_succeeds() throws ImageNotFoundException { final ImageChangeDto request = ImageChangeDto.builder() .registry(IMAGE_1_REGISTRY) .defaultPort(IMAGE_1_PORT) .dialect(IMAGE_1_DIALECT) .jdbcMethod(IMAGE_1_JDBC) .driverClass(IMAGE_1_DRIVER) - .environment(IMAGE_1_ENV_DTO) .build(); /* mock */ @@ -305,7 +290,7 @@ public class ImageEndpointUnitTest extends BaseUnitTest { } public void create_generic(ImageCreateDto data, Principal principal) throws UserNotFoundException, - ImageAlreadyExistsException, DockerClientException, ImageNotFoundException, ImageInvalidException { + ImageAlreadyExistsException, ImageNotFoundException, ImageInvalidException { /* mock */ when(imageService.create(data, principal)) @@ -342,7 +327,7 @@ public class ImageEndpointUnitTest extends BaseUnitTest { } public void modify_generic(Long imageId, ContainerImage image, ImageChangeDto data, Principal principal) - throws ImageNotFoundException, DockerClientException { + throws ImageNotFoundException { /* mock */ when(imageService.find(imageId)) diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java index 20f54cca5a41d74b37fcc278d372f00cd82971b1..f3d4ae4b5ca8d3fc944559b835877d5051ff6354 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java @@ -2,8 +2,6 @@ package at.tuwien.service; import at.tuwien.BaseUnitTest; import at.tuwien.api.container.ContainerCreateRequestDto; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.config.DockerConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.container.Container; import at.tuwien.exception.*; @@ -12,7 +10,8 @@ import at.tuwien.repository.mdb.ImageRepository; import at.tuwien.repository.mdb.RealmRepository; import at.tuwien.repository.mdb.UserRepository; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -51,9 +50,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { @BeforeEach public void beforeEach() { - afterEach(); - /* create networks */ - DockerConfig.createAllNetworks(); /* mock data */ realmRepository.save(REALM_DBREPO); userRepository.save(USER_1_SIMPLE); @@ -61,39 +57,27 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { imageRepository.save(IMAGE_1_SIMPLE); } - @AfterEach - public void afterEach() { - DockerConfig.removeAllContainers(); - DockerConfig.removeAllNetworks(); - } - @Test - public void create_succeeds() - throws DockerClientException, ImageNotFoundException, ContainerAlreadyExistsException, - UserNotFoundException { + public void create_succeeds() throws ImageNotFoundException, ContainerAlreadyExistsException, UserNotFoundException { final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .imageId(IMAGE_1_ID) .name(CONTAINER_1_NAME) .build(); /* test */ final Container container = containerService.create(request, USER_1_PRINCIPAL); assertEquals(CONTAINER_1_NAME, container.getName()); - assertEquals(USER_1_USERNAME, container.getCreator().getUsername()); - assertEquals(USER_1_USERNAME, container.getOwner().getUsername()); } @Test public void create_conflictingNames_fails() { final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .imageId(IMAGE_1_ID) .name(CONTAINER_1_NAME) .build(); /* mock */ - containerRepository.save(CONTAINER_1_SIMPLE); + containerRepository.save(CONTAINER_1); /* test */ assertThrows(ContainerAlreadyExistsException.class, () -> { @@ -113,9 +97,8 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { @Test public void create_notFound_fails() { final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder() - .repository(IMAGE_2_REPOSITORY) - .tag(IMAGE_2_TAG) .name(CONTAINER_3_NAME) + .imageId(IMAGE_2_ID) .build(); /* test */ @@ -133,60 +116,11 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { }); } - @Test - public void change_start_succeeds() throws DockerClientException, ContainerNotFoundException, - ContainerAlreadyRunningException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - containerService.start(CONTAINER_1_ID); - } - - @Test - public void change_stop_succeeds() throws DockerClientException, ContainerNotFoundException, - ContainerAlreadyStoppedException, InterruptedException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.startContainer(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - containerService.stop(CONTAINER_1_ID); - } - - @Test - public void change_startSavedButNotFound_fails() { - - /* mock */ - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerNotFoundException.class, () -> { - containerService.start(CONTAINER_1_ID); - }); - } - - @Test - public void change_removeSavedButNotFound_fails() { - - /* mock */ - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerNotFoundException.class, () -> { - containerService.remove(CONTAINER_1_ID); - }); - } - @Test public void getAll_succeeds() { /* mock */ - containerRepository.save(CONTAINER_1_SIMPLE); + containerRepository.save(CONTAINER_1); containerRepository.save(CONTAINER_2_SIMPLE); /* test */ @@ -198,7 +132,7 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void getAll_limit_succeeds() { /* mock */ - containerRepository.save(CONTAINER_1_SIMPLE); + containerRepository.save(CONTAINER_1); containerRepository.save(CONTAINER_2_SIMPLE); /* test */ @@ -207,14 +141,10 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { } @Test - public void remove_succeeds() throws DockerClientException, ContainerStillRunningException, - ContainerNotFoundException, ContainerAlreadyRemovedException, InterruptedException { + public void remove_succeeds() throws ContainerStillRunningException, ContainerNotFoundException, ContainerAlreadyRemovedException { /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.startContainer(CONTAINER_1_SIMPLE); - DockerConfig.stopContainer(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); + containerRepository.save(CONTAINER_1); /* test */ containerService.remove(CONTAINER_1_ID); @@ -228,138 +158,4 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { containerService.remove(CONTAINER_1_ID); }); } - - @Test - public void remove_stillRunning_fails() throws InterruptedException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.startContainer(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerStillRunningException.class, () -> { - containerService.remove(CONTAINER_1_ID); - }); - } - - @Test - public void change_alreadyRunning_fails() throws InterruptedException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.startContainer(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerAlreadyRunningException.class, () -> { - containerService.start(CONTAINER_1_ID); - }); - } - - @Test - public void change_startNotFound_fails() { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1, CONTAINER_1_ENV); - - /* test */ - assertThrows(ContainerNotFoundException.class, () -> { - containerService.start(CONTAINER_1_ID); - }); - } - - @Test - public void change_alreadyStopped_fails() throws InterruptedException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.startContainer(CONTAINER_1_SIMPLE); - DockerConfig.stopContainer(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerAlreadyStoppedException.class, () -> { - containerService.stop(CONTAINER_1_ID); - }); - } - - @Test - public void change_stopNeverStarted_fails() { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerAlreadyStoppedException.class, () -> { - containerService.stop(CONTAINER_1_ID); - }); - } - - @Test - public void change_stopSavedButNotFound_fails() { - - /* mock */ - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerNotFoundException.class, () -> { - containerService.stop(CONTAINER_1_ID); - }); - } - - @Test - public void inspect_succeeds() throws InterruptedException, DockerClientException, ContainerNotFoundException, - ContainerNotRunningException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.startContainer(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - final ContainerDto response = containerService.inspect(CONTAINER_1_ID); - assertEquals(CONTAINER_1_ID, response.getId()); - assertEquals(CONTAINER_1_NAME, response.getName()); - assertEquals(CONTAINER_1_INTERNALNAME, response.getInternalName()); - assertEquals(CONTAINER_1_IP, response.getIpAddress()); - } - - @Test - public void inspect_notFound_fails() { - - /* test */ - assertThrows(ContainerNotFoundException.class, () -> { - containerService.inspect(CONTAINER_2_ID); - }); - } - - @Test - public void inspect_notRunning_fails() { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - containerRepository.save(CONTAINER_1_SIMPLE); - - /* test */ - assertThrows(ContainerNotRunningException.class, () -> { - containerService.inspect(CONTAINER_1_ID); - }); - } - - @Test - public void list_notRunning_succeeds() throws InterruptedException { - - /* mock */ - DockerConfig.createContainer(null, CONTAINER_1_SIMPLE, CONTAINER_1_ENV); - DockerConfig.createContainer(null, CONTAINER_2_SIMPLE, CONTAINER_2_ENV); - DockerConfig.startContainer(CONTAINER_2_SIMPLE); - containerRepository.save(CONTAINER_1_SIMPLE); - containerRepository.save(CONTAINER_2_SIMPLE); - - /* test */ - final List<com.github.dockerjava.api.model.Container> response = containerService.list(); - assertEquals(2, response.size()); - } } diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java index 5231fe2eef09c2f72d4a994265e7c41fe9c1123f..30340c89a914b2cdb64d7f0c04f85d9c6052f634 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceIntegrationTest.java @@ -3,15 +3,14 @@ package at.tuwien.service; import at.tuwien.BaseUnitTest; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.config.ReadyConfig; -import at.tuwien.exception.*; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.repository.mdb.ContainerRepository; import at.tuwien.repository.mdb.ImageRepository; import at.tuwien.repository.mdb.UserRepository; import at.tuwien.service.impl.ImageServiceImpl; import lombok.extern.log4j.Log4j2; -import org.apache.commons.lang3.RandomUtils; import org.apache.http.auth.BasicUserPrincipal; -import org.apache.tomcat.util.buf.HexUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -53,16 +52,13 @@ public class ImageServiceIntegrationTest extends BaseUnitTest { } @Test - public void create_succeeds() - throws ImageAlreadyExistsException, DockerClientException, ImageNotFoundException, UserNotFoundException { + public void create_succeeds() throws ImageAlreadyExistsException { final ImageCreateDto request = ImageCreateDto.builder() - .registry(IMAGE_2_REGISTRY) - .repository(IMAGE_2_REPOSITORY) - .tag(IMAGE_2_TAG) + .name(IMAGE_2_NAME) + .version(IMAGE_2_VERSION) .jdbcMethod(IMAGE_2_JDBC) .dialect(IMAGE_2_DIALECT) .driverClass(IMAGE_2_DRIVER) - .environment(IMAGE_2_ENV_DTO) .defaultPort(IMAGE_2_PORT) .build(); final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); @@ -71,44 +67,15 @@ public class ImageServiceIntegrationTest extends BaseUnitTest { imageService.create(request, principal); } - @Test - public void inspect_notFound_fails() { - - /* test */ - assertThrows(ImageNotFoundException.class, () -> { - imageService.inspect("abcdefu", "999.999"); - }); - } - - @Test - public void create_notFound_fails() { - final ImageCreateDto request = ImageCreateDto.builder() - .repository("s0m3th1ng_n0t3x1st1ng") - .tag("d3v_h3ll") - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .jdbcMethod(IMAGE_1_JDBC) - .defaultPort(IMAGE_1_PORT) - .environment(IMAGE_1_ENV_DTO) - .build(); - final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); - - /* test */ - assertThrows(ImageNotFoundException.class, () -> { - imageService.create(request, principal); - }); - } - @Test public void create_duplicate_fails() { final ImageCreateDto request = ImageCreateDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .name(IMAGE_1_NAME) + .version(IMAGE_1_VERSION) .defaultPort(IMAGE_1_PORT) .driverClass(IMAGE_1_DRIVER) .jdbcMethod(IMAGE_1_JDBC) .dialect(IMAGE_1_DIALECT) - .environment(IMAGE_1_ENV_DTO) .build(); final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); @@ -135,15 +102,4 @@ public class ImageServiceIntegrationTest extends BaseUnitTest { assertTrue(imageRepository.findById(IMAGE_1_ID).isEmpty()); } - @Test - public void pull_fails() { - final String repository = HexUtils.toHexString(RandomUtils.nextBytes(16)); - final String tag = HexUtils.toHexString(RandomUtils.nextBytes(16)); - - /* test */ - assertThrows(ImageNotFoundException.class, () -> { - imageService.pull("docker.io/library", repository, tag); - }); - } - } diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java index f92fa9102ad43cc1d3c9f0abcfccfdc354d4b111..39f07b466158fb9c7dfdd48fbae214d6f0563e26 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/ImageServiceUnitTest.java @@ -3,11 +3,13 @@ package at.tuwien.service; import at.tuwien.BaseUnitTest; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; -import at.tuwien.config.ReadyConfig; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.*; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.repository.mdb.ImageRepository; import at.tuwien.service.impl.ImageServiceImpl; +import jakarta.persistence.EntityNotFoundException; +import jakarta.validation.ConstraintViolationException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -15,9 +17,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; -import jakarta.persistence.EntityNotFoundException; -import jakarta.validation.ConstraintViolationException; - import java.util.List; import java.util.Optional; @@ -29,9 +28,6 @@ import static org.mockito.Mockito.*; @SpringBootTest public class ImageServiceUnitTest extends BaseUnitTest { - @MockBean - private ReadyConfig readyConfig; - @Autowired private ImageServiceImpl imageService; @@ -48,8 +44,8 @@ public class ImageServiceUnitTest extends BaseUnitTest { /* test */ final List<ContainerImage> response = imageService.getAll(); assertEquals(1, response.size()); - assertEquals(IMAGE_1_REPOSITORY, response.get(0).getRepository()); - assertEquals(IMAGE_1_TAG, response.get(0).getTag()); + assertEquals(IMAGE_1_NAME, response.get(0).getName()); + assertEquals(IMAGE_1_VERSION, response.get(0).getVersion()); } @Test @@ -61,8 +57,8 @@ public class ImageServiceUnitTest extends BaseUnitTest { /* test */ final ContainerImage response = imageService.find(IMAGE_1_ID); - assertEquals(IMAGE_1_REPOSITORY, response.getRepository()); - assertEquals(IMAGE_1_TAG, response.getTag()); + assertEquals(IMAGE_1_NAME, response.getName()); + assertEquals(IMAGE_1_VERSION, response.getVersion()); } @Test @@ -81,10 +77,9 @@ public class ImageServiceUnitTest extends BaseUnitTest { @Test public void create_duplicate_fails() { final ImageCreateDto request = ImageCreateDto.builder() - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) + .name(IMAGE_1_NAME) + .version(IMAGE_1_VERSION) .defaultPort(IMAGE_1_PORT) - .environment(IMAGE_1_ENV_DTO) .build(); /* mock */ @@ -101,8 +96,6 @@ public class ImageServiceUnitTest extends BaseUnitTest { public void update_succeeds() throws ImageNotFoundException { final ImageServiceImpl mockImageService = mock(ImageServiceImpl.class); final ImageChangeDto request = ImageChangeDto.builder() - .registry(IMAGE_1_REGISTRY) - .environment(IMAGE_1_ENV_DTO) .defaultPort(IMAGE_1_PORT) .build(); @@ -116,16 +109,14 @@ public class ImageServiceUnitTest extends BaseUnitTest { /* test */ final ContainerImage response = mockImageService.update(IMAGE_1_ID, request); - assertEquals(IMAGE_1_REPOSITORY, response.getRepository()); - assertEquals(IMAGE_1_TAG, response.getTag()); + assertEquals(IMAGE_1_NAME, response.getName()); + assertEquals(IMAGE_1_VERSION, response.getVersion()); } @Test public void update_port_succeeds() throws ImageNotFoundException { final ImageServiceImpl mockImageService = mock(ImageServiceImpl.class); final ImageChangeDto request = ImageChangeDto.builder() - .registry(IMAGE_1_REGISTRY) - .environment(IMAGE_1_ENV_DTO) .defaultPort(9999) .build(); @@ -139,14 +130,13 @@ public class ImageServiceUnitTest extends BaseUnitTest { /* test */ final ContainerImage response = mockImageService.update(IMAGE_1_ID, request); - assertEquals(IMAGE_1_REPOSITORY, response.getRepository()); - assertEquals(IMAGE_1_TAG, response.getTag()); + assertEquals(IMAGE_1_NAME, response.getName()); + assertEquals(IMAGE_1_VERSION, response.getVersion()); } @Test public void update_notFound_fails() { final ImageChangeDto request = ImageChangeDto.builder() - .environment(IMAGE_1_ENV_DTO) .defaultPort(IMAGE_1_PORT) .build(); diff --git a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/PersistenceIntegrationTest.java b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/PersistenceIntegrationTest.java index 5de85233045cedd229443e0c6113b99ca4d8c691..1903625514efcb773ee871681faade7ab7651412 100644 --- a/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/PersistenceIntegrationTest.java +++ b/dbrepo-container-service/rest-service/src/test/java/at/tuwien/service/PersistenceIntegrationTest.java @@ -16,7 +16,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertThrows; @Log4j2 @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) diff --git a/dbrepo-container-service/rest-service/src/test/resources/application.properties b/dbrepo-container-service/rest-service/src/test/resources/application.properties index 246afd93696a55296d38085f6c82c24876e4be1b..5c7ce656a49cadede00801f966bc83264e508000 100644 --- a/dbrepo-container-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-container-service/rest-service/src/test/resources/application.properties @@ -9,14 +9,20 @@ spring.cloud.config.discovery.enabled = false spring.cloud.config.enabled = false # disable datasource -# spring 6 fix https://github.com/h2database/h2database/issues/3363 -spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=VALUE,KEY;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS FDA -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.jpa.hibernate.ddl-auto=create-drop -spring.jpa.show-sql=true +spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver +spring.datasource.url=jdbc:hsqldb:mem:testdb;db_close_delay=-1;sql.syntax_mys=true +spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect +spring.datasource.username=root +spring.datasource.password=dbrepo +spring.sql.init.mode=always +spring.sql.init.schema-locations=classpath*:init/schema.sql +spring.jpa.hibernate.ddl-auto=create + +mariaDB4j.port=3308 +#mariaDB4j.baseDir=target/mariaDB4j +# mariaDB4j.dataDir= +mariaDB4j.userName=root +mariaDB4j.password=dbrepo # additional logging logging.level.root=error \ No newline at end of file diff --git a/dbrepo-container-service/rest-service/src/test/resources/docker/inspect_running.json b/dbrepo-container-service/rest-service/src/test/resources/docker/inspect_running.json deleted file mode 100644 index bf635d99347773e5629040ac541df8eaf90b793c..0000000000000000000000000000000000000000 --- a/dbrepo-container-service/rest-service/src/test/resources/docker/inspect_running.json +++ /dev/null @@ -1,234 +0,0 @@ -{ - "Id": "23a3af8f5fd56049f8c8125e40ef1cea5313ac189606b14d41cf19fe60ec1a2a", - "Created": "2023-01-17T06:28:50.195711258Z", - "Path": "docker-entrypoint.sh", - "Args": [ - "mysqld" - ], - "State": { - "Status": "running", - "Running": true, - "Paused": false, - "Restarting": false, - "OOMKilled": false, - "Dead": false, - "Pid": 23461, - "ExitCode": 0, - "Error": "", - "StartedAt": "2023-01-17T06:28:50.716059841Z", - "FinishedAt": "0001-01-01T00:00:00Z" - }, - "Image": "sha256:819fb13996d3660fa44ff4c25c570072609c60a6da58078a5e8c287c957b3f54", - "ResolvConfPath": "/var/lib/docker/containers/23a3af8f5fd56049f8c8125e40ef1cea5313ac189606b14d41cf19fe60ec1a2a/resolv.conf", - "HostnamePath": "/var/lib/docker/containers/23a3af8f5fd56049f8c8125e40ef1cea5313ac189606b14d41cf19fe60ec1a2a/hostname", - "HostsPath": "/var/lib/docker/containers/23a3af8f5fd56049f8c8125e40ef1cea5313ac189606b14d41cf19fe60ec1a2a/hosts", - "LogPath": "/var/lib/docker/containers/23a3af8f5fd56049f8c8125e40ef1cea5313ac189606b14d41cf19fe60ec1a2a/23a3af8f5fd56049f8c8125e40ef1cea5313ac189606b14d41cf19fe60ec1a2a-json.log", - "Name": "/hungry_hamilton", - "RestartCount": 0, - "Driver": "overlay2", - "Platform": "linux", - "MountLabel": "", - "ProcessLabel": "", - "ExecIDs": null, - "HostConfig": { - "Binds": null, - "ContainerIDFile": "", - "LogConfig": { - "Type": "json-file", - "Config": {} - }, - "NetworkMode": "default", - "PortBindings": { - "3306/tcp": [ - { - "HostIp": "", - "HostPort": "3306" - } - ] - }, - "RestartPolicy": { - "Name": "no", - "MaximumRetryCount": 0 - }, - "AutoRemove": false, - "VolumeDriver": "", - "VolumesFrom": null, - "CapAdd": null, - "CapDrop": null, - "Dns": [], - "DnsOptions": [], - "DnsSearch": [], - "ExtraHosts": null, - "GroupAdd": null, - "IpcMode": "private", - "Cgroup": "", - "Links": null, - "OomScoreAdj": 0, - "PidMode": "", - "Privileged": false, - "PublishAllPorts": false, - "ReadonlyRootfs": false, - "SecurityOpt": null, - "UTSMode": "", - "UsernsMode": "", - "ShmSize": 67108864, - "Runtime": "runc", - "ConsoleSize": [ - 0, - 0 - ], - "Isolation": "", - "CpuShares": 0, - "Memory": 0, - "NanoCpus": 0, - "CgroupParent": "", - "BlkioWeight": 0, - "BlkioWeightDevice": [], - "BlkioDeviceReadBps": null, - "BlkioDeviceWriteBps": null, - "BlkioDeviceReadIOps": null, - "BlkioDeviceWriteIOps": null, - "CpuPeriod": 0, - "CpuQuota": 0, - "CpuRealtimePeriod": 0, - "CpuRealtimeRuntime": 0, - "CpusetCpus": "", - "CpusetMems": "", - "Devices": [], - "DeviceCgroupRules": null, - "DeviceRequests": null, - "KernelMemory": 0, - "MemoryReservation": 0, - "MemorySwap": 0, - "MemorySwappiness": null, - "OomKillDisable": null, - "PidsLimit": null, - "Ulimits": null, - "CpuCount": 0, - "CpuPercent": 0, - "IOMaximumIOps": 0, - "IOMaximumBandwidth": 0, - "ReadonlyPaths": [ - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger" - ] - }, - "GraphDriver": { - "Data": { - "LowerDir": "/var/lib/docker/overlay2/7c618d295d30848e4e4350c4df9eba320f9984653f98580b66d72b9f30513e0a-init/diff:/var/lib/docker/overlay2/e099f5757d669f94105b4905937db644dfa9f321f698e628437c7eecc82bdcc4/diff:/var/lib/docker/overlay2/a6e3caf0412a91b304c4b3f4f27e539382d95f0dc988ab12b43ac3767a8d97de/diff:/var/lib/docker/overlay2/03c7ad528d0a2211716e56e9c55c52d8ca109d1cb72768cf27d9b7399cfa4dd5/diff:/var/lib/docker/overlay2/c78c10c3af319f60eade40553e099312d3f7d7e007488d41cebf6b06ea997395/diff:/var/lib/docker/overlay2/310abccdb390948550514a1c659a9f3e65c6432633968698eb73e1f1dadf66b4/diff:/var/lib/docker/overlay2/bde922688557af8d2c46f79db0aa670917383745938d02dd0554c9ae98d050df/diff:/var/lib/docker/overlay2/1e812aa3eb838984a2325e4ccd0a28f0b20fc04a4dab735e8f21166ed3e52afc/diff:/var/lib/docker/overlay2/2f80cd19669a8ceded8ba79b3530b144ecced5c72de4562cde38461891c35295/diff", - "MergedDir": "/var/lib/docker/overlay2/7c618d295d30848e4e4350c4df9eba320f9984653f98580b66d72b9f30513e0a/merged", - "UpperDir": "/var/lib/docker/overlay2/7c618d295d30848e4e4350c4df9eba320f9984653f98580b66d72b9f30513e0a/diff", - "WorkDir": "/var/lib/docker/overlay2/7c618d295d30848e4e4350c4df9eba320f9984653f98580b66d72b9f30513e0a/work" - }, - "Name": "overlay2" - }, - "Mounts": [ - { - "Type": "volume", - "Name": "0e37b84407c6b8fd0ad5d42554e398425c5096bf52e3690fd7553f1e177977aa", - "Source": "/var/lib/docker/volumes/0e37b84407c6b8fd0ad5d42554e398425c5096bf52e3690fd7553f1e177977aa/_data", - "Destination": "/var/lib/mysql", - "Driver": "local", - "Mode": "", - "RW": true, - "Propagation": "" - } - ], - "Config": { - "Hostname": "23a3af8f5fd5", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": false, - "AttachStderr": false, - "ExposedPorts": { - "3306/tcp": {} - }, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": [ - "MARIADB_DATABASE=fda", - "MARIADB_ROOT_PASSWORD=dbrepo", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "GOSU_VERSION=1.14", - "LANG=C.UTF-8", - "MARIADB_MAJOR=10.5", - "MARIADB_VERSION=1:10.5.18+maria~ubu2004" - ], - "Cmd": [ - "mysqld" - ], - "Image": "mariadb:10.5", - "Volumes": { - "/var/lib/mysql": {} - }, - "WorkingDir": "", - "Entrypoint": [ - "docker-entrypoint.sh" - ], - "OnBuild": null, - "Labels": { - "org.opencontainers.image.authors": "MariaDB Community", - "org.opencontainers.image.base.name": "docker.io/library/ubuntu:focal", - "org.opencontainers.image.description": "MariaDB Database for relational SQL", - "org.opencontainers.image.documentation": "https://hub.docker.com/_/mariadb/", - "org.opencontainers.image.licenses": "GPL-2.0", - "org.opencontainers.image.source": "https://github.com/MariaDB/mariadb-docker", - "org.opencontainers.image.title": "MariaDB Database", - "org.opencontainers.image.url": "https://github.com/MariaDB/mariadb-docker", - "org.opencontainers.image.vendor": "MariaDB Community", - "org.opencontainers.image.version": "10.5.18" - } - }, - "NetworkSettings": { - "Bridge": "", - "SandboxID": "c6ac88f8ab8ba4afb7ab8dc85cee3f7aafff11c65c1042a3502c1cef8663786b", - "HairpinMode": false, - "LinkLocalIPv6Address": "", - "LinkLocalIPv6PrefixLen": 0, - "Ports": { - "3306/tcp": [ - { - "HostIp": "0.0.0.0", - "HostPort": "3306" - }, - { - "HostIp": "::", - "HostPort": "3306" - } - ] - }, - "SandboxKey": "/var/run/docker/netns/c6ac88f8ab8b", - "SecondaryIPAddresses": null, - "SecondaryIPv6Addresses": null, - "EndpointID": "722de33edafba6c64992775c320e9f1fba1e168b8aa3f0bbdc48e9517a95d20b", - "Gateway": "172.17.0.1", - "GlobalIPv6Address": "", - "GlobalIPv6PrefixLen": 0, - "IPAddress": "172.17.0.2", - "IPPrefixLen": 16, - "IPv6Gateway": "", - "MacAddress": "02:42:ac:11:00:02", - "Networks": { - "bridge": { - "IPAMConfig": null, - "Links": null, - "Aliases": null, - "NetworkID": "3ce5ab207db94ff91188b6670b881aaaeea4b1b8c6bed0f3eec9e2fe09732366", - "EndpointID": "722de33edafba6c64992775c320e9f1fba1e168b8aa3f0bbdc48e9517a95d20b", - "Gateway": "172.17.0.1", - "IPAddress": "172.17.0.2", - "IPPrefixLen": 16, - "IPv6Gateway": "", - "GlobalIPv6Address": "", - "GlobalIPv6PrefixLen": 0, - "MacAddress": "02:42:ac:11:00:02", - "DriverOpts": null - } - } - } -} \ No newline at end of file diff --git a/dbrepo-container-service/rest-service/src/test/resources/init/schema.sql b/dbrepo-container-service/rest-service/src/test/resources/init/schema.sql new file mode 100644 index 0000000000000000000000000000000000000000..f8482e47d5b0827e87537d940b54900a8f2d8f3b --- /dev/null +++ b/dbrepo-container-service/rest-service/src/test/resources/init/schema.sql @@ -0,0 +1 @@ +CREATE SCHEMA IF NOT EXISTS fda; \ No newline at end of file diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/config/DockerDaemonConfig.java b/dbrepo-container-service/services/src/main/java/at/tuwien/config/DockerDaemonConfig.java deleted file mode 100644 index 1d2dc0d6ecccb55f7a2a2dabe4b4d422b78464e2..0000000000000000000000000000000000000000 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/config/DockerDaemonConfig.java +++ /dev/null @@ -1,45 +0,0 @@ -package at.tuwien.config; - -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.model.HostConfig; -import com.github.dockerjava.api.model.RestartPolicy; -import com.github.dockerjava.core.DefaultDockerClientConfig; -import com.github.dockerjava.core.DockerClientBuilder; -import com.github.dockerjava.core.DockerClientConfig; -import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; -import com.github.dockerjava.transport.DockerHttpClient; -import lombok.Getter; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Getter -@Configuration -public class DockerDaemonConfig { - - @Value("${fda.mount.path}") - private String mountPath; - - @Value("${fda.network}") - private String userNetwork; - - @Bean - public HostConfig hostConfig() { - return HostConfig.newHostConfig() - .withRestartPolicy(RestartPolicy.alwaysRestart()); - } - - @Bean - public DockerClient dockerClientConfiguration() { - final DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder() - .withDockerHost("unix:///var/run/docker.sock") - .build(); - final DockerHttpClient dockerHttpClient = new ApacheDockerHttpClient.Builder() - .dockerHost(dockerClientConfig.getDockerHost()) - .sslConfig(dockerClientConfig.getSSLConfig()) - .build(); - return DockerClientBuilder.getInstance() - .withDockerHttpClient(dockerHttpClient) - .build(); - } -} diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java b/dbrepo-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java index 07dd871683a1e5ba8cc992cd81bd8d1a803c5402..2250fa50884df3f47b0b063975aea74f06203f80 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java @@ -1,10 +1,7 @@ package at.tuwien.config; -import at.tuwien.exception.ImageNotFoundException; -import at.tuwien.service.ImageService; import com.google.common.io.Files; import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.annotation.Configuration; @@ -17,31 +14,12 @@ import java.io.IOException; @Configuration public class ReadyConfig { - private final ImageService imageService; - private final static String registry = "docker.io/library"; - private final static String imageRepository = "mariadb"; - private final static String imageTag = "10.5"; - - @Autowired - public ReadyConfig(ImageService imageService) { - this.imageService = imageService; - } - @Value("${fda.ready.path}") private String readyPath; @EventListener(ApplicationReadyEvent.class) - public void init() throws IOException, ImageNotFoundException { - if (!imageService.exists(imageRepository, imageTag)) { - log.debug("image {}/{}:{} is not present on the host", registry, imageRepository, imageTag); - log.debug("pulling image {}/{}:{}", registry, imageRepository, imageTag); - imageService.pull(registry, imageRepository, imageTag); - } else { - log.debug("image {}/{}:{} is present on the host", registry, imageRepository, imageTag); - log.trace("skip pulling image {}/{}:{}", registry, imageRepository, imageTag); - } + public void init() throws IOException { Files.touch(new File(readyPath)); - log.info("Service is ready"); } } diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/exception/DockerClientException.java b/dbrepo-container-service/services/src/main/java/at/tuwien/exception/DockerClientException.java deleted file mode 100644 index cb1126733add4adc5e0bfbe3d3eb9fcec095fd4e..0000000000000000000000000000000000000000 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/exception/DockerClientException.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.tuwien.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.BAD_GATEWAY, reason = "Docker failed") -public class DockerClientException extends Exception { - - public DockerClientException(String message) { - super(message); - } - - public DockerClientException(String message, Throwable thr) { - super(message, thr); - } - - public DockerClientException(Throwable thr) { - super(thr); - } - -} diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java b/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java index 335ecdc23d7dc020ac50bb3c7b58668332cf484a..fbaeb76ef1df394d517f354e44c49712d0095fa9 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java @@ -3,16 +3,14 @@ package at.tuwien.mapper; import at.tuwien.api.container.ContainerBriefDto; import at.tuwien.api.container.ContainerCreateRequestDto; import at.tuwien.api.container.ContainerDto; -import at.tuwien.api.container.ContainerStateDto; import at.tuwien.entities.container.Container; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.user.User; -import com.github.dockerjava.api.command.InspectContainerResponse; -import org.mapstruct.*; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; import java.text.Normalizer; import java.util.Locale; -import java.util.Objects; import java.util.regex.Pattern; @Mapper(componentModel = "spring", uses = {ImageMapper.class, DatabaseMapper.class, UserMapper.class}) @@ -20,14 +18,7 @@ public interface ContainerMapper { org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ContainerMapper.class); - default String containerCreateRequestDtoToDockerImage(ContainerCreateRequestDto data) { - final String image = data.getRepository() + ":" + data.getTag(); - log.trace("mapped container request {} to image {}", data, image); - final User user; - return image; - } - - ContainerImage containerCreateRequestDtoToContainerImage(ContainerCreateRequestDto data); + Container containerCreateRequestDtoToContainer(ContainerCreateRequestDto data); ContainerDto containerToContainerDto(Container data); @@ -36,21 +27,6 @@ public interface ContainerMapper { }) ContainerBriefDto containerToDatabaseContainerBriefDto(Container data); - @Mappings({ - @Mapping(source = "state", target = "state", qualifiedByName = "containerStateDto"), - @Mapping(source = "id", target = "hash"), - @Mapping(target = "id", ignore = true), - @Mapping(target = "database", ignore = true), - }) - ContainerDto inspectContainerResponseToContainerDto(InspectContainerResponse data); - - @Named("containerStateDto") - default ContainerStateDto containerStateToContainerStateDto(InspectContainerResponse.ContainerState data) { - final ContainerStateDto dto = ContainerStateDto.valueOf(Objects.requireNonNull(data.getStatus()).toUpperCase()); - log.trace("mapped container state {} to state {}", data, dto); - return dto; - } - // https://stackoverflow.com/questions/1657193/java-code-library-for-generating-slugs-for-use-in-pretty-urls#answer-1657250 default String containerToInternalContainerName(Container data) { final Pattern NONLATIN = Pattern.compile("[^\\w-]"); diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ImageMapper.java b/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ImageMapper.java index 7ce7406595501fb1e1541f8cbc6c7132f34ee6f5..8ea6609f164127a43bf59647f9612758483ed76d 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ImageMapper.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/mapper/ImageMapper.java @@ -1,61 +1,26 @@ package at.tuwien.mapper; import at.tuwien.api.container.image.ImageBriefDto; +import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.api.container.image.ImageDto; -import at.tuwien.api.container.image.ImageEnvItemDto; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.container.image.ContainerImageEnvironmentItem; -import com.github.dockerjava.api.command.InspectImageResponse; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import java.time.Instant; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; @Mapper(componentModel = "spring") public interface ImageMapper { org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImageMapper.class); + ContainerImage createImageDtoToContainerImage(ImageCreateDto data); + ImageBriefDto containerImageToImageBriefDto(ContainerImage data); - @Mappings({ - @Mapping(target = "environment", ignore = true), // cannot map since front-end would know credentials - }) ImageDto containerImageToImageDto(ContainerImage data); - @Mappings({ - @Mapping(source = "id", target = "hash"), - @Mapping(source = "created", target = "compiled"), - @Mapping(target = "id", ignore = true), - @Mapping(target = "repository", expression = "java(data.getRepoTags().get(0).substring(0,data.getRepoTags().get(0).indexOf(\":\")))"), - @Mapping(target = "tag", expression = "java(data.getRepoTags().get(0).substring(data.getRepoTags().get(0).indexOf(\":\")+1))"), - }) - ContainerImage inspectImageResponseToContainerImage(InspectImageResponse data); - - ContainerImageEnvironmentItem imageEnvItemDtoToEnvironmentItem(ImageEnvItemDto data); - default Instant dateToInstant(String date) { return Instant.parse(date); } - default String[] environmentItemsToStringList(List<ContainerImageEnvironmentItem> data) { - final String[] list = data.stream() - .map(i -> i.getKey() + "=" + i.getValue()) - .toArray(String[]::new); - log.trace("mapped environment items {} to list {}", data, list); - return list; - } - - default List<ContainerImageEnvironmentItem> imageEnvironmentItemDtoToEnvironmentItemList(List<ImageEnvItemDto> data) { - final List<ContainerImageEnvironmentItem> list = data.stream() - .map(this::imageEnvItemDtoToEnvironmentItem) - .collect(Collectors.toList()); - log.trace("mapped environment item {} to environment item {}", data, list); - return list; - } - } diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/repository/mdb/ImageRepository.java b/dbrepo-container-service/services/src/main/java/at/tuwien/repository/mdb/ImageRepository.java index 3e9b129fc0e32e423e909736f09a89ed8bc35acf..21d3ba44512580effb87645bb53e04b8e72831a9 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/repository/mdb/ImageRepository.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/repository/mdb/ImageRepository.java @@ -9,6 +9,6 @@ import java.util.Optional; @Repository public interface ImageRepository extends JpaRepository<ContainerImage, Long> { - Optional<ContainerImage> findByRepositoryAndTag(String repository, String tag); + Optional<ContainerImage> findByNameAndVersion(String name, String version); } diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/service/ContainerService.java b/dbrepo-container-service/services/src/main/java/at/tuwien/service/ContainerService.java index 9f1cee243b03fa059059836691f52b0332702d48..9b50bdda73cd4018dbf4b6aa31e40c7a7c99a8e9 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/service/ContainerService.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/service/ContainerService.java @@ -1,10 +1,8 @@ package at.tuwien.service; import at.tuwien.api.container.ContainerCreateRequestDto; -import at.tuwien.api.container.ContainerDto; import at.tuwien.entities.container.Container; import at.tuwien.exception.*; -import org.springframework.transaction.annotation.Transactional; import java.security.Principal; import java.util.List; @@ -23,27 +21,16 @@ public interface ContainerService { * @throws UserNotFoundException The user creating the container was not found in the metadata database. */ Container create(ContainerCreateRequestDto createDto, Principal principal) throws ImageNotFoundException, - DockerClientException, ContainerAlreadyExistsException, UserNotFoundException; + ContainerAlreadyExistsException, UserNotFoundException; /** - * Stops a container by given id from the metadata database. - * - * @param containerId The container id. - * @return The container object, if successful. - * @throws ContainerNotFoundException The container was not found in the metadata database. - * @throws DockerClientException The docker client was unable to perform this action. - */ - Container stop(Long containerId) throws ContainerNotFoundException, DockerClientException, ContainerAlreadyStoppedException; - - /** - * Removes a stopped container by given id from the metadata database. + * Removes a container by given id from the metadata database. * * @param containerId The container id. * @throws ContainerNotFoundException The container was not found in the metadata database. - * @throws DockerClientException The docker client was unable to perform this action. * @throws ContainerStillRunningException The container is still running and this action cannot be performed. */ - void remove(Long containerId) throws ContainerNotFoundException, DockerClientException, + void remove(Long containerId) throws ContainerNotFoundException, ContainerStillRunningException, ContainerAlreadyRemovedException; /** @@ -55,16 +42,6 @@ public interface ContainerService { */ Container find(Long id) throws ContainerNotFoundException; - /** - * Inspects a container state and resources by given id. - * - * @param id The container id. - * @return The container object. - * @throws DockerClientException The docker client was unable to perform this action. - * @throws ContainerNotRunningException The docker container is not running. - */ - ContainerDto inspect(Long id) throws DockerClientException, ContainerNotRunningException, ContainerNotFoundException; - /** * Retrieve a list of all containers from the metadata database * @@ -72,21 +49,4 @@ public interface ContainerService { * @return The list of containers. */ List<Container> getAll(Integer limit); - - /** - * Find all containers on the server. - * - * @return List of containers. - */ - List<com.github.dockerjava.api.model.Container> list(); - - /** - * Starts a container with given id from the metadata database. - * - * @param containerId The container id. - * @return The container object, if successful. - * @throws ContainerNotFoundException The container was not found in the metadata database. - * @throws DockerClientException The docker client was unable to perform this action. - */ - Container start(Long containerId) throws ContainerNotFoundException, DockerClientException, ContainerAlreadyRunningException; } diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/service/ImageService.java b/dbrepo-container-service/services/src/main/java/at/tuwien/service/ImageService.java index e95c86e6eb7874b3390a0e86ea7a16cf14377d0c..8b416a1beafca2f8d422122c992aea88d817a84f 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/service/ImageService.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/service/ImageService.java @@ -3,8 +3,10 @@ package at.tuwien.service; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.*; -import org.springframework.transaction.annotation.Transactional; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageNotFoundException; +import at.tuwien.exception.PersistenceException; +import at.tuwien.exception.UserNotFoundException; import java.security.Principal; import java.util.List; @@ -33,24 +35,22 @@ public interface ImageService { * @param createDto The new image. * @param principal The user principal. * @return The container image, if successful. - * @throws ImageNotFoundException The image was not found in the docker.io registry. + * @throws ImageNotFoundException The image was not found. * @throws ImageAlreadyExistsException An image with this repository name and tag already exists. - * @throws DockerClientException The image could not be created due to the Docker daemon refusing to create it. * @throws UserNotFoundException The user could not be found by the user principal. */ ContainerImage create(ImageCreateDto createDto, Principal principal) throws ImageNotFoundException, - ImageAlreadyExistsException, DockerClientException, UserNotFoundException; + ImageAlreadyExistsException, UserNotFoundException; /** - * Updates a container image with given id in the metadata database and pull an updated docker image from the docker.io repository. + * Updates a container image with given id in the metadata database. * * @param imageId The image id. * @param changeDto The update request. * @return The updated container image, if successful. * @throws ImageNotFoundException The image was not found in the metadata database. - * @throws DockerClientException The image could not be updated due to the Docker daemon refusing to pull it. */ - ContainerImage update(Long imageId, ImageChangeDto changeDto) throws ImageNotFoundException, DockerClientException; + ContainerImage update(Long imageId, ImageChangeDto changeDto) throws ImageNotFoundException; /** * Deletes a container image with given id in the metadata database. @@ -60,23 +60,4 @@ public interface ImageService { * @throws PersistenceException The database returned an error. */ void delete(Long imageId) throws ImageNotFoundException, PersistenceException; - - /** - * Checks if an image exists locally. - * - * @param repository The image repository. - * @param tag The image tag. - * @return True if the image exists, false otherwise. - */ - boolean exists(String repository, String tag); - - /** - * Pulls a container image by given registry, repository and tag. - * - * @param registry The registry. - * @param repository The repository. - * @param tag The tag. - * @throws ImageNotFoundException The image was not found. - */ - void pull(String registry, String repository, String tag) throws ImageNotFoundException; } diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java b/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java index 2a0008f4f6406319663e1622138d2c3635a34084..f537bc3137b1d8568196ef7a272f588bf94845ef 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java @@ -1,32 +1,20 @@ package at.tuwien.service.impl; import at.tuwien.api.container.ContainerCreateRequestDto; -import at.tuwien.api.container.ContainerDto; -import at.tuwien.config.DockerDaemonConfig; import at.tuwien.entities.container.Container; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.user.User; -import at.tuwien.exception.*; +import at.tuwien.exception.ContainerAlreadyExistsException; +import at.tuwien.exception.ContainerNotFoundException; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.ContainerMapper; -import at.tuwien.mapper.ImageMapper; import at.tuwien.repository.mdb.ContainerRepository; import at.tuwien.repository.mdb.ImageRepository; import at.tuwien.service.ContainerService; -import at.tuwien.service.UserService; -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.command.CreateVolumeResponse; -import com.github.dockerjava.api.command.InspectContainerResponse; -import com.github.dockerjava.api.exception.ConflictException; -import com.github.dockerjava.api.exception.NotFoundException; -import com.github.dockerjava.api.exception.NotModifiedException; -import com.github.dockerjava.api.model.*; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; - import org.springframework.transaction.annotation.Transactional; import java.security.Principal; @@ -37,37 +25,25 @@ import java.util.Optional; @Service public class ContainerServiceImpl implements ContainerService { - private final HostConfig hostConfig; - private final ImageMapper imageMapper; - private final UserService userService; - private final DockerClient dockerClient; private final ContainerMapper containerMapper; private final ImageRepository imageRepository; - private final DockerDaemonConfig dockerDaemonConfig; private final ContainerRepository containerRepository; @Autowired - public ContainerServiceImpl(DockerClient dockerClient, ContainerRepository containerRepository, - ImageRepository imageRepository, HostConfig hostConfig, ContainerMapper containerMapper, - ImageMapper imageMapper, UserService userService, DockerDaemonConfig dockerDaemonConfig) { - this.hostConfig = hostConfig; - this.dockerClient = dockerClient; + public ContainerServiceImpl(ContainerRepository containerRepository, ImageRepository imageRepository, + ContainerMapper containerMapper) { this.imageRepository = imageRepository; this.containerRepository = containerRepository; this.containerMapper = containerMapper; - this.imageMapper = imageMapper; - this.userService = userService; - this.dockerDaemonConfig = dockerDaemonConfig; } @Override @Transactional public Container create(ContainerCreateRequestDto createDto, Principal principal) throws ImageNotFoundException, - DockerClientException, ContainerAlreadyExistsException, UserNotFoundException { - final Optional<ContainerImage> image = imageRepository.findByRepositoryAndTag(createDto.getRepository(), - createDto.getTag()); + ContainerAlreadyExistsException { + final Optional<ContainerImage> image = imageRepository.findById(createDto.getImageId()); if (image.isEmpty()) { - log.error("failed to get image with name {}:{}", createDto.getRepository(), createDto.getTag()); + log.error("failed to get image with id {}", createDto.getImageId()); throw new ImageNotFoundException("image was not found in metadata database."); } /* entity */ @@ -81,93 +57,14 @@ public class ContainerServiceImpl implements ContainerService { log.error("Failed to create container with internal name {}, it already exists", container.getInternalName()); throw new ContainerAlreadyExistsException("Container name already exists"); } - /* create the volume */ - final CreateVolumeResponse response = dockerClient.createVolumeCmd() - .withName(container.getInternalName()) - .exec(); - log.info("Created volume {} with mapping /var/lib/mysql", response.getName()); - log.trace("created volume {}", response); - /* create host mapping */ - final HostConfig hostConfig = this.hostConfig - .withNetworkMode(dockerDaemonConfig.getUserNetwork()) - .withBinds(Bind.parse(dockerDaemonConfig.getMountPath() + ":/tmp"), Bind.parse(response.getName() + ":/var/lib/mysql")); - log.debug("container has network {}, volume bind {}, volume bind {}", - dockerDaemonConfig.getUserNetwork(), dockerDaemonConfig.getMountPath() + ":/tmp", - response.getName() + ":/var/lib/mysql"); - log.trace("host config {}", hostConfig); - final User user = userService.findByUsername(principal.getName()); - container.setCreatedBy(user.getId()); - container.setOwnedBy(user.getId()); - /* create the container */ - final CreateContainerResponse response1; - try { - response1 = dockerClient.createContainerCmd( - containerMapper.containerCreateRequestDtoToDockerImage(createDto)) - .withName(container.getInternalName()) - .withHostName(container.getInternalName()) - .withEnv(imageMapper.environmentItemsToStringList(image.get().getEnvironment())) - .withHostConfig(hostConfig) - .exec(); - } catch (ConflictException e) { - log.error("Conflicting names {}, reason: {}", createDto.getName(), e.getMessage()); - throw new ContainerAlreadyExistsException("Conflicting names", e); - } catch (NotFoundException e) { - log.error("The image {}:{} not available on the container service", createDto.getRepository(), - createDto.getTag()); - throw new DockerClientException("Image not available", e); - } - container.setHash(response1.getId()); - container = containerRepository.save(container); - container.setCreator(user); - container.setOwner(user); log.info("Created container {}", container.getId()); return container; } @Override @Transactional - public Container stop(Long containerId) throws ContainerNotFoundException, - ContainerAlreadyStoppedException { - final Container container = find(containerId); - final InspectContainerResponse response; - try { - response = dockerClient.inspectContainerCmd(container.getHash()) - .withSize(true) - .exec(); - if (response.getState() == null || response.getState().getRunning() == null) { - log.warn("Failed to determine container state"); - } else if (!response.getState().getRunning()) { - throw new NotModifiedException("Already stopped"); - } - dockerClient.stopContainerCmd(container.getHash()).exec(); - } catch (NotFoundException e) { - log.error("Failed to stop container: {}", e.getMessage()); - throw new ContainerNotFoundException("Failed to stop container: " + e.getMessage(), e); - } catch (NotModifiedException e) { - log.warn("Failed to stop container: {}", e.getMessage()); - throw new ContainerAlreadyStoppedException("Failed to stop container: " + e.getMessage(), e); - } - log.info("Stopped container with id {}", containerId); - return container; - } - - @Override - @Transactional - public void remove(Long containerId) throws ContainerNotFoundException, - ContainerStillRunningException, ContainerAlreadyRemovedException { + public void remove(Long containerId) throws ContainerNotFoundException { final Container container = find(containerId); - try { - dockerClient.removeContainerCmd(container.getHash()).exec(); - } catch (NotFoundException e) { - log.error("Failed to remove container: {}", e.getMessage()); - throw new ContainerNotFoundException("Failed to remove container", e); - } catch (NotModifiedException e) { - log.warn("Failed to remove container: {}", e.getMessage()); - throw new ContainerAlreadyRemovedException("Failed to remove container", e); - } catch (ConflictException e) { - log.error("Failed to remove container: {}", e.getMessage()); - throw new ContainerStillRunningException("Failed to remove container", e); - } containerRepository.deleteById(containerId); log.info("Removed container with id {}", containerId); } @@ -183,45 +80,6 @@ public class ContainerServiceImpl implements ContainerService { return container.get(); } - @Override - @Transactional - public ContainerDto inspect(Long id) throws DockerClientException, ContainerNotRunningException, ContainerNotFoundException { - final Container container = find(id); - final InspectContainerResponse response; - try { - response = dockerClient.inspectContainerCmd(container.getHash()) - .withSize(true) - .exec(); - } catch (NotFoundException e) { - log.error("Failed to find container: {}", e.getMessage()); - throw new DockerClientException("Failed to find container", e); - } - if (response.getState() == null) { - log.error("Failed to retrieve container state: is null"); - throw new DockerClientException("Failed to retrieve container state"); - } else if (response.getState().getRunning() == null) { - log.error("Failed to retrieve container running state: is null"); - throw new DockerClientException("Failed to retrieve container running state"); - } - if (!response.getState().getRunning()) { - log.error("Failed to inspect container state: container is not running"); - throw new ContainerNotRunningException("Failed to inspect container state"); - } - final ContainerDto dto = containerMapper.containerToContainerDto(container); - dto.setHash(container.getHash()); - dto.setRunning(response.getState().getRunning()); - dto.setState(containerMapper.containerStateToContainerStateDto(response.getState())); - /* now we only support one network */ - response.getNetworkSettings() - .getNetworks() - .forEach((key, network) -> { - log.trace("key {} network {}", key, network); - dto.setIpAddress(network.getIpAddress()); - }); - log.info("Inspected container with hash {}", container.getHash()); - return dto; - } - @Override @Transactional(readOnly = true) public List<Container> getAll(Integer limit) { @@ -235,40 +93,4 @@ public class ContainerServiceImpl implements ContainerService { log.info("Found {} containers", containers.size()); return containers; } - - @Override - public List<com.github.dockerjava.api.model.Container> list() { - return dockerClient.listContainersCmd() - .withShowAll(true) - .exec(); - } - - @Override - @Transactional - public Container start(Long containerId) throws ContainerNotFoundException, - ContainerAlreadyRunningException { - final Container container = find(containerId); - final InspectContainerResponse response; - try { - response = dockerClient.inspectContainerCmd(container.getHash()) - .withSize(true) - .exec(); - if (response.getState() == null || response.getState().getRunning() == null) { - log.warn("Failed to determine container state"); - } else if (response.getState().getRunning()) { - throw new NotModifiedException("Already started"); - } - dockerClient.startContainerCmd(container.getHash()) - .exec(); - } catch (NotFoundException e) { - log.error("Failed to start container, not found: {}", e.getMessage()); - throw new ContainerNotFoundException("Failed to start container: " + e.getMessage(), e); - } catch (NotModifiedException e) { - log.warn("Failed to start container, already running: {}", e.getMessage()); - throw new ContainerAlreadyRunningException("Failed to start container: " + e.getMessage(), e); - } - log.info("Started container with id {}", containerId); - return container; - } - } diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java b/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java index a9f2f4f7c1c250fe1497fec0f9338622f4a43bef..260f95dd9c8c09c50dafbd4382c1298eb136fe6f 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java @@ -3,18 +3,13 @@ package at.tuwien.service.impl; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.entities.container.image.ContainerImageEnvironmentItem; -import at.tuwien.exception.*; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.ImageMapper; import at.tuwien.repository.mdb.ImageRepository; import at.tuwien.service.ImageService; -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.async.ResultCallback; -import com.github.dockerjava.api.command.InspectImageResponse; -import com.github.dockerjava.api.exception.InternalServerErrorException; -import com.github.dockerjava.api.exception.NotFoundException; -import com.github.dockerjava.api.model.Image; -import com.github.dockerjava.api.model.PullResponseItem; +import jakarta.persistence.EntityNotFoundException; +import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; @@ -22,15 +17,8 @@ import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import jakarta.persistence.EntityNotFoundException; -import jakarta.validation.ConstraintViolationException; - import java.security.Principal; -import java.time.Duration; -import java.time.Instant; -import java.util.Arrays; import java.util.List; -import java.util.Objects; import java.util.Optional; @Slf4j @@ -38,12 +26,10 @@ import java.util.Optional; public class ImageServiceImpl implements ImageService { private final ImageMapper imageMapper; - private final DockerClient dockerClient; private final ImageRepository imageRepository; @Autowired - public ImageServiceImpl(DockerClient dockerClient, ImageRepository imageRepository, ImageMapper imageMapper) { - this.dockerClient = dockerClient; + public ImageServiceImpl(ImageRepository imageRepository, ImageMapper imageMapper) { this.imageRepository = imageRepository; this.imageMapper = imageMapper; } @@ -67,21 +53,13 @@ public class ImageServiceImpl implements ImageService { @Override @Transactional - public ContainerImage create(ImageCreateDto createDto, Principal principal) throws ImageNotFoundException, - ImageAlreadyExistsException, - DockerClientException, UserNotFoundException { - final ContainerImage image = inspect(createDto.getRepository(), createDto.getTag()); - if (imageRepository.findByRepositoryAndTag(createDto.getRepository(), createDto.getTag()).isPresent()) { + public ContainerImage create(ImageCreateDto createDto, Principal principal) throws ImageAlreadyExistsException { + final ContainerImage image = imageMapper.createImageDtoToContainerImage(createDto); + if (imageRepository.findByNameAndVersion(createDto.getName(), createDto.getVersion()).isPresent()) { log.error("Failed to create image {}:{}, it already exists in the metadata database", - createDto.getRepository(), createDto.getTag()); - throw new ImageAlreadyExistsException("Failed to create image " + createDto.getRepository() + ":" + createDto.getTag()); + createDto.getName(), createDto.getVersion()); + throw new ImageAlreadyExistsException("Failed to create image " + createDto.getName() + ":" + createDto.getVersion()); } - image.setRegistry(createDto.getRegistry()); - image.setEnvironment(imageMapper.imageEnvironmentItemDtoToEnvironmentItemList(createDto.getEnvironment())); - image.setDefaultPort(createDto.getDefaultPort()); - image.setDialect(createDto.getDialect()); - image.setDriverClass(createDto.getDriverClass()); - image.setJdbcMethod(createDto.getJdbcMethod()); final ContainerImage dto; try { dto = imageRepository.save(image); @@ -98,28 +76,14 @@ public class ImageServiceImpl implements ImageService { @Transactional public ContainerImage update(Long imageId, ImageChangeDto changeDto) throws ImageNotFoundException { final ContainerImage image = find(imageId); - /* get new infos */ - final ContainerImage dockerImage = inspect(image.getRepository(), image.getTag()); if (!changeDto.getDefaultPort().equals(image.getDefaultPort())) { image.setDefaultPort(changeDto.getDefaultPort()); log.debug("default port changed from {} to {} for image with id {}", image.getDefaultPort(), changeDto.getDefaultPort(), imageId); } - final List<ContainerImageEnvironmentItem> env = imageMapper.imageEnvironmentItemDtoToEnvironmentItemList(changeDto.getEnvironment()); - if (env.equals(image.getEnvironment())) { - image.setEnvironment(env); - log.debug("environment changed for image with id {}", imageId); - log.trace("environment changed from {} to {} for image with id {}", env, image.getEnvironment(), imageId); - } - image.setRegistry(changeDto.getRegistry()); - image.setCompiled(dockerImage.getCompiled()); - image.setHash(dockerImage.getHash()); - image.setSize(dockerImage.getSize()); image.setDialect(changeDto.getDialect()); image.setDriverClass(changeDto.getDriverClass()); image.setJdbcMethod(changeDto.getJdbcMethod()); - /* pull changes */ - pull(image.getRegistry(), image.getRepository(), image.getTag()); /* update metadata db */ final ContainerImage out = imageRepository.save(image); log.info("Updated image with id {}", out.getId()); @@ -141,55 +105,4 @@ public class ImageServiceImpl implements ImageService { } } - /** - * Inspects a container image by given repository and tag. - * - * @param repository The repository. - * @param tag The tag. - * @return The container image if successful. - * @throws ImageNotFoundException The image was not found. - */ - public ContainerImage inspect(String repository, String tag) throws ImageNotFoundException { - final InspectImageResponse response; - try { - response = dockerClient.inspectImageCmd(repository + ":" + tag) - .exec(); - log.trace("inspected image {}", response); - } catch (NotFoundException e) { - log.error("Failed to find image {}:{}, reason: {}", repository, tag, e.getMessage()); - throw new ImageNotFoundException("Failed to find image", e); - } - return imageMapper.inspectImageResponseToContainerImage(response); - } - - @Override - public boolean exists(String repository, String tag) { - final List<Image> images = dockerClient.listImagesCmd() - .exec(); - return images.stream() - .filter(i -> Objects.nonNull(i.getRepoTags())) - .filter(i -> i.getRepoTags().length > 0) - .anyMatch(i -> Arrays.stream(i.getRepoTags()) - .anyMatch(t -> t.equals(repository + ":" + tag))); - } - - @Override - public void pull(String registry, String repository, String tag) throws ImageNotFoundException { - log.debug("pulling image {}/{}:{}", registry, repository, tag); - final ResultCallback.Adapter<PullResponseItem> response; - try { - response = dockerClient.pullImageCmd(repository) - .withRegistry(registry) - .withTag(tag) - .start(); - final Instant now = Instant.now(); - response.awaitCompletion(); - log.info("Pulled image {}/{}:{}", registry, repository, tag); - log.debug("pulled image {}/{}:{} in {} seconds", registry, repository, tag, Duration.between(now, Instant.now()).getSeconds()); - } catch (NotFoundException | InternalServerErrorException | InterruptedException e) { - log.warn("Failed to pull image {}/{}:{}, reason: {}", registry, repository, tag, e.getMessage()); - throw new ImageNotFoundException("Failed to pull image " + registry + "/" + repository + ":" + tag, e); - } - } - } diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java index f3266c631e2e235c8aed1c8d6542dff2b3310f86..bd4bcd27370c1c392efba5f413aaa56a93c58293 100644 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java +++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/auth/RealmAccessDto.java @@ -19,6 +19,4 @@ public class RealmAccessDto { @Schema(description = "list of roles associated to the user", example = "[\"create-container\",\"create-database\"]") private String[] roles; - - }