fix bug: change sql-query in localArtifactRepository (#820)
Also-by: Nazife Basbaz <nazife.basbaz@bosch-si.com> Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>
This commit is contained in:
committed by
Jeroen Laverman
parent
b8ca7d24c8
commit
fde0cbdf16
@@ -106,4 +106,8 @@ public class ArtifactFilesystemRepository extends AbstractArtifactRepository {
|
|||||||
FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile());
|
FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsByTenantAndSha1(final String tenant, final String sha1) {
|
||||||
|
return getFile(tenant, sha1).exists();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ public enum ApiType {
|
|||||||
/**
|
/**
|
||||||
* Support for Direct Device Integration API.
|
* Support for Direct Device Integration API.
|
||||||
*/
|
*/
|
||||||
DDI;
|
DDI
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,4 +84,16 @@ public interface ArtifactRepository {
|
|||||||
* to erase
|
* to erase
|
||||||
*/
|
*/
|
||||||
void deleteByTenant(@NotEmpty String tenant);
|
void deleteByTenant(@NotEmpty String tenant);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an artifact exists for a given tenant by its sha1 hash
|
||||||
|
*
|
||||||
|
* @param tenant
|
||||||
|
* the tenant
|
||||||
|
* @param sha1Hash
|
||||||
|
* the sha1-hash of the file to lookup.
|
||||||
|
*
|
||||||
|
* @return the boolean whether the atrifact exists or not
|
||||||
|
*/
|
||||||
|
boolean existsByTenantAndSha1(@NotEmpty String tenant, @NotEmpty String sha1Hash);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,6 @@ public enum EventTopic {
|
|||||||
/**
|
/**
|
||||||
* Topic to send multiple actions to the device.
|
* Topic to send multiple actions to the device.
|
||||||
*/
|
*/
|
||||||
MULTI_ACTION;
|
MULTI_ACTION
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,6 @@ public enum MessageType {
|
|||||||
/**
|
/**
|
||||||
* DMF receiver health check reponse type.
|
* DMF receiver health check reponse type.
|
||||||
*/
|
*/
|
||||||
PING_RESPONSE;
|
PING_RESPONSE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,5 +64,5 @@ public enum DmfActionStatus {
|
|||||||
/**
|
/**
|
||||||
* Action has been downloaded for this target.
|
* Action has been downloaded for this target.
|
||||||
*/
|
*/
|
||||||
DOWNLOADED;
|
DOWNLOADED
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ public enum DmfUpdateMode {
|
|||||||
/**
|
/**
|
||||||
* Removal update strategy
|
* Removal update strategy
|
||||||
*/
|
*/
|
||||||
REMOVE;
|
REMOVE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public interface ArtifactManagement {
|
|||||||
* @param artifactSha1Hash
|
* @param artifactSha1Hash
|
||||||
* no longer needed
|
* no longer needed
|
||||||
* @param moduleId
|
* @param moduleId
|
||||||
* the garbage colelction call is made for
|
* the garbage collection call is made for
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if an binary was actually garbage collected
|
* @return <code>true</code> if an binary was actually garbage collected
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public interface Action extends TenantAwareBaseEntity {
|
|||||||
* Status enum declaration!
|
* Status enum declaration!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public enum Status {
|
enum Status {
|
||||||
/**
|
/**
|
||||||
* Action is finished successfully for this target.
|
* Action is finished successfully for this target.
|
||||||
*/
|
*/
|
||||||
@@ -206,14 +206,14 @@ public interface Action extends TenantAwareBaseEntity {
|
|||||||
* Action has been downloaded by the target and waiting for update to
|
* Action has been downloaded by the target and waiting for update to
|
||||||
* start.
|
* start.
|
||||||
*/
|
*/
|
||||||
DOWNLOADED;
|
DOWNLOADED
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action type for this action relation.
|
* The action type for this action relation.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public enum ActionType {
|
enum ActionType {
|
||||||
/**
|
/**
|
||||||
* Forced action execution. Target is advised to executed immediately.
|
* Forced action execution. Target is advised to executed immediately.
|
||||||
*/
|
*/
|
||||||
@@ -234,7 +234,7 @@ public interface Action extends TenantAwareBaseEntity {
|
|||||||
/**
|
/**
|
||||||
* Target is only advised to download, but not install
|
* Target is only advised to download, but not install
|
||||||
*/
|
*/
|
||||||
DOWNLOAD_ONLY;
|
DOWNLOAD_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public interface Rollout extends NamedEntity {
|
|||||||
* State machine for rollout.
|
* State machine for rollout.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public enum RolloutStatus {
|
enum RolloutStatus {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollouts is being created.
|
* Rollouts is being created.
|
||||||
@@ -181,7 +181,7 @@ public interface Rollout extends NamedEntity {
|
|||||||
* @deprecated legacy status is not used anymore
|
* @deprecated legacy status is not used anymore
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
ERROR_STARTING;
|
ERROR_STARTING
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -40,5 +40,5 @@ public enum TargetUpdateStatus {
|
|||||||
/**
|
/**
|
||||||
* Controller registered at SP but no {@link DistributionSet} assigned.
|
* Controller registered at SP but no {@link DistributionSet} assigned.
|
||||||
*/
|
*/
|
||||||
REGISTERED;
|
REGISTERED
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] writeContent(final Object payload) {
|
private static byte[] writeContent(final Object payload) {
|
||||||
final Class<? extends Object> serializeClass = payload.getClass();
|
final Class<?> serializeClass = payload.getClass();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Schema<Object> schema = (Schema<Object>) RuntimeSchema.getSchema(serializeClass);
|
final Schema<Object> schema = (Schema<Object>) RuntimeSchema.getSchema(serializeClass);
|
||||||
final LinkedBuffer buffer = LinkedBuffer.allocate();
|
final LinkedBuffer buffer = LinkedBuffer.allocate();
|
||||||
@@ -137,7 +137,7 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
|
|||||||
}
|
}
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Schema<Object> schema = (Schema<Object>) RuntimeSchema
|
final Schema<Object> schema = (Schema<Object>) RuntimeSchema
|
||||||
.getSchema((Class<? extends Object>) EventType.class);
|
.getSchema((Class<?>) EventType.class);
|
||||||
final LinkedBuffer buffer = LinkedBuffer.allocate();
|
final LinkedBuffer buffer = LinkedBuffer.allocate();
|
||||||
return ProtobufIOUtil.toByteArray(clazzEventType, schema, buffer);
|
return ProtobufIOUtil.toByteArray(clazzEventType, schema, buffer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.retry.annotation.Backoff;
|
import org.springframework.retry.annotation.Backoff;
|
||||||
import org.springframework.retry.annotation.Retryable;
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,20 +99,35 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
public Artifact create(final ArtifactUpload artifactUpload) {
|
public Artifact create(final ArtifactUpload artifactUpload) {
|
||||||
final String filename = artifactUpload.getFilename();
|
final String filename = artifactUpload.getFilename();
|
||||||
final long moduleId = artifactUpload.getModuleId();
|
final long moduleId = artifactUpload.getModuleId();
|
||||||
AbstractDbArtifact result = null;
|
|
||||||
|
|
||||||
final SoftwareModule softwareModule = getModuleAndThrowExceptionIfThatFails(moduleId);
|
final SoftwareModule softwareModule = getModuleAndThrowExceptionIfThatFails(moduleId);
|
||||||
|
|
||||||
final Artifact existing = checkForExistingArtifact(filename, artifactUpload.overrideExisting(),
|
final Artifact existing = checkForExistingArtifact(filename, artifactUpload.overrideExisting(), softwareModule);
|
||||||
softwareModule);
|
|
||||||
|
|
||||||
assertArtifactQuota(moduleId, 1);
|
assertArtifactQuota(moduleId, 1);
|
||||||
assertMaxArtifactSizeQuota(filename, moduleId, artifactUpload.getFilesize());
|
assertMaxArtifactSizeQuota(filename, moduleId, artifactUpload.getFilesize());
|
||||||
assertMaxArtifactStorageQuota(filename, artifactUpload.getFilesize());
|
assertMaxArtifactStorageQuota(filename, artifactUpload.getFilesize());
|
||||||
|
|
||||||
|
return getOrCreateArtifact(artifactUpload)
|
||||||
|
.map(artifact -> storeArtifactMetadata(softwareModule, filename, artifact, existing))
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<AbstractDbArtifact> getOrCreateArtifact(final ArtifactUpload artifactUpload) {
|
||||||
|
final String providedSha1Sum = artifactUpload.getProvidedSha1Sum();
|
||||||
|
AbstractDbArtifact artifact = null;
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(providedSha1Sum)) {
|
||||||
|
artifact = artifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), providedSha1Sum);
|
||||||
|
}
|
||||||
|
artifact = (artifact == null) ? storeArtifact(artifactUpload) : artifact;
|
||||||
|
return Optional.ofNullable(artifact);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload) {
|
||||||
try {
|
try {
|
||||||
result = artifactRepository.store(tenantAware.getCurrentTenant(), artifactUpload.getInputStream(), filename,
|
return artifactRepository.store(tenantAware.getCurrentTenant(), artifactUpload.getInputStream(),
|
||||||
artifactUpload.getContentType(),
|
artifactUpload.getFilename(), artifactUpload.getContentType(),
|
||||||
new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum()));
|
new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum()));
|
||||||
} catch (final ArtifactStoreException e) {
|
} catch (final ArtifactStoreException e) {
|
||||||
throw new ArtifactUploadFailedException(e);
|
throw new ArtifactUploadFailedException(e);
|
||||||
@@ -122,11 +138,6 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
throw new InvalidMD5HashException(e.getMessage(), e);
|
throw new InvalidMD5HashException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return storeArtifactMetadata(softwareModule, filename, result, existing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertArtifactQuota(final long id, final int requested) {
|
private void assertArtifactQuota(final long id, final int requested) {
|
||||||
@@ -166,12 +177,12 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
@Retryable(include = {
|
@Retryable(include = {
|
||||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public boolean clearArtifactBinary(final String sha1Hash, final long moduleId) {
|
public boolean clearArtifactBinary(final String sha1Hash, final long moduleId) {
|
||||||
|
final long count = localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash,
|
||||||
if (localArtifactRepository.existsWithSha1HashAndSoftwareModuleIdIsNot(sha1Hash, moduleId)) {
|
tenantAware.getCurrentTenant());
|
||||||
|
if (count > 1) {
|
||||||
// there are still other artifacts that need the binary
|
// there are still other artifacts that need the binary
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LOG.debug("deleting artifact from repository {}", sha1Hash);
|
LOG.debug("deleting artifact from repository {}", sha1Hash);
|
||||||
artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash);
|
artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash);
|
||||||
|
|||||||
@@ -56,19 +56,18 @@ public interface LocalArtifactRepository extends BaseEntityRepository<JpaArtifac
|
|||||||
List<Artifact> findBySha1Hash(String sha1Hash);
|
List<Artifact> findBySha1Hash(String sha1Hash);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies if an artifact exists that has given hash and is still related
|
* Counts current elements based on the sha1 and tenant, as well as having
|
||||||
* to a {@link SoftwareModule} other than a given one and not
|
* the {@link SoftwareModule} property 'deleted' with value 'false
|
||||||
* {@link SoftwareModule#isDeleted()}.
|
|
||||||
*
|
*
|
||||||
* @param sha1
|
* @param sha1
|
||||||
* to search for
|
* the sha1 of the {@link Artifact}
|
||||||
* @param moduleId
|
* @param tenant
|
||||||
* to ignore in relationship check
|
* the current tenant
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if such an artifact exists
|
* @return the count of the elements
|
||||||
*/
|
*/
|
||||||
@Query("SELECT CASE WHEN COUNT(a)>0 THEN 'true' ELSE 'false' END FROM JpaArtifact a WHERE a.sha1Hash = :sha1 AND a.softwareModule.id != :moduleId AND a.softwareModule.deleted = 0")
|
long countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(@Param("sha1") String sha1,
|
||||||
boolean existsWithSha1HashAndSoftwareModuleIdIsNot(@Param("sha1") String sha1, @Param("moduleId") Long moduleId);
|
@Param("tenant") String tenant);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for a {@link Artifact} based on given gridFsFileName.
|
* Searches for a {@link Artifact} based on given gridFsFileName.
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ public final class RSQLUtility {
|
|||||||
// values JPA can do it by it's own but not for classes like enums.
|
// values JPA can do it by it's own but not for classes like enums.
|
||||||
// So we need to transform the given value string into the enum
|
// So we need to transform the given value string into the enum
|
||||||
// class.
|
// class.
|
||||||
final Class<? extends Object> javaType = fieldPath.getJavaType();
|
final Class<?> javaType = fieldPath.getJavaType();
|
||||||
if (javaType != null && javaType.isEnum()) {
|
if (javaType != null && javaType.isEnum()) {
|
||||||
return transformEnumValue(node, value, javaType);
|
return transformEnumValue(node, value, javaType);
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,7 @@ public final class RSQLUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object convertBooleanValue(final ComparisonNode node, final String value,
|
private Object convertBooleanValue(final ComparisonNode node, final String value,
|
||||||
final Class<? extends Object> javaType) {
|
final Class<?> javaType) {
|
||||||
try {
|
try {
|
||||||
return simpleTypeConverter.convertIfNecessary(value, javaType);
|
return simpleTypeConverter.convertIfNecessary(value, javaType);
|
||||||
} catch (final TypeMismatchException e) {
|
} catch (final TypeMismatchException e) {
|
||||||
@@ -513,7 +513,7 @@ public final class RSQLUtility {
|
|||||||
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked", "squid:S2095" })
|
@SuppressWarnings({ "rawtypes", "unchecked", "squid:S2095" })
|
||||||
private static Object transformEnumValue(final ComparisonNode node, final String value,
|
private static Object transformEnumValue(final ComparisonNode node, final String value,
|
||||||
final Class<? extends Object> javaType) {
|
final Class<?> javaType) {
|
||||||
final Class<? extends Enum> tmpEnumType = (Class<? extends Enum>) javaType;
|
final Class<? extends Enum> tmpEnumType = (Class<? extends Enum>) javaType;
|
||||||
try {
|
try {
|
||||||
return Enum.valueOf(tmpEnumType, value.toUpperCase());
|
return Enum.valueOf(tmpEnumType, value.toUpperCase());
|
||||||
@@ -680,13 +680,10 @@ public final class RSQLUtility {
|
|||||||
final char escapeChar) {
|
final char escapeChar) {
|
||||||
final String escaped;
|
final String escaped;
|
||||||
|
|
||||||
switch (database) {
|
if (database == Database.SQL_SERVER) {
|
||||||
case SQL_SERVER:
|
|
||||||
escaped = transformedValue.replace("%", "[%]").replace("_", "[_]");
|
escaped = transformedValue.replace("%", "[%]").replace("_", "[_]");
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
escaped = transformedValue.replace("%", escapeChar + "%").replace("_", escapeChar + "_");
|
escaped = transformedValue.replace("%", escapeChar + "%").replace("_", escapeChar + "_");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return escaped.replace(LIKE_WILDCARD, '%');
|
return escaped.replace(LIKE_WILDCARD, '%');
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import javax.validation.ConstraintViolationException;
|
import javax.validation.ConstraintViolationException;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent;
|
||||||
@@ -38,6 +40,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|||||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||||
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
|
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
|
||||||
|
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -98,7 +101,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test if a local artifact can be created by API including metadata.")
|
@Description("Test if a local artifact can be created by API including metadata.")
|
||||||
public void createArtifact() throws NoSuchAlgorithmException, IOException {
|
public void createArtifact() throws IOException {
|
||||||
|
|
||||||
// check baseline
|
// check baseline
|
||||||
assertThat(softwareModuleRepository.findAll()).hasSize(0);
|
assertThat(softwareModuleRepository.findAll()).hasSize(0);
|
||||||
@@ -162,7 +165,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies that the quota specifying the maximum number of artifacts per software module is enforced.")
|
@Description("Verifies that the quota specifying the maximum number of artifacts per software module is enforced.")
|
||||||
public void createArtifactsUntilQuotaIsExceeded() throws NoSuchAlgorithmException, IOException {
|
public void createArtifactsUntilQuotaIsExceeded() throws IOException {
|
||||||
|
|
||||||
// create a software module
|
// create a software module
|
||||||
final long smId = softwareModuleRepository.save(new JpaSoftwareModule(osType, "sm1", "1.0", null, null))
|
final long smId = softwareModuleRepository.save(new JpaSoftwareModule(osType, "sm1", "1.0", null, null))
|
||||||
@@ -193,7 +196,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).")
|
@Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).")
|
||||||
public void createArtifactsUntilStorageQuotaIsExceeded() throws NoSuchAlgorithmException, IOException {
|
public void createArtifactsUntilStorageQuotaIsExceeded() throws IOException {
|
||||||
|
|
||||||
// create as many small artifacts as possible w/o violating the storage
|
// create as many small artifacts as possible w/o violating the storage
|
||||||
// quota
|
// quota
|
||||||
@@ -224,7 +227,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).")
|
@Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).")
|
||||||
public void createArtifactWhichExceedsMaxStorage() throws NoSuchAlgorithmException, IOException {
|
public void createArtifactWhichExceedsMaxStorage() throws IOException {
|
||||||
|
|
||||||
// create one artifact which exceeds the storage quota at once
|
// create one artifact which exceeds the storage quota at once
|
||||||
final long maxBytes = quotaManagement.getMaxArtifactStorage();
|
final long maxBytes = quotaManagement.getMaxArtifactStorage();
|
||||||
@@ -236,7 +239,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies that you cannot create artifacts which exceed the configured maximum size.")
|
@Description("Verifies that you cannot create artifacts which exceed the configured maximum size.")
|
||||||
public void createArtifactFailsIfTooLarge() throws NoSuchAlgorithmException, IOException {
|
public void createArtifactFailsIfTooLarge() {
|
||||||
|
|
||||||
// create a software module
|
// create a software module
|
||||||
final JpaSoftwareModule sm1 = softwareModuleRepository
|
final JpaSoftwareModule sm1 = softwareModuleRepository
|
||||||
@@ -250,7 +253,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests hard delete directly on repository.")
|
@Description("Tests hard delete directly on repository.")
|
||||||
public void hardDeleteSoftwareModule() throws NoSuchAlgorithmException, IOException {
|
public void hardDeleteSoftwareModule() throws IOException {
|
||||||
|
|
||||||
final JpaSoftwareModule sm = softwareModuleRepository
|
final JpaSoftwareModule sm = softwareModuleRepository
|
||||||
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
||||||
@@ -268,12 +271,10 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
* .
|
* .
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws NoSuchAlgorithmException
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the deletion of a local artifact including metadata.")
|
@Description("Tests the deletion of a local artifact including metadata.")
|
||||||
public void deleteArtifact() throws NoSuchAlgorithmException, IOException {
|
public void deleteArtifact() throws IOException {
|
||||||
|
|
||||||
final JpaSoftwareModule sm = softwareModuleRepository
|
final JpaSoftwareModule sm = softwareModuleRepository
|
||||||
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
||||||
final JpaSoftwareModule sm2 = softwareModuleRepository
|
final JpaSoftwareModule sm2 = softwareModuleRepository
|
||||||
@@ -304,6 +305,8 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
artifactManagement.delete(artifact1.getId());
|
artifactManagement.delete(artifact1.getId());
|
||||||
|
|
||||||
|
assertThat(artifactRepository.findAll()).hasSize(1);
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
||||||
.isNull();
|
.isNull();
|
||||||
@@ -323,7 +326,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Test the deletion of an artifact metadata where the binary is still linked to another "
|
@Description("Test the deletion of an artifact metadata where the binary is still linked to another "
|
||||||
+ "metadata element. The expected result is that the metadata is deleted but the binary kept.")
|
+ "metadata element. The expected result is that the metadata is deleted but the binary kept.")
|
||||||
public void deleteDuplicateArtifacts() throws NoSuchAlgorithmException, IOException {
|
public void deleteDuplicateArtifacts() throws IOException {
|
||||||
|
|
||||||
final JpaSoftwareModule sm = softwareModuleRepository
|
final JpaSoftwareModule sm = softwareModuleRepository
|
||||||
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
||||||
@@ -347,21 +350,92 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(
|
assertThat(
|
||||||
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
||||||
.isNotNull();
|
.isNotNull();
|
||||||
|
|
||||||
artifactManagement.delete(artifact1.getId());
|
artifactManagement.delete(artifact1.getId());
|
||||||
assertThat(
|
assertThat(
|
||||||
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
||||||
.isNotNull();
|
.isNotNull();
|
||||||
|
assertThat(artifactRepository.findAll()).hasSize(1);
|
||||||
|
assertThat(artifactRepository.existsById(artifact1.getId())).isFalse();
|
||||||
|
|
||||||
artifactManagement.delete(artifact2.getId());
|
artifactManagement.delete(artifact2.getId());
|
||||||
assertThat(
|
assertThat(
|
||||||
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash()))
|
||||||
.isNull();
|
.isNull();
|
||||||
|
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that you cannot delete an artifact which exists with the same hash, in the same tenant and the SoftwareModule is not deleted .")
|
||||||
|
public void deleteArtifactWithSameHashAndSoftwareModuleIsNotDeletedInSameTenants() throws IOException {
|
||||||
|
|
||||||
|
final JpaSoftwareModule sm = softwareModuleRepository
|
||||||
|
.save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null));
|
||||||
|
final JpaSoftwareModule sm2 = softwareModuleRepository
|
||||||
|
.save(new JpaSoftwareModule(osType, "name 2", "version 2", null, null));
|
||||||
|
|
||||||
|
final int artifactSize = 5 * 1024;
|
||||||
|
final byte[] randomBytes = randomBytes(artifactSize);
|
||||||
|
|
||||||
|
try (final InputStream inputStream1 = new ByteArrayInputStream(randomBytes);
|
||||||
|
final InputStream inputStream2 = new ByteArrayInputStream(randomBytes)) {
|
||||||
|
|
||||||
|
final Artifact artifact1 = createArtifactForSoftwareModule("file1", sm.getId(), artifactSize, inputStream1);
|
||||||
|
final Artifact artifact2 = createArtifactForSoftwareModule("file2", sm2.getId(), artifactSize,
|
||||||
|
inputStream2);
|
||||||
|
|
||||||
|
assertEqualFileContents(artifactManagement.loadArtifactBinary(artifact2.getSha1Hash()), randomBytes);
|
||||||
|
|
||||||
|
assertThat(artifactRepository.findAll()).hasSize(2);
|
||||||
|
|
||||||
|
assertThat(artifact1.getSha1Hash()).isEqualTo(artifact2.getSha1Hash());
|
||||||
|
|
||||||
|
assertThat(artifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(
|
||||||
|
artifact1.getSha1Hash(), artifact1.getTenant())).isGreaterThan(1);
|
||||||
|
|
||||||
|
artifactRepository.deleteById(artifact1.getId());
|
||||||
|
assertThat(artifactRepository.findAll()).hasSize(1);
|
||||||
|
|
||||||
|
assertThat(artifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(
|
||||||
|
artifact2.getSha1Hash(), artifact2.getTenant())).isLessThanOrEqualTo(1);
|
||||||
|
|
||||||
|
artifactRepository.deleteById(artifact2.getId());
|
||||||
|
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that you can not delete artifacts from another tenant which exists in another tenant with the same hash and the SoftwareModule is not deleted")
|
||||||
|
public void deleteArtifactWithSameHashAndSoftwareModuleIsNotDeletedInDifferentTenants() throws Exception {
|
||||||
|
final String tenant1 = "mytenant";
|
||||||
|
final String tenant2 = "tenant2";
|
||||||
|
|
||||||
|
final SoftwareModule module = createSoftwareModuleForTenant(tenant1);
|
||||||
|
final SoftwareModule module2 = createSoftwareModuleForTenant(tenant2);
|
||||||
|
|
||||||
|
createArtifactForTenant(tenant1, "myInput", module.getId(), "myFirstFile");
|
||||||
|
createArtifactForTenant(tenant2, "myInput", module2.getId(), "mySecondFile");
|
||||||
|
final Artifact artifactTenant2 = createArtifactForTenant(tenant2, "myInput", module2.getId(), "myThirdFile");
|
||||||
|
|
||||||
|
verifyTenantArtifactCountIs(tenant1, 1);
|
||||||
|
verifyTenantArtifactCountIs(tenant2, 2);
|
||||||
|
|
||||||
|
assertThat(runAsTenant(tenant1, () -> artifactRepository
|
||||||
|
.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(artifactTenant2.getSha1Hash(), tenant2)))
|
||||||
|
.isLessThanOrEqualTo(1);
|
||||||
|
runAsTenant(tenant2, () -> {
|
||||||
|
artifactRepository.deleteById(artifactTenant2.getId());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
verifyTenantArtifactCountIs(tenant1, 1);
|
||||||
|
verifyTenantArtifactCountIs(tenant2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Loads an local artifact based on given ID.")
|
@Description("Loads an local artifact based on given ID.")
|
||||||
public void findArtifact() throws NoSuchAlgorithmException, IOException {
|
public void findArtifact() throws IOException {
|
||||||
final int artifactSize = 5 * 1024;
|
final int artifactSize = 5 * 1024;
|
||||||
try (final InputStream inputStream = new RandomGeneratedInputStream(artifactSize)) {
|
try (final InputStream inputStream = new RandomGeneratedInputStream(artifactSize)) {
|
||||||
final Artifact artifact = createArtifactForSoftwareModule("file1",
|
final Artifact artifact = createArtifactForSoftwareModule("file1",
|
||||||
@@ -372,17 +446,13 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Loads an artifact binary based on given ID.")
|
@Description("Loads an artifact binary based on given ID.")
|
||||||
public void loadStreamOfArtifact() throws NoSuchAlgorithmException, IOException {
|
public void loadStreamOfArtifact() throws IOException {
|
||||||
final int artifactSize = 5 * 1024;
|
final int artifactSize = 5 * 1024;
|
||||||
final byte[] randomBytes = randomBytes(artifactSize);
|
final byte[] randomBytes = randomBytes(artifactSize);
|
||||||
try (final InputStream input = new ByteArrayInputStream(randomBytes)) {
|
try (final InputStream input = new ByteArrayInputStream(randomBytes)) {
|
||||||
final Artifact artifact = createArtifactForSoftwareModule("file1",
|
final Artifact artifact = createArtifactForSoftwareModule("file1",
|
||||||
testdataFactory.createSoftwareModuleOs().getId(), artifactSize, input);
|
testdataFactory.createSoftwareModuleOs().getId(), artifactSize, input);
|
||||||
try (final InputStream inputStream = artifactManagement.loadArtifactBinary(artifact.getSha1Hash()).get()
|
assertEqualFileContents(artifactManagement.loadArtifactBinary(artifact.getSha1Hash()), randomBytes);
|
||||||
.getFileInputStream()) {
|
|
||||||
assertTrue("The stored binary matches the given binary",
|
|
||||||
IOUtils.contentEquals(new ByteArrayInputStream(randomBytes), inputStream));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +495,6 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
createArtifactForSoftwareModule("file2", sm.getId(), artifactSize, inputStream2);
|
createArtifactForSoftwareModule("file2", sm.getId(), artifactSize, inputStream2);
|
||||||
assertThat(artifactManagement.getByFilenameAndSoftwareModule("file1", sm.getId())).isPresent();
|
assertThat(artifactManagement.getByFilenameAndSoftwareModule("file1", sm.getId())).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Artifact createArtifactForSoftwareModule(final String filename, final long moduleId, final int artifactSize)
|
private Artifact createArtifactForSoftwareModule(final String filename, final long moduleId, final int artifactSize)
|
||||||
@@ -437,11 +506,38 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Artifact createArtifactForSoftwareModule(final String filename, final long moduleId, final int artifactSize,
|
private Artifact createArtifactForSoftwareModule(final String filename, final long moduleId, final int artifactSize,
|
||||||
final InputStream inputStream) throws IOException {
|
final InputStream inputStream) {
|
||||||
return artifactManagement.create(new ArtifactUpload(inputStream, moduleId, filename, false, artifactSize));
|
return artifactManagement.create(new ArtifactUpload(inputStream, moduleId, filename, false, artifactSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] randomBytes(final int len) {
|
private static byte[] randomBytes(final int len) {
|
||||||
return RandomStringUtils.randomAlphanumeric(len).getBytes();
|
return RandomStringUtils.randomAlphanumeric(len).getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T runAsTenant(final String tenant, final Callable<T> callable) throws Exception {
|
||||||
|
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SoftwareModule createSoftwareModuleForTenant(final String tenant) throws Exception {
|
||||||
|
return runAsTenant(tenant, () -> testdataFactory.createSoftwareModuleApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Artifact createArtifactForTenant(final String tenant, final String artifactData, final long moduleId,
|
||||||
|
final String filename) throws Exception {
|
||||||
|
return runAsTenant(tenant, () -> testdataFactory.createArtifact(artifactData, moduleId, filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyTenantArtifactCountIs(final String tenant, final int count) throws Exception {
|
||||||
|
assertThat(runAsTenant(tenant, () -> artifactRepository.findAll())).hasSize(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEqualFileContents(final Optional<AbstractDbArtifact> artifact, final byte[] randomBytes)
|
||||||
|
throws IOException {
|
||||||
|
try (final InputStream inputStream = artifactManagement.loadArtifactBinary(artifact.get().getHashes().getSha1())
|
||||||
|
.get().getFileInputStream()) {
|
||||||
|
assertTrue("The stored binary matches the given binary",
|
||||||
|
IOUtils.contentEquals(new ByteArrayInputStream(randomBytes), inputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import static org.assertj.core.api.Assertions.fail;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
@@ -59,7 +60,6 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(findTargetsForAnotherTenant).hasSize(1);
|
assertThat(findTargetsForAnotherTenant).hasSize(1);
|
||||||
assertThat(findTargetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase())
|
assertThat(findTargetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase())
|
||||||
.isEqualTo(anotherTenant.toUpperCase());
|
.isEqualTo(anotherTenant.toUpperCase());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -163,34 +163,32 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(findDistributionSetsForAnotherTenant).hasSize(1);
|
assertThat(findDistributionSetsForAnotherTenant).hasSize(1);
|
||||||
assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase())
|
assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase())
|
||||||
.isEqualTo(anotherTenant.toUpperCase());
|
.isEqualTo(anotherTenant.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T runAsTenant(final String tenant, final Callable<T> callable) throws Exception {
|
||||||
|
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Target createTargetForTenant(final String controllerId, final String tenant) throws Exception {
|
private Target createTargetForTenant(final String controllerId, final String tenant) throws Exception {
|
||||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
return runAsTenant(tenant, () -> testdataFactory.createTarget(controllerId));
|
||||||
() -> testdataFactory.createTarget(controllerId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Slice<Target> findTargetsForTenant(final String tenant) throws Exception {
|
private Slice<Target> findTargetsForTenant(final String tenant) throws Exception {
|
||||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
return runAsTenant(tenant, () -> targetManagement.findAll(PAGE));
|
||||||
() -> targetManagement.findAll(PAGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteTargetsForTenant(final String tenant, final Collection<Long> targetIds) throws Exception {
|
private void deleteTargetsForTenant(final String tenant, final Collection<Long> targetIds) throws Exception {
|
||||||
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), () -> {
|
runAsTenant(tenant, () -> {
|
||||||
targetManagement.delete(targetIds);
|
targetManagement.delete(targetIds);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private DistributionSet createDistributionSetForTenant(final String tenant) throws Exception {
|
private DistributionSet createDistributionSetForTenant(final String tenant) throws Exception {
|
||||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
return runAsTenant(tenant, () -> testdataFactory.createDistributionSet());
|
||||||
() -> testdataFactory.createDistributionSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Page<DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
|
private Page<DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
|
||||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(PAGE, true));
|
||||||
() -> distributionSetManagement.findByCompleted(PAGE, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -465,15 +465,33 @@ public class TestdataFactory {
|
|||||||
final List<Artifact> artifacts = new ArrayList<>();
|
final List<Artifact> artifacts = new ArrayList<>();
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
final String artifactData = "some test data" + i;
|
final String artifactData = "some test data" + i;
|
||||||
final InputStream stubInputStream = IOUtils.toInputStream(artifactData, Charset.forName("UTF-8"));
|
artifacts.add(createArtifact(artifactData, moduleId, "filename" + i));
|
||||||
artifacts.add(artifactManagement.create(
|
|
||||||
new ArtifactUpload(stubInputStream, moduleId, "filename" + i, false, artifactData.length())));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return artifacts;
|
return artifacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an {@link Artifact} for given {@link SoftwareModule} with a small
|
||||||
|
* text payload.
|
||||||
|
*
|
||||||
|
* @param artifactData
|
||||||
|
* the {@link Artifact} Inputstream
|
||||||
|
*
|
||||||
|
* @param moduleId
|
||||||
|
* the {@link Artifact} belongs to
|
||||||
|
*
|
||||||
|
* @param filename
|
||||||
|
* that was provided during upload.
|
||||||
|
*
|
||||||
|
* @return {@link Artifact} entity.
|
||||||
|
*/
|
||||||
|
public Artifact createArtifact(final String artifactData, final Long moduleId, final String filename) {
|
||||||
|
final InputStream stubInputStream = IOUtils.toInputStream(artifactData, Charset.forName("UTF-8"));
|
||||||
|
return artifactManagement
|
||||||
|
.create(new ArtifactUpload(stubInputStream, moduleId, filename, false, artifactData.length()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates {@link SoftwareModule} with {@link #DEFAULT_VENDOR} and
|
* Creates {@link SoftwareModule} with {@link #DEFAULT_VENDOR} and
|
||||||
* {@link #DEFAULT_VERSION} and random generated
|
* {@link #DEFAULT_VERSION} and random generated
|
||||||
|
|||||||
@@ -65,6 +65,6 @@ public class MgmtRolloutCondition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum Condition {
|
public enum Condition {
|
||||||
THRESHOLD;
|
THRESHOLD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,6 @@ public class MgmtRolloutErrorAction {
|
|||||||
* Possible actions
|
* Possible actions
|
||||||
*/
|
*/
|
||||||
public enum ErrorAction {
|
public enum ErrorAction {
|
||||||
PAUSE;
|
PAUSE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,6 @@ public class MgmtRolloutSuccessAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum SuccessAction {
|
public enum SuccessAction {
|
||||||
NEXTGROUP;
|
NEXTGROUP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class SecurityContextTenantAware implements TenantAware {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAuthenticated() {
|
public boolean isAuthenticated() {
|
||||||
return (delegate != null) ? delegate.isAuthenticated() : true;
|
return delegate == null || delegate.isAuthenticated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -95,10 +95,7 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
|
|||||||
}
|
}
|
||||||
final Optional<Target> foundTarget = systemSecurityContext.runAsSystemAsTenant(
|
final Optional<Target> foundTarget = systemSecurityContext.runAsSystemAsTenant(
|
||||||
() -> controllerManagement.get(securityToken.getTargetId()), securityToken.getTenant());
|
() -> controllerManagement.get(securityToken.getTargetId()), securityToken.getTenant());
|
||||||
if (!foundTarget.isPresent()) {
|
return foundTarget.map(Target::getControllerId).orElse(null);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return foundTarget.get().getControllerId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -249,10 +249,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
|||||||
@Override
|
@Override
|
||||||
protected String getDeletedEntityName(final Long entityId) {
|
protected String getDeletedEntityName(final Long entityId) {
|
||||||
final Optional<SoftwareModule> softwareModule = softwareModuleManagement.get(entityId);
|
final Optional<SoftwareModule> softwareModule = softwareModuleManagement.get(entityId);
|
||||||
if (softwareModule.isPresent()) {
|
return softwareModule.map(module -> module.getName() + ":" + module.getVersion()).orElse("");
|
||||||
return softwareModule.get().getName() + ":" + softwareModule.get().getVersion();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.common.detailslayout;
|
package org.eclipse.hawkbit.ui.common.detailslayout;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
|
||||||
import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout;
|
import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout;
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
@@ -64,11 +61,9 @@ public class DistributionSetMetadataDetailsLayout extends AbstractMetadataDetail
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedDistSetId = distributionSet.getId();
|
selectedDistSetId = distributionSet.getId();
|
||||||
final List<DistributionSetMetadata> dsMetadataList = distributionSetManagement
|
final PageRequest pageRequest = PageRequest.of(0, MAX_METADATA_QUERY);
|
||||||
.findMetaDataByDistributionSetId(PageRequest.of(0, MAX_METADATA_QUERY), selectedDistSetId).getContent();
|
distributionSetManagement.findMetaDataByDistributionSetId(pageRequest, selectedDistSetId).getContent()
|
||||||
if (!dsMetadataList.isEmpty()) {
|
.forEach(this::setMetadataProperties);
|
||||||
dsMetadataList.forEach(this::setMetadataProperties);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,11 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.common.detailslayout;
|
package org.eclipse.hawkbit.ui.common.detailslayout;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
|
||||||
import org.eclipse.hawkbit.ui.management.targettable.TargetMetadataPopupLayout;
|
import org.eclipse.hawkbit.ui.management.targettable.TargetMetadataPopupLayout;
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
@@ -63,12 +60,8 @@ public class TargetMetadataDetailsLayout extends AbstractMetadataDetailsLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedTargetId = target.getId();
|
selectedTargetId = target.getId();
|
||||||
final List<TargetMetadata> targetMetadataList = targetManagement
|
targetManagement.findMetaDataByControllerId(PageRequest.of(0, MAX_METADATA_QUERY), target.getControllerId())
|
||||||
.findMetaDataByControllerId(PageRequest.of(0, MAX_METADATA_QUERY), target.getControllerId())
|
.getContent().forEach(this::setMetadataProperties);
|
||||||
.getContent();
|
|
||||||
if (!targetMetadataList.isEmpty()) {
|
|
||||||
targetMetadataList.forEach(this::setMetadataProperties);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ package org.eclipse.hawkbit.ui.common.table;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public enum BaseEntityEventType {
|
public enum BaseEntityEventType {
|
||||||
ADD_ENTITY, REMOVE_ENTITY, UPDATED_ENTITY, SELECTED_ENTITY, MAXIMIZED, MINIMIZED;
|
ADD_ENTITY, REMOVE_ENTITY, UPDATED_ENTITY, SELECTED_ENTITY, MAXIMIZED, MINIMIZED
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,10 +338,7 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule> {
|
|||||||
@Override
|
@Override
|
||||||
protected String getDeletedEntityName(final Long entityId) {
|
protected String getDeletedEntityName(final Long entityId) {
|
||||||
final Optional<SoftwareModule> softwareModule = softwareModuleManagement.get(entityId);
|
final Optional<SoftwareModule> softwareModule = softwareModuleManagement.get(entityId);
|
||||||
if (softwareModule.isPresent()) {
|
return softwareModule.map(module -> module.getName() + ":" + module.getVersion()).orElse("");
|
||||||
return softwareModule.get().getName() + ":" + softwareModule.get().getVersion();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,11 +200,9 @@ public class MaintenanceWindowLayout extends VerticalLayout {
|
|||||||
* Get list of all time zone offsets supported.
|
* Get list of all time zone offsets supported.
|
||||||
*/
|
*/
|
||||||
private static List<String> getAllTimeZones() {
|
private static List<String> getAllTimeZones() {
|
||||||
final List<String> lst = ZoneId.getAvailableZoneIds().stream()
|
return ZoneId.getAvailableZoneIds().stream()
|
||||||
.map(id -> ZonedDateTime.now(ZoneId.of(id)).getOffset().getId().replace("Z", "+00:00")).distinct()
|
.map(id -> ZonedDateTime.now(ZoneId.of(id)).getOffset().getId().replace("Z", "+00:00"))
|
||||||
.collect(Collectors.toList());
|
.distinct().sorted().collect(Collectors.toList());
|
||||||
lst.sort(null);
|
|
||||||
return lst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -337,14 +337,9 @@ public final class DashboardMenu extends CustomComponent {
|
|||||||
* with given viewname does not exists
|
* with given viewname does not exists
|
||||||
*/
|
*/
|
||||||
public DashboardMenuItem getByViewName(final String viewName) {
|
public DashboardMenuItem getByViewName(final String viewName) {
|
||||||
final Optional<DashboardMenuItem> findFirst = dashboardVaadinViews.stream()
|
|
||||||
.filter(view -> view.getViewName().equals(viewName)).findAny();
|
|
||||||
|
|
||||||
if (!findFirst.isPresent()) {
|
return dashboardVaadinViews.stream()
|
||||||
return null;
|
.filter(view -> view.getViewName().equals(viewName)).findAny().orElse(null);
|
||||||
}
|
|
||||||
|
|
||||||
return findFirst.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -355,14 +350,8 @@ public final class DashboardMenu extends CustomComponent {
|
|||||||
* @return <code>true</code> = denied, <code>false</code> = accessible
|
* @return <code>true</code> = denied, <code>false</code> = accessible
|
||||||
*/
|
*/
|
||||||
public boolean isAccessDenied(final String viewName) {
|
public boolean isAccessDenied(final String viewName) {
|
||||||
final List<DashboardMenuItem> accessibleViews = getAccessibleViews();
|
return getAccessibleViews().stream()
|
||||||
boolean accessDeined = Boolean.TRUE.booleanValue();
|
.noneMatch(dashboardMenuItem -> dashboardMenuItem.getViewName().equals(viewName));
|
||||||
for (final DashboardMenuItem dashboardViewType : accessibleViews) {
|
|
||||||
if (dashboardViewType.getViewName().equals(viewName)) {
|
|
||||||
accessDeined = Boolean.FALSE.booleanValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return accessDeined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MenuToggleClickListenerMyClickListener implements ClickListener {
|
private class MenuToggleClickListenerMyClickListener implements ClickListener {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public class AutoStartOptionGroupLayout extends HorizontalLayout {
|
|||||||
* Rollout start options
|
* Rollout start options
|
||||||
*/
|
*/
|
||||||
enum AutoStartOption {
|
enum AutoStartOption {
|
||||||
MANUAL, AUTO_START, SCHEDULED;
|
MANUAL, AUTO_START, SCHEDULED
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user