ArtifactRepository tenant aware. (#539)
* ArtifactRepository tenant aware. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * No need to have this protected. Updated event to boot > 1.3 Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove conditional. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove Debug log. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Cleanup Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Missing validation and readability. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix test after change. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix computation is DosFilter Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix session state on RESTful APIs. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Performance improvement controllermanagement Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Added cross tenant test. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Typos. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -23,11 +23,11 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -118,13 +118,15 @@ public interface ControllerManagement {
|
||||
/**
|
||||
* Retrieves oldest {@link Action} that is active and assigned to a
|
||||
* {@link Target}.
|
||||
*
|
||||
* For performance reasons this method does not throw
|
||||
* {@link EntityNotFoundException} in case target with given controlelrId
|
||||
* does not exist but will return an {@link Optional#empty()} instead.
|
||||
*
|
||||
* @param controllerId
|
||||
* identifies the target to retrieve the actions from
|
||||
* @return a list of actions assigned to given target which are active
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
Optional<Action> findOldestActiveActionByTarget(@NotNull String controllerId);
|
||||
|
||||
@@ -116,6 +116,17 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
@EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD)
|
||||
Optional<Action> findFirstByTargetControllerIdAndActive(final Sort sort, final String controllerId, boolean active);
|
||||
|
||||
/**
|
||||
* Checks if an active action exists for given
|
||||
* {@link Target#getControllerId()}.
|
||||
*
|
||||
* @param controllerId
|
||||
* of target to check
|
||||
* @return <code>true</code> if an active action for the target exists.
|
||||
*/
|
||||
@Query("SELECT CASE WHEN COUNT(a)>0 THEN 'true' ELSE 'false' END FROM JpaAction a JOIN a.target t WHERE t.controllerId=:controllerId AND a.active=1")
|
||||
boolean activeActionExistsForControllerId(@Param("controllerId") String controllerId);
|
||||
|
||||
/**
|
||||
* Retrieves latest {@link Action} for given target and
|
||||
* {@link SoftwareModule}.
|
||||
|
||||
@@ -28,9 +28,9 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -49,14 +49,22 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JpaArtifactManagement.class);
|
||||
|
||||
@Autowired
|
||||
private LocalArtifactRepository localArtifactRepository;
|
||||
private final LocalArtifactRepository localArtifactRepository;
|
||||
|
||||
@Autowired
|
||||
private SoftwareModuleRepository softwareModuleRepository;
|
||||
private final SoftwareModuleRepository softwareModuleRepository;
|
||||
|
||||
@Autowired
|
||||
private ArtifactRepository artifactRepository;
|
||||
private final ArtifactRepository artifactRepository;
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
JpaArtifactManagement(final LocalArtifactRepository localArtifactRepository,
|
||||
final SoftwareModuleRepository softwareModuleRepository, final ArtifactRepository artifactRepository,
|
||||
final TenantAware tenantAware) {
|
||||
this.localArtifactRepository = localArtifactRepository;
|
||||
this.softwareModuleRepository = softwareModuleRepository;
|
||||
this.artifactRepository = artifactRepository;
|
||||
this.tenantAware = tenantAware;
|
||||
}
|
||||
|
||||
private static Artifact checkForExistingArtifact(final String filename, final boolean overrideExisting,
|
||||
final SoftwareModule softwareModule) {
|
||||
@@ -87,7 +95,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
final Artifact existing = checkForExistingArtifact(filename, overrideExisting, softwareModule);
|
||||
|
||||
try {
|
||||
result = artifactRepository.store(stream, filename, contentType,
|
||||
result = artifactRepository.store(tenantAware.getCurrentTenant(), stream, filename, contentType,
|
||||
new DbArtifactHash(providedSha1Sum, providedMd5Sum));
|
||||
} catch (final ArtifactStoreException e) {
|
||||
throw new ArtifactUploadFailedException(e);
|
||||
@@ -118,7 +126,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
|
||||
try {
|
||||
LOG.debug("deleting artifact from repository {}", sha1Hash);
|
||||
artifactRepository.deleteBySha1(sha1Hash);
|
||||
artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash);
|
||||
return true;
|
||||
} catch (final ArtifactStoreException e) {
|
||||
throw new ArtifactDeleteFailedException(e);
|
||||
@@ -177,7 +185,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
|
||||
@Override
|
||||
public Optional<DbArtifact> loadArtifactBinary(final String sha1Hash) {
|
||||
return Optional.ofNullable(artifactRepository.getArtifactBySha1(sha1Hash));
|
||||
return Optional.ofNullable(artifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), sha1Hash));
|
||||
}
|
||||
|
||||
private Artifact storeArtifactMetadata(final SoftwareModule softwareModule, final String providedFilename,
|
||||
|
||||
@@ -188,7 +188,9 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
|
||||
@Override
|
||||
public Optional<Action> findOldestActiveActionByTarget(final String controllerId) {
|
||||
throwExceptionIfTargetDoesNotExist(controllerId);
|
||||
if (!actionRepository.activeActionExistsForControllerId(controllerId)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// used in favorite to findFirstByTargetAndActiveOrderByIdAsc due to
|
||||
// DATAJPA-841 issue.
|
||||
|
||||
@@ -73,7 +73,6 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* JPA implementation of {@link SoftwareModuleManagement}.
|
||||
@@ -591,7 +590,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
@Retryable(include = {
|
||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteSoftwareModule(final Long moduleId) {
|
||||
deleteSoftwareModules(Sets.newHashSet(moduleId));
|
||||
deleteSoftwareModules(Arrays.asList(moduleId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.eclipse.hawkbit.repository.RolloutStatusCache;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
@@ -116,6 +117,9 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
@Autowired
|
||||
private RolloutStatusCache rolloutStatusCache;
|
||||
|
||||
@Autowired
|
||||
private ArtifactRepository artifactRepository;
|
||||
|
||||
@Override
|
||||
public SystemUsageReport getSystemUsageStatistics() {
|
||||
|
||||
@@ -236,6 +240,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
distributionSetRepository.deleteByTenant(tenant);
|
||||
distributionSetTypeRepository.deleteByTenant(tenant);
|
||||
softwareModuleRepository.deleteByTenant(tenant);
|
||||
artifactRepository.deleteByTenant(tenant);
|
||||
softwareModuleTypeRepository.deleteByTenant(tenant);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.Map;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
@@ -502,16 +503,13 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return new JpaControllerManagement();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link JpaArtifactManagement} bean.
|
||||
*
|
||||
* @return a new {@link ArtifactManagement}
|
||||
*/
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ArtifactManagement artifactManagement() {
|
||||
return new JpaArtifactManagement();
|
||||
ArtifactManagement artifactManagement(final LocalArtifactRepository localArtifactRepository,
|
||||
final SoftwareModuleRepository softwareModuleRepository, final ArtifactRepository artifactRepository,
|
||||
final TenantAware tenantAware) {
|
||||
return new JpaArtifactManagement(localArtifactRepository, softwareModuleRepository, artifactRepository,
|
||||
tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -175,16 +175,21 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(result2.getId()).isNotNull();
|
||||
assertThat(((JpaArtifact) result).getSha1Hash()).isNotEqualTo(((JpaArtifact) result2).getSha1Hash());
|
||||
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getSha1Hash())).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result2.getSha1Hash()))
|
||||
.isNotNull();
|
||||
|
||||
artifactManagement.deleteArtifact(result.getId());
|
||||
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getSha1Hash())).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result2.getSha1Hash()))
|
||||
.isNotNull();
|
||||
|
||||
artifactManagement.deleteArtifact(result2.getId());
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getSha1Hash())).isNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result2.getSha1Hash()))
|
||||
.isNull();
|
||||
|
||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||
}
|
||||
@@ -211,12 +216,15 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(result2.getId()).isNotNull();
|
||||
assertThat(((JpaArtifact) result).getSha1Hash()).isEqualTo(((JpaArtifact) result2).getSha1Hash());
|
||||
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNotNull();
|
||||
artifactManagement.deleteArtifact(result.getId());
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNotNull();
|
||||
|
||||
artifactManagement.deleteArtifact(result2.getId());
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -78,6 +78,8 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(controllerManagement.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(),
|
||||
module.getId())).isNotPresent();
|
||||
|
||||
assertThat(controllerManagement.findOldestActiveActionByTarget(NOT_EXIST_ID)).isNotPresent();
|
||||
|
||||
assertThat(controllerManagement.hasTargetArtifactAssigned(target.getControllerId(), "XXX")).isFalse();
|
||||
assertThat(controllerManagement.hasTargetArtifactAssigned(target.getId(), "XXX")).isFalse();
|
||||
}
|
||||
@@ -100,8 +102,6 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
verifyThrownExceptionBy(() -> controllerManagement.addUpdateActionStatus(
|
||||
entityFactory.actionStatus().create(NOT_EXIST_IDL).status(Action.Status.FINISHED)), "Action");
|
||||
|
||||
verifyThrownExceptionBy(() -> controllerManagement.findOldestActiveActionByTarget(NOT_EXIST_ID), "Target");
|
||||
|
||||
verifyThrownExceptionBy(() -> controllerManagement
|
||||
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), NOT_EXIST_IDL),
|
||||
"SoftwareModule");
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.List;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
@@ -490,13 +489,15 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(artifactRepository.findAll()).hasSize(results.length);
|
||||
for (final Artifact result : results) {
|
||||
assertThat(result.getId()).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNotNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertArtfiactNull(final Artifact... results) {
|
||||
for (final Artifact result : results) {
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getSha1Hash())).isNull();
|
||||
assertThat(binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), result.getSha1Hash()))
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
# Test utility properties for easier fault investigation - START
|
||||
## Logging - START
|
||||
logging.level.=INFO
|
||||
logging.level.org.eclipse.persistence=ERROR
|
||||
logging.level.org.eclipse.hawkbit.repository.test.matcher.EventVerifier=ERROR
|
||||
logging.level.org.eclipse.persistence=ERROR
|
||||
spring.datasource.eclipselink.logging.logger=JavaLogger
|
||||
spring.jpa.properties.eclipselink.logging.level=FINE
|
||||
spring.jpa.properties.eclipselink.logging.level.sql=FINE
|
||||
spring.jpa.properties.eclipselink.logging.parameters=true
|
||||
|
||||
Reference in New Issue
Block a user