From 9d0a0649127b9ba2b470e54ef71130f3925132e6 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Thu, 19 Jan 2017 08:43:04 +0100 Subject: [PATCH] Removed deprecated GridFS column from repository (#419) * Merged artifact sha1 hash and gridfs column. Signed-off-by: kaizimmerm * Renamed exception to get rid of old GridFS name. Signed-off-by: kaizimmerm * Added test description. Signed-off-by: kaizimmerm * Fix typo. Signed-off-by: kaizimmerm --- .../resource/DdiArtifactStoreController.java | 2 +- .../ddi/rest/resource/DdiRootController.java | 2 +- .../AmqpAuthenticationMessageHandler.java | 59 +++++++++---------- .../AmqpControllerAuthenticationTest.java | 10 ++-- .../amqp/AmqpMessageHandlerServiceTest.java | 17 +++--- .../MgmtDownloadArtifactResource.java | 2 +- .../MgmtSoftwareModuleResourceTest.java | 3 +- .../repository/ArtifactManagement.java | 11 ++-- .../repository/ControllerManagement.java | 12 ++-- ...a => ArtifactBinaryNotFoundException.java} | 8 +-- .../hawkbit/repository/model/Artifact.java | 4 +- .../repository/jpa/JpaArtifactManagement.java | 25 +++----- .../jpa/JpaControllerManagement.java | 8 +-- .../jpa/LocalArtifactRepository.java | 8 +-- .../repository/jpa/model/JpaArtifact.java | 18 ++---- .../specifications/ActionSpecifications.java | 10 ++-- ...V1_10_1__consolidate_artifact_sha1__H2.sql | 3 + ...10_1__consolidate_artifact_sha1__MYSQL.sql | 3 + .../jpa/ArtifactManagementTest.java | 30 +++++----- .../jpa/ControllerManagementTest.java | 41 +++++++++++++ .../jpa/SoftwareManagementTest.java | 5 +- 21 files changed, 156 insertions(+), 125 deletions(-) rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/{GridFSDBFileNotFoundException.java => ArtifactBinaryNotFoundException.java} (79%) create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_1__consolidate_artifact_sha1__H2.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactStoreController.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactStoreController.java index 2d4086055..bf447d01c 100644 --- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactStoreController.java +++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactStoreController.java @@ -89,7 +89,7 @@ public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerR if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED); } else { - final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getId()); + final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash()); // we set a download status only if we are aware of the // targetid, i.e. authenticated and not anonymous diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index dcc5173f0..5f2875e42 100644 --- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -159,7 +159,7 @@ public class DdiRootController implements DdiRootControllerRestApi { @SuppressWarnings("squid:S3655") final Artifact artifact = module.getArtifactByFilename(fileName).get(); - final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getId()); + final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash()); final String ifMatch = requestResponseContextHolder.getHttpServletRequest().getHeader("If-Match"); if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpAuthenticationMessageHandler.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpAuthenticationMessageHandler.java index 828645875..11b20b726 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpAuthenticationMessageHandler.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpAuthenticationMessageHandler.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.amqp; import java.net.URISyntaxException; +import java.util.Optional; import java.util.UUID; import org.eclipse.hawkbit.api.HostnameResolver; @@ -116,60 +117,60 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService { * * @param secruityToken * the security token which holds the target ID to check on - * @param artifactId - * the artifact to verify if the given target is allowed to + * @param sha1Hash + * of the artifact to verify if the given target is allowed to * download it */ - private void checkIfArtifactIsAssignedToTarget(final TenantSecurityToken secruityToken, final Long artifactId) { + private void checkIfArtifactIsAssignedToTarget(final TenantSecurityToken secruityToken, final String sha1Hash) { if (secruityToken.getControllerId() != null) { - checkByControllerId(artifactId, secruityToken.getControllerId()); + checkByControllerId(sha1Hash, secruityToken.getControllerId()); } else if (secruityToken.getTargetId() != null) { - checkByTargetId(artifactId, secruityToken.getTargetId()); + checkByTargetId(sha1Hash, secruityToken.getTargetId()); } else { - LOG.info("anonymous download no authentication check for artifact {}", artifactId); + LOG.info("anonymous download no authentication check for artifact {}", sha1Hash); return; } } - private void checkByTargetId(final Long artifactId, final Long targetId) { + private void checkByTargetId(final String sha1Hash, final Long targetId) { LOG.debug("no anonymous download request, doing authentication check for target {} and artifact {}", targetId, - artifactId); - if (!controllerManagement.hasTargetArtifactAssigned(targetId, artifactId)) { - LOG.info("target {} tried to download artifact {} which is not assigned to the target", targetId, - artifactId); + sha1Hash); + if (!controllerManagement.hasTargetArtifactAssigned(targetId, sha1Hash)) { + LOG.info("target {} tried to download artifact {} which is not assigned to the target", targetId, sha1Hash); throw new EntityNotFoundException(); } - LOG.info("download security check for target {} and artifact {} granted", targetId, artifactId); + LOG.info("download security check for target {} and artifact {} granted", targetId, sha1Hash); } - private void checkByControllerId(final Long artifactId, final String controllerId) { + private void checkByControllerId(final String sha1Hash, final String controllerId) { LOG.debug("no anonymous download request, doing authentication check for target {} and artifact {}", - controllerId, artifactId); - if (!controllerManagement.hasTargetArtifactAssigned(controllerId, artifactId)) { + controllerId, sha1Hash); + if (!controllerManagement.hasTargetArtifactAssigned(controllerId, sha1Hash)) { LOG.info("target {} tried to download artifact {} which is not assigned to the target", controllerId, - artifactId); + sha1Hash); throw new EntityNotFoundException(); } - LOG.info("download security check for target {} and artifact {} granted", controllerId, artifactId); + LOG.info("download security check for target {} and artifact {} granted", controllerId, sha1Hash); } - private org.eclipse.hawkbit.repository.model.Artifact findArtifactByFileResource(final FileResource fileResource) { + private Optional findArtifactByFileResource(final FileResource fileResource) { if (fileResource.getSha1() != null) { - return artifactManagement.findFirstArtifactBySHA1(fileResource.getSha1()); + return Optional.ofNullable(fileResource.getSha1()); } else if (fileResource.getFilename() != null) { return artifactManagement.findArtifactByFilename(fileResource.getFilename()).stream().findFirst() - .orElse(null); + .map(org.eclipse.hawkbit.repository.model.Artifact::getSha1Hash); } else if (fileResource.getArtifactId() != null) { - return artifactManagement.findArtifact(fileResource.getArtifactId()); + return Optional.ofNullable(artifactManagement.findArtifact(fileResource.getArtifactId())) + .map(org.eclipse.hawkbit.repository.model.Artifact::getSha1Hash); } else if (fileResource.getSoftwareModuleFilenameResource() != null) { return artifactManagement .findByFilenameAndSoftwareModule(fileResource.getSoftwareModuleFilenameResource().getFilename(), fileResource.getSoftwareModuleFilenameResource().getSoftwareModuleId()) - .stream().findFirst().orElse(null); + .stream().findFirst().map(org.eclipse.hawkbit.repository.model.Artifact::getSha1Hash); } - return null; + return Optional.empty(); } private static Artifact convertDbArtifact(final DbArtifact dbArtifact) { @@ -189,26 +190,24 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService { try { SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken)); - final org.eclipse.hawkbit.repository.model.Artifact localArtifact = findArtifactByFileResource( - fileResource); + final Optional sha1Hash = findArtifactByFileResource(fileResource); - if (localArtifact == null) { + if (!sha1Hash.isPresent()) { LOG.info("target {} requested file resource {} which does not exists to download", secruityToken.getControllerId(), fileResource); throw new EntityNotFoundException(); } - checkIfArtifactIsAssignedToTarget(secruityToken, localArtifact.getId()); + checkIfArtifactIsAssignedToTarget(secruityToken, sha1Hash.get()); - final Artifact artifact = convertDbArtifact(artifactManagement.loadArtifactBinary(localArtifact.getId())); + final Artifact artifact = convertDbArtifact(artifactManagement.loadArtifactBinary(sha1Hash.get())); if (artifact == null) { throw new EntityNotFoundException(); } authentificationResponse.setArtifact(artifact); final String downloadId = UUID.randomUUID().toString(); // SHA1 key is set, download by SHA1 - final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, - localArtifact.getSha1Hash()); + final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, sha1Hash.get()); cache.put(downloadId, downloadCache); authentificationResponse .setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI()) diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java index f7f57537b..e8ff41d93 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java @@ -152,7 +152,7 @@ public class AmqpControllerAuthenticationTest { authenticationManager.postConstruct(); - final JpaArtifact testArtifact = new JpaArtifact("afilename", "afilename", new JpaSoftwareModule( + final JpaArtifact testArtifact = new JpaArtifact(SHA1, "afilename", new JpaSoftwareModule( new JpaSoftwareModuleType("a key", "a name", null, 1), "a name", null, null, null)); testArtifact.setId(1L); @@ -161,8 +161,8 @@ public class AmqpControllerAuthenticationTest { final DbArtifact artifact = new DbArtifact(); artifact.setSize(ARTIFACT_SIZE); - artifact.setHashes(new DbArtifactHash("sha1 test", "md5 test")); - when(artifactManagementMock.loadArtifactBinary(1L)).thenReturn(artifact); + artifact.setHashes(new DbArtifactHash(SHA1, "md5 test")); + when(artifactManagementMock.loadArtifactBinary(SHA1)).thenReturn(artifact); amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, mock(AmqpMessageDispatcherService.class), controllerManagementMock, new JpaEntityFactory()); @@ -173,8 +173,8 @@ public class AmqpControllerAuthenticationTest { when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost")); - when(controllerManagementMock.hasTargetArtifactAssigned(TARGET_ID, 1L)).thenReturn(true); - when(controllerManagementMock.hasTargetArtifactAssigned(CONTROLLER_ID, 1L)).thenReturn(true); + when(controllerManagementMock.hasTargetArtifactAssigned(TARGET_ID, SHA1)).thenReturn(true); + when(controllerManagementMock.hasTargetArtifactAssigned(CONTROLLER_ID, SHA1)).thenReturn(true); } @Test diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java index 75403e1a0..beeb90b62 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.amqp; import static org.fest.assertions.api.Assertions.assertThat; import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; @@ -79,9 +78,10 @@ import ru.yandex.qatools.allure.annotations.Stories; @Stories("AmqpMessage Handler Service Test") public class AmqpMessageHandlerServiceTest { + private static final String SHA1 = "12345"; private static final String TENANT = "DEFAULT"; private static final Long TENANT_ID = 123L; - private static String CONTROLLLER_ID = "123"; + private static final String CONTROLLLER_ID = "123"; private static final Long TARGET_ID = 123L; private AmqpMessageHandlerService amqpMessageHandlerService; @@ -362,17 +362,16 @@ public class AmqpMessageHandlerServiceTest { // mock final Artifact localArtifactMock = mock(Artifact.class); - final Long mockedArtifactId = 1L; - when(localArtifactMock.getId()).thenReturn(mockedArtifactId); + when(localArtifactMock.getSha1Hash()).thenReturn(SHA1); final DbArtifact dbArtifactMock = mock(DbArtifact.class); - when(artifactManagementMock.findFirstArtifactBySHA1(anyString())).thenReturn(localArtifactMock); - when(controllerManagementMock.hasTargetArtifactAssigned(securityToken.getControllerId(), mockedArtifactId)) + when(artifactManagementMock.findFirstArtifactBySHA1(SHA1)).thenReturn(localArtifactMock); + when(controllerManagementMock.hasTargetArtifactAssigned(securityToken.getControllerId(), SHA1)) .thenReturn(true); - when(artifactManagementMock.loadArtifactBinary(anyLong())).thenReturn(dbArtifactMock); + when(artifactManagementMock.loadArtifactBinary(anyString())).thenReturn(dbArtifactMock); when(dbArtifactMock.getArtifactId()).thenReturn("artifactId"); when(dbArtifactMock.getSize()).thenReturn(1L); - when(dbArtifactMock.getHashes()).thenReturn(new DbArtifactHash("sha1", "md5")); + when(dbArtifactMock.getHashes()).thenReturn(new DbArtifactHash(SHA1, "md5")); when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost")); // test @@ -384,7 +383,7 @@ public class AmqpMessageHandlerServiceTest { assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong") .isEqualTo(HttpStatus.OK.value()); assertThat(downloadResponse.getArtifact().getSize()).as("Wrong artifact size in message body").isEqualTo(1L); - assertThat(downloadResponse.getArtifact().getHashes().getSha1()).as("Wrong sha1 hash").isEqualTo("sha1"); + assertThat(downloadResponse.getArtifact().getHashes().getSha1()).as("Wrong sha1 hash").isEqualTo(SHA1); assertThat(downloadResponse.getArtifact().getHashes().getMd5()).as("Wrong md5 hash").isEqualTo("md5"); assertThat(downloadResponse.getDownloadUrl()).as("download url is wrong") .startsWith("http://localhost/api/v1/downloadserver/downloadId/"); diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java index 10513d568..c567752e4 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java @@ -67,7 +67,7 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi } final Artifact artifact = module.getArtifact(artifactId).get(); - final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getId()); + final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash()); final HttpServletRequest request = requestResponseContextHolder.getHttpServletRequest(); final String ifMatch = request.getHeader("If-Match"); if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index b0e85bbb4..3af56383b 100644 --- a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -163,7 +163,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra // binary try (InputStream fileInputStream = artifactManagement - .loadArtifactBinary(softwareManagement.findSoftwareModuleById(sm.getId()).getArtifacts().get(0).getId()) + .loadArtifactBinary( + softwareManagement.findSoftwareModuleById(sm.getId()).getArtifacts().get(0).getSha1Hash()) .getFileInputStream()) { assertTrue("Wrong artifact content", IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream)); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java index 5b5a91796..92d172fa1 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException; import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.GridFSDBFileNotFoundException; +import org.eclipse.hawkbit.repository.exception.ArtifactBinaryNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; import org.eclipse.hawkbit.repository.model.Artifact; @@ -186,18 +186,15 @@ public interface ArtifactManagement { /** * Loads {@link DbArtifact} from store for given {@link Artifact}. * - * @param artifactId + * @param sha1Hash * to search for * @return loaded {@link DbArtifact} * - * @throws GridFSDBFileNotFoundException + * @throws ArtifactBinaryNotFoundException * if file could not be found in store - * - * @throws EntityNotFoundException - * is artifact with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DOWNLOAD_ARTIFACT + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_CONTROLLER_DOWNLOAD) - DbArtifact loadArtifactBinary(@NotNull Long artifactId); + DbArtifact loadArtifactBinary(@NotEmpty String sha1Hash); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index 63b6b1523..351e46282 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -178,15 +178,15 @@ public interface ControllerManagement { * * @param controllerId * the ID of the target to check - * @param artifactId - * the artifact to verify if the given target had even been + * @param sha1Hash + * of the artifact to verify if the given target had even been * assigned to * @return {@code true} if the given target has currently or had ever a * relation to the given artifact through the action history, * otherwise {@code false} */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - boolean hasTargetArtifactAssigned(@NotNull String controllerId, @NotNull Long artifactId); + boolean hasTargetArtifactAssigned(@NotEmpty String controllerId, @NotEmpty String sha1Hash); /** * Checks if a given target has currently or has even been assigned to the @@ -197,15 +197,15 @@ public interface ControllerManagement { * * @param targetId * the ID of the target to check - * @param artifactId - * the artifact to verify if the given target had even been + * @param sha1Hash + * of the artifact to verify if the given target had even been * assigned to * @return {@code true} if the given target has currently or had ever a * relation to the given artifact through the action history, * otherwise {@code false} */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - boolean hasTargetArtifactAssigned(@NotNull Long targetId, @NotNull Long artifactId); + boolean hasTargetArtifactAssigned(@NotNull Long targetId, @NotEmpty String sha1Hash); /** * Registers retrieved status for given {@link Target} and {@link Action} if diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java similarity index 79% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java index 99200efab..3ddea09ed 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java @@ -16,7 +16,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * * */ -public final class GridFSDBFileNotFoundException extends AbstractServerRtException { +public final class ArtifactBinaryNotFoundException extends AbstractServerRtException { /** * @@ -27,7 +27,7 @@ public final class GridFSDBFileNotFoundException extends AbstractServerRtExcepti * Creates a new FileUploadFailedException with * {@link SpServerError#SP_REST_BODY_NOT_READABLE} error. */ - public GridFSDBFileNotFoundException() { + public ArtifactBinaryNotFoundException() { super(SpServerError.SP_ARTIFACT_LOAD_FAILED); } @@ -35,7 +35,7 @@ public final class GridFSDBFileNotFoundException extends AbstractServerRtExcepti * @param cause * for the exception */ - public GridFSDBFileNotFoundException(final Throwable cause) { + public ArtifactBinaryNotFoundException(final Throwable cause) { super(SpServerError.SP_ARTIFACT_LOAD_FAILED, cause); } @@ -43,7 +43,7 @@ public final class GridFSDBFileNotFoundException extends AbstractServerRtExcepti * @param message * of the error */ - public GridFSDBFileNotFoundException(final String message) { + public ArtifactBinaryNotFoundException(final String message) { super(message, SpServerError.SP_ARTIFACT_LOAD_FAILED); } } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java index c83f7c1ee..81e061569 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java @@ -8,6 +8,8 @@ */ package org.eclipse.hawkbit.repository.model; +import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; + import com.google.common.io.BaseEncoding; /** @@ -34,7 +36,7 @@ public interface Artifact extends TenantAwareBaseEntity { /** * @return SHA-1 hash of the artifact in {@link BaseEncoding#base16()} - * format. + * format that identifies the {@link DbArtifact} in the system. */ String getSha1Hash(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java index bade56ab3..6e5af9b68 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java @@ -18,11 +18,11 @@ import org.eclipse.hawkbit.artifact.repository.HashNotMatchException; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; import org.eclipse.hawkbit.repository.ArtifactManagement; +import org.eclipse.hawkbit.repository.exception.ArtifactBinaryNotFoundException; import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException; import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.GridFSDBFileNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; @@ -112,7 +112,7 @@ public class JpaArtifactManagement implements ArtifactManagement { private boolean clearArtifactBinary(final JpaArtifact existing) { - for (final Artifact lArtifact : localArtifactRepository.findByGridFsFileName(existing.getGridFsFileName())) { + for (final Artifact lArtifact : localArtifactRepository.findBySha1Hash(existing.getSha1Hash())) { if (!lArtifact.getSoftwareModule().isDeleted() && Long.compare(lArtifact.getSoftwareModule().getId(), existing.getSoftwareModule().getId()) != 0) { return false; @@ -120,8 +120,8 @@ public class JpaArtifactManagement implements ArtifactManagement { } try { - LOG.debug("deleting artifact from repository {}", existing.getGridFsFileName()); - artifactRepository.deleteBySha1(existing.getGridFsFileName()); + LOG.debug("deleting artifact from repository {}", existing.getSha1Hash()); + artifactRepository.deleteBySha1(existing.getSha1Hash()); return true; } catch (final ArtifactStoreException e) { throw new ArtifactDeleteFailedException(e); @@ -156,8 +156,8 @@ public class JpaArtifactManagement implements ArtifactManagement { } @Override - public Artifact findFirstArtifactBySHA1(final String sha1) { - return localArtifactRepository.findFirstByGridFsFileName(sha1); + public Artifact findFirstArtifactBySHA1(final String sha1Hash) { + return localArtifactRepository.findFirstBySha1Hash(sha1Hash); } @Override @@ -171,16 +171,9 @@ public class JpaArtifactManagement implements ArtifactManagement { } @Override - public DbArtifact loadArtifactBinary(final Long artifactId) { - final JpaArtifact artifact = Optional.ofNullable(localArtifactRepository.findOne(artifactId)) - .orElseThrow(() -> new EntityNotFoundException("Artifact with given id " + artifactId + " not found.")); - - final DbArtifact result = artifactRepository.getArtifactBySha1(artifact.getGridFsFileName()); - if (result == null) { - throw new GridFSDBFileNotFoundException(artifact.getGridFsFileName()); - } - - return result; + public DbArtifact loadArtifactBinary(final String sha1Hash) { + return Optional.ofNullable(artifactRepository.getArtifactBySha1(sha1Hash)) + .orElseThrow(() -> new ArtifactBinaryNotFoundException(sha1Hash)); } private Artifact storeArtifactMetadata(final SoftwareModule softwareModule, final String providedFilename, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index c98d65834..68080312a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -156,21 +156,21 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - public boolean hasTargetArtifactAssigned(final String controllerId, final Long localArtifact) { + public boolean hasTargetArtifactAssigned(final String controllerId, final String sha1Hash) { final Target target = targetRepository.findByControllerId(controllerId); if (target == null) { return false; } - return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(target, localArtifact)) > 0; + return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(target, sha1Hash)) > 0; } @Override - public boolean hasTargetArtifactAssigned(final Long targetId, final Long localArtifact) { + public boolean hasTargetArtifactAssigned(final Long targetId, final String sha1Hash) { final Target target = targetRepository.findOne(targetId); if (target == null) { return false; } - return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(target, localArtifact)) > 0; + return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(target, sha1Hash)) > 0; } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java index 53720e79d..78dd31142 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java @@ -48,20 +48,20 @@ public interface LocalArtifactRepository extends BaseEntityRepository findByGridFsFileName(String gridFsFileName); + List findBySha1Hash(String sha1Hash); /** * Searches for a {@link Artifact} based on given gridFsFileName. * - * @param gridFsFileName + * @param sha1Hash * to search * @return {@link Artifact} the first in the result list */ - JpaArtifact findFirstByGridFsFileName(String gridFsFileName); + JpaArtifact findFirstBySha1Hash(String sha1Hash); /** * Searches for a {@link Artifact} based user provided filename at upload. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java index 63125e8f5..afb8395e6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java @@ -30,6 +30,7 @@ import org.hibernate.validator.constraints.NotEmpty; * */ @Table(name = "sp_artifact", indexes = { @Index(name = "sp_idx_artifact_01", columnList = "tenant,software_module"), + @Index(name = "sp_idx_artifact_02", columnList = "tenant,sha1_hash"), @Index(name = "sp_idx_artifact_prim", columnList = "tenant,id") }) @Entity // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for @@ -38,10 +39,10 @@ import org.hibernate.validator.constraints.NotEmpty; public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Artifact { private static final long serialVersionUID = 1L; - @Column(name = "gridfs_file_name", length = 40) + @Column(name = "sha1_hash", length = 40, nullable = false, updatable = false) @Size(max = 40) @NotEmpty - private String gridFsFileName; + private String sha1Hash; @Column(name = "provided_file_name", length = 256) @Size(max = 256) @@ -52,9 +53,6 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art @JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_assigned_sm")) private JpaSoftwareModule softwareModule; - @Column(name = "sha1_hash", length = 40, nullable = true) - private String sha1Hash; - @Column(name = "md5_hash", length = 32, nullable = true) private String md5Hash; @@ -71,17 +69,17 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art /** * Constructs artifact. * - * @param gridFsFileName + * @param sha1Hash * that is the link to the {@link DbArtifact} entity. * @param filename * that is used by {@link DbArtifact} store. * @param softwareModule * of this artifact */ - public JpaArtifact(@NotNull final String gridFsFileName, @NotNull final String filename, + public JpaArtifact(@NotEmpty final String sha1Hash, @NotNull final String filename, final SoftwareModule softwareModule) { setSoftwareModule(softwareModule); - this.gridFsFileName = gridFsFileName; + this.sha1Hash = sha1Hash; this.filename = filename; } @@ -122,10 +120,6 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art this.softwareModule.addArtifact(this); } - public String getGridFsFileName() { - return gridFsFileName; - } - @Override public String getFilename() { return filename; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java index a3b88f660..47a40b0f5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/ActionSpecifications.java @@ -43,18 +43,18 @@ public final class ActionSpecifications { * @param target * the target to verfiy if the given artifact is currently * assigned or had been assigned - * @param localArtifact - * the local artifact to check wherever the target had ever been - * assigned + * @param sha1Hash + * of the local artifact to check wherever the target had ever + * been assigned * @return a specification to use with spring JPA */ - public static Specification hasTargetAssignedArtifact(final Target target, final Long localArtifact) { + public static Specification hasTargetAssignedArtifact(final Target target, final String sha1Hash) { return (actionRoot, query, criteriaBuilder) -> { final Join dsJoin = actionRoot.join(JpaAction_.distributionSet); final SetJoin modulesJoin = dsJoin.join(JpaDistributionSet_.modules); final ListJoin artifactsJoin = modulesJoin .join(JpaSoftwareModule_.artifacts); - return criteriaBuilder.and(criteriaBuilder.equal(artifactsJoin.get(JpaArtifact_.id), localArtifact), + return criteriaBuilder.and(criteriaBuilder.equal(artifactsJoin.get(JpaArtifact_.sha1Hash), sha1Hash), criteriaBuilder.equal(actionRoot.get(JpaAction_.target), target)); }; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_1__consolidate_artifact_sha1__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_1__consolidate_artifact_sha1__H2.sql new file mode 100644 index 000000000..05b34fd5f --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_10_1__consolidate_artifact_sha1__H2.sql @@ -0,0 +1,3 @@ +ALTER TABLE sp_artifact DROP COLUMN sha1_hash; +ALTER TABLE sp_artifact CHANGE gridfs_file_name sha1_hash varchar(40) not null; +CREATE INDEX sp_idx_artifact_02 ON sp_artifact (tenant, sha1_hash); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql new file mode 100644 index 000000000..05b34fd5f --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_10_1__consolidate_artifact_sha1__MYSQL.sql @@ -0,0 +1,3 @@ +ALTER TABLE sp_artifact DROP COLUMN sha1_hash; +ALTER TABLE sp_artifact CHANGE gridfs_file_name sha1_hash varchar(40) not null; +CREATE INDEX sp_idx_artifact_02 ON sp_artifact (tenant, sha1_hash); \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java index 123b47f2b..e9f1c6193 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java @@ -87,9 +87,9 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(result.getSoftwareModule().getId()).isEqualTo(sm.getId()); assertThat(result2.getSoftwareModule().getId()).isEqualTo(sm2.getId()); assertThat(((JpaArtifact) result).getFilename()).isEqualTo("file1"); - assertThat(((JpaArtifact) result).getGridFsFileName()).isNotNull(); + assertThat(((JpaArtifact) result).getSha1Hash()).isNotNull(); assertThat(result).isNotEqualTo(result2); - assertThat(((JpaArtifact) result).getGridFsFileName()).isEqualTo(((JpaArtifact) result2).getGridFsFileName()); + assertThat(((JpaArtifact) result).getSha1Hash()).isEqualTo(((JpaArtifact) result2).getSha1Hash()); assertThat(artifactManagement.findArtifactByFilename("file1").get(0).getSha1Hash()) .isEqualTo(HashGeneratorUtils.generateSHA1(random)); @@ -148,19 +148,18 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(result.getId()).isNotNull(); assertThat(result2.getId()).isNotNull(); - assertThat(((JpaArtifact) result).getGridFsFileName()) - .isNotEqualTo(((JpaArtifact) result2).getGridFsFileName()); + assertThat(((JpaArtifact) result).getSha1Hash()).isNotEqualTo(((JpaArtifact) result2).getSha1Hash()); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNotNull(); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getGridFsFileName())).isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getSha1Hash())).isNotNull(); artifactManagement.deleteArtifact(result.getId()); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNull(); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getGridFsFileName())).isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getSha1Hash())).isNotNull(); artifactManagement.deleteArtifact(result2.getId()); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getGridFsFileName())).isNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getSha1Hash())).isNull(); assertThat(artifactRepository.findAll()).hasSize(0); } @@ -187,14 +186,14 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(artifactRepository.findAll()).hasSize(2); assertThat(result.getId()).isNotNull(); assertThat(result2.getId()).isNotNull(); - assertThat(((JpaArtifact) result).getGridFsFileName()).isEqualTo(((JpaArtifact) result2).getGridFsFileName()); + assertThat(((JpaArtifact) result).getSha1Hash()).isEqualTo(((JpaArtifact) result2).getSha1Hash()); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull(); artifactManagement.deleteArtifact(result.getId()); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull(); artifactManagement.deleteArtifact(result2.getId()); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNull(); } @Test @@ -214,7 +213,8 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { final Artifact result = artifactManagement.createArtifact(new ByteArrayInputStream(random), testdataFactory.createSoftwareModuleOs().getId(), "file1", false); - try (InputStream fileInputStream = artifactManagement.loadArtifactBinary(result.getId()).getFileInputStream()) { + try (InputStream fileInputStream = artifactManagement.loadArtifactBinary(result.getSha1Hash()) + .getFileInputStream()) { assertTrue("The stored binary matches the given binary", IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream)); } @@ -225,7 +225,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Description("Trys and fails to load an artifact without required permission. Checks if expected InsufficientPermissionException is thrown.") public void loadArtifactBinaryWithoutDownloadArtifactThrowsPermissionDenied() { try { - artifactManagement.loadArtifactBinary(1L); + artifactManagement.loadArtifactBinary("123"); fail("Should not have worked with missing permission."); } catch (final InsufficientPermissionException e) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java index 9992305d9..f9a469c8a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java @@ -11,18 +11,23 @@ package org.eclipse.hawkbit.repository.jpa; import static org.fest.assertions.api.Assertions.assertThat; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; + import javax.validation.ConstraintViolationException; +import org.apache.commons.lang3.RandomUtils; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; +import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; @@ -80,6 +85,42 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { .isEqualTo(3); } + @Test + @Description("Verifies that assignement verification works based on SHA1 hash. By design it is not important which artifact " + + "is actually used for the check as long as they have an identical binary, i.e. same SHA1 hash. ") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), + @Expect(type = DistributionSetCreatedEvent.class, count = 2), + @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), + @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 2) }) + public void hasTargetArtifactAssignedIsTrueWithMultipleArtifacts() { + final byte[] random = RandomUtils.nextBytes(5 * 1024); + + final DistributionSet ds = testdataFactory.createDistributionSet(""); + final DistributionSet ds2 = testdataFactory.createDistributionSet("2"); + Target savedTarget = testdataFactory.createTarget(); + + // create two artifacts with identical SHA1 hash + final Artifact artifact = artifactManagement.createArtifact(new ByteArrayInputStream(random), + ds.findFirstModuleByType(osType).getId(), "file1", false); + final Artifact artifact2 = artifactManagement.createArtifact(new ByteArrayInputStream(random), + ds2.findFirstModuleByType(osType).getId(), "file1", false); + assertThat(artifact.getSha1Hash()).isEqualTo(artifact2.getSha1Hash()); + + assertThat( + controllerManagament.hasTargetArtifactAssigned(savedTarget.getControllerId(), artifact.getSha1Hash())) + .isFalse(); + savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator() + .next(); + assertThat( + controllerManagament.hasTargetArtifactAssigned(savedTarget.getControllerId(), artifact.getSha1Hash())) + .isTrue(); + assertThat( + controllerManagament.hasTargetArtifactAssigned(savedTarget.getControllerId(), artifact2.getSha1Hash())) + .isTrue(); + } + @Test @Description("Register a controller which does not exist") public void testfindOrRegisterTargetIfItDoesNotexist() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareManagementTest.java index d500c0cb9..d2904d9b2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareManagementTest.java @@ -501,14 +501,13 @@ public class SoftwareManagementTest extends AbstractJpaIntegrationTest { assertThat(artifactRepository.findAll()).hasSize(results.length); for (final Artifact result : results) { assertThat(result.getId()).isNotNull(); - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())) - .isNotNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull(); } } private void assertArtfiactNull(final Artifact... results) { for (final Artifact result : results) { - assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNull(); + assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNull(); } }