Feature/fix sonar warnings (#1226)
* Fixed sonar warnings - "Cognitive Complexity" - "Do not use replaceAll when not using a regex" - java:S5869 - Character classes in regular expressions should not contain the same character twice - Improved bad name - Typos - reduced code duplications - Replaced hand-made wait-utility with Awaitility - Log messages - Duplicate code - Typos - Removed Thread.sleep, instead relaxed check condition - Removed use of deprecated API - Removed use of deprecated API - Added supress-warnings as I do not see a better way to write the tests - Removed Thread.sleep / redundant functionality to Awaitility - Fixed other warnings (use isZero, isEmpty, hasToString) - Removed/Reduced duplicate code - Added generics - Fixed asserts - removed: field.setAccessible(true) actually should not be needed for public static fields! - Too long constructor passes arguments in wrong order - how surprisingly... - Clean-up use of varargs arguments - Fixed regex - Fixed typos and other minor stuff - Making public constructors protected in abstract classes - Swapped expected and asserted argument - volatile not enough for syncing threads - volatile not enough for syncing threads - out-commented code - Made regex not-greedy, added tests for verification - Avoid exposure of thread-local member var Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixed Sonar warnings * License header fix Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * License header fix #2 Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixing review findings Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixing tests - Fixed '&' usage in javadoc and typos - Fixing some warnings Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io>
This commit is contained in:
@@ -109,7 +109,7 @@ Please make sure newly created files contain a proper license header like this:
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.artifact.repository;
|
||||
|
||||
/**
|
||||
* Exception thrown in case that the artifact could not be read.
|
||||
*/
|
||||
public class ArtifactFileNotFoundException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Creates the Exception from it's cause
|
||||
* @param cause the original exception
|
||||
*/
|
||||
public ArtifactFileNotFoundException(final Exception cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,12 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
/**
|
||||
* {@link AbstractDbArtifact} implementation which dynamically creates a
|
||||
@@ -28,11 +28,11 @@ public class ArtifactFilesystem extends AbstractDbArtifact {
|
||||
|
||||
private final File file;
|
||||
|
||||
public ArtifactFilesystem(final File file, final String artifactId, final DbArtifactHash hashes, final Long size,
|
||||
public ArtifactFilesystem(@NotNull final File file, @NotNull final String artifactId,
|
||||
@NotNull final DbArtifactHash hashes, final Long size,
|
||||
final String contentType) {
|
||||
super(artifactId, hashes, size, contentType);
|
||||
Assert.notNull(file, "File cannot be null");
|
||||
this.file = file;
|
||||
this.file = Objects.requireNonNull(file, "Artifact file may not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,7 +43,7 @@ public class ArtifactFilesystem extends AbstractDbArtifact {
|
||||
try {
|
||||
return new BufferedInputStream(new FileInputStream(file));
|
||||
} catch (final FileNotFoundException e) {
|
||||
throw Throwables.propagate(e);
|
||||
throw new ArtifactFileNotFoundException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
/**
|
||||
* Auto configuration for {@link HostnameResolver} and
|
||||
* {@link ArtifactUrlHandler} based on a properties.
|
||||
@@ -46,7 +44,7 @@ public class PropertyHostnameResolverAutoConfiguration {
|
||||
try {
|
||||
return new URL(serverProperties.getUrl());
|
||||
} catch (final MalformedURLException e) {
|
||||
throw Throwables.propagate(e);
|
||||
throw new IllegalArgumentException("URL not valid: " + serverProperties.getUrl(), e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Container for variables available to the {@link ArtifactUrlHandler}.
|
||||
*
|
||||
@@ -107,59 +109,22 @@ public class URLPlaceholder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((artifactId == null) ? 0 : artifactId.hashCode());
|
||||
result = prime * result + ((filename == null) ? 0 : filename.hashCode());
|
||||
result = prime * result + ((sha1Hash == null) ? 0 : sha1Hash.hashCode());
|
||||
result = prime * result + ((softwareModuleId == null) ? 0 : softwareModuleId.hashCode());
|
||||
return result;
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
final SoftwareData that = (SoftwareData) o;
|
||||
return Objects.equals(softwareModuleId, that.softwareModuleId)
|
||||
&& Objects.equals(filename, that.filename)
|
||||
&& Objects.equals(artifactId, that.artifactId)
|
||||
&& Objects.equals(sha1Hash, that.sha1Hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
public int hashCode() {
|
||||
return Objects.hash(softwareModuleId, filename, artifactId, sha1Hash);
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final SoftwareData other = (SoftwareData) obj;
|
||||
if (artifactId == null) {
|
||||
if (other.artifactId != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!artifactId.equals(other.artifactId)) {
|
||||
return false;
|
||||
}
|
||||
if (filename == null) {
|
||||
if (other.filename != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!filename.equals(other.filename)) {
|
||||
return false;
|
||||
}
|
||||
if (sha1Hash == null) {
|
||||
if (other.sha1Hash != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!sha1Hash.equals(other.sha1Hash)) {
|
||||
return false;
|
||||
}
|
||||
if (softwareModuleId == null) {
|
||||
if (other.softwareModuleId != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!softwareModuleId.equals(other.softwareModuleId)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getTenant() {
|
||||
@@ -183,65 +148,18 @@ public class URLPlaceholder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((controllerId == null) ? 0 : controllerId.hashCode());
|
||||
result = prime * result + ((softwareData == null) ? 0 : softwareData.hashCode());
|
||||
result = prime * result + ((targetId == null) ? 0 : targetId.hashCode());
|
||||
result = prime * result + ((tenant == null) ? 0 : tenant.hashCode());
|
||||
result = prime * result + ((tenantId == null) ? 0 : tenantId.hashCode());
|
||||
return result;
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
final URLPlaceholder that = (URLPlaceholder) o;
|
||||
return tenantId.equals(that.tenantId) && Objects.equals(controllerId, that.controllerId) && Objects.equals(
|
||||
targetId, that.targetId) && Objects.equals(softwareData, that.softwareData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
public int hashCode() {
|
||||
return Objects.hash(tenantId, controllerId, targetId, softwareData);
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final URLPlaceholder other = (URLPlaceholder) obj;
|
||||
if (controllerId == null) {
|
||||
if (other.controllerId != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!controllerId.equals(other.controllerId)) {
|
||||
return false;
|
||||
}
|
||||
if (softwareData == null) {
|
||||
if (other.softwareData != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!softwareData.equals(other.softwareData)) {
|
||||
return false;
|
||||
}
|
||||
if (targetId == null) {
|
||||
if (other.targetId != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!targetId.equals(other.targetId)) {
|
||||
return false;
|
||||
}
|
||||
if (tenant == null) {
|
||||
if (other.tenant != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!tenant.equals(other.tenant)) {
|
||||
return false;
|
||||
}
|
||||
if (tenantId == null) {
|
||||
if (other.tenantId != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!tenantId.equals(other.tenantId)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -98,25 +99,23 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
|
||||
protected void deleteTempFile(final String tempFile) {
|
||||
final File file = new File(tempFile);
|
||||
|
||||
if (file.exists() && !file.delete()) {
|
||||
LOG.error("Could not delete temp file {}", file);
|
||||
try {
|
||||
Files.deleteIfExists(file.toPath());
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not delete temp file {} ({})", file, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected String storeTempFile(final InputStream content) throws IOException {
|
||||
final File file = createTempFile();
|
||||
|
||||
try (final OutputStream outputstream = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
ByteStreams.copy(content, outputstream);
|
||||
outputstream.flush();
|
||||
}
|
||||
|
||||
return file.getPath();
|
||||
}
|
||||
|
||||
private static File createTempFile() {
|
||||
|
||||
try {
|
||||
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
|
||||
} catch (final IOException e) {
|
||||
@@ -160,5 +159,4 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
protected static String sanitizeTenant(final String tenant) {
|
||||
return tenant.trim().toUpperCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.cache;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.Cache.ValueWrapper;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -27,7 +28,6 @@ public class DefaultDownloadIdCache implements DownloadIdCache {
|
||||
* @param cacheManager
|
||||
* the underlying cache-manager to store the download-ids
|
||||
*/
|
||||
@Autowired
|
||||
public DefaultDownloadIdCache(final CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
@@ -49,9 +49,9 @@ public class DefaultDownloadIdCache implements DownloadIdCache {
|
||||
}
|
||||
|
||||
private Cache getCache() {
|
||||
if (cacheManager instanceof TenancyCacheManager) {
|
||||
return ((TenancyCacheManager) cacheManager).getDirectCache(DOWNLOAD_ID_CACHE);
|
||||
}
|
||||
return cacheManager.getCache(DOWNLOAD_ID_CACHE);
|
||||
final Cache cache = (cacheManager instanceof TenancyCacheManager)
|
||||
? ((TenancyCacheManager) cacheManager).getDirectCache(DOWNLOAD_ID_CACHE)
|
||||
: cacheManager.getCache(DOWNLOAD_ID_CACHE);
|
||||
return Objects.requireNonNull(cache, "Cache(s) returned by cache-manager must not be null!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public abstract class AbstractServerRtException extends RuntimeException {
|
||||
* @param error
|
||||
* detail
|
||||
*/
|
||||
public AbstractServerRtException(final SpServerError error) {
|
||||
protected AbstractServerRtException(final SpServerError error) {
|
||||
super(error.getMessage());
|
||||
this.error = error;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public abstract class AbstractServerRtException extends RuntimeException {
|
||||
* @param error
|
||||
* detail
|
||||
*/
|
||||
public AbstractServerRtException(final String message, final SpServerError error) {
|
||||
protected AbstractServerRtException(final String message, final SpServerError error) {
|
||||
super(message);
|
||||
this.error = error;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public abstract class AbstractServerRtException extends RuntimeException {
|
||||
* @param cause
|
||||
* of the exception
|
||||
*/
|
||||
public AbstractServerRtException(final String message, final SpServerError error, final Throwable cause) {
|
||||
protected AbstractServerRtException(final String message, final SpServerError error, final Throwable cause) {
|
||||
super(message, cause);
|
||||
this.error = error;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public abstract class AbstractServerRtException extends RuntimeException {
|
||||
* @param cause
|
||||
* of the exception
|
||||
*/
|
||||
public AbstractServerRtException(final SpServerError error, final Throwable cause) {
|
||||
protected AbstractServerRtException(final SpServerError error, final Throwable cause) {
|
||||
super(error.getMessage(), cause);
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Unit Tests - Artifact URL Handler")
|
||||
@Story("Base62 Utility tests")
|
||||
public class Base62UtilTest {
|
||||
class Base62UtilTest {
|
||||
|
||||
@Test
|
||||
@Description("Convert Base10 numbres to Base62 ASCII strings.")
|
||||
public void fromBase10() {
|
||||
void fromBase10() {
|
||||
assertThat(Base62Util.fromBase10(0L)).isEqualTo("0");
|
||||
assertThat(Base62Util.fromBase10(11L)).isEqualTo("B");
|
||||
assertThat(Base62Util.fromBase10(36L)).isEqualTo("a");
|
||||
@@ -31,8 +31,8 @@ public class Base62UtilTest {
|
||||
|
||||
@Test
|
||||
@Description("Convert Base62 ASCII strings to Base10 numbers.")
|
||||
public void toBase10() {
|
||||
assertThat(Base62Util.toBase10("0")).isEqualTo(0L);
|
||||
void toBase10() {
|
||||
assertThat(Base62Util.toBase10("0")).isZero();
|
||||
assertThat(Base62Util.toBase10("B")).isEqualTo(11);
|
||||
assertThat(Base62Util.toBase10("a")).isEqualTo(36L);
|
||||
assertThat(Base62Util.toBase10("G7")).isEqualTo(999L);
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.api;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Unit Tests - Artifact URL Handler")
|
||||
@Story("URL placeholder tests")
|
||||
class URLPlaceholderTest {
|
||||
|
||||
private final URLPlaceholder.SoftwareData softwareData;
|
||||
private final URLPlaceholder placeholder;
|
||||
|
||||
public URLPlaceholderTest() {
|
||||
this.softwareData = new URLPlaceholder.SoftwareData(1L, "file.txt", 123L, "someHash123");
|
||||
this.placeholder = new URLPlaceholder("SuperCorp", 123L, "Super-1", 1L, softwareData);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Same object should be equal")
|
||||
// Exception squid:S5785 - JUnit assertTrue/assertFalse should be simplified to
|
||||
// the corresponding dedicated assertion
|
||||
// Need to test the equals method and need to bypass magic logic in utility
|
||||
// classes
|
||||
@SuppressWarnings({ "squid:S5838" })
|
||||
void sameObjectShouldBeEqual() {
|
||||
assertThat(softwareData.equals(softwareData)).isTrue();
|
||||
assertThat(placeholder.equals(placeholder)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Different object should not be equal")
|
||||
@SuppressWarnings({ "squid:S5838" })
|
||||
void differentObjectShouldNotBeEqual() {
|
||||
final URLPlaceholder.SoftwareData softwareData2 = new URLPlaceholder.SoftwareData(2L, "file.txt", 123L, "someHash123");
|
||||
final URLPlaceholder placeholder2 = new URLPlaceholder("SuperCorp", 123L, "Super-2", 2L, softwareData2);
|
||||
final URLPlaceholder placeholderWithOtherSoftwareData = new URLPlaceholder(placeholder.getTenant(),
|
||||
placeholder.getTenantId(), placeholder.getControllerId(), placeholder.getTargetId(), softwareData2);
|
||||
assertThat(placeholder.equals(placeholder2)).isFalse();
|
||||
assertThat(placeholder2.equals(placeholder)).isFalse();
|
||||
assertThat(softwareData.equals(softwareData2)).isFalse();
|
||||
assertThat(softwareData2.equals(softwareData)).isFalse();
|
||||
assertThat(placeholder.equals(placeholderWithOtherSoftwareData)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Different objects with same properties should be equal")
|
||||
void differentObjectsWithSamePropertiesShouldBeEqual() {
|
||||
final URLPlaceholder placeholderWithSameProperties = new URLPlaceholder(placeholder.getTenant(), placeholder.getTenantId(),
|
||||
placeholder.getControllerId(), placeholder.getTargetId(), softwareData);
|
||||
assertThat(placeholder).isEqualTo(placeholderWithSameProperties);
|
||||
assertThat(placeholderWithSameProperties).isEqualTo(placeholder);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Should not equal null")
|
||||
// Exception squid:S5785 - JUnit assertTrue/assertFalse should be simplified to
|
||||
// the corresponding dedicated assertion
|
||||
// Need to test the equals method and need to bypass magic logic in utility
|
||||
// classes
|
||||
@SuppressWarnings({ "squid:S5838" })
|
||||
void shouldNotEqualNull() {
|
||||
assertThat(placeholder.equals(null)).isFalse();
|
||||
assertThat(softwareData.equals(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("HashCode should not change")
|
||||
void hashCodeShouldNotChange() {
|
||||
final URLPlaceholder placeholderWithSameProperties = new URLPlaceholder(placeholder.getTenant(), placeholder.getTenantId(),
|
||||
placeholder.getControllerId(), placeholder.getTargetId(), softwareData);
|
||||
assertThat(placeholder).hasSameHashCodeAs(placeholder).hasSameHashCodeAs(placeholderWithSameProperties);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -32,7 +31,7 @@ import io.qameta.allure.Story;
|
||||
@Feature("Unit Tests - Cache")
|
||||
@Story("Download ID Cache")
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class DefaultDownloadIdCacheTest {
|
||||
class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Mock
|
||||
private CacheManager cacheManagerMock;
|
||||
@@ -61,7 +60,7 @@ public class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that putting key and value is delegated to the CacheManager implementation")
|
||||
public void putKeyAndValueIsDelegatedToCacheManager() {
|
||||
void putKeyAndValueIsDelegatedToCacheManager() {
|
||||
final DownloadArtifactCache value = new DownloadArtifactCache(DownloadType.BY_SHA1, knownKey);
|
||||
|
||||
underTest.put(knownKey, value);
|
||||
@@ -74,7 +73,7 @@ public class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that evicting a key is delegated to the CacheManager implementation")
|
||||
public void evictKeyIsDelegatedToCacheManager() {
|
||||
void evictKeyIsDelegatedToCacheManager() {
|
||||
|
||||
underTest.evict(knownKey);
|
||||
|
||||
@@ -85,7 +84,7 @@ public class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that retrieving a value for a specific key is delegated to the CacheManager implementation")
|
||||
public void getValueReturnsTheAssociatedValueForKey() {
|
||||
void getValueReturnsTheAssociatedValueForKey() {
|
||||
final String knownKey = "12345";
|
||||
final DownloadArtifactCache knownValue = new DownloadArtifactCache(DownloadType.BY_SHA1, knownKey);
|
||||
|
||||
@@ -98,7 +97,7 @@ public class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that retrieving a null value for a specific key is delegated to the CacheManager implementation")
|
||||
public void getValueReturnsNullIfNoKeyIsAssociated() {
|
||||
void getValueReturnsNullIfNoKeyIsAssociated() {
|
||||
|
||||
when(cacheMock.get(knownKey)).thenReturn(new SimpleValueWrapper(null));
|
||||
|
||||
@@ -109,7 +108,7 @@ public class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that TenancyCacheManager is using direct cache because download-ids are global unique and don't need to run as tenant aware")
|
||||
public void tenancyCacheManagerIsUsingDirectCache() {
|
||||
void tenancyCacheManagerIsUsingDirectCache() {
|
||||
|
||||
when(tenancyCacheManagerMock.getDirectCache(DefaultDownloadIdCache.DOWNLOAD_ID_CACHE)).thenReturn(cacheMock);
|
||||
underTest = new DefaultDownloadIdCache(tenancyCacheManagerMock);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class DefaultAmqpMessageSenderService extends BaseAmqpService implements
|
||||
LOGGER.debug("Sending message to exchange {} with correlationId {}", exchange, correlationId);
|
||||
}
|
||||
|
||||
getRabbitTemplate().send(exchange, null, message, new CorrelationData(correlationId));
|
||||
getRabbitTemplate().send(exchange, "", message, new CorrelationData(correlationId));
|
||||
}
|
||||
|
||||
protected static boolean isCorrelationIdEmpty(final Message message) {
|
||||
|
||||
@@ -68,7 +68,7 @@ import io.qameta.allure.Story;
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("AmqpMessage Dispatcher Service Test")
|
||||
@SpringBootTest(classes = { RepositoryApplicationConfiguration.class })
|
||||
public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String TENANT = "default";
|
||||
private static final Long TENANT_ID = 4711L;
|
||||
@@ -127,7 +127,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that download and install event with 3 software modules and no artifacts works")
|
||||
public void testSendDownloadRequestWithSoftwareModulesAndNoArtifacts() {
|
||||
void testSendDownloadRequestWithSoftwareModulesAndNoArtifacts() {
|
||||
final DistributionSet createDistributionSet = testdataFactory
|
||||
.createDistributionSet(UUID.randomUUID().toString());
|
||||
testdataFactory.addSoftwareModuleMetadata(createDistributionSet);
|
||||
@@ -154,17 +154,19 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
|
||||
continue;
|
||||
}
|
||||
assertThat(softwareModule.getModuleType()).isEqualTo(softwareModule2.getType().getKey()).as(
|
||||
"Software module type in event should be the same as the softwaremodule in the distribution set");
|
||||
assertThat(softwareModule.getModuleVersion()).isEqualTo(softwareModule2.getVersion()).as(
|
||||
"Software module version in event should be the same as the softwaremodule in the distribution set");
|
||||
assertThat(softwareModule.getModuleType())
|
||||
.as("Software module type in event should be the same as the softwaremodule in the distribution set")
|
||||
.isEqualTo(softwareModule2.getType().getKey());
|
||||
assertThat(softwareModule.getModuleVersion())
|
||||
.as("Software module version in event should be the same as the softwaremodule in the distribution set")
|
||||
.isEqualTo(softwareModule2.getVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that download and install event with software modules and artifacts works")
|
||||
public void testSendDownloadRequest() {
|
||||
void testSendDownloadRequest() {
|
||||
DistributionSet dsA = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
SoftwareModule module = dsA.getModules().iterator().next();
|
||||
final List<AbstractDbArtifact> receivedList = new ArrayList<>();
|
||||
@@ -186,15 +188,18 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage,
|
||||
action.getId());
|
||||
|
||||
assertThat(downloadAndUpdateRequest.getSoftwareModules()).hasSize(3)
|
||||
.as("DownloadAndUpdateRequest event should contains 3 software modules");
|
||||
assertThat(downloadAndUpdateRequest.getSoftwareModules())
|
||||
.as("DownloadAndUpdateRequest event should contains 3 software modules")
|
||||
.hasSize(3);
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
|
||||
|
||||
for (final DmfSoftwareModule softwareModule : downloadAndUpdateRequest.getSoftwareModules()) {
|
||||
if (!softwareModule.getModuleId().equals(module.getId())) {
|
||||
continue;
|
||||
}
|
||||
assertThat(softwareModule.getArtifacts().size()).isEqualTo(module.getArtifacts().size()).isGreaterThan(0);
|
||||
assertThat(softwareModule.getArtifacts().size())
|
||||
.isEqualTo(module.getArtifacts().size())
|
||||
.isNotZero();
|
||||
|
||||
module.getArtifacts().forEach(dbArtifact -> {
|
||||
final Optional<org.eclipse.hawkbit.dmf.json.model.DmfArtifact> found = softwareModule.getArtifacts()
|
||||
@@ -211,7 +216,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that sending update controller attributes event works.")
|
||||
public void sendUpdateAttributesRequest() {
|
||||
void sendUpdateAttributesRequest() {
|
||||
final String amqpUri = "amqp://anyhost";
|
||||
final TargetAttributesRequestedEvent targetAttributesRequestedEvent = new TargetAttributesRequestedEvent(TENANT,
|
||||
1L, CONTROLLER_ID, amqpUri, Target.class.getName(), serviceMatcher.getServiceId());
|
||||
@@ -224,7 +229,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that send cancel event works")
|
||||
public void testSendCancelRequest() {
|
||||
void testSendCancelRequest() {
|
||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
||||
testTarget, 1L, serviceMatcher.getServiceId());
|
||||
amqpMessageDispatcherService
|
||||
@@ -237,7 +242,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that sending a delete message when receiving a delete event works.")
|
||||
public void sendDeleteRequest() {
|
||||
void sendDeleteRequest() {
|
||||
|
||||
// setup
|
||||
final String amqpUri = "amqp://anyhost";
|
||||
@@ -254,7 +259,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a delete message is not send if the address is not an amqp address.")
|
||||
public void sendDeleteRequestWithNoAmqpAddress() {
|
||||
void sendDeleteRequestWithNoAmqpAddress() {
|
||||
|
||||
// setup
|
||||
final String noAmqpUri = "http://anyhost";
|
||||
@@ -270,7 +275,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a delete message is not send if the address is null.")
|
||||
public void sendDeleteRequestWithNullAddress() {
|
||||
void sendDeleteRequestWithNullAddress() {
|
||||
|
||||
// setup
|
||||
final String noAmqpUri = null;
|
||||
@@ -287,19 +292,22 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
private void assertCancelMessage(final Message sendMessage) {
|
||||
assertEventMessage(sendMessage);
|
||||
final DmfActionRequest actionId = convertMessage(sendMessage, DmfActionRequest.class);
|
||||
assertThat(actionId.getActionId()).isEqualTo(Long.valueOf(1)).as("Action ID should be 1");
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC))
|
||||
.isEqualTo(EventTopic.CANCEL_DOWNLOAD).as("The topc in the message should be a CANCEL_DOWNLOAD value");
|
||||
assertThat(actionId.getActionId())
|
||||
.as("Action ID should be 1")
|
||||
.isOne();
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The topc in the message should be a CANCEL_DOWNLOAD value")
|
||||
.containsEntry(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD);
|
||||
}
|
||||
|
||||
private void assertDeleteMessage(final Message sendMessage) {
|
||||
|
||||
assertThat(sendMessage).isNotNull();
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID))
|
||||
.isEqualTo(CONTROLLER_ID);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TENANT)).isEqualTo(TENANT);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TYPE))
|
||||
.isEqualTo(MessageType.THING_DELETED);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.containsEntry(MessageHeaderKey.THING_ID, CONTROLLER_ID);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.containsEntry(MessageHeaderKey.TENANT, TENANT);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.containsEntry(MessageHeaderKey.TYPE,MessageType.THING_DELETED);
|
||||
}
|
||||
|
||||
private DmfDownloadAndUpdateRequest assertDownloadAndInstallMessage(final Message sendMessage, final Long action) {
|
||||
@@ -307,32 +315,35 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage,
|
||||
DmfDownloadAndUpdateRequest.class);
|
||||
assertThat(downloadAndUpdateRequest.getActionId()).isEqualTo(action);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC))
|
||||
.isEqualTo(EventTopic.DOWNLOAD_AND_INSTALL)
|
||||
.as("The topic of the event should contain DOWNLOAD_AND_INSTALL");
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN)
|
||||
.as("Security token of target");
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The topic of the event should contain DOWNLOAD_AND_INSTALL")
|
||||
.containsEntry(MessageHeaderKey.TOPIC,EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken())
|
||||
.as("Security token of target")
|
||||
.isEqualTo(TEST_TOKEN);
|
||||
|
||||
return downloadAndUpdateRequest;
|
||||
}
|
||||
|
||||
private void assertUpdateAttributesMessage(final Message sendMessage) {
|
||||
assertEventMessage(sendMessage);
|
||||
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC))
|
||||
.isEqualTo(EventTopic.REQUEST_ATTRIBUTES_UPDATE)
|
||||
.as("The topic of the event should contain REQUEST_ATTRIBUTES_UPDATE");
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The topic of the event should contain REQUEST_ATTRIBUTES_UPDATE")
|
||||
.containsEntry(MessageHeaderKey.TOPIC, EventTopic.REQUEST_ATTRIBUTES_UPDATE);
|
||||
}
|
||||
|
||||
private void assertEventMessage(final Message sendMessage) {
|
||||
assertThat(sendMessage).isNotNull().as("The message should not be null");
|
||||
assertThat(sendMessage).as("The message should not be null").isNotNull();
|
||||
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.THING_ID))
|
||||
.isEqualTo(CONTROLLER_ID).as("The value of the message header THING_ID should be " + CONTROLLER_ID);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TYPE))
|
||||
.isEqualTo(MessageType.EVENT).as("The value of the message header TYPE should be EVENT");
|
||||
assertThat(sendMessage.getMessageProperties().getContentType()).isEqualTo(MessageProperties.CONTENT_TYPE_JSON)
|
||||
.as("The content type message should be " + MessageProperties.CONTENT_TYPE_JSON);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The value of the message header THING_ID should be " + CONTROLLER_ID)
|
||||
.containsEntry(MessageHeaderKey.THING_ID, CONTROLLER_ID);
|
||||
assertThat(sendMessage.getMessageProperties().getHeaders())
|
||||
.as("The value of the message header TYPE should be EVENT")
|
||||
.containsEntry(MessageHeaderKey.TYPE,MessageType.EVENT);
|
||||
assertThat(sendMessage.getMessageProperties().getContentType())
|
||||
.as("The content type message should be " + MessageProperties.CONTENT_TYPE_JSON)
|
||||
.isEqualTo(MessageProperties.CONTENT_TYPE_JSON);
|
||||
}
|
||||
|
||||
protected Message createArgumentCapture(final URI uri) {
|
||||
|
||||
@@ -153,9 +153,9 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
final Message replyMessage = replyToListener.getDeleteMessages().get(target);
|
||||
assertAllTargetsCount(0);
|
||||
final Map<String, Object> headers = replyMessage.getMessageProperties().getHeaders();
|
||||
assertThat(headers.get(MessageHeaderKey.THING_ID)).isEqualTo(target);
|
||||
assertThat(headers.get(MessageHeaderKey.TENANT)).isEqualTo(TENANT_EXIST);
|
||||
assertThat(headers.get(MessageHeaderKey.TYPE)).isEqualTo(MessageType.THING_DELETED.toString());
|
||||
assertThat(headers).containsEntry(MessageHeaderKey.THING_ID, target)
|
||||
.containsEntry(MessageHeaderKey.TENANT, TENANT_EXIST)
|
||||
.containsEntry(MessageHeaderKey.TYPE, MessageType.THING_DELETED.toString());
|
||||
}
|
||||
|
||||
protected void assertRequestAttributesUpdateMessage(final String target) {
|
||||
@@ -173,9 +173,9 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
|
||||
final Map<String, Object> headers = replyMessage.getMessageProperties().getHeaders();
|
||||
|
||||
assertThat(headers.get(MessageHeaderKey.TENANT)).isEqualTo(TENANT_EXIST);
|
||||
assertThat(headers).containsEntry(MessageHeaderKey.TENANT, TENANT_EXIST);
|
||||
assertThat(correlationId).isEqualTo(replyMessage.getMessageProperties().getCorrelationId());
|
||||
assertThat(headers.get(MessageHeaderKey.TYPE)).isEqualTo(MessageType.PING_RESPONSE.toString());
|
||||
assertThat(headers).containsEntry(MessageHeaderKey.TYPE, MessageType.PING_RESPONSE.toString());
|
||||
assertThat(Long.valueOf(new String(replyMessage.getBody(), StandardCharsets.UTF_8)))
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
|
||||
@@ -212,22 +212,17 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
assertAssignmentMessage(dsModules, controllerId, EventTopic.DOWNLOAD);
|
||||
}
|
||||
|
||||
protected void createAndSendThingCreated(final String controllerId, final String tenant) {
|
||||
createAndSendThingCreated(controllerId, null, null, tenant);
|
||||
protected void createAndSendThingCreated(final String controllerId) {
|
||||
createAndSendThingCreated(controllerId, null, null);
|
||||
}
|
||||
|
||||
protected void createAndSendThingCreated(final String controllerId, final String name,
|
||||
final Map<String, String> attributes, final String tenant) {
|
||||
final Message message = createTargetMessage(controllerId, name, attributes, tenant);
|
||||
final Map<String, String> attributes) {
|
||||
final Message message = createTargetMessage(controllerId, name, attributes,
|
||||
AbstractAmqpServiceIntegrationTest.TENANT_EXIST);
|
||||
getDmfClient().send(message);
|
||||
}
|
||||
|
||||
protected Message createAndSendPingMessage(final String correlationId, final String tenant) {
|
||||
final Message message = createPingMessage(correlationId, tenant);
|
||||
getDmfClient().send(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
protected void verifyReplyToListener() {
|
||||
createConditionFactory()
|
||||
.untilAsserted(() -> Mockito.verify(replyToListener, Mockito.atLeast(1)).handleMessage(Mockito.any()));
|
||||
@@ -254,10 +249,11 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
final Message replyMessage = replyToListener.getLatestEventMessage(eventTopic);
|
||||
assertAllTargetsCount(1);
|
||||
final Map<String, Object> headers = replyMessage.getMessageProperties().getHeaders();
|
||||
assertThat(headers.get(MessageHeaderKey.TOPIC)).isEqualTo(eventTopic.toString());
|
||||
assertThat(headers.get(MessageHeaderKey.THING_ID)).isEqualTo(controllerId);
|
||||
assertThat(headers.get(MessageHeaderKey.TENANT)).isEqualTo(TENANT_EXIST);
|
||||
assertThat(headers.get(MessageHeaderKey.TYPE)).isEqualTo(MessageType.EVENT.toString());
|
||||
|
||||
assertThat(headers).containsEntry(MessageHeaderKey.TOPIC, eventTopic.toString())
|
||||
.containsEntry(MessageHeaderKey.THING_ID, controllerId)
|
||||
.containsEntry(MessageHeaderKey.TENANT, TENANT_EXIST)
|
||||
.containsEntry(MessageHeaderKey.TYPE, MessageType.EVENT.toString());
|
||||
return replyMessage;
|
||||
}
|
||||
|
||||
@@ -290,7 +286,7 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
final int existingTargetsAfterCreation, final TargetUpdateStatus expectedTargetStatus,
|
||||
final String createdBy, final Map<String, String> attributes,
|
||||
final Callable<Optional<Target>> fetchTarget) {
|
||||
createAndSendThingCreated(controllerId, name, attributes, TENANT_EXIST);
|
||||
createAndSendThingCreated(controllerId, name, attributes);
|
||||
final Target registeredTarget = waitUntilIsPresent(fetchTarget::call);
|
||||
assertAllTargetsCount(existingTargetsAfterCreation);
|
||||
assertThat(registeredTarget).isNotNull();
|
||||
@@ -372,14 +368,15 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
final DmfActionStatus status) {
|
||||
final DmfActionUpdateStatus dmfActionUpdateStatus = new DmfActionUpdateStatus(actionId, status);
|
||||
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, dmfActionUpdateStatus);
|
||||
final Message eventMessage = createUpdateActionEventMessage(dmfActionUpdateStatus);
|
||||
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.THING_ID, target);
|
||||
|
||||
getDmfClient().send(eventMessage);
|
||||
}
|
||||
|
||||
protected Message createUpdateActionEventMessage(final String tenant, final Object payload) {
|
||||
final MessageProperties messageProperties = createMessagePropertiesWithTenant(tenant);
|
||||
protected Message createUpdateActionEventMessage(final Object payload) {
|
||||
final MessageProperties messageProperties = createMessagePropertiesWithTenant(
|
||||
AbstractAmqpServiceIntegrationTest.TENANT_EXIST);
|
||||
messageProperties.getHeaders().put(MessageHeaderKey.TYPE, MessageType.EVENT.toString());
|
||||
messageProperties.getHeaders().put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.toString());
|
||||
messageProperties.setCorrelationId(CORRELATION_ID);
|
||||
@@ -404,8 +401,9 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
|
||||
}
|
||||
|
||||
protected Message createUpdateAttributesMessageWrongBody(final String target, final String tenant) {
|
||||
final MessageProperties messageProperties = createMessagePropertiesWithTenant(tenant);
|
||||
protected Message createUpdateAttributesMessageWrongBody(final String target) {
|
||||
final MessageProperties messageProperties = createMessagePropertiesWithTenant(
|
||||
AbstractAmqpServiceIntegrationTest.TENANT_EXIST);
|
||||
messageProperties.getHeaders().put(MessageHeaderKey.THING_ID, target);
|
||||
messageProperties.getHeaders().put(MessageHeaderKey.TYPE, MessageType.EVENT.toString());
|
||||
messageProperties.getHeaders().put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ATTRIBUTES.toString());
|
||||
@@ -423,19 +421,13 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
final Map<String, String> controllerAttributes = WithSpringAuthorityRule
|
||||
.runAsPrivileged(() -> targetManagement.getControllerAttributes(controllerId));
|
||||
assertThat(controllerAttributes.size()).isEqualTo(attributes.size());
|
||||
attributes.forEach((k, v) -> assertKeyValueInMap(k, v, controllerAttributes));
|
||||
assertThat(controllerAttributes).containsAllEntriesOf(attributes);
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void assertKeyValueInMap(final String key, final String value,
|
||||
final Map<String, String> controllerAttributes) {
|
||||
assertThat(controllerAttributes.containsKey(key)).isTrue();
|
||||
assertThat(controllerAttributes.get(key)).isEqualTo(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExchange() {
|
||||
return AmqpSettings.DMF_EXCHANGE;
|
||||
|
||||
@@ -163,7 +163,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
assertCancelActionMessage(getFirstAssignedActionId(assignmentResult), controllerId);
|
||||
|
||||
// cancelation message is returned upon polling
|
||||
createAndSendThingCreated(controllerId, TENANT_EXIST);
|
||||
createAndSendThingCreated(controllerId);
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.CANCEL_DOWNLOAD);
|
||||
assertCancelActionMessage(getFirstAssignedActionId(assignmentResult), controllerId);
|
||||
|
||||
@@ -176,7 +176,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
assertDownloadAndInstallMessage(distributionSet2.getModules(), controllerId);
|
||||
|
||||
// latest action is returned upon polling
|
||||
createAndSendThingCreated(controllerId, TENANT_EXIST);
|
||||
createAndSendThingCreated(controllerId);
|
||||
waitUntilEventMessagesAreDispatchedToTarget(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
assertDownloadAndInstallMessage(distributionSet2.getModules(), controllerId);
|
||||
}
|
||||
@@ -478,7 +478,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
|
||||
final Long actionId = registerTargetAndCancelActionId(controllerId);
|
||||
|
||||
createAndSendThingCreated(controllerId, TENANT_EXIST);
|
||||
createAndSendThingCreated(controllerId);
|
||||
waitUntilTargetHasStatus(controllerId, TargetUpdateStatus.PENDING);
|
||||
assertCancelActionMessage(actionId, controllerId);
|
||||
}
|
||||
|
||||
@@ -58,8 +58,12 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.TargetTestData;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
@@ -75,8 +79,11 @@ import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("Amqp Message Handler Service")
|
||||
public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegrationTest {
|
||||
class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegrationTest {
|
||||
private static final String TARGET_PREFIX = "Dmf_hand_";
|
||||
public static final String DMF_REGISTER_TEST_CONTROLLER_ID = "Dmf_hand_registerTargets_1";
|
||||
public static final String DMF_ATTR_TEST_CONTROLLER_ID = "Dmf_hand_updateAttributes";
|
||||
public static final String UPDATE_ATTR_TEST_CONTROLLER_ID = "ControllerAttributeTestTarget";
|
||||
|
||||
@Autowired
|
||||
private AmqpProperties amqpProperties;
|
||||
@@ -86,7 +93,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests DMF PING request and expected response.")
|
||||
public void pingDmfInterface() {
|
||||
void pingDmfInterface() {
|
||||
final Message pingMessage = createPingMessage(CORRELATION_ID, TENANT_EXIST);
|
||||
getDmfClient().send(pingMessage);
|
||||
|
||||
@@ -99,7 +106,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Tests register target")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetPollEvent.class, count = 3) })
|
||||
public void registerTargets() {
|
||||
void registerTargets() {
|
||||
final String controllerId = TARGET_PREFIX + "registerTargets";
|
||||
registerAndAssertTargetWithExistingTenant(controllerId, 1);
|
||||
|
||||
@@ -114,7 +121,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Tests register target with name")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void registerTargetWithName() {
|
||||
void registerTargetWithName() {
|
||||
final String controllerId = TARGET_PREFIX + "registerTargetWithName";
|
||||
final String name = "NonDefaultTargetName";
|
||||
registerAndAssertTargetWithExistingTenant(controllerId, name, 1, TargetUpdateStatus.REGISTERED, CREATED_BY,
|
||||
@@ -130,7 +137,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Tests register target with attributes")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void registerTargetWithAttributes() {
|
||||
void registerTargetWithAttributes() {
|
||||
final String controllerId = TARGET_PREFIX + "registerTargetWithAttributes";
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("testKey1", "testValue1");
|
||||
@@ -149,7 +156,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Tests register target with name and attributes")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void registerTargetWithNameAndAttributes() {
|
||||
void registerTargetWithNameAndAttributes() {
|
||||
final String controllerId = TARGET_PREFIX + "registerTargetWithAttributes";
|
||||
final String name = "NonDefaultTargetName";
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
@@ -166,46 +173,30 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
Mockito.verifyNoInteractions(getDeadletterListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"", "Invalid Invalid"})
|
||||
@NullSource
|
||||
@Description("Tests register invalid target with empty controller id.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void registerEmptyTarget() {
|
||||
createAndSendThingCreated("", TENANT_EXIST);
|
||||
assertAllTargetsCount(0);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests register invalid target with whitespace controller id.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void registerWhitespaceTarget() {
|
||||
createAndSendThingCreated("Invalid Invalid", TENANT_EXIST);
|
||||
assertAllTargetsCount(0);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests register invalid target with null controller id.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void registerInvalidNullTarget() {
|
||||
createAndSendThingCreated(null, TENANT_EXIST);
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void shouldNotRegisterTargetsWithInvalidControllerIds(String controllerId) {
|
||||
createAndSendThingCreated(controllerId);
|
||||
assertAllTargetsCount(0);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests register invalid target with too long controller id")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void registerInvalidTargetWithTooLongControllerId() {
|
||||
createAndSendThingCreated(RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1), TENANT_EXIST);
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void registerInvalidTargetWithTooLongControllerId() {
|
||||
createAndSendThingCreated(RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1));
|
||||
assertAllTargetsCount(0);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests null reply to property in message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void missingReplyToProperty() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void missingReplyToProperty() {
|
||||
final String controllerId = TARGET_PREFIX + "missingReplyToProperty";
|
||||
final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().setReplyTo(null);
|
||||
@@ -217,8 +208,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests missing reply to property in message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void emptyReplyToProperty() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void emptyReplyToProperty() {
|
||||
final String controllerId = TARGET_PREFIX + "emptyReplyToProperty";
|
||||
final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().setReplyTo("");
|
||||
@@ -230,8 +221,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests missing thing id property in message. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void missingThingIdProperty() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void missingThingIdProperty() {
|
||||
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.THING_ID);
|
||||
getDmfClient().send(createTargetMessage);
|
||||
@@ -242,8 +233,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests null thing id property in message. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void nullThingIdProperty() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void nullThingIdProperty() {
|
||||
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
|
||||
getDmfClient().send(createTargetMessage);
|
||||
|
||||
@@ -253,8 +244,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests missing tenant message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void missingTenantHeader() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void missingTenantHeader() {
|
||||
final String controllerId = TARGET_PREFIX + "missingTenantHeader";
|
||||
final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TENANT);
|
||||
@@ -266,8 +257,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests null tenant message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void nullTenantHeader() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void nullTenantHeader() {
|
||||
final String controllerId = TARGET_PREFIX + "nullTenantHeader";
|
||||
final Message createTargetMessage = createTargetMessage(controllerId, null);
|
||||
getDmfClient().send(createTargetMessage);
|
||||
@@ -278,8 +269,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests empty tenant message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void emptyTenantHeader() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void emptyTenantHeader() {
|
||||
final String controllerId = TARGET_PREFIX + "emptyTenantHeader";
|
||||
final Message createTargetMessage = createTargetMessage(controllerId, "");
|
||||
getDmfClient().send(createTargetMessage);
|
||||
@@ -290,8 +281,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests tenant not exist. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void tenantNotExist() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void tenantNotExist() {
|
||||
final String controllerId = TARGET_PREFIX + "tenantNotExist";
|
||||
final Message createTargetMessage = createTargetMessage(controllerId, "TenantNotExist");
|
||||
getDmfClient().send(createTargetMessage);
|
||||
@@ -302,8 +293,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests missing type message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void missingTypeHeader() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void missingTypeHeader() {
|
||||
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TYPE);
|
||||
getDmfClient().send(createTargetMessage);
|
||||
@@ -312,70 +303,28 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
assertAllTargetsCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings={"", "NotExist"})
|
||||
@NullSource
|
||||
@Description("Tests null type message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void nullTypeHeader() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void shouldNotCreateTargetsWithInvalidTypeInHeader(String type) {
|
||||
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TYPE, null);
|
||||
createTargetMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TYPE, type);
|
||||
getDmfClient().send(createTargetMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
assertAllTargetsCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests empty type message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void emptyTypeHeader() {
|
||||
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TYPE, "");
|
||||
getDmfClient().send(createTargetMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
assertAllTargetsCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests invalid type message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void invalidTypeHeader() {
|
||||
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
|
||||
createTargetMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TYPE, "NotExist");
|
||||
getDmfClient().send(createTargetMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
assertAllTargetsCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"", "NotExist"})
|
||||
@NullSource
|
||||
@Description("Tests null topic message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void nullTopicHeader() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, "");
|
||||
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TOPIC, null);
|
||||
getDmfClient().send(eventMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests null topic message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void emptyTopicHeader() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, "");
|
||||
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TOPIC, "");
|
||||
getDmfClient().send(eventMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests null topic message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void invalidTopicHeader() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, "");
|
||||
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TOPIC, "NotExist");
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void shouldNotSendMessagesWithInvalidTopic(String topic) {
|
||||
final Message eventMessage = createUpdateActionEventMessage("");
|
||||
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TOPIC, topic);
|
||||
getDmfClient().send(eventMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
@@ -383,48 +332,32 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Tests missing topic message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void missingTopicHeader() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, "");
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void missingTopicHeader() {
|
||||
final Message eventMessage = createUpdateActionEventMessage("");
|
||||
eventMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TOPIC);
|
||||
getDmfClient().send(eventMessage);
|
||||
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "", "Invalid Content"})
|
||||
@NullSource
|
||||
@Description("Tests invalid null message content. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void updateActionStatusWithNullContent() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, null);
|
||||
getDmfClient().send(eventMessage);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests invalid empty message content. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void updateActionStatusWithEmptyContent() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, "");
|
||||
getDmfClient().send(eventMessage);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests invalid json message content. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void updateActionStatusWithInvalidJsonContent() {
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, "Invalid Content");
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void shouldMoveUpdateActionStatusWithInvalidPayloadIntoDeadLetter(String payload) {
|
||||
final Message eventMessage = createUpdateActionEventMessage(payload);
|
||||
getDmfClient().send(eventMessage);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests invalid topic message header. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void updateActionStatusWithInvalidActionId() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void updateActionStatusWithInvalidActionId() {
|
||||
final DmfActionUpdateStatus actionUpdateStatus = new DmfActionUpdateStatus(1L, DmfActionStatus.RUNNING);
|
||||
final Message eventMessage = createUpdateActionEventMessage(TENANT_EXIST, actionUpdateStatus);
|
||||
final Message eventMessage = createUpdateActionEventMessage(actionUpdateStatus);
|
||||
getDmfClient().send(eventMessage);
|
||||
verifyOneDeadLetterMessage();
|
||||
}
|
||||
@@ -439,7 +372,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void finishActionStatus() {
|
||||
void finishActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "finishActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.FINISHED, Status.FINISHED, controllerId);
|
||||
}
|
||||
@@ -448,12 +381,12 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Register a target and send a update action status (running). Verify if the updated action status is correct.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void runningActionStatus() {
|
||||
void runningActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "runningActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.RUNNING, Status.RUNNING, controllerId);
|
||||
}
|
||||
@@ -462,12 +395,12 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Register a target and send an update action status (downloaded). Verify if the updated action status is correct.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void downloadedActionStatus() {
|
||||
void downloadedActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "downloadedActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.DOWNLOADED, Status.DOWNLOADED, controllerId);
|
||||
}
|
||||
@@ -481,7 +414,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void downloadActionStatus() {
|
||||
void downloadActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "downloadActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.DOWNLOAD, Status.DOWNLOAD, controllerId);
|
||||
}
|
||||
@@ -495,7 +428,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void errorActionStatus() {
|
||||
void errorActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "errorActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.ERROR, Status.ERROR, controllerId);
|
||||
}
|
||||
@@ -509,7 +442,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void warningActionStatus() {
|
||||
void warningActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "warningActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.WARNING, Status.WARNING, controllerId);
|
||||
}
|
||||
@@ -523,7 +456,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void retrievedActionStatus() {
|
||||
void retrievedActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "retrievedActionStatus";
|
||||
registerTargetAndSendAndAssertUpdateActionStatus(DmfActionStatus.RETRIEVED, Status.RETRIEVED, controllerId);
|
||||
}
|
||||
@@ -537,7 +470,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void cancelNotAllowActionStatus() {
|
||||
void cancelNotAllowActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "cancelNotAllowActionStatus";
|
||||
registerTargetAndSendActionStatus(DmfActionStatus.CANCELED, controllerId);
|
||||
verifyOneDeadLetterMessage();
|
||||
@@ -552,7 +485,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void receiveDownLoadAndInstallMessageAfterAssignment() {
|
||||
void receiveDownLoadAndInstallMessageAfterAssignment() {
|
||||
final String controllerId = TARGET_PREFIX + "receiveDownLoadAndInstallMessageAfterAssignment";
|
||||
|
||||
// setup
|
||||
@@ -578,7 +511,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void receiveDownloadMessageBeforeMaintenanceWindowStartTime() {
|
||||
void receiveDownloadMessageBeforeMaintenanceWindowStartTime() {
|
||||
final String controllerId = TARGET_PREFIX + "receiveDownLoadMessageBeforeMaintenanceWindowStartTime";
|
||||
|
||||
// setup
|
||||
@@ -605,7 +538,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void receiveDownloadAndInstallMessageDuringMaintenanceWindow() {
|
||||
void receiveDownloadAndInstallMessageDuringMaintenanceWindow() {
|
||||
final String controllerId = TARGET_PREFIX + "receiveDownLoadAndInstallMessageDuringMaintenanceWindow";
|
||||
|
||||
// setup
|
||||
@@ -633,7 +566,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void receiveCancelUpdateMessageAfterAssignmentWasCanceled() {
|
||||
void receiveCancelUpdateMessageAfterAssignmentWasCanceled() {
|
||||
final String controllerId = TARGET_PREFIX + "receiveCancelUpdateMessageAfterAssignmentWasCanceled";
|
||||
|
||||
// Setup
|
||||
@@ -661,11 +594,11 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void actionNotExists() {
|
||||
void actionNotExists() {
|
||||
final String controllerId = TARGET_PREFIX + "actionNotExists";
|
||||
|
||||
final Long actionId = registerTargetAndCancelActionId(controllerId);
|
||||
final Long actionNotExist = actionId + 1;
|
||||
final long actionNotExist = actionId + 1;
|
||||
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionNotExist, DmfActionStatus.CANCELED);
|
||||
verifyOneDeadLetterMessage();
|
||||
@@ -680,7 +613,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void canceledRejectedNotAllowActionStatus() {
|
||||
void canceledRejectedNotAllowActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "canceledRejectedNotAllowActionStatus";
|
||||
registerTargetAndSendActionStatus(DmfActionStatus.CANCEL_REJECTED, controllerId);
|
||||
verifyOneDeadLetterMessage();
|
||||
@@ -696,7 +629,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void canceledRejectedActionStatus() {
|
||||
void canceledRejectedActionStatus() {
|
||||
final String controllerId = TARGET_PREFIX + "canceledRejectedActionStatus";
|
||||
|
||||
final Long actionId = registerTargetAndCancelActionId(controllerId);
|
||||
@@ -709,35 +642,36 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Description("Verify that sending an update controller attribute message to an existing target works. Verify that different update modes (merge, replace, remove) can be used.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 4), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void updateAttributesWithDifferentUpdateModes() {
|
||||
void updateAttributesWithDifferentUpdateModes() {
|
||||
final String controllerId = TARGET_PREFIX + "updateAttributes";
|
||||
|
||||
// setup
|
||||
registerAndAssertTargetWithExistingTenant(controllerId);
|
||||
|
||||
// no update mode specified
|
||||
updateAttributesWithoutUpdateMode(controllerId);
|
||||
updateAttributesWithoutUpdateMode();
|
||||
|
||||
// update mode REPLACE
|
||||
updateAttributesWithUpdateModeReplace(controllerId);
|
||||
updateAttributesWithUpdateModeReplace();
|
||||
|
||||
// update mode MERGE
|
||||
updateAttributesWithUpdateModeMerge(controllerId);
|
||||
updateAttributesWithUpdateModeMerge();
|
||||
|
||||
// update mode REMOVE
|
||||
updateAttributesWithUpdateModeRemove(controllerId);
|
||||
updateAttributesWithUpdateModeRemove();
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeRemove(final String controllerId) {
|
||||
private void updateAttributesWithUpdateModeRemove() {
|
||||
|
||||
// assemble the expected attributes
|
||||
final Map<String, String> expectedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
final Map<String, String> expectedAttributes = targetManagement
|
||||
.getControllerAttributes(DMF_ATTR_TEST_CONTROLLER_ID);
|
||||
expectedAttributes.remove("k1");
|
||||
expectedAttributes.remove("k3");
|
||||
|
||||
// send a update message with update mode
|
||||
// send an update message with update mode
|
||||
final Map<String, String> removeAttributes = new HashMap<>();
|
||||
removeAttributes.put("k1", "foo");
|
||||
removeAttributes.put("k3", "bar");
|
||||
@@ -745,19 +679,19 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
final DmfAttributeUpdate remove = new DmfAttributeUpdate();
|
||||
remove.setMode(DmfUpdateMode.REMOVE);
|
||||
remove.getAttributes().putAll(removeAttributes);
|
||||
sendUpdateAttributeMessage(controllerId, TENANT_EXIST, remove);
|
||||
sendUpdateAttributeMessage(remove);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(controllerId, expectedAttributes);
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeMerge(final String controllerId) {
|
||||
|
||||
private void updateAttributesWithUpdateModeMerge() {
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(controllerId));
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DMF_ATTR_TEST_CONTROLLER_ID));
|
||||
|
||||
// send a update message with update mode MERGE
|
||||
// send an update message with update mode MERGE
|
||||
final Map<String, String> mergeAttributes = new HashMap<>();
|
||||
mergeAttributes.put("k1", "v1_modified_again");
|
||||
mergeAttributes.put("k4", "v4");
|
||||
@@ -765,19 +699,18 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
final DmfAttributeUpdate merge = new DmfAttributeUpdate();
|
||||
merge.setMode(DmfUpdateMode.MERGE);
|
||||
merge.getAttributes().putAll(mergeAttributes);
|
||||
sendUpdateAttributeMessage(controllerId, TENANT_EXIST, merge);
|
||||
sendUpdateAttributeMessage(merge);
|
||||
|
||||
// validate
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.putAll(attributes);
|
||||
expectedAttributes.putAll(mergeAttributes);
|
||||
assertUpdateAttributes(controllerId, expectedAttributes);
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithUpdateModeReplace(final String controllerId) {
|
||||
|
||||
// send a update message with update mode REPLACE
|
||||
private void updateAttributesWithUpdateModeReplace() {
|
||||
// send an update message with update mode REPLACE
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.put("k1", "v1_modified");
|
||||
expectedAttributes.put("k2", "v2");
|
||||
@@ -786,33 +719,32 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
final DmfAttributeUpdate replace = new DmfAttributeUpdate();
|
||||
replace.setMode(DmfUpdateMode.REPLACE);
|
||||
replace.getAttributes().putAll(expectedAttributes);
|
||||
sendUpdateAttributeMessage(controllerId, TENANT_EXIST, replace);
|
||||
sendUpdateAttributeMessage(replace);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(controllerId, expectedAttributes);
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void updateAttributesWithoutUpdateMode(final String controllerId) {
|
||||
|
||||
// send a update message which does not specify an update mode
|
||||
private void updateAttributesWithoutUpdateMode() {
|
||||
// send an update message which does not specify an update mode
|
||||
final Map<String, String> expectedAttributes = new HashMap<>();
|
||||
expectedAttributes.put("k0", "v0");
|
||||
expectedAttributes.put("k1", "v1");
|
||||
|
||||
final DmfAttributeUpdate defaultUpdate = new DmfAttributeUpdate();
|
||||
defaultUpdate.getAttributes().putAll(expectedAttributes);
|
||||
sendUpdateAttributeMessage(controllerId, TENANT_EXIST, defaultUpdate);
|
||||
sendUpdateAttributeMessage(defaultUpdate);
|
||||
|
||||
// validate
|
||||
assertUpdateAttributes(controllerId, expectedAttributes);
|
||||
assertUpdateAttributes(DMF_ATTR_TEST_CONTROLLER_ID, expectedAttributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that sending an update controller attribute message with no thingid header to an existing target does not work.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 0), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void updateAttributesWithNoThingId() {
|
||||
@Expect(type = TargetUpdatedEvent.class), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void updateAttributesWithNoThingId() {
|
||||
final String controllerId = TARGET_PREFIX + "updateAttributesWithNoThingId";
|
||||
|
||||
// setup
|
||||
@@ -836,17 +768,15 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Test
|
||||
@Description("Verify that sending an update controller attribute message with invalid body to an existing target does not work.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 0), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void updateAttributesWithWrongBody() {
|
||||
|
||||
@Expect(type = TargetUpdatedEvent.class), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void updateAttributesWithWrongBody() {
|
||||
// setup
|
||||
final String target = "ControllerAttributeTestTarget";
|
||||
registerAndAssertTargetWithExistingTenant(target);
|
||||
registerAndAssertTargetWithExistingTenant(UPDATE_ATTR_TEST_CONTROLLER_ID);
|
||||
final DmfAttributeUpdate controllerAttribute = new DmfAttributeUpdate();
|
||||
controllerAttribute.getAttributes().put("test1", "testA");
|
||||
controllerAttribute.getAttributes().put("test2", "testB");
|
||||
final Message createUpdateAttributesMessageWrongBody = createUpdateAttributesMessageWrongBody(target,
|
||||
TENANT_EXIST);
|
||||
final Message createUpdateAttributesMessageWrongBody = createUpdateAttributesMessageWrongBody(
|
||||
UPDATE_ATTR_TEST_CONTROLLER_ID);
|
||||
|
||||
// test
|
||||
getDmfClient().send(createUpdateAttributesMessageWrongBody);
|
||||
@@ -857,20 +787,12 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
|
||||
@Test
|
||||
@Description("Verifies that sending an UPDATE_ATTRIBUTES message with invalid attributes is handled correctly.")
|
||||
public void updateAttributesWithInvalidValues() {
|
||||
// setup
|
||||
final String target = "ControllerAttributeTestTarget";
|
||||
registerAndAssertTargetWithExistingTenant(target);
|
||||
final String keyTooLong = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE + 1);
|
||||
final String keyValid = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE);
|
||||
final String valueTooLong = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE + 1);
|
||||
final String valueValid = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE);
|
||||
void updateAttributesWithInvalidValues() {
|
||||
registerAndAssertTargetWithExistingTenant(UPDATE_ATTR_TEST_CONTROLLER_ID);
|
||||
|
||||
sendUpdateAttributesMessageWithGivenAttributes(target, keyTooLong, valueValid);
|
||||
|
||||
sendUpdateAttributesMessageWithGivenAttributes(target, keyTooLong, valueTooLong);
|
||||
|
||||
sendUpdateAttributesMessageWithGivenAttributes(target, keyValid, valueTooLong);
|
||||
sendUpdateAttributesMessageWithGivenAttributes(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_VALID);
|
||||
sendUpdateAttributesMessageWithGivenAttributes(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG);
|
||||
sendUpdateAttributesMessageWithGivenAttributes(TargetTestData.ATTRIBUTE_KEY_VALID, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG);
|
||||
|
||||
verifyNumberOfDeadLetterMessages(3);
|
||||
}
|
||||
@@ -885,7 +807,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void downloadOnlyAssignmentFinishesActionWhenTargetReportsDownloaded() throws IOException {
|
||||
void downloadOnlyAssignmentFinishesActionWhenTargetReportsDownloaded() throws IOException {
|
||||
// create target
|
||||
final String controllerId = TARGET_PREFIX + "registerTargets_1";
|
||||
final DistributionSet distributionSet = createTargetAndDistributionSetAndAssign(controllerId, DOWNLOAD_ONLY);
|
||||
@@ -895,14 +817,14 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
Mockito.verifyNoInteractions(getDeadletterListener());
|
||||
|
||||
// get actionId from Message
|
||||
final Long actionId = Long.parseLong(getJsonFieldFromBody(message.getBody(), "actionId"));
|
||||
final long actionId = Long.parseLong(getActionIdFromBody(message.getBody()));
|
||||
|
||||
// Send DOWNLOADED message
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.DOWNLOADED);
|
||||
assertAction(actionId, 1, Status.RUNNING, Status.DOWNLOADED);
|
||||
Mockito.verifyNoInteractions(getDeadletterListener());
|
||||
|
||||
verifyAssignedDsAndInstalledDs(controllerId, distributionSet.getId(), null);
|
||||
verifyAssignedDsAndInstalledDs(distributionSet.getId(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -915,9 +837,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void downloadOnlyAssignmentAllowsActionStatusUpdatesWhenTargetReportsFinishedAndUpdatesInstalledDS()
|
||||
void downloadOnlyAssignmentAllowsActionStatusUpdatesWhenTargetReportsFinishedAndUpdatesInstalledDS()
|
||||
throws IOException {
|
||||
|
||||
// create target
|
||||
final String controllerId = TARGET_PREFIX + "registerTargets_1";
|
||||
final DistributionSet distributionSet = createTargetAndDistributionSetAndAssign(controllerId, DOWNLOAD_ONLY);
|
||||
@@ -927,29 +848,28 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
Mockito.verifyNoInteractions(getDeadletterListener());
|
||||
|
||||
// get actionId from Message
|
||||
final Long actionId = Long.parseLong(getJsonFieldFromBody(message.getBody(), "actionId"));
|
||||
final long actionId = Long.parseLong(getActionIdFromBody(message.getBody()));
|
||||
|
||||
// Send DOWNLOADED message, should result in the action being closed
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.DOWNLOADED);
|
||||
assertAction(actionId, 1, Status.RUNNING, Status.DOWNLOADED);
|
||||
Mockito.verifyNoInteractions(getDeadletterListener());
|
||||
|
||||
verifyAssignedDsAndInstalledDs(controllerId, distributionSet.getId(), null);
|
||||
verifyAssignedDsAndInstalledDs(distributionSet.getId(), null);
|
||||
|
||||
// Send FINISHED message
|
||||
createAndSendActionStatusUpdateMessage(controllerId, actionId, DmfActionStatus.FINISHED);
|
||||
assertAction(actionId, 2, Status.RUNNING, Status.DOWNLOADED, Status.FINISHED);
|
||||
Mockito.verifyNoInteractions(getDeadletterListener());
|
||||
|
||||
verifyAssignedDsAndInstalledDs(controllerId, distributionSet.getId(), distributionSet.getId());
|
||||
verifyAssignedDsAndInstalledDs(distributionSet.getId(), distributionSet.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Messages that result into certain exceptions being raised should not be requeued. This message should forwarded to the deadletter queue")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void ignoredExceptionTypesShouldNotBeRequeued() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void ignoredExceptionTypesShouldNotBeRequeued() {
|
||||
final ControllerManagement mockedControllerManagement = Mockito.mock(ControllerManagement.class);
|
||||
|
||||
final List<Class<? extends RuntimeException>> exceptionsThatShouldNotBeRequeued = Arrays
|
||||
.asList(IllegalArgumentException.class, EntityAlreadyExistsException.class);
|
||||
final String controllerId = "dummy_target";
|
||||
@@ -960,7 +880,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
.findOrRegisterTargetIfItDoesNotExist(eq(controllerId), any());
|
||||
|
||||
amqpMessageHandlerService.setControllerManagement(mockedControllerManagement);
|
||||
createAndSendThingCreated(controllerId, TENANT_EXIST);
|
||||
createAndSendThingCreated(controllerId);
|
||||
verifyOneDeadLetterMessage();
|
||||
assertThat(targetManagement.getByControllerID(controllerId)).isEmpty();
|
||||
}
|
||||
@@ -970,9 +890,8 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
}
|
||||
|
||||
@Step
|
||||
private void verifyAssignedDsAndInstalledDs(final String controllerId, final Long assignedDsId,
|
||||
final Long installedDsId) {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(controllerId);
|
||||
private void verifyAssignedDsAndInstalledDs(final Long assignedDsId, final Long installedDsId) {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(DMF_REGISTER_TEST_CONTROLLER_ID);
|
||||
assertThat(target).isPresent();
|
||||
|
||||
// verify the DS was assigned to the Target
|
||||
@@ -989,11 +908,11 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
}
|
||||
}
|
||||
|
||||
private void sendUpdateAttributesMessageWithGivenAttributes(final String target, final String key,
|
||||
final String value) {
|
||||
private void sendUpdateAttributesMessageWithGivenAttributes(final String key, final String value) {
|
||||
final DmfAttributeUpdate controllerAttribute = new DmfAttributeUpdate();
|
||||
controllerAttribute.getAttributes().put(key, value);
|
||||
final Message message = createUpdateAttributesMessage(target, TENANT_EXIST, controllerAttribute);
|
||||
final Message message = createUpdateAttributesMessage(UPDATE_ATTR_TEST_CONTROLLER_ID, TENANT_EXIST,
|
||||
controllerAttribute);
|
||||
getDmfClient().send(message);
|
||||
}
|
||||
|
||||
@@ -1041,9 +960,9 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
});
|
||||
}
|
||||
|
||||
private void sendUpdateAttributeMessage(final String target, final String tenant,
|
||||
final DmfAttributeUpdate attributeUpdate) {
|
||||
final Message updateMessage = createUpdateAttributesMessage(target, tenant, attributeUpdate);
|
||||
private void sendUpdateAttributeMessage(final DmfAttributeUpdate attributeUpdate) {
|
||||
final Message updateMessage = createUpdateAttributesMessage(DMF_ATTR_TEST_CONTROLLER_ID,
|
||||
AbstractAmqpServiceIntegrationTest.TENANT_EXIST, attributeUpdate);
|
||||
getDmfClient().send(updateMessage);
|
||||
}
|
||||
|
||||
@@ -1068,10 +987,10 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic
|
||||
Mockito.reset(getDeadletterListener());
|
||||
}
|
||||
|
||||
private static String getJsonFieldFromBody(final byte[] body, final String fieldName) throws IOException {
|
||||
private static String getActionIdFromBody(final byte[] body) throws IOException {
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
final ObjectNode node = objectMapper.readValue(new String(body, Charset.defaultCharset()), ObjectNode.class);
|
||||
assertThat(node.has(fieldName)).isTrue();
|
||||
return node.get(fieldName).asText();
|
||||
assertThat(node.has("actionId")).isTrue();
|
||||
return node.get("actionId").asText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,7 @@ import org.springframework.util.AntPathMatcher;
|
||||
/**
|
||||
* An abstraction for all controller based security to parse the e.g. the tenant
|
||||
* name from the URL and the controller ID from the URL to do security checks
|
||||
* based on these information.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* based on this information.
|
||||
*/
|
||||
public abstract class AbstractHttpControllerAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
@@ -77,8 +73,9 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
* @param systemSecurityContext
|
||||
* the system secruity context
|
||||
*/
|
||||
public AbstractHttpControllerAuthenticationFilter(final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final TenantAware tenantAware, final SystemSecurityContext systemSecurityContext) {
|
||||
protected AbstractHttpControllerAuthenticationFilter(
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||
this.tenantAware = tenantAware;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
@@ -127,7 +124,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
*
|
||||
* @param request
|
||||
* the Http request to extract the path variables.
|
||||
* @return the extracted {@link PathVariables} or {@code null} if the
|
||||
* @return the extracted {@link DmfTenantSecurityToken} or {@code null} if the
|
||||
* request does not match the pattern and no variables could be
|
||||
* extracted
|
||||
*/
|
||||
|
||||
@@ -8,15 +8,15 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.event.remote;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
/**
|
||||
* Generic deployment event for the Multi-Assignments feature. The event payload
|
||||
* holds a list of controller IDs identifying the targets which are affected by
|
||||
@@ -33,7 +33,7 @@ public abstract class MultiActionEvent extends RemoteTenantAwareEvent implements
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public MultiActionEvent() {
|
||||
protected MultiActionEvent() {
|
||||
// for serialization libs like jackson
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public abstract class MultiActionEvent extends RemoteTenantAwareEvent implements
|
||||
* @param actions
|
||||
* the actions involved
|
||||
*/
|
||||
public MultiActionEvent(String tenant, String applicationId, List<Action> actions) {
|
||||
protected MultiActionEvent(String tenant, String applicationId, List<Action> actions) {
|
||||
super(applicationId, tenant, applicationId);
|
||||
this.controllerIds.addAll(getControllerIdsFromActions(actions));
|
||||
this.actionIds.addAll(getIdsFromActions(actions));
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.event.remote.entity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
|
||||
/**
|
||||
@@ -16,15 +18,18 @@ import org.eclipse.hawkbit.repository.model.Action;
|
||||
public abstract class AbstractActionEvent extends RemoteEntityEvent<Action> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long targetId;
|
||||
private Long rolloutId;
|
||||
private Long rolloutGroupId;
|
||||
private final Long targetId;
|
||||
private final Long rolloutId;
|
||||
private final Long rolloutGroupId;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AbstractActionEvent() {
|
||||
protected AbstractActionEvent() {
|
||||
// for serialization libs like jackson
|
||||
this.targetId = null;
|
||||
this.rolloutId = null;
|
||||
this.rolloutGroupId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,7 +46,7 @@ public abstract class AbstractActionEvent extends RemoteEntityEvent<Action> {
|
||||
* @param applicationId
|
||||
* the origin application id
|
||||
*/
|
||||
public AbstractActionEvent(final Action action, final Long targetId, final Long rolloutId,
|
||||
protected AbstractActionEvent(final Action action, final Long targetId, final Long rolloutId,
|
||||
final Long rolloutGroupId, final String applicationId) {
|
||||
super(action, applicationId);
|
||||
this.targetId = targetId;
|
||||
@@ -61,4 +66,21 @@ public abstract class AbstractActionEvent extends RemoteEntityEvent<Action> {
|
||||
return rolloutGroupId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
if (!super.equals(o))
|
||||
return false;
|
||||
final AbstractActionEvent that = (AbstractActionEvent) o;
|
||||
return Objects.equals(targetId, that.targetId) && Objects.equals(rolloutId, that.rolloutId)
|
||||
&& Objects.equals(rolloutGroupId, that.rolloutGroupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), targetId, rolloutId, rolloutGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,26 +8,28 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.event.remote.entity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
|
||||
/**
|
||||
* TenantAwareEvent definition which is been published in case a rollout group
|
||||
* has been created for a specific rollout or updated.
|
||||
*
|
||||
* Event which is published in case a {@linkplain RolloutGroup} is created or
|
||||
* updated
|
||||
*/
|
||||
public abstract class AbstractRolloutGroupEvent extends RemoteEntityEvent<RolloutGroup> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long rolloutId;
|
||||
private final Long rolloutId;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AbstractRolloutGroupEvent() {
|
||||
protected AbstractRolloutGroupEvent() {
|
||||
// for serialization libs like jackson
|
||||
this.rolloutId = null;
|
||||
}
|
||||
|
||||
public AbstractRolloutGroupEvent(final RolloutGroup rolloutGroup, final Long rolloutId,
|
||||
protected AbstractRolloutGroupEvent(final RolloutGroup rolloutGroup, final Long rolloutId,
|
||||
final String applicationId) {
|
||||
super(rolloutGroup, applicationId);
|
||||
this.rolloutId = rolloutId;
|
||||
@@ -37,4 +39,20 @@ public abstract class AbstractRolloutGroupEvent extends RemoteEntityEvent<Rollou
|
||||
return rolloutId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
if (!super.equals(o))
|
||||
return false;
|
||||
final AbstractRolloutGroupEvent that = (AbstractRolloutGroupEvent) o;
|
||||
return Objects.equals(rolloutId, that.rolloutId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), rolloutId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public abstract class AbstractAssignmentResult<T extends BaseEntity> {
|
||||
* @param unassignedEntity
|
||||
* {@link List} of unassigned entity.
|
||||
*/
|
||||
public AbstractAssignmentResult(final int alreadyAssigned, final List<? extends T> assignedEntity,
|
||||
protected AbstractAssignmentResult(final int alreadyAssigned, final List<? extends T> assignedEntity,
|
||||
final List<? extends T> unassignedEntity) {
|
||||
this.alreadyAssigned = alreadyAssigned;
|
||||
this.assignedEntity = assignedEntity;
|
||||
|
||||
@@ -156,12 +156,15 @@ public interface Action extends TenantAwareBaseEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if action type is either forced or time-forced <i>and</i> force-time is
|
||||
* exceeded.
|
||||
*
|
||||
* @return {@code true} if either the {@link #getActionType()} is
|
||||
* {@link ActionType#FORCED} or {@link ActionType#TIMEFORCED} but
|
||||
* then if the {@link #getForcedTime()} has been exceeded otherwise
|
||||
* always {@code false}
|
||||
* {@link ActionType#FORCED} or {@link ActionType#TIMEFORCED} but then
|
||||
* if the {@link #getForcedTime()} has been exceeded otherwise always
|
||||
* {@code false}
|
||||
*/
|
||||
default boolean isForce() {
|
||||
default boolean isForcedOrTimeForced() {
|
||||
switch (getActionType()) {
|
||||
case FORCED:
|
||||
return true;
|
||||
|
||||
@@ -14,6 +14,8 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent;
|
||||
@@ -74,9 +76,7 @@ public class RolloutStatusCache {
|
||||
* @return map of cached entries
|
||||
*/
|
||||
public Map<Long, List<TotalTargetCountActionStatus>> getRolloutStatus(final List<Long> rollouts) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_RO_NAME);
|
||||
|
||||
return retrieveFromCache(rollouts, cache);
|
||||
return retrieveFromCache(rollouts, getRolloutStatusCache());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,9 +88,7 @@ public class RolloutStatusCache {
|
||||
* @return map of cached entries
|
||||
*/
|
||||
public List<TotalTargetCountActionStatus> getRolloutStatus(final Long rolloutId) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_RO_NAME);
|
||||
|
||||
return retrieveFromCache(rolloutId, cache);
|
||||
return retrieveFromCache(rolloutId, getRolloutStatusCache());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,9 +100,7 @@ public class RolloutStatusCache {
|
||||
* @return map of cached entries
|
||||
*/
|
||||
public Map<Long, List<TotalTargetCountActionStatus>> getRolloutGroupStatus(final List<Long> rolloutGroups) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_GR_NAME);
|
||||
|
||||
return retrieveFromCache(rolloutGroups, cache);
|
||||
return retrieveFromCache(rolloutGroups, getGroupStatusCache());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,9 +112,7 @@ public class RolloutStatusCache {
|
||||
* @return map of cached entries
|
||||
*/
|
||||
public List<TotalTargetCountActionStatus> getRolloutGroupStatus(final Long groupId) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_GR_NAME);
|
||||
|
||||
return retrieveFromCache(groupId, cache);
|
||||
return retrieveFromCache(groupId, getGroupStatusCache());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,8 +123,7 @@ public class RolloutStatusCache {
|
||||
* map of cached entries
|
||||
*/
|
||||
public void putRolloutStatus(final Map<Long, List<TotalTargetCountActionStatus>> put) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_RO_NAME);
|
||||
putIntoCache(put, cache);
|
||||
putIntoCache(put, getRolloutStatusCache());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,10 +137,10 @@ public class RolloutStatusCache {
|
||||
*
|
||||
*/
|
||||
public void putRolloutStatus(final Long rolloutId, final List<TotalTargetCountActionStatus> status) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_RO_NAME);
|
||||
putIntoCache(rolloutId, status, cache);
|
||||
putIntoCache(rolloutId, status, getRolloutStatusCache());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put {@link TotalTargetCountActionStatus} for multiple
|
||||
* {@link RolloutGroup}s into cache.
|
||||
@@ -156,8 +149,7 @@ public class RolloutStatusCache {
|
||||
* map of cached entries
|
||||
*/
|
||||
public void putRolloutGroupStatus(final Map<Long, List<TotalTargetCountActionStatus>> put) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_GR_NAME);
|
||||
putIntoCache(put, cache);
|
||||
putIntoCache(put, getGroupStatusCache());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,17 +162,17 @@ public class RolloutStatusCache {
|
||||
* list to cache
|
||||
*/
|
||||
public void putRolloutGroupStatus(final Long groupId, final List<TotalTargetCountActionStatus> status) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_GR_NAME);
|
||||
putIntoCache(groupId, status, cache);
|
||||
putIntoCache(groupId, status, getGroupStatusCache());
|
||||
}
|
||||
|
||||
private Map<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> ids, final Cache cache) {
|
||||
private Map<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> ids,
|
||||
@NotNull final Cache cache) {
|
||||
return ids.stream().map(id -> cache.get(id, CachedTotalTargetCountActionStatus.class)).filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(CachedTotalTargetCountActionStatus::getId,
|
||||
CachedTotalTargetCountActionStatus::getStatus));
|
||||
}
|
||||
|
||||
private List<TotalTargetCountActionStatus> retrieveFromCache(final Long id, final Cache cache) {
|
||||
private List<TotalTargetCountActionStatus> retrieveFromCache(final Long id, @NotNull final Cache cache) {
|
||||
final CachedTotalTargetCountActionStatus cacheItem = cache.get(id, CachedTotalTargetCountActionStatus.class);
|
||||
|
||||
if (cacheItem == null) {
|
||||
@@ -190,17 +182,17 @@ public class RolloutStatusCache {
|
||||
return cacheItem.getStatus();
|
||||
}
|
||||
|
||||
private void putIntoCache(final Long id, final List<TotalTargetCountActionStatus> status, final Cache cache) {
|
||||
private void putIntoCache(final Long id, final List<TotalTargetCountActionStatus> status,
|
||||
@NotNull final Cache cache) {
|
||||
cache.put(id, new CachedTotalTargetCountActionStatus(id, status));
|
||||
}
|
||||
|
||||
private void putIntoCache(final Map<Long, List<TotalTargetCountActionStatus>> put, final Cache cache) {
|
||||
put.entrySet().forEach(entry -> cache.put(entry.getKey(),
|
||||
new CachedTotalTargetCountActionStatus(entry.getKey(), entry.getValue())));
|
||||
private void putIntoCache(final Map<Long, List<TotalTargetCountActionStatus>> put, @NotNull final Cache cache) {
|
||||
put.forEach((k, v) -> cache.put(k, new CachedTotalTargetCountActionStatus(k, v)));
|
||||
}
|
||||
|
||||
@EventListener(classes = AbstractActionEvent.class)
|
||||
void invalidateCachedTotalTargetCountActionStatus(final AbstractActionEvent event) {
|
||||
public void invalidateCachedTotalTargetCountActionStatus(final AbstractActionEvent event) {
|
||||
if (event.getRolloutId() != null) {
|
||||
final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME));
|
||||
cache.evict(event.getRolloutId());
|
||||
@@ -213,19 +205,19 @@ public class RolloutStatusCache {
|
||||
}
|
||||
|
||||
@EventListener(classes = RolloutDeletedEvent.class)
|
||||
void invalidateCachedTotalTargetCountOnRolloutDelete(final RolloutDeletedEvent event) {
|
||||
public void invalidateCachedTotalTargetCountOnRolloutDelete(final RolloutDeletedEvent event) {
|
||||
final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME));
|
||||
cache.evict(event.getEntityId());
|
||||
}
|
||||
|
||||
@EventListener(classes = RolloutGroupDeletedEvent.class)
|
||||
void invalidateCachedTotalTargetCountOnRolloutGroupDelete(final RolloutGroupDeletedEvent event) {
|
||||
public void invalidateCachedTotalTargetCountOnRolloutGroupDelete(final RolloutGroupDeletedEvent event) {
|
||||
final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_GR_NAME));
|
||||
cache.evict(event.getEntityId());
|
||||
}
|
||||
|
||||
@EventListener(classes = RolloutStoppedEvent.class)
|
||||
void invalidateCachedTotalTargetCountOnRolloutStopped(final RolloutStoppedEvent event) {
|
||||
public void invalidateCachedTotalTargetCountOnRolloutStopped(final RolloutStoppedEvent event) {
|
||||
final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME));
|
||||
cache.evict(event.getRolloutId());
|
||||
|
||||
@@ -247,6 +239,14 @@ public class RolloutStatusCache {
|
||||
cacheManager.evictCaches(tenant);
|
||||
}
|
||||
|
||||
private @NotNull Cache getRolloutStatusCache() {
|
||||
return Objects.requireNonNull(cacheManager.getCache(CACHE_RO_NAME), "Cache '" + CACHE_RO_NAME + "' is null!");
|
||||
}
|
||||
|
||||
private @NotNull Cache getGroupStatusCache() {
|
||||
return Objects.requireNonNull(cacheManager.getCache(CACHE_GR_NAME), "Cache '" + CACHE_RO_NAME + "' is null!");
|
||||
}
|
||||
|
||||
private static final class CachedTotalTargetCountActionStatus {
|
||||
private final long id;
|
||||
private final List<TotalTargetCountActionStatus> status;
|
||||
|
||||
@@ -14,6 +14,7 @@ import javax.persistence.PersistenceException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.orm.jpa.JpaSystemException;
|
||||
import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect;
|
||||
|
||||
@@ -53,13 +54,12 @@ public class HawkBitEclipseLinkJpaDialect extends EclipseLinkJpaDialect {
|
||||
private static final SQLStateSQLExceptionTranslator SQLSTATE_EXCEPTION_TRANSLATOR = new SQLStateSQLExceptionTranslator();
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(final RuntimeException ex) {
|
||||
public DataAccessException translateExceptionIfPossible(@NonNull final RuntimeException ex) {
|
||||
final DataAccessException dataAccessException = super.translateExceptionIfPossible(ex);
|
||||
|
||||
if (dataAccessException == null) {
|
||||
return searchAndTranslateSqlException(ex);
|
||||
}
|
||||
|
||||
return translateJpaSystemExceptionIfPossible(dataAccessException);
|
||||
}
|
||||
|
||||
@@ -69,22 +69,19 @@ public class HawkBitEclipseLinkJpaDialect extends EclipseLinkJpaDialect {
|
||||
return accessException;
|
||||
}
|
||||
|
||||
final DataAccessException sql = searchAndTranslateSqlException(accessException);
|
||||
if (sql == null) {
|
||||
final DataAccessException sqlException = searchAndTranslateSqlException(accessException);
|
||||
if (sqlException == null) {
|
||||
return accessException;
|
||||
}
|
||||
|
||||
return sql;
|
||||
return sqlException;
|
||||
}
|
||||
|
||||
private static DataAccessException searchAndTranslateSqlException(final RuntimeException ex) {
|
||||
final SQLException sqlException = findSqlException(ex);
|
||||
|
||||
if (sqlException == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SQLSTATE_EXCEPTION_TRANSLATOR.translate(null, null, sqlException);
|
||||
return SQLSTATE_EXCEPTION_TRANSLATOR.translate("", null, sqlException);
|
||||
}
|
||||
|
||||
private static SQLException findSqlException(final RuntimeException jpaSystemException) {
|
||||
|
||||
@@ -767,7 +767,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
final JpaAction action = actionRepository.findById(actionId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
|
||||
if (!action.isForce()) {
|
||||
if (!action.isForcedOrTimeForced()) {
|
||||
action.setActionType(ActionType.FORCED);
|
||||
return actionRepository.save(action);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -25,7 +24,6 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
@@ -202,11 +200,11 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
// Create if it does not exist
|
||||
if (result == null) {
|
||||
try {
|
||||
currentTenantCacheKeyGenerator.getCreateInitialTenant().set(tenant);
|
||||
currentTenantCacheKeyGenerator.setTenantInCreation(tenant);
|
||||
return createInitialTenantMetaData(tenant);
|
||||
|
||||
} finally {
|
||||
currentTenantCacheKeyGenerator.getCreateInitialTenant().remove();
|
||||
currentTenantCacheKeyGenerator.removeTenantInCreation();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -276,20 +274,17 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
if (tenantAware.getCurrentTenant() == null) {
|
||||
throw new IllegalStateException("Tenant not set");
|
||||
}
|
||||
|
||||
return getTenantMetadata(tenantAware.getCurrentTenant());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator", cacheManager = "directCacheManager", unless = "#result == null")
|
||||
public String currentTenant() {
|
||||
final String initialTenantCreation = currentTenantCacheKeyGenerator.getCreateInitialTenant().get();
|
||||
if (initialTenantCreation == null) {
|
||||
return currentTenantCacheKeyGenerator.getTenantInCreation().orElseGet(() -> {
|
||||
final TenantMetaData findByTenant = tenantMetaDataRepository
|
||||
.findByTenantIgnoreCase(tenantAware.getCurrentTenant());
|
||||
return findByTenant != null ? findByTenant.getTenant() : null;
|
||||
}
|
||||
return initialTenantCreation;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -312,7 +307,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
Integer.MAX_VALUE));
|
||||
final SoftwareModuleType os = softwareModuleTypeRepository.save(new JpaSoftwareModuleType(
|
||||
org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_OS_KEY,
|
||||
org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_OS_NAME, "Core firmware or operationg system", 1));
|
||||
org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_OS_NAME, "Core firmware or operation system", 1));
|
||||
|
||||
// make sure the module types get their IDs
|
||||
entityManager.flush();
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -18,7 +22,6 @@ import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CurrentTenantCacheKeyGenerator}.
|
||||
*
|
||||
*/
|
||||
public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyGenerator {
|
||||
|
||||
@@ -28,25 +31,17 @@ public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyG
|
||||
private final ThreadLocal<String> createInitialTenant = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* A implementation of the {@link KeyGenerator} to generate a key based on
|
||||
* An implementation of the {@link KeyGenerator} to generate a key based on
|
||||
* either the {@code createInitialTenant} thread local and the
|
||||
* {@link TenantAware}, but in case we are in a tenant creation with its
|
||||
* default types we need to use the tenant the current tenant which is
|
||||
* currently created and not the one currently in the {@link TenantAware}.
|
||||
*
|
||||
* {@link TenantAware}, but in case we are in a tenant creation with its default
|
||||
* types we need to use as the tenant the current tenant which is currently
|
||||
* created and not the one currently in the {@link TenantAware}.
|
||||
*/
|
||||
public class CurrentTenantKeyGenerator implements KeyGenerator {
|
||||
@Override
|
||||
// Exception squid:S923 - override
|
||||
@SuppressWarnings({ "squid:S923" })
|
||||
public Object generate(final Object target, final Method method, final Object... params) {
|
||||
final String initialTenantCreation = createInitialTenant.get();
|
||||
if (initialTenantCreation == null) {
|
||||
return SimpleKeyGenerator.generateKey(tenantAware.getCurrentTenant().toUpperCase(),
|
||||
tenantAware.getCurrentTenant().toUpperCase());
|
||||
}
|
||||
return SimpleKeyGenerator.generateKey(initialTenantCreation.toUpperCase(),
|
||||
initialTenantCreation.toUpperCase());
|
||||
String tenant = getTenantInCreation().orElseGet(() -> tenantAware.getCurrentTenant()).toUpperCase();
|
||||
return SimpleKeyGenerator.generateKey(tenant, tenant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +51,33 @@ public class SystemManagementCacheKeyGenerator implements CurrentTenantCacheKeyG
|
||||
return new CurrentTenantKeyGenerator();
|
||||
}
|
||||
|
||||
ThreadLocal<String> getCreateInitialTenant() {
|
||||
return createInitialTenant;
|
||||
/**
|
||||
* Get the tenant which overwrites the actual tenant used by the
|
||||
* {@linkplain #currentTenantKeyGenerator()}.
|
||||
*
|
||||
* @return A present optional in case that there is a tenant in the progress of
|
||||
* creation.
|
||||
*/
|
||||
public Optional<String> getTenantInCreation() {
|
||||
return Optional.ofNullable(createInitialTenant.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the tenant used by the key generator in case that the tenant is in
|
||||
* the process of creation.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant which should be used instead of the actual one.
|
||||
*/
|
||||
public void setTenantInCreation(@NotNull String tenant) {
|
||||
createInitialTenant.set(Objects.requireNonNull(tenant));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the tenant overwriting the standard one used by the
|
||||
* {@linkplain #currentTenantKeyGenerator()}.
|
||||
*/
|
||||
public void removeTenantInCreation() {
|
||||
createInitialTenant.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.configuration;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.transaction.Transaction;
|
||||
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
@@ -37,8 +40,10 @@ public class MultiTenantJpaTransactionManager extends JpaTransactionManager {
|
||||
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant != null) {
|
||||
final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager
|
||||
.getResource(getEntityManagerFactory());
|
||||
final EntityManagerFactory emFactory = Objects.requireNonNull(getEntityManagerFactory());
|
||||
final EntityManagerHolder emHolder = Objects.requireNonNull(
|
||||
(EntityManagerHolder) TransactionSynchronizationManager.getResource(emFactory),
|
||||
"No EntityManagerHolder provided by TransactionSynchronizationManager");
|
||||
final EntityManager em = emHolder.getEntityManager();
|
||||
em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, currentTenant.toUpperCase());
|
||||
}
|
||||
|
||||
@@ -55,34 +55,34 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
||||
/**
|
||||
* Default constructor needed for JPA entities.
|
||||
*/
|
||||
public AbstractJpaBaseEntity() {
|
||||
protected AbstractJpaBaseEntity() {
|
||||
// Default constructor needed for JPA entities.
|
||||
}
|
||||
|
||||
@Override
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "created_at", insertable = true, updatable = false, nullable = false)
|
||||
@Column(name = "created_at", updatable = false, nullable = false)
|
||||
public long getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "created_by", insertable = true, updatable = false, nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||
@Column(name = "created_by", updatable = false, nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "last_modified_at", insertable = true, updatable = true, nullable = false)
|
||||
@Column(name = "last_modified_at", nullable = false)
|
||||
public long getLastModifiedAt() {
|
||||
return lastModifiedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "last_modified_by", insertable = true, updatable = true, nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||
@Column(name = "last_modified_by", nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||
public String getLastModifiedBy() {
|
||||
return lastModifiedBy;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
@@ -36,12 +38,12 @@ public abstract class AbstractJpaMetaData implements MetaData {
|
||||
@Basic
|
||||
private String value;
|
||||
|
||||
public AbstractJpaMetaData(final String key, final String value) {
|
||||
protected AbstractJpaMetaData(final String key, final String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public AbstractJpaMetaData() {
|
||||
protected AbstractJpaMetaData() {
|
||||
// Default constructor needed for JPA entities
|
||||
}
|
||||
|
||||
@@ -64,41 +66,17 @@ public abstract class AbstractJpaMetaData implements MetaData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
final AbstractJpaMetaData that = (AbstractJpaMetaData) o;
|
||||
return Objects.equals(key, that.key) && Objects.equals(value, that.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
public int hashCode() {
|
||||
return Objects.hash(key, value);
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(this.getClass().isInstance(obj))) {
|
||||
return false;
|
||||
}
|
||||
final AbstractJpaMetaData other = (AbstractJpaMetaData) obj;
|
||||
if (key == null) {
|
||||
if (other.key != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!key.equals(other.key)) {
|
||||
return false;
|
||||
}
|
||||
if (value == null) {
|
||||
if (other.value != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!value.equals(other.value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,14 +32,14 @@ public abstract class AbstractJpaNamedEntity extends AbstractJpaTenantAwareBaseE
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
@Column(name = "description", nullable = true, length = NamedEntity.DESCRIPTION_MAX_SIZE)
|
||||
@Column(name = "description", length = NamedEntity.DESCRIPTION_MAX_SIZE)
|
||||
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AbstractJpaNamedEntity() {
|
||||
protected AbstractJpaNamedEntity() {
|
||||
// Default constructor needed for JPA entities
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn
|
||||
/**
|
||||
* Default constructor needed for JPA entities.
|
||||
*/
|
||||
public AbstractJpaTenantAwareBaseEntity() {
|
||||
protected AbstractJpaTenantAwareBaseEntity() {
|
||||
// Default constructor needed for JPA entities.
|
||||
}
|
||||
|
||||
|
||||
@@ -299,22 +299,10 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeModule(final SoftwareModule softwareModule) {
|
||||
if (modules == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Optional<SoftwareModule> found = modules.stream()
|
||||
.filter(module -> module.getId().equals(softwareModule.getId())).findAny();
|
||||
|
||||
if (found.isPresent()) {
|
||||
modules.remove(found.get());
|
||||
public void removeModule(final SoftwareModule softwareModule) {
|
||||
if (modules != null && modules.removeIf(m -> m.getId().equals(softwareModule.getId()))) {
|
||||
complete = type.checkComplete(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -371,11 +359,11 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
private static boolean isSoftDeleted(final DescriptorEvent event) {
|
||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||
final List<DirectToFieldChangeRecord> changes = changeSet.getChanges().stream()
|
||||
.filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||
.map(record -> (DirectToFieldChangeRecord) record).collect(Collectors.toList());
|
||||
.filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return changes.stream().filter(record -> DELETED_PROPERTY.equals(record.getAttribute())
|
||||
&& Boolean.parseBoolean(record.getNewValue().toString())).count() > 0;
|
||||
return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute())
|
||||
&& Boolean.parseBoolean(changeRecord.getNewValue().toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -278,11 +278,11 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
|
||||
private static boolean isSoftDeleted(final DescriptorEvent event) {
|
||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||
final List<DirectToFieldChangeRecord> changes = changeSet.getChanges().stream()
|
||||
.filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||
.map(record -> (DirectToFieldChangeRecord) record).collect(Collectors.toList());
|
||||
.filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return changes.stream().filter(record -> DELETED_PROPERTY.equals(record.getAttribute())
|
||||
&& Boolean.parseBoolean(record.getNewValue().toString())).count() > 0;
|
||||
return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute())
|
||||
&& Boolean.parseBoolean(changeRecord.getNewValue().toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -258,11 +258,11 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement
|
||||
private static boolean isSoftDeleted(final DescriptorEvent event) {
|
||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||
final List<DirectToFieldChangeRecord> changes = changeSet.getChanges().stream()
|
||||
.filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||
.map(record -> (DirectToFieldChangeRecord) record).collect(Collectors.toList());
|
||||
.filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return changes.stream().filter(record -> DELETED_PROPERTY.equals(record.getAttribute())
|
||||
&& Boolean.parseBoolean(record.getNewValue().toString())).count() > 0;
|
||||
return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute())
|
||||
&& Boolean.parseBoolean(changeRecord.getNewValue().toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -96,7 +96,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
|
||||
@Column(name = "controller_id", length = Target.CONTROLLER_ID_MAX_SIZE, updatable = false, nullable = false)
|
||||
@Size(min = 1, max = Target.CONTROLLER_ID_MAX_SIZE)
|
||||
@NotNull
|
||||
@Pattern(regexp = "[.\\S]*", message = "has whitespaces which are not allowed")
|
||||
@Pattern(regexp = "[\\S]*", message = "has whitespaces which are not allowed")
|
||||
private String controllerId;
|
||||
|
||||
@CascadeOnDelete
|
||||
@@ -243,34 +243,28 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
|
||||
if (rolloutTargetGroup == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(rolloutTargetGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tag
|
||||
* tag
|
||||
* @return boolean true or false
|
||||
* to be added
|
||||
*/
|
||||
public boolean addTag(final TargetTag tag) {
|
||||
public void addTag(final TargetTag tag) {
|
||||
if (tags == null) {
|
||||
tags = new HashSet<>();
|
||||
}
|
||||
|
||||
return tags.add(tag);
|
||||
tags.add(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tag
|
||||
* tag
|
||||
* @return boolean true or false
|
||||
* the tag to be removed from the target
|
||||
*/
|
||||
public boolean removeTag(final TargetTag tag) {
|
||||
if (tags == null) {
|
||||
return false;
|
||||
public void removeTag(final TargetTag tag) {
|
||||
if (tags != null) {
|
||||
tags.remove(tag);
|
||||
}
|
||||
|
||||
return tags.remove(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,14 +297,12 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
|
||||
/**
|
||||
* @param action
|
||||
* Action
|
||||
* @return boolean true or false
|
||||
*/
|
||||
public boolean addAction(final Action action) {
|
||||
public void addAction(final Action action) {
|
||||
if (actions == null) {
|
||||
actions = new ArrayList<>();
|
||||
}
|
||||
|
||||
return actions.add((JpaAction) action);
|
||||
actions.add((JpaAction) action);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.repository.FieldNameProvider;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.slf4j.Logger;
|
||||
@@ -25,7 +27,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
||||
|
||||
private final Class<A> fieldNameProvider;
|
||||
|
||||
public AbstractFieldNameRSQLVisitor(final Class<A> fieldNameProvider) {
|
||||
protected AbstractFieldNameRSQLVisitor(final Class<A> fieldNameProvider) {
|
||||
this.fieldNameProvider = fieldNameProvider;
|
||||
}
|
||||
|
||||
@@ -51,7 +53,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
||||
|
||||
// sub entity need minimum 1 dot
|
||||
if (!propertyEnum.getSubEntityAttributes().isEmpty() && graph.length < 2) {
|
||||
throw createRSQLParameterUnsupportedException(node);
|
||||
throw createRSQLParameterUnsupportedException(node, null);
|
||||
}
|
||||
|
||||
final StringBuilder fieldNameBuilder = new StringBuilder(propertyEnum.getFieldName());
|
||||
@@ -67,7 +69,7 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
||||
}
|
||||
|
||||
if (!propertyEnum.containsSubEntityAttribute(propertyField)) {
|
||||
throw createRSQLParameterUnsupportedException(node);
|
||||
throw createRSQLParameterUnsupportedException(node, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,30 +95,21 @@ public abstract class AbstractFieldNameRSQLVisitor<A extends Enum<A> & FieldName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* current processing node
|
||||
* @param rootException
|
||||
* in case there is a cause otherwise {@code null}
|
||||
* @return Exception with prepared message extracted from the comparison node.
|
||||
*/
|
||||
protected RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(
|
||||
final ComparisonNode node) {
|
||||
return createRSQLParameterUnsupportedException(node, new Exception());
|
||||
}
|
||||
|
||||
protected RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(final ComparisonNode node,
|
||||
@NotNull final ComparisonNode node,
|
||||
final Exception rootException) {
|
||||
return createRSQLParameterUnsupportedException(String.format(
|
||||
return new RSQLParameterUnsupportedFieldException(String.format(
|
||||
"The given search parameter field {%s} does not exist, must be one of the following fields %s",
|
||||
node.getSelector(), getExpectedFieldList()), rootException);
|
||||
}
|
||||
|
||||
protected RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(final String message) {
|
||||
return createRSQLParameterUnsupportedException(message, null);
|
||||
}
|
||||
|
||||
protected RSQLParameterUnsupportedFieldException createRSQLParameterUnsupportedException(final String message,
|
||||
final Exception rootException) {
|
||||
return new RSQLParameterUnsupportedFieldException(message, rootException);
|
||||
}
|
||||
|
||||
// Exception squid:S2095 - see
|
||||
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
private List<String> getExpectedFieldList() {
|
||||
final List<String> expectedFieldList = Arrays.stream(fieldNameProvider.getEnumConstants())
|
||||
.filter(enumField -> enumField.getSubEntityAttributes().isEmpty()).map(enumField -> {
|
||||
|
||||
@@ -181,7 +181,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
private Path<Object> getFieldPath(final A enumField, final String finalProperty) {
|
||||
return (Path<Object>) getFieldPath(root, enumField.getSubAttributes(finalProperty), enumField.isMap(),
|
||||
this::getJoinFieldPath).orElseThrow(
|
||||
() -> createRSQLParameterUnsupportedException("RSQL field path cannot be empty", null));
|
||||
() -> new RSQLParameterUnsupportedFieldException("RSQL field path cannot be empty", null));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -279,7 +279,7 @@ public class JpaQueryRsqlVisitor<A extends Enum<A> & FieldNameProvider, T> exten
|
||||
private Object convertFieldConverterValue(final ComparisonNode node, final A fieldName, final String value) {
|
||||
final Object convertedValue = ((FieldValueConverter) fieldName).convertValue(fieldName, value);
|
||||
if (convertedValue == null) {
|
||||
throw createRSQLParameterUnsupportedException(
|
||||
throw new RSQLParameterUnsupportedFieldException(
|
||||
"field {" + node.getSelector() + "} must be one of the following values {"
|
||||
+ Arrays.toString(((FieldValueConverter) fieldName).possibleValues(fieldName)) + "}",
|
||||
null);
|
||||
|
||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import cz.jirutka.rsql.parser.ParseException;
|
||||
|
||||
@@ -24,13 +24,7 @@ import cz.jirutka.rsql.parser.ParseException;
|
||||
*/
|
||||
public class ParseExceptionWrapper {
|
||||
|
||||
private static final String FIELD_EXPECTED_TOKEN_SEQ = "expectedTokenSequences";
|
||||
private static final String FIELD_CURRENT_TOKEN = "currentToken";
|
||||
|
||||
private final ParseException parseException;
|
||||
private final Class<? extends ParseException> parseExceptionClass;
|
||||
private Field expectedTokenSequenceField;
|
||||
private Field currentTokenField;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -41,33 +35,24 @@ public class ParseExceptionWrapper {
|
||||
*/
|
||||
public ParseExceptionWrapper(final ParseException parseException) {
|
||||
this.parseException = parseException;
|
||||
parseExceptionClass = parseException.getClass();
|
||||
|
||||
try {
|
||||
expectedTokenSequenceField = getAccessibleField(parseExceptionClass, FIELD_EXPECTED_TOKEN_SEQ);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
expectedTokenSequenceField = null;
|
||||
}
|
||||
|
||||
try {
|
||||
currentTokenField = getAccessibleField(parseExceptionClass, FIELD_CURRENT_TOKEN);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
currentTokenField = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int[][] getExpectedTokenSequence() {
|
||||
if (expectedTokenSequenceField == null) {
|
||||
return new int[0][0];
|
||||
}
|
||||
return (int[][]) getValue(expectedTokenSequenceField, parseException);
|
||||
return (parseException.expectedTokenSequences != null) // unclear if this can happen
|
||||
? parseException.expectedTokenSequences
|
||||
: new int[0][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current token
|
||||
*
|
||||
* @return the current token or {@code null} if there is non.
|
||||
*/
|
||||
public TokenWrapper getCurrentToken() {
|
||||
if (currentTokenField == null) {
|
||||
return null;
|
||||
}
|
||||
return new TokenWrapper(getValue(currentTokenField, parseException));
|
||||
return (parseException.currentToken != null) // unclear if this can happen
|
||||
? new TokenWrapper(parseException.currentToken)
|
||||
: null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,19 +61,6 @@ public class ParseExceptionWrapper {
|
||||
+ ", getCurrentToken()=" + getCurrentToken() + "]";
|
||||
}
|
||||
|
||||
private static Field getAccessibleField(final Class<?> clazz, final String field) throws NoSuchFieldException {
|
||||
final Field declaredField = clazz.getDeclaredField(field);
|
||||
declaredField.setAccessible(true);
|
||||
return declaredField;
|
||||
}
|
||||
|
||||
private static Object getValue(final Field field, final Object instance) {
|
||||
try {
|
||||
return field.get(instance);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link TokenWrapper} which wraps the
|
||||
@@ -115,37 +87,37 @@ public class ParseExceptionWrapper {
|
||||
this.tokenInstance = tokenField;
|
||||
|
||||
try {
|
||||
nextTokenField = getAccessibleField(tokenField.getClass(), FIELD_NEXT);
|
||||
nextTokenField = getAccessibleField(FIELD_NEXT);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
nextTokenField = null;
|
||||
}
|
||||
try {
|
||||
kindTokenField = getAccessibleField(tokenField.getClass(), FIELD_KIND);
|
||||
kindTokenField = getAccessibleField(FIELD_KIND);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
kindTokenField = null;
|
||||
}
|
||||
|
||||
try {
|
||||
imageTokenField = getAccessibleField(tokenField.getClass(), FIELD_IMAGE);
|
||||
imageTokenField = getAccessibleField(FIELD_IMAGE);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
imageTokenField = null;
|
||||
}
|
||||
|
||||
try {
|
||||
beginColumnTokenField = getAccessibleField(tokenField.getClass(), FIELD_BEGIN_COL);
|
||||
beginColumnTokenField = getAccessibleField(FIELD_BEGIN_COL);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
beginColumnTokenField = null;
|
||||
}
|
||||
|
||||
try {
|
||||
endColumnTokenField = getAccessibleField(tokenField.getClass(), FIELD_END_COL);
|
||||
endColumnTokenField = getAccessibleField(FIELD_END_COL);
|
||||
} catch (@SuppressWarnings("squid:S1166") final NoSuchFieldException e) {
|
||||
endColumnTokenField = null;
|
||||
}
|
||||
}
|
||||
|
||||
public TokenWrapper getNext() {
|
||||
final Object nextToken = getValue(nextTokenField, tokenInstance);
|
||||
final Object nextToken = getValue(nextTokenField);
|
||||
return nextToken != null ? new TokenWrapper(nextToken) : null;
|
||||
|
||||
}
|
||||
@@ -154,28 +126,42 @@ public class ParseExceptionWrapper {
|
||||
if (kindTokenField == null) {
|
||||
return 0;
|
||||
}
|
||||
return (int) getValue(kindTokenField, tokenInstance);
|
||||
return (int) getValue(kindTokenField);
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
if (imageTokenField == null) {
|
||||
return null;
|
||||
}
|
||||
return (String) getValue(imageTokenField, tokenInstance);
|
||||
return (String) getValue(imageTokenField);
|
||||
}
|
||||
|
||||
public int getBeginColumn() {
|
||||
if (beginColumnTokenField == null) {
|
||||
return 0;
|
||||
}
|
||||
return (int) getValue(beginColumnTokenField, tokenInstance);
|
||||
return (int) getValue(beginColumnTokenField);
|
||||
}
|
||||
|
||||
public int getEndColumn() {
|
||||
if (endColumnTokenField == null) {
|
||||
return 0;
|
||||
}
|
||||
return (int) getValue(endColumnTokenField, tokenInstance);
|
||||
return (int) getValue(endColumnTokenField);
|
||||
}
|
||||
|
||||
private Field getAccessibleField(final String field) throws NoSuchFieldException {
|
||||
final Field declaredField = tokenInstance.getClass().getDeclaredField(field);
|
||||
ReflectionUtils.makeAccessible(declaredField);
|
||||
return declaredField;
|
||||
}
|
||||
|
||||
private Object getValue(final Field field) {
|
||||
try {
|
||||
return field.get(tokenInstance);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new IllegalFieldAccessExeption(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,4 +171,11 @@ public class ParseExceptionWrapper {
|
||||
+ ", getEndColumn()=" + getEndColumn() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
static class IllegalFieldAccessExeption extends RuntimeException {
|
||||
public IllegalFieldAccessExeption(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ public class RsqlParserValidationOracle implements RsqlValidationOracle {
|
||||
private static List<SuggestToken> getNextTokens(final ParseException parseException) {
|
||||
final List<SuggestToken> listTokens = new ArrayList<>();
|
||||
final ParseExceptionWrapper parseExceptionWrapper = new ParseExceptionWrapper(parseException);
|
||||
final int[][] expectedTokenSequence = parseExceptionWrapper.getExpectedTokenSequence();
|
||||
final int[][] expectedTokenSequence = parseException.expectedTokenSequences;
|
||||
final TokenWrapper currentToken = parseExceptionWrapper.getCurrentToken();
|
||||
if (currentToken == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -243,8 +243,8 @@ public class RsqlParserValidationOracle implements RsqlValidationOracle {
|
||||
}
|
||||
builder = builder.replace('\r', ' ');
|
||||
builder = builder.replace('\n', ' ');
|
||||
builder = builder.replaceAll(">", " ");
|
||||
builder = builder.replaceAll("<", " ");
|
||||
builder = builder.replace(">", " ");
|
||||
builder = builder.replace("<", " ");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -24,7 +26,7 @@ public class ActionTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that timeforced moded switch from soft to forces after defined timeframe.")
|
||||
public void timeforcedHitNewHasCodeIsGenerated() throws InterruptedException {
|
||||
public void timeforcedHitNewHasCodeIsGenerated() {
|
||||
|
||||
// current time + 1 seconds
|
||||
final long sleepTime = 1000;
|
||||
@@ -32,10 +34,10 @@ public class ActionTest {
|
||||
final JpaAction timeforcedAction = new JpaAction();
|
||||
timeforcedAction.setActionType(ActionType.TIMEFORCED);
|
||||
timeforcedAction.setForcedTime(timeForceTimeAt);
|
||||
assertThat(timeforcedAction.isForce()).isFalse();
|
||||
assertThat(timeforcedAction.isForcedOrTimeForced()).isFalse();
|
||||
|
||||
// wait until timeforce time is hit
|
||||
Thread.sleep(sleepTime + 100);
|
||||
assertThat(timeforcedAction.isForce()).isTrue();
|
||||
Awaitility.await().atMost(Duration.TWO_SECONDS).pollInterval(Duration.ONE_HUNDRED_MILLISECONDS)
|
||||
.until(timeforcedAction::isForcedOrTimeForced);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,11 +50,11 @@ import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedE
|
||||
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.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
@@ -69,6 +69,7 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.TargetTestData;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
@@ -85,7 +86,7 @@ import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Controller Management")
|
||||
public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private RepositoryProperties repositoryProperties;
|
||||
@@ -95,7 +96,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final SoftwareModule module = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
@@ -116,7 +117,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
+ " by means of throwing EntityNotFoundException.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() throws URISyntaxException {
|
||||
void entityQueriesReferringToNotExistingEntitiesThrowsException() throws URISyntaxException {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final SoftwareModule module = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
@@ -157,7 +158,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerConfirmsUpdateWithFinished() {
|
||||
void controllerConfirmsUpdateWithFinished() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
simulateIntermediateStatusOnUpdate(actionId);
|
||||
@@ -178,7 +179,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerConfirmationFailsWithInvalidMessages() {
|
||||
void controllerConfirmationFailsWithInvalidMessages() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
simulateIntermediateStatusOnUpdate(actionId);
|
||||
@@ -209,7 +210,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerConfirmsUpdateWithFinishedAndIgnoresCancellationWithThat() {
|
||||
void controllerConfirmsUpdateWithFinishedAndIgnoresCancellationWithThat() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
|
||||
@@ -229,7 +230,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void cancellationFeedbackRejectedIfActionIsNotInCanceling() {
|
||||
void cancellationFeedbackRejectedIfActionIsNotInCanceling() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
assertThatExceptionOfType(CancelActionNotAllowedException.class)
|
||||
@@ -253,7 +254,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerConfirmsActionCancellationWithFinished() {
|
||||
void controllerConfirmsActionCancellationWithFinished() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -280,7 +281,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerConfirmsActionCancellationWithCanceled() {
|
||||
void controllerConfirmsActionCancellationWithCanceled() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -308,7 +309,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerRejectsActionCancellationWithReject() {
|
||||
void controllerRejectsActionCancellationWithReject() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -336,7 +337,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerRejectsActionCancellationWithError() {
|
||||
void controllerRejectsActionCancellationWithError() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
@@ -472,7 +473,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 2) })
|
||||
public void hasTargetArtifactAssignedIsTrueWithMultipleArtifacts() {
|
||||
void hasTargetArtifactAssignedIsTrueWithMultipleArtifacts() {
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte[] random = RandomUtils.nextBytes(artifactSize);
|
||||
|
||||
@@ -503,7 +504,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Register a controller which does not exist")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void findOrRegisterTargetIfItDoesNotExist() {
|
||||
void findOrRegisterTargetIfItDoesNotExist() {
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
assertThat(target).as("target should not be null").isNotNull();
|
||||
|
||||
@@ -516,7 +517,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Register a controller with name which does not exist and update its name")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 2), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void findOrRegisterTargetIfItDoesNotExistWithName() {
|
||||
void findOrRegisterTargetIfItDoesNotExistWithName() {
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST, "TestName");
|
||||
final Target sameTarget = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST,
|
||||
"ChangedTestName");
|
||||
@@ -528,7 +529,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Tries to register a target with an invalid controller id")
|
||||
public void findOrRegisterTargetIfItDoesNotExistThrowsExceptionForInvalidControllerIdParam() {
|
||||
void findOrRegisterTargetIfItDoesNotExistThrowsExceptionForInvalidControllerIdParam() {
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("register target with null as controllerId should fail")
|
||||
.isThrownBy(() -> controllerManagement.findOrRegisterTargetIfItDoesNotExist(null, LOCALHOST));
|
||||
@@ -550,7 +551,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Register a controller which does not exist, when a ConcurrencyFailureException is raised, the "
|
||||
+ "exception is rethrown after max retries")
|
||||
public void findOrRegisterTargetIfItDoesNotExistThrowsExceptionAfterMaxRetries() {
|
||||
void findOrRegisterTargetIfItDoesNotExistThrowsExceptionAfterMaxRetries() {
|
||||
final TargetRepository mockTargetRepository = Mockito.mock(TargetRepository.class);
|
||||
when(mockTargetRepository.findOne(any())).thenThrow(ConcurrencyFailureException.class);
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(mockTargetRepository);
|
||||
@@ -572,7 +573,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
+ "exception is not rethrown when the max retries are not yet reached")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void findOrRegisterTargetIfItDoesNotExistDoesNotThrowExceptionBeforeMaxRetries() {
|
||||
void findOrRegisterTargetIfItDoesNotExistDoesNotThrowExceptionBeforeMaxRetries() {
|
||||
|
||||
final TargetRepository mockTargetRepository = Mockito.mock(TargetRepository.class);
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(mockTargetRepository);
|
||||
@@ -598,7 +599,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Register a controller which does not exist, then update the controller twice, first time by providing a name property and second time without a new name")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 3), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void findOrRegisterTargetIfItDoesNotExistDoesUpdateNameOnExistingTargetProperly() {
|
||||
void findOrRegisterTargetIfItDoesNotExistDoesUpdateNameOnExistingTargetProperly() {
|
||||
|
||||
final String controllerId = "12345";
|
||||
final String targetName = "UpdatedName";
|
||||
@@ -620,7 +621,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Register a controller which does not exist, if a EntityAlreadyExistsException is raised, the "
|
||||
+ "exception is rethrown and no further retries will be attempted")
|
||||
public void findOrRegisterTargetIfItDoesNotExistDoesntRetryWhenEntityAlreadyExistsException() {
|
||||
void findOrRegisterTargetIfItDoesNotExistDoesntRetryWhenEntityAlreadyExistsException() {
|
||||
|
||||
final TargetRepository mockTargetRepository = Mockito.mock(TargetRepository.class);
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(mockTargetRepository);
|
||||
@@ -643,7 +644,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Retry is aborted when an unchecked exception is thrown and the exception should also be "
|
||||
+ "rethrown")
|
||||
public void recoverFindOrRegisterTargetIfItDoesNotExistIsNotInvokedForOtherExceptions() {
|
||||
void recoverFindOrRegisterTargetIfItDoesNotExistIsNotInvokedForOtherExceptions() {
|
||||
|
||||
final TargetRepository mockTargetRepository = Mockito.mock(TargetRepository.class);
|
||||
((JpaControllerManagement) controllerManagement).setTargetRepository(mockTargetRepository);
|
||||
@@ -666,7 +667,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6) })
|
||||
public void findTargetVisibleMetaDataBySoftwareModuleId() {
|
||||
void findTargetVisibleMetaDataBySoftwareModuleId() {
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
testdataFactory.addSoftwareModuleMetadata(set);
|
||||
|
||||
@@ -682,7 +683,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Verify that controller registration does not result in a TargetPollEvent if feature is disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 0) })
|
||||
public void targetPollEventNotSendIfDisabled() {
|
||||
void targetPollEventNotSendIfDisabled() {
|
||||
repositoryProperties.setPublishTargetPollEvent(false);
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
repositoryProperties.setPublishTargetPollEvent(true);
|
||||
@@ -696,7 +697,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void tryToFinishWithErrorUpdateProcessMoreThanOnce() {
|
||||
void tryToFinishWithErrorUpdateProcessMoreThanOnce() {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
// test and verify
|
||||
@@ -743,7 +744,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void tryToFinishUpdateProcessMoreThanOnce() {
|
||||
void tryToFinishUpdateProcessMoreThanOnce() {
|
||||
final Long actionId = prepareFinishedUpdate().getId();
|
||||
|
||||
// try with disabled late feedback
|
||||
@@ -780,7 +781,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void sendUpdatesForFinishUpdateProcessDroppedIfDisabled() {
|
||||
void sendUpdatesForFinishUpdateProcessDroppedIfDisabled() {
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(true);
|
||||
|
||||
final Action action = prepareFinishedUpdate();
|
||||
@@ -807,7 +808,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void sendUpdatesForFinishUpdateProcessAcceptedIfEnabled() {
|
||||
void sendUpdatesForFinishUpdateProcessAcceptedIfEnabled() {
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(false);
|
||||
|
||||
Action action = prepareFinishedUpdate();
|
||||
@@ -828,7 +829,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Ensures that target attribute update is reflected by the repository.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3) })
|
||||
public void updateTargetAttributes() throws Exception {
|
||||
void updateTargetAttributes() throws Exception {
|
||||
final String controllerId = "test123";
|
||||
final Target target = testdataFactory.createTarget(controllerId);
|
||||
|
||||
@@ -884,7 +885,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Ensures that target attributes can be updated using different update modes.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 4) })
|
||||
public void updateTargetAttributesWithDifferentUpdateModes() {
|
||||
void updateTargetAttributesWithDifferentUpdateModes() {
|
||||
|
||||
final String controllerId = "testCtrl";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
@@ -1027,33 +1028,28 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Checks if invalid values of attribute-key and attribute-value are handled correctly")
|
||||
public void updateTargetAttributesFailsForInvalidAttributes() {
|
||||
final String keyTooLong = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE + 1);
|
||||
final String keyValid = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE);
|
||||
final String valueTooLong = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE + 1);
|
||||
final String valueValid = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE);
|
||||
final String keyNull = null;
|
||||
|
||||
final String controllerId = "targetId123";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with key too long should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyTooLong, valueValid), null));
|
||||
Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_VALID), null));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with key too long and value too long should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyTooLong, valueTooLong), null));
|
||||
Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_TOO_LONG, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG), null));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with value too long should not be created")
|
||||
.isThrownBy(() -> controllerManagement.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(keyValid, valueTooLong), null));
|
||||
Collections.singletonMap(TargetTestData.ATTRIBUTE_KEY_VALID, TargetTestData.ATTRIBUTE_VALUE_TOO_LONG), null));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAttributeException.class)
|
||||
.as("Attribute with key NULL should not be created").isThrownBy(() -> controllerManagement
|
||||
.updateControllerAttributes(controllerId, Collections.singletonMap(keyNull, valueValid), null));
|
||||
.updateControllerAttributes(controllerId,
|
||||
Collections.singletonMap(null, TargetTestData.ATTRIBUTE_VALUE_VALID), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1198,7 +1194,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsDownloadedForDownloadOnlyAction() {
|
||||
void controllerReportsDownloadedForDownloadOnlyAction() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
@@ -1221,7 +1217,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsActionFinishedForDownloadOnlyActionThatIsNotActive() {
|
||||
void controllerReportsActionFinishedForDownloadOnlyActionThatIsNotActive() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
@@ -1244,7 +1240,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsMultipleDownloadedForDownloadOnlyAction() {
|
||||
void controllerReportsMultipleDownloadedForDownloadOnlyAction() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
@@ -1269,7 +1265,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 9),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void quotaExceptionWhencontrollerReportsTooManyDownloadedMessagesForDownloadOnlyAction() {
|
||||
void quotaExceptionWhencontrollerReportsTooManyDownloadedMessagesForDownloadOnlyAction() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
@@ -1289,7 +1285,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void quotaExceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForDownloadOnlyAction() {
|
||||
void quotaExceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForDownloadOnlyAction() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
@@ -1318,7 +1314,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void quotaExceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForForced() {
|
||||
void quotaExceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForForced() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
assertThat(actionId).isNotNull();
|
||||
@@ -1341,7 +1337,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that the attaching externalRef to an action is properly stored")
|
||||
public void updatedExternalRefOnActionIsReallyUpdated() {
|
||||
void updatedExternalRefOnActionIsReallyUpdated() {
|
||||
final List<String> allExternalRef = new ArrayList<>();
|
||||
final List<Long> allActionId = new ArrayList<>();
|
||||
final int numberOfActions = 3;
|
||||
@@ -1369,7 +1365,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that getting a single action using externalRef works")
|
||||
public void getActionUsingSingleExternalRef() {
|
||||
void getActionUsingSingleExternalRef() {
|
||||
|
||||
final String knownControllerId = "controllerId";
|
||||
final String knownExternalRef = "externalRefId";
|
||||
@@ -1392,7 +1388,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that a null externalRef cannot be assigned to an action")
|
||||
public void externalRefCannotBeNull() {
|
||||
void externalRefCannotBeNull() {
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("No ConstraintViolationException thrown when a null externalRef was set on an action")
|
||||
.isThrownBy(() -> controllerManagement.updateActionExternalRef(1L, null));
|
||||
@@ -1408,7 +1404,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 6),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 8),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 12) })
|
||||
public void targetCanAlwaysReportFinishedOrErrorAfterActionIsClosedForDownloadOnlyAssignments() {
|
||||
void targetCanAlwaysReportFinishedOrErrorAfterActionIsClosedForDownloadOnlyAssignments() {
|
||||
|
||||
testdataFactory.createTarget();
|
||||
|
||||
@@ -1459,7 +1455,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6) })
|
||||
public void controllerReportsFinishedForOldDownloadOnlyActionAfterSuccessfulForcedAssignment() {
|
||||
void controllerReportsFinishedForOldDownloadOnlyActionAfterSuccessfulForcedAssignment() {
|
||||
|
||||
testdataFactory.createTarget();
|
||||
final DistributionSet downloadOnlyDs = testdataFactory.createDistributionSet("downloadOnlyDs1");
|
||||
@@ -1495,7 +1491,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Actions are exposed according to thier weight in multi assignment mode.")
|
||||
public void actionsAreExposedAccordingToTheirWeight() {
|
||||
void actionsAreExposedAccordingToTheirWeight() {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
final Long actionWeightNull = assignDistributionSet(ds.getId(), targetId).getAssignedEntity().get(0).getId();
|
||||
@@ -1552,7 +1548,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Delete a target on requested target deletion from client side")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1), @Expect(type = TargetDeletedEvent.class, count = 1) })
|
||||
public void deleteTargetWithValidThingId() {
|
||||
void deleteTargetWithValidThingId() {
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
assertThat(target).as("target should not be null").isNotNull();
|
||||
assertThat(targetRepository.count()).as("target exists and is ready for deletion").isEqualTo(1L);
|
||||
@@ -1565,7 +1561,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Delete a target with a non existing thingId")
|
||||
@ExpectEvents({ @Expect(type = TargetDeletedEvent.class, count = 0) })
|
||||
public void deleteTargetWithInvalidThingId() {
|
||||
void deleteTargetWithInvalidThingId() {
|
||||
assertThatExceptionOfType(EntityNotFoundException.class)
|
||||
.as("No EntityNotFoundException thrown when deleting a non-existing target")
|
||||
.isThrownBy(() -> controllerManagement.deleteExistingTarget("BB"));
|
||||
@@ -1576,7 +1572,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Delete a target after it has been deleted already")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1), @Expect(type = TargetDeletedEvent.class, count = 1) })
|
||||
public void deleteTargetAfterItWasDeleted() {
|
||||
void deleteTargetAfterItWasDeleted() {
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
assertThat(target).as("target should not be null").isNotNull();
|
||||
assertThat(targetRepository.count()).as("target exists and is ready for deletion").isEqualTo(1L);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
@@ -18,6 +19,8 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -74,14 +77,16 @@ import io.qameta.allure.Story;
|
||||
*/
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("DistributionSet Management")
|
||||
public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
public static final String TAG1_NAME = "Tag1";
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access react as specfied on calls for non existing entities by means "
|
||||
@Description("Verifies that management get access react as specified on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
assertThat(distributionSetManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(distributionSetManagement.getWithDetails(NOT_EXIST_IDL)).isNotPresent();
|
||||
@@ -95,16 +100,16 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetTagCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 4) })
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
final DistributionSetTag dsTag = testdataFactory.createDistributionSetTags(1).get(0);
|
||||
final SoftwareModule module = testdataFactory.createSoftwareModuleApp();
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.assignSoftwareModules(NOT_EXIST_IDL, Arrays.asList(module.getId())),
|
||||
() -> distributionSetManagement.assignSoftwareModules(NOT_EXIST_IDL, singletonList(module.getId())),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.assignSoftwareModules(set.getId(), Arrays.asList(NOT_EXIST_IDL)),
|
||||
() -> distributionSetManagement.assignSoftwareModules(set.getId(), singletonList(NOT_EXIST_IDL)),
|
||||
"SoftwareModule");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.countByTypeId(NOT_EXIST_IDL), "DistributionSet");
|
||||
@@ -114,10 +119,10 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.unassignSoftwareModule(set.getId(), NOT_EXIST_IDL),
|
||||
"SoftwareModule");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.assignTag(Arrays.asList(set.getId()), NOT_EXIST_IDL),
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.assignTag(singletonList(set.getId()), NOT_EXIST_IDL),
|
||||
"DistributionSetTag");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.assignTag(Arrays.asList(NOT_EXIST_IDL), dsTag.getId()),
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.assignTag(singletonList(NOT_EXIST_IDL), dsTag.getId()),
|
||||
"DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findByTag(PAGE, NOT_EXIST_IDL), "DistributionSetTag");
|
||||
@@ -125,10 +130,10 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
"DistributionSetTag");
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.toggleTagAssignment(Arrays.asList(NOT_EXIST_IDL), dsTag.getName()),
|
||||
() -> distributionSetManagement.toggleTagAssignment(singletonList(NOT_EXIST_IDL), dsTag.getName()),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.toggleTagAssignment(Arrays.asList(set.getId()), NOT_EXIST_ID),
|
||||
() -> distributionSetManagement.toggleTagAssignment(singletonList(set.getId()), NOT_EXIST_ID),
|
||||
"DistributionSetTag");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.unAssignTag(set.getId(), NOT_EXIST_IDL),
|
||||
@@ -143,9 +148,9 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
"DistributionSetType");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.createMetaData(NOT_EXIST_IDL,
|
||||
Arrays.asList(entityFactory.generateDsMetadata("123", "123"))), "DistributionSet");
|
||||
singletonList(entityFactory.generateDsMetadata("123", "123"))), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(Arrays.asList(NOT_EXIST_IDL)),
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(singletonList(NOT_EXIST_IDL)),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(NOT_EXIST_IDL), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetaData(NOT_EXIST_IDL, "xxx"),
|
||||
@@ -191,8 +196,8 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Verify that a DistributionSet with invalid properties cannot be created or updated")
|
||||
@ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 0) })
|
||||
public void createAndUpdateDistributionSetWithInvalidFields() {
|
||||
@Expect(type = DistributionSetUpdatedEvent.class) })
|
||||
void createAndUpdateDistributionSetWithInvalidFields() {
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
|
||||
createAndUpdateDistributionSetWithInvalidDescription(set);
|
||||
@@ -204,57 +209,57 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too long description should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a")
|
||||
.version("a").description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("entity with too long description should not be created");
|
||||
.version("a").description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with invalid description should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(
|
||||
entityFactory.distributionSet().create().name("a").version("a").description(INVALID_TEXT_HTML)))
|
||||
.as("entity with invalid description should not be created");
|
||||
entityFactory.distributionSet().create().name("a").version("a")
|
||||
.description(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too long description should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("entity with too long description should not be updated");
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with invalid characters should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML)))
|
||||
.as("entity with invalid characters should not be updated");
|
||||
|
||||
.update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too long name should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a")
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("entity with too long name should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a").name("")))
|
||||
.as("entity with too short name should not be created");
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too short name should not be created").isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().version("a").name("")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with invalid characters in name should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML)))
|
||||
.as("entity with invalid characters in name should not be created");
|
||||
.create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too long name should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("entity with too long name should not be updated");
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with invalid characters should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML)))
|
||||
.as("entity with invalid characters should not be updated");
|
||||
.update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()).name("")))
|
||||
.as("entity with too short name should not be updated");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too short name should not be updated").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).name("")));
|
||||
|
||||
}
|
||||
|
||||
@@ -262,28 +267,28 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too long version should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a")
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))))
|
||||
.as("entity with too long version should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a").version("")))
|
||||
.as("entity with too short version should not be created");
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))))
|
||||
.as("entity with too long version should not be updated");
|
||||
.as("entity with too short version should not be created").isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("a").version("")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()).version("")))
|
||||
.as("entity with too short version should not be updated");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too long version should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("entity with too short version should not be updated").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).version("")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that it is not possible to create a DS that already exists (unique constraint is on name,version for DS).")
|
||||
public void createDuplicateDistributionSetsFailsWithException() {
|
||||
void createDuplicateDistributionSetsFailsWithException() {
|
||||
testdataFactory.createDistributionSet("a");
|
||||
|
||||
assertThatThrownBy(() -> testdataFactory.createDistributionSet("a"))
|
||||
@@ -292,7 +297,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a DS is of default type if not specified explicitly at creation time.")
|
||||
public void createDistributionSetWithImplicitType() {
|
||||
void createDistributionSetWithImplicitType() {
|
||||
final DistributionSet set = distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("newtypesoft").version("1"));
|
||||
|
||||
@@ -303,7 +308,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a DS cannot be created if another DS with same name and version exists.")
|
||||
public void createDistributionSetWithDuplicateNameAndVersionFails() {
|
||||
void createDistributionSetWithDuplicateNameAndVersionFails() {
|
||||
distributionSetManagement.create(entityFactory.distributionSet().create().name("newtypesoft").version("1"));
|
||||
|
||||
assertThatExceptionOfType(EntityAlreadyExistsException.class).isThrownBy(() -> distributionSetManagement
|
||||
@@ -313,7 +318,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that multiple DS are of default type if not specified explicitly at creation time.")
|
||||
public void createMultipleDistributionSetsWithImplicitType() {
|
||||
void createMultipleDistributionSetsWithImplicitType() {
|
||||
|
||||
final List<DistributionSetCreate> creates = Lists.newArrayListWithExpectedSize(10);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -333,7 +338,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Checks that metadata for a distribution set can be created.")
|
||||
public void createDistributionSetMetadata() {
|
||||
void createDistributionSetMetadata() {
|
||||
final String knownKey = "dsMetaKnownKey";
|
||||
final String knownValue = "dsMetaKnownValue";
|
||||
|
||||
@@ -351,7 +356,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies the enforcement of the metadata quota per distribution set.")
|
||||
public void createDistributionSetMetadataUntilQuotaIsExceeded() {
|
||||
void createDistributionSetMetadataUntilQuotaIsExceeded() {
|
||||
|
||||
// add meta data one by one
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
@@ -378,7 +383,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// add some meta data entries
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("ds3");
|
||||
final int firstHalf = Math.round(maxMetaData / 2);
|
||||
final int firstHalf = Math.round(((float) maxMetaData) / 2.f);
|
||||
for (int i = 0; i < firstHalf; ++i) {
|
||||
createDistributionSetMetadata(ds3.getId(), new JpaDistributionSetMetadata("k" + i, ds3, "v" + i));
|
||||
}
|
||||
@@ -396,20 +401,21 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that distribution sets can assigned and unassigned to a distribution set tag.")
|
||||
public void assignAndUnassignDistributionSetToTag() {
|
||||
void assignAndUnassignDistributionSetToTag() {
|
||||
final List<Long> assignDS = Lists.newArrayListWithExpectedSize(4);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
assignDS.add(testdataFactory.createDistributionSet("DS" + i, "1.0", Collections.emptyList()).getId());
|
||||
}
|
||||
|
||||
final DistributionSetTag tag = distributionSetTagManagement.create(entityFactory.tag().create().name("Tag1"));
|
||||
final DistributionSetTag tag = distributionSetTagManagement
|
||||
.create(entityFactory.tag().create().name(TAG1_NAME));
|
||||
|
||||
final List<DistributionSet> assignedDS = distributionSetManagement.assignTag(assignDS, tag.getId());
|
||||
assertThat(assignedDS.size()).as("assigned ds has wrong size").isEqualTo(4);
|
||||
assignedDS.stream().map(c -> (JpaDistributionSet) c)
|
||||
.forEach(ds -> assertThat(ds.getTags().size()).as("ds has wrong tag size").isEqualTo(1));
|
||||
|
||||
DistributionSetTag findDistributionSetTag = distributionSetTagManagement.getByName("Tag1").get();
|
||||
DistributionSetTag findDistributionSetTag = getOrThrow(distributionSetTagManagement.getByName(TAG1_NAME));
|
||||
|
||||
assertThat(assignedDS.size()).as("assigned ds has wrong size")
|
||||
.isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements());
|
||||
@@ -417,20 +423,20 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final JpaDistributionSet unAssignDS = (JpaDistributionSet) distributionSetManagement
|
||||
.unAssignTag(assignDS.get(0), findDistributionSetTag.getId());
|
||||
assertThat(unAssignDS.getId()).as("unassigned ds is wrong").isEqualTo(assignDS.get(0));
|
||||
assertThat(unAssignDS.getTags().size()).as("unassigned ds has wrong tag size").isEqualTo(0);
|
||||
findDistributionSetTag = distributionSetTagManagement.getByName("Tag1").get();
|
||||
assertThat(unAssignDS.getTags().size()).as("unassigned ds has wrong tag size").isZero();
|
||||
assertThat(distributionSetTagManagement.getByName(TAG1_NAME)).isPresent();
|
||||
assertThat(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements())
|
||||
.as("ds tag ds has wrong ds size").isEqualTo(3);
|
||||
|
||||
assertThat(distributionSetManagement.findByRsqlAndTag(PAGE, "name==" + unAssignDS.getName(), tag.getId())
|
||||
.getNumberOfElements()).as("ds tag ds has wrong ds size").isEqualTo(0);
|
||||
.getNumberOfElements()).as("ds tag ds has wrong ds size").isZero();
|
||||
assertThat(distributionSetManagement.findByRsqlAndTag(PAGE, "name!=" + unAssignDS.getName(), tag.getId())
|
||||
.getNumberOfElements()).as("ds tag ds has wrong ds size").isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that updates concerning the internal software structure of a DS are not possible if the DS is already assigned.")
|
||||
public void updateDistributionSetForbiddedWithIllegalUpdate() {
|
||||
void updateDistributionSetForbiddenWithIllegalUpdate() {
|
||||
// prepare data
|
||||
final Target target = testdataFactory.createTarget();
|
||||
|
||||
@@ -444,7 +450,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// assign target
|
||||
assignDistributionSet(ds.getId(), target.getControllerId());
|
||||
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
|
||||
ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId()));
|
||||
|
||||
final Long dsId = ds.getId();
|
||||
// not allowed as it is assigned now
|
||||
@@ -452,20 +458,20 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.isInstanceOf(EntityReadOnlyException.class);
|
||||
|
||||
// not allowed as it is assigned now
|
||||
final Long appId = ds.findFirstModuleByType(appType).get().getId();
|
||||
final Long appId = getOrThrow(ds.findFirstModuleByType(appType)).getId();
|
||||
assertThatThrownBy(() -> distributionSetManagement.unassignSoftwareModule(dsId, appId))
|
||||
.isInstanceOf(EntityReadOnlyException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that it is not possible to add a software module that is not defined of the DS's type.")
|
||||
public void updateDistributionSetUnsupportedModuleFails() {
|
||||
void updateDistributionSetUnsupportedModuleFails() {
|
||||
final DistributionSet set = distributionSetManagement
|
||||
.create(entityFactory
|
||||
.distributionSet().create().name("agent-hub2").version(
|
||||
"1.0.5")
|
||||
.type(distributionSetTypeManagement.create(entityFactory.distributionSetType().create()
|
||||
.key("test").name("test").mandatory(Arrays.asList(osType.getId()))).getKey()));
|
||||
.key("test").name("test").mandatory(singletonList(osType.getId()))).getKey()));
|
||||
|
||||
final SoftwareModule module = softwareModuleManagement.create(
|
||||
entityFactory.softwareModule().create().name("agent-hub2").version("1.0.5").type(appType.getKey()));
|
||||
@@ -478,7 +484,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Legal updates of a DS, e.g. name or description and module addition, removal while still unassigned.")
|
||||
public void updateDistributionSet() {
|
||||
void updateDistributionSet() {
|
||||
// prepare data
|
||||
DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final SoftwareModule os = testdataFactory.createSoftwareModuleOs();
|
||||
@@ -486,18 +492,19 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
// update data
|
||||
// legal update of module addition
|
||||
distributionSetManagement.assignSoftwareModules(ds.getId(), Sets.newHashSet(os.getId()));
|
||||
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
|
||||
assertThat(ds.findFirstModuleByType(osType).get()).isEqualTo(os);
|
||||
ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId()));
|
||||
assertThat(getOrThrow(ds.findFirstModuleByType(osType))).isEqualTo(os);
|
||||
|
||||
// legal update of module removal
|
||||
distributionSetManagement.unassignSoftwareModule(ds.getId(), ds.findFirstModuleByType(appType).get().getId());
|
||||
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
|
||||
assertThat(ds.findFirstModuleByType(appType).isPresent()).isFalse();
|
||||
distributionSetManagement.unassignSoftwareModule(ds.getId(),
|
||||
getOrThrow(ds.findFirstModuleByType(appType)).getId());
|
||||
ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId()));
|
||||
assertThat(ds.findFirstModuleByType(appType)).isNotPresent();
|
||||
|
||||
// Update description
|
||||
distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).name("a new name")
|
||||
.description("a new description").version("a new version").requiredMigrationStep(true));
|
||||
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
|
||||
ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId()));
|
||||
assertThat(ds.getDescription()).isEqualTo("a new description");
|
||||
assertThat(ds.getName()).isEqualTo("a new name");
|
||||
assertThat(ds.getVersion()).isEqualTo("a new version");
|
||||
@@ -506,7 +513,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update an invalid distribution set")
|
||||
public void updateInvalidDistributionSet() {
|
||||
void updateInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
@@ -516,7 +523,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies the enforcement of the software module quota per distribution set.")
|
||||
public void assignSoftwareModulesUntilQuotaIsExceeded() {
|
||||
void assignSoftwareModulesUntilQuotaIsExceeded() {
|
||||
|
||||
// create some software modules
|
||||
final int maxModules = quotaManagement.getMaxSoftwareModulesPerDistributionSet();
|
||||
@@ -528,13 +535,11 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
// assign software modules one by one
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSetWithNoSoftwareModules("ds1", "1.0");
|
||||
for (int i = 0; i < maxModules; ++i) {
|
||||
distributionSetManagement.assignSoftwareModules(ds1.getId(), Collections.singletonList(modules.get(i)));
|
||||
distributionSetManagement.assignSoftwareModules(ds1.getId(), singletonList(modules.get(i)));
|
||||
}
|
||||
// add one more to cause the quota to be exceeded
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> {
|
||||
distributionSetManagement.assignSoftwareModules(ds1.getId(),
|
||||
Collections.singletonList(modules.get(maxModules)));
|
||||
});
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> distributionSetManagement
|
||||
.assignSoftwareModules(ds1.getId(), singletonList(modules.get(maxModules))));
|
||||
|
||||
// assign all software modules at once
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSetWithNoSoftwareModules("ds2", "1.0");
|
||||
@@ -544,9 +549,9 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// assign some software modules
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSetWithNoSoftwareModules("ds3", "1.0");
|
||||
final int firstHalf = Math.round(maxModules / 2);
|
||||
final int firstHalf = Math.round(((float) maxModules) / 2.f);
|
||||
for (int i = 0; i < firstHalf; ++i) {
|
||||
distributionSetManagement.assignSoftwareModules(ds3.getId(), Collections.singletonList(modules.get(i)));
|
||||
distributionSetManagement.assignSoftwareModules(ds3.getId(), singletonList(modules.get(i)));
|
||||
}
|
||||
// assign the remaining modules to cause the quota to be exceeded
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> distributionSetManagement
|
||||
@@ -556,25 +561,25 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to assign software modules to an invalidated distribution set.")
|
||||
public void verifyAssignSoftwareModulesToInvalidDistributionSet() {
|
||||
void verifyAssignSoftwareModulesToInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSet.getId(),
|
||||
Collections.singletonList(softwareModule.getId())));
|
||||
singletonList(softwareModule.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to unassign a software module from an invalidated distribution set.")
|
||||
public void verifyUnassignSoftwareModulesToInvalidDistributionSet() {
|
||||
void verifyUnassignSoftwareModulesToInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs();
|
||||
distributionSetManagement.assignSoftwareModules(distributionSet.getId(),
|
||||
Collections.singletonList(softwareModule.getId()));
|
||||
singletonList(softwareModule.getId()));
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation(
|
||||
Collections.singletonList(distributionSet.getId()), CancelationType.NONE, false));
|
||||
singletonList(distributionSet.getId()), CancelationType.NONE, false));
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement
|
||||
@@ -584,7 +589,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that metadata for a distribution set can be updated.")
|
||||
public void updateDistributionSetMetadata() throws InterruptedException {
|
||||
void updateDistributionSetMetadata() {
|
||||
final String knownKey = "myKnownKey";
|
||||
final String knownValue = "myKnownValue";
|
||||
final String knownUpdateValue = "myNewUpdatedValue";
|
||||
@@ -597,20 +602,17 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
// create an DS meta data entry
|
||||
createDistributionSetMetadata(ds.getId(), new JpaDistributionSetMetadata(knownKey, ds, knownValue));
|
||||
|
||||
DistributionSet changedLockRevisionDS = distributionSetManagement.get(ds.getId()).get();
|
||||
final DistributionSet changedLockRevisionDS = getOrThrow(distributionSetManagement.get(ds.getId()));
|
||||
assertThat(changedLockRevisionDS.getOptLockRevision()).isEqualTo(2);
|
||||
|
||||
Thread.sleep(100);
|
||||
|
||||
// update the DS metadata
|
||||
final JpaDistributionSetMetadata updated = (JpaDistributionSetMetadata) distributionSetManagement
|
||||
.updateMetaData(ds.getId(), entityFactory.generateDsMetadata(knownKey, knownUpdateValue));
|
||||
// we are updating the sw meta data so also modifying the base software
|
||||
// module so opt lock
|
||||
// revision must be three
|
||||
changedLockRevisionDS = distributionSetManagement.get(ds.getId()).get();
|
||||
assertThat(changedLockRevisionDS.getOptLockRevision()).isEqualTo(3);
|
||||
assertThat(changedLockRevisionDS.getLastModifiedAt()).isGreaterThan(0L);
|
||||
// we are updating the sw metadata so also modifying the base software
|
||||
// module so opt lock revision must be three
|
||||
final DistributionSet reloadedDS = getOrThrow(distributionSetManagement.get(ds.getId()));
|
||||
assertThat(reloadedDS.getOptLockRevision()).isEqualTo(3);
|
||||
assertThat(reloadedDS.getLastModifiedAt()).isPositive();
|
||||
|
||||
// verify updated meta data contains the updated value
|
||||
assertThat(updated).isNotNull();
|
||||
@@ -621,7 +623,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Tests that a DS queue is possible where the result is ordered by the target assignment, i.e. assigned first in the list.")
|
||||
public void findDistributionSetsAllOrderedByLinkTarget() {
|
||||
void findDistributionSetsAllOrderedByLinkTarget() {
|
||||
|
||||
final List<DistributionSet> buildDistributionSets = testdataFactory.createDistributionSets("dsOrder", 10);
|
||||
|
||||
@@ -641,7 +643,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assignDistributionSet(dsThree.getId(), tFirst.getControllerId());
|
||||
// set installed
|
||||
testdataFactory.sendUpdateActionStatusToTargets(Collections.singleton(tSecond), Status.FINISHED,
|
||||
Arrays.asList("some message"));
|
||||
singletonList("some message"));
|
||||
|
||||
assignDistributionSet(dsFour.getId(), tSecond.getControllerId());
|
||||
|
||||
@@ -669,7 +671,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("searches for distribution sets based on the various filter options, e.g. name, version, desc., tags.")
|
||||
public void searchDistributionSetsOnFilters() {
|
||||
void searchDistributionSetsOnFilters() {
|
||||
DistributionSetTag dsTagA = distributionSetTagManagement
|
||||
.create(entityFactory.tag().create().name("DistributionSetTag-A"));
|
||||
final DistributionSetTag dsTagB = distributionSetTagManagement
|
||||
@@ -689,7 +691,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.create(entityFactory.distributionSetType().create().key("foo").name("bar").description("test"));
|
||||
|
||||
distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(newType.getId(),
|
||||
Arrays.asList(osType.getId()));
|
||||
singletonList(osType.getId()));
|
||||
newType = distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(newType.getId(),
|
||||
Arrays.asList(appType.getId(), runtimeType.getId()));
|
||||
|
||||
@@ -699,14 +701,14 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
assignDistributionSet(dsDeleted, testdataFactory.createTargets(5));
|
||||
distributionSetManagement.delete(dsDeleted.getId());
|
||||
dsDeleted = distributionSetManagement.get(dsDeleted.getId()).get();
|
||||
dsDeleted = getOrThrow(distributionSetManagement.get(dsDeleted.getId()));
|
||||
|
||||
dsGroup1 = toggleTagAssignment(dsGroup1, dsTagA).getAssignedEntity();
|
||||
dsTagA = distributionSetTagRepository.findByNameEquals(dsTagA.getName()).get();
|
||||
dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName()));
|
||||
dsGroup1 = toggleTagAssignment(dsGroup1, dsTagB).getAssignedEntity();
|
||||
dsTagA = distributionSetTagRepository.findByNameEquals(dsTagA.getName()).get();
|
||||
dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName()));
|
||||
dsGroup2 = toggleTagAssignment(dsGroup2, dsTagA).getAssignedEntity();
|
||||
dsTagA = distributionSetTagRepository.findByNameEquals(dsTagA.getName()).get();
|
||||
dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName()));
|
||||
|
||||
final List<DistributionSet> allDistributionSets = Stream
|
||||
.of(dsGroup1, dsGroup2, Arrays.asList(dsDeleted, dsInComplete, dsNewType)).flatMap(Collection::stream)
|
||||
@@ -743,7 +745,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void validateDeleted(final DistributionSet deletedDistributionSet, final int notDeletedSize) {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsDeleted(Boolean.TRUE),
|
||||
Arrays.asList(deletedDistributionSet));
|
||||
singletonList(deletedDistributionSet));
|
||||
|
||||
assertThatFilterHasSizeAndDoesNotContainDistributionSet(
|
||||
getDistributionSetFilterBuilder().setIsDeleted(Boolean.FALSE), notDeletedSize, deletedDistributionSet);
|
||||
@@ -756,7 +758,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE), completedSize, dsIncomplete);
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.FALSE), Arrays.asList(dsIncomplete));
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.FALSE), singletonList(dsIncomplete));
|
||||
}
|
||||
|
||||
@Step
|
||||
@@ -764,7 +766,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final int standardDsTypeSize) {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(newType),
|
||||
Arrays.asList(dsNewType));
|
||||
singletonList(dsNewType));
|
||||
|
||||
assertThatFilterHasSizeAndDoesNotContainDistributionSet(
|
||||
getDistributionSetFilterBuilder().setType(standardDsType), standardDsTypeSize, dsNewType);
|
||||
@@ -772,7 +774,6 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Step
|
||||
private void validateSearchText(final List<DistributionSet> withText, final String text) {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setSearchText(text),
|
||||
withText);
|
||||
}
|
||||
@@ -825,10 +826,10 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final List<DistributionSet> dsWithTagB) {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setTagNames(Arrays.asList(dsTagA.getName())), dsWithTagA);
|
||||
getDistributionSetFilterBuilder().setTagNames(singletonList(dsTagA.getName())), dsWithTagA);
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setTagNames(Arrays.asList(dsTagB.getName())), dsWithTagB);
|
||||
getDistributionSetFilterBuilder().setTagNames(singletonList(dsTagB.getName())), dsWithTagB);
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setTagNames(Arrays.asList(dsTagA.getName(), dsTagB.getName())),
|
||||
@@ -839,7 +840,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
dsWithTagB);
|
||||
|
||||
assertThatFilterDoesNotContainAnyDistributionSet(
|
||||
getDistributionSetFilterBuilder().setTagNames(Arrays.asList(dsTagC.getName())));
|
||||
getDistributionSetFilterBuilder().setTagNames(singletonList(dsTagC.getName())));
|
||||
}
|
||||
|
||||
@Step
|
||||
@@ -854,7 +855,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.TRUE),
|
||||
Arrays.asList(dsDeleted));
|
||||
singletonList(dsDeleted));
|
||||
|
||||
assertThatFilterDoesNotContainAnyDistributionSet(
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.TRUE));
|
||||
@@ -868,14 +869,14 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.setIsComplete(Boolean.TRUE).setType(standardDsType), deletedAndCompletedAndStandardType);
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
|
||||
.setType(standardDsType).setIsDeleted(Boolean.TRUE), Arrays.asList(dsDeleted));
|
||||
.setType(standardDsType).setIsDeleted(Boolean.TRUE), singletonList(dsDeleted));
|
||||
|
||||
assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setIsDeleted(Boolean.TRUE)
|
||||
.setIsComplete(Boolean.FALSE).setType(standardDsType));
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setType(newType),
|
||||
Arrays.asList(dsNewType));
|
||||
singletonList(dsNewType));
|
||||
}
|
||||
|
||||
@Step
|
||||
@@ -915,15 +916,15 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
|
||||
.setIsDeleted(Boolean.TRUE).setType(standardDsType).setFilterString(filterString),
|
||||
Arrays.asList(dsDeleted));
|
||||
singletonList(dsDeleted));
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(standardDsType)
|
||||
.setFilterString(filterString).setIsComplete(Boolean.FALSE).setIsDeleted(Boolean.FALSE),
|
||||
Arrays.asList(dsInComplete));
|
||||
singletonList(dsInComplete));
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(getDistributionSetFilterBuilder().setType(newType)
|
||||
.setFilterString(filterString).setIsComplete(Boolean.TRUE).setIsDeleted(Boolean.FALSE),
|
||||
Arrays.asList(dsNewType));
|
||||
singletonList(dsNewType));
|
||||
}
|
||||
|
||||
@Step
|
||||
@@ -933,11 +934,11 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
assertThatFilterContainsOnlyGivenDistributionSets(
|
||||
getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE).setType(standardDsType)
|
||||
.setSearchText(text).setTagNames(Arrays.asList(dsTagA.getName())),
|
||||
.setSearchText(text).setTagNames(singletonList(dsTagA.getName())),
|
||||
completedAndStandartTypeAndSearchTextAndTagA);
|
||||
|
||||
assertThatFilterDoesNotContainAnyDistributionSet(getDistributionSetFilterBuilder().setType(standardDsType)
|
||||
.setSearchText(text).setTagNames(Arrays.asList(dsTagA.getName())).setIsComplete(Boolean.FALSE)
|
||||
.setSearchText(text).setTagNames(singletonList(dsTagA.getName())).setIsComplete(Boolean.FALSE)
|
||||
.setIsDeleted(Boolean.FALSE));
|
||||
}
|
||||
|
||||
@@ -954,7 +955,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private void assertThatFilterDoesNotContainAnyDistributionSet(final DistributionSetFilterBuilder filterBuilder) {
|
||||
assertThat(distributionSetManagement.findByDistributionSetFilter(PAGE, filterBuilder.build()).getContent())
|
||||
.hasSize(0);
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
private void assertThatFilterHasSizeAndDoesNotContainDistributionSet(
|
||||
@@ -965,7 +966,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Simple DS load without the related data that should be loaded lazy.")
|
||||
public void findDistributionSetsWithoutLazy() {
|
||||
void findDistributionSetsWithoutLazy() {
|
||||
testdataFactory.createDistributionSets(20);
|
||||
|
||||
assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(20);
|
||||
@@ -973,7 +974,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Deltes a DS that is no in use. Expected behaviour is a hard delete on the database.")
|
||||
public void deleteUnassignedDistributionSet() {
|
||||
void deleteUnassignedDistributionSet() {
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds-1");
|
||||
testdataFactory.createDistributionSet("ds-2");
|
||||
|
||||
@@ -987,7 +988,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Deletes an invalid distribution set")
|
||||
public void deleteInvalidDistributionSet() {
|
||||
void deleteInvalidDistributionSet() {
|
||||
final DistributionSet set = testdataFactory.createAndInvalidateDistributionSet();
|
||||
assertThat(distributionSetRepository.findById(set.getId())).isNotEmpty();
|
||||
distributionSetManagement.delete(set.getId());
|
||||
@@ -996,7 +997,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Deletes an incomplete distribution set")
|
||||
public void deleteIncompleteDistributionSet() {
|
||||
void deleteIncompleteDistributionSet() {
|
||||
final DistributionSet set = testdataFactory.createIncompleteDistributionSet();
|
||||
assertThat(distributionSetRepository.findById(set.getId())).isNotEmpty();
|
||||
distributionSetManagement.delete(set.getId());
|
||||
@@ -1005,7 +1006,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Queries and loads the metadata related to a given software module.")
|
||||
public void findAllDistributionSetMetadataByDsId() {
|
||||
void findAllDistributionSetMetadataByDsId() {
|
||||
// create a DS
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("testDs1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("testDs2");
|
||||
@@ -1036,7 +1037,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Deletes a DS that is in use by either target assignment or rollout. Expected behaviour is a soft delete on the database, i.e. only marked as "
|
||||
+ "deleted, kept as reference but unavailable for future use..")
|
||||
public void deleteAssignedDistributionSet() {
|
||||
void deleteAssignedDistributionSet() {
|
||||
testdataFactory.createDistributionSet("ds-1");
|
||||
testdataFactory.createDistributionSet("ds-2");
|
||||
final DistributionSet dsToTargetAssigned = testdataFactory.createDistributionSet("ds-3");
|
||||
@@ -1062,7 +1063,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Verify that the find all by ids contains the entities which are looking for")
|
||||
@ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 12),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 36) })
|
||||
public void verifyFindDistributionSetAllById() {
|
||||
void verifyFindDistributionSetAllById() {
|
||||
final List<Long> searchIds = new ArrayList<>();
|
||||
searchIds.add(testdataFactory.createDistributionSet("ds-4").getId());
|
||||
searchIds.add(testdataFactory.createDistributionSet("ds-5").getId());
|
||||
@@ -1081,7 +1082,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that an exception is thrown when trying to get an invalid distribution set")
|
||||
public void verifyGetValid() {
|
||||
void verifyGetValid() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
@@ -1094,7 +1095,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that an exception is thrown when trying to get an incomplete distribution set")
|
||||
public void verifyGetValidAndComplete() {
|
||||
void verifyGetValidAndComplete() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
@@ -1104,7 +1105,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that an exception is thrown when trying to create or update metadata for an invalid distribution set.")
|
||||
public void createMetadataForInvalidDistributionSet() {
|
||||
void createMetadataForInvalidDistributionSet() {
|
||||
final String knownKey1 = "myKnownKey1";
|
||||
final String knownKey2 = "myKnownKey2";
|
||||
final String knownValue = "myKnownValue";
|
||||
@@ -1112,16 +1113,16 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.createMetaData(ds.getId(),
|
||||
Collections.singletonList(entityFactory.generateDsMetadata(knownKey1, knownValue)));
|
||||
singletonList(entityFactory.generateDsMetadata(knownKey1, knownValue)));
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(Arrays.asList(ds.getId()), CancelationType.NONE, false));
|
||||
new DistributionSetInvalidation(singletonList(ds.getId()), CancelationType.NONE, false));
|
||||
|
||||
// assert that no new metadata can be created
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.createMetaData(ds.getId(),
|
||||
Collections.singletonList(entityFactory.generateDsMetadata(knownKey2, knownValue))));
|
||||
singletonList(entityFactory.generateDsMetadata(knownKey2, knownValue))));
|
||||
|
||||
// assert that an existing metadata can not be updated
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
@@ -1129,4 +1130,8 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.updateMetaData(ds.getId(), entityFactory.generateDsMetadata(knownKey1, knownUpdateValue)));
|
||||
}
|
||||
|
||||
// can be removed with java-11
|
||||
private <T> T getOrThrow(Optional<T> opt) {
|
||||
return opt.orElseThrow(NoSuchElementException::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
@@ -27,8 +27,8 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreated
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
@@ -70,16 +70,19 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes
|
||||
@Expect(type = DistributionSetTypeCreatedEvent.class, count = 1) })
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
|
||||
final List<Long> softwareModuleTypes = Collections.singletonList(osType.getId());
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(NOT_EXIST_IDL,
|
||||
Arrays.asList(osType.getId())), "DistributionSetType");
|
||||
softwareModuleTypes), "DistributionSetType");
|
||||
final List<Long> notExistingSwModuleTypeIds = Collections.singletonList(NOT_EXIST_IDL);
|
||||
verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(
|
||||
testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), Arrays.asList(NOT_EXIST_IDL)),
|
||||
testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), notExistingSwModuleTypeIds),
|
||||
"SoftwareModuleType");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(NOT_EXIST_IDL,
|
||||
Arrays.asList(osType.getId())), "DistributionSetType");
|
||||
softwareModuleTypes), "DistributionSetType");
|
||||
verifyThrownExceptionBy(() -> distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(
|
||||
testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), Arrays.asList(NOT_EXIST_IDL)),
|
||||
testdataFactory.findOrCreateDistributionSetType("xxx", "xxx").getId(), notExistingSwModuleTypeIds),
|
||||
"SoftwareModuleType");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetTypeManagement.delete(NOT_EXIST_IDL), "DistributionSetType");
|
||||
@@ -106,99 +109,91 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes
|
||||
private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too long description should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a")
|
||||
.version("a").description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("set with too long description should not be created");
|
||||
.version("a").description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set invalid description text should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(
|
||||
entityFactory.distributionSet().create().name("a").version("a").description(INVALID_TEXT_HTML)))
|
||||
.as("set invalid description text should not be created");
|
||||
entityFactory.distributionSet().create().name("a").version("a")
|
||||
.description(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too long description should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("set with too long description should not be updated");
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML)))
|
||||
.as("set with invalid description should not be updated");
|
||||
.as("set with invalid description should not be updated").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML)));
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("set with too long name should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a")
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("set with too long name should not be created");
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("set with invalid name should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML)))
|
||||
.as("set with invalid name should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.create(entityFactory.distributionSet().create().version("a").name("")))
|
||||
.as("set with too short name should not be created");
|
||||
.create(entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too short name should not be created").isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().version("a").name("")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("set with null name should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().version("a").name(null)))
|
||||
.as("set with null name should not be created");
|
||||
.create(entityFactory.distributionSet().create().version("a").name(null)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("set with too long name should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("set with too long name should not be updated");
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("set with invalid name should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML)))
|
||||
.as("set with invalid name should not be updated");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()).name("")))
|
||||
.as("set with too short name should not be updated");
|
||||
.as("set with too short name should not be updated").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).name("")));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too long version should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a")
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))))
|
||||
.as("set with too long version should not be created");
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with invalid version should not be created").isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("a").version(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too short version should not be created").isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("a").version("")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("set with null version should not be created")
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("a").version(INVALID_TEXT_HTML)))
|
||||
.as("set with invalid version should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.create(entityFactory.distributionSet().create().name("a").version("")))
|
||||
.as("set with too short version should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("a").version(null)))
|
||||
.as("set with null version should not be created");
|
||||
.create(entityFactory.distributionSet().create().name("a").version(null)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too long version should not be updated")
|
||||
.isThrownBy(() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))))
|
||||
.as("set with too long version should not be updated");
|
||||
.version(RandomStringUtils.randomAlphanumeric(NamedVersionedEntity.VERSION_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).version(INVALID_TEXT_HTML)))
|
||||
.as("set with invalid version should not be updated");
|
||||
.as("set with invalid version should not be updated").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).version(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()).version("")))
|
||||
.as("set with too short version should not be updated");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("set with too short version should not be updated").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(set.getId()).version("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -278,11 +273,7 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes
|
||||
@Test
|
||||
@Description("Tests the successfull update of used distribution set type meta data which is in fact allowed.")
|
||||
public void updateAssignedDistributionSetTypeMetaData() {
|
||||
final DistributionSetType nonUpdatableType = distributionSetTypeManagement.create(entityFactory
|
||||
.distributionSetType().create().key("updatableType").name("to be deleted").colour("test123"));
|
||||
assertThat(distributionSetTypeManagement.getByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty();
|
||||
distributionSetManagement.create(entityFactory.distributionSet().create().name("newtypesoft").version("1")
|
||||
.type(nonUpdatableType.getKey()));
|
||||
final DistributionSetType nonUpdatableType = createDistributionSetTypeUsedByDs();
|
||||
|
||||
distributionSetTypeManagement.update(
|
||||
entityFactory.distributionSetType().update(nonUpdatableType.getId()).description("a new description"));
|
||||
@@ -295,17 +286,22 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes
|
||||
@Test
|
||||
@Description("Tests the unsuccessfull update of used distribution set type (module addition).")
|
||||
public void addModuleToAssignedDistributionSetTypeFails() {
|
||||
final DistributionSetType nonUpdatableType = distributionSetTypeManagement
|
||||
.create(entityFactory.distributionSetType().create().key("updatableType").name("to be deleted"));
|
||||
assertThat(distributionSetTypeManagement.getByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty();
|
||||
distributionSetManagement.create(entityFactory.distributionSet().create().name("newtypesoft").version("1")
|
||||
.type(nonUpdatableType.getKey()));
|
||||
final DistributionSetType nonUpdatableType = createDistributionSetTypeUsedByDs();
|
||||
|
||||
assertThatThrownBy(() -> distributionSetTypeManagement
|
||||
.assignMandatorySoftwareModuleTypes(nonUpdatableType.getId(), Sets.newHashSet(osType.getId())))
|
||||
.isInstanceOf(EntityReadOnlyException.class);
|
||||
}
|
||||
|
||||
private DistributionSetType createDistributionSetTypeUsedByDs() {
|
||||
final DistributionSetType nonUpdatableType = distributionSetTypeManagement.create(entityFactory
|
||||
.distributionSetType().create().key("updatableType").name("to be deleted").colour("test123"));
|
||||
assertThat(distributionSetTypeManagement.getByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty();
|
||||
distributionSetManagement.create(entityFactory.distributionSet().create().name("newtypesoft").version("1")
|
||||
.type(nonUpdatableType.getKey()));
|
||||
return nonUpdatableType;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the unsuccessfull update of used distribution set type (module removal).")
|
||||
public void removeModuleToAssignedDistributionSetTypeFails() {
|
||||
@@ -338,15 +334,17 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes
|
||||
@Test
|
||||
@Description("Tests the successfull deletion of used (soft delete) distribution set types.")
|
||||
public void deleteAssignedDistributionSetType() {
|
||||
final JpaDistributionSetType softDelete = (JpaDistributionSetType) distributionSetTypeManagement
|
||||
final JpaDistributionSetType toBeDeleted = (JpaDistributionSetType) distributionSetTypeManagement
|
||||
.create(entityFactory.distributionSetType().create().key("softdeleted").name("to be deleted"));
|
||||
|
||||
assertThat(distributionSetTypeRepository.findAll()).contains(softDelete);
|
||||
assertThat(distributionSetTypeRepository.findAll()).contains(toBeDeleted);
|
||||
distributionSetManagement.create(
|
||||
entityFactory.distributionSet().create().name("softdeleted").version("1").type(softDelete.getKey()));
|
||||
entityFactory.distributionSet().create().name("softdeleted").version("1").type(toBeDeleted.getKey()));
|
||||
|
||||
distributionSetTypeManagement.delete(softDelete.getId());
|
||||
assertThat(distributionSetTypeManagement.getByKey("softdeleted").get().isDeleted()).isEqualTo(true);
|
||||
distributionSetTypeManagement.delete(toBeDeleted.getId());
|
||||
final Optional<DistributionSetType> softdeleted = distributionSetTypeManagement.getByKey("softdeleted");
|
||||
assertThat(softdeleted).isPresent();
|
||||
assertThat(softdeleted.get().isDeleted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,17 +17,18 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.ValidationException;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
||||
@@ -54,8 +55,6 @@ import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledExcep
|
||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.MultipleInvokeHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.SuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
@@ -76,6 +75,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -138,9 +138,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a running action is auto canceled by a rollout which assigns another distribution-set.")
|
||||
void rolloutAssignesNewDistributionSetAndAutoCloseActiveActions() {
|
||||
tenantConfigurationManagement
|
||||
.addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true);
|
||||
void rolloutAssignsNewDistributionSetAndAutoCloseActiveActions() {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(
|
||||
TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true);
|
||||
|
||||
try {
|
||||
// manually assign distribution set to target
|
||||
@@ -182,7 +182,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verifies that management get access reacts as specified on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
assertThat(rolloutManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(rolloutManagement.getByName(NOT_EXIST_ID)).isNotPresent();
|
||||
@@ -192,7 +192,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verifies that management queries react as specified on calls for non existing entities "
|
||||
+ " by means of throwing EntityNotFoundException.")
|
||||
@ExpectEvents({ @Expect(type = RolloutDeletedEvent.class, count = 0),
|
||||
@ExpectEvents({ @Expect(type = RolloutDeletedEvent.class),
|
||||
@Expect(type = RolloutGroupCreatedEvent.class, count = 10),
|
||||
@Expect(type = RolloutGroupUpdatedEvent.class, count = 10),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@@ -225,7 +225,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// verify the split of the target and targetGroup
|
||||
final Page<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(PAGE, createdRollout.getId());
|
||||
// we have total of #amountTargetsForRollout in rollouts splitted in
|
||||
// we have total of #amountTargetsForRollout in rollouts split in
|
||||
// group size #groupSize
|
||||
assertThat(rolloutGroups).hasSize(amountGroups);
|
||||
}
|
||||
@@ -254,11 +254,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
scheduledGroups.forEach(group -> assertThat(group.getStatus())
|
||||
.as("group which should be in scheduled state is in " + group.getStatus() + " state")
|
||||
.isEqualTo(RolloutGroupStatus.SCHEDULED));
|
||||
// verify that the first group actions has been started and are in state
|
||||
// running
|
||||
// verify that the first group actions has been started and are in state running
|
||||
final List<Action> runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING);
|
||||
assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups);
|
||||
assertThat(runningActions).as("Created actions are initiated by rollout creator")
|
||||
assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups)
|
||||
.as("Created actions are initiated by rollout creator")
|
||||
.allMatch(a -> a.getInitiatedBy().equals(createdRollout.getCreatedBy()));
|
||||
// the rest targets are only scheduled
|
||||
assertThat(findActionsByRolloutAndStatus(createdRollout, Status.SCHEDULED))
|
||||
@@ -308,7 +307,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
// @Title("Deleting targets of a rollout")
|
||||
@Description("Verfiying that next group is started when targets of the group have been deleted.")
|
||||
@Description("Verifying that next group is started when targets of the group have been deleted.")
|
||||
void checkRunningRolloutsStartsNextGroupIfTargetsDeleted() {
|
||||
|
||||
final int amountTargetsForRollout = 15;
|
||||
@@ -342,7 +341,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
return rolloutManagement.get(createdRollout.getId()).get();
|
||||
return reloadRollout(createdRollout);
|
||||
}
|
||||
|
||||
@Step("Finish three actions of the rollout group and delete two targets")
|
||||
@@ -399,7 +398,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(runningRolloutGroups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED);
|
||||
assertThat(runningRolloutGroups.get(1).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED);
|
||||
assertThat(runningRolloutGroups.get(2).getStatus()).isEqualTo(RolloutGroupStatus.FINISHED);
|
||||
assertThat(rolloutManagement.get(createdRollout.getId()).get().getStatus()).isEqualTo(RolloutStatus.FINISHED);
|
||||
assertThat(reloadRollout(createdRollout).getStatus()).isEqualTo(RolloutStatus.FINISHED);
|
||||
|
||||
}
|
||||
|
||||
@@ -409,7 +408,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfiying that the error handling action of a group is executed to pause the current rollout")
|
||||
@Description("Verifying that the error handling action of a group is executed to pause the current rollout")
|
||||
void checkErrorHitOfGroupCallsErrorActionToPauseTheRollout() {
|
||||
final int amountTargetsForRollout = 10;
|
||||
final int amountOtherTargets = 15;
|
||||
@@ -433,7 +432,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
// and should execute the error action
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
final Rollout rollout = rolloutManagement.get(createdRollout.getId()).get();
|
||||
final Rollout rollout = reloadRollout(createdRollout);
|
||||
// the rollout itself should be in paused based on the error action
|
||||
assertThat(rollout.getStatus()).isEqualTo(RolloutStatus.PAUSED);
|
||||
|
||||
@@ -452,7 +451,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfiying a paused rollout in case of error action hit can be resumed again")
|
||||
@Description("Verifying a paused rollout in case of error action hit can be resumed again")
|
||||
void errorActionPausesRolloutAndRolloutGetsResumedStartsNextScheduledGroup() {
|
||||
final int amountTargetsForRollout = 10;
|
||||
final int amountOtherTargets = 15;
|
||||
@@ -475,7 +474,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
// and should execute the error action
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
final Rollout rollout = rolloutManagement.get(createdRollout.getId()).get();
|
||||
final Rollout rollout = reloadRollout(createdRollout);
|
||||
// the rollout itself should be in paused based on the error action
|
||||
assertThat(rollout.getStatus()).isEqualTo(RolloutStatus.PAUSED);
|
||||
|
||||
@@ -489,7 +488,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
rolloutManagement.resumeRollout(createdRollout.getId());
|
||||
|
||||
// the rollout should be running again
|
||||
assertThat(rolloutManagement.get(createdRollout.getId()).get().getStatus()).isEqualTo(RolloutStatus.RUNNING);
|
||||
assertThat(reloadRollout(createdRollout).getStatus()).isEqualTo(RolloutStatus.RUNNING);
|
||||
|
||||
// checking rollouts again
|
||||
rolloutManagement.handleRollouts();
|
||||
@@ -503,7 +502,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfiying that the rollout is starting group after group and gets finished at the end")
|
||||
@Description("Verifying that the rollout is starting group after group and gets finished at the end")
|
||||
void rolloutStartsGroupAfterGroupAndGetsFinished() {
|
||||
final int amountTargetsForRollout = 10;
|
||||
final int amountOtherTargets = 15;
|
||||
@@ -522,7 +521,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
rolloutManagement.handleRollouts();
|
||||
// finish running actions, 2 actions should be finished
|
||||
assertThat(changeStatusForAllRunningActions(createdRollout, Status.FINISHED)).isEqualTo(2);
|
||||
assertThat(rolloutManagement.get(createdRollout.getId()).get().getStatus())
|
||||
assertThat(getRollout(createdRollout.getId()).getStatus())
|
||||
.isEqualTo(RolloutStatus.RUNNING);
|
||||
|
||||
}
|
||||
@@ -536,7 +535,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
.forEach(group -> assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.FINISHED));
|
||||
|
||||
// verify that rollout itself is in finished state
|
||||
final Rollout findRolloutById = rolloutManagement.get(createdRollout.getId()).get();
|
||||
final Rollout findRolloutById = reloadRollout(createdRollout);
|
||||
assertThat(findRolloutById.getStatus()).isEqualTo(RolloutStatus.FINISHED);
|
||||
}
|
||||
|
||||
@@ -726,7 +725,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
// round(7/3)=2 targets running (Group 3)
|
||||
// round(5/2)=3 targets SCHEDULED (Group 3)
|
||||
// round(2/1)=2 targets SCHEDULED (Group 4)
|
||||
createdRollout = rolloutManagement.get(createdRollout.getId()).get();
|
||||
createdRollout = reloadRollout(createdRollout);
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(PAGE, createdRollout.getId())
|
||||
.getContent();
|
||||
|
||||
@@ -761,7 +760,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
successCondition, errorCondition);
|
||||
final DistributionSet ds = createdRollout.getDistributionSet();
|
||||
|
||||
createdRollout = rolloutManagement.get(createdRollout.getId()).get();
|
||||
createdRollout = reloadRollout(createdRollout);
|
||||
// 5 targets are running
|
||||
final List<Action> runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING);
|
||||
assertThat(runningActions.size()).isEqualTo(5);
|
||||
@@ -803,7 +802,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
Rollout rolloutOne = createAndStartRollout(amountTargetsForRollout, amountOtherTargets, amountGroups,
|
||||
successCondition, errorCondition);
|
||||
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
|
||||
final DistributionSet dsForRolloutTwo = testdataFactory.createDistributionSet("dsForRolloutTwo");
|
||||
|
||||
@@ -834,7 +833,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that error status of DistributionSet installation during rollout can get rerun with second rollout so that all targets have some DistributionSet installed at the end.")
|
||||
void startSecondRolloutAfterFristRolloutEndenWithErrors() {
|
||||
void startSecondRolloutAfterFirstRolloutEndsWithErrors() {
|
||||
|
||||
final int amountTargetsForRollout = 15;
|
||||
final int amountOtherTargets = 0;
|
||||
@@ -845,7 +844,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
successCondition, errorCondition);
|
||||
final DistributionSet distributionSet = rolloutOne.getDistributionSet();
|
||||
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
changeStatusForRunningActions(rolloutOne, Status.ERROR, 2);
|
||||
changeStatusForRunningActions(rolloutOne, Status.FINISHED, 3);
|
||||
rolloutManagement.handleRollouts();
|
||||
@@ -862,7 +861,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.ERROR, 6L);
|
||||
validateRolloutActionStatus(rolloutOne.getId(), expectedTargetCountStatus);
|
||||
// rollout is finished
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
assertThat(rolloutOne.getStatus()).isEqualTo(RolloutStatus.FINISHED);
|
||||
|
||||
final int amountGroupsForRolloutTwo = 1;
|
||||
@@ -875,7 +874,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
rolloutTwo = rolloutManagement.get(rolloutTwo.getId()).get();
|
||||
rolloutTwo = reloadRollout(rolloutTwo);
|
||||
// 6 error targets are now running
|
||||
expectedTargetCountStatus = createInitStatusMap();
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 6L);
|
||||
@@ -902,21 +901,21 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
Rollout rolloutOne = createAndStartRollout(amountTargetsForRollout, amountOtherTargets, amountGroups,
|
||||
successCondition, errorCondition);
|
||||
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
changeStatusForRunningActions(rolloutOne, Status.ERROR, 2);
|
||||
changeStatusForRunningActions(rolloutOne, Status.FINISHED, 3);
|
||||
rolloutManagement.handleRollouts();
|
||||
// verify: 40% error but 60% finished -> should move to next group
|
||||
final List<RolloutGroup> rolloutGruops = rolloutGroupManagement.findByRollout(PAGE, rolloutOne.getId())
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(PAGE, rolloutOne.getId())
|
||||
.getContent();
|
||||
final Map<TotalTargetCountStatus.Status, Long> expectedTargetCountStatus = createInitStatusMap();
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 5L);
|
||||
validateRolloutGroupActionStatus(rolloutGruops.get(1), expectedTargetCountStatus);
|
||||
validateRolloutGroupActionStatus(rolloutGroups.get(1), expectedTargetCountStatus);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the rollout does not move to the next group when the sucess condition was not achieved.")
|
||||
@Description("Verify that the rollout does not move to the next group when the success condition was not achieved.")
|
||||
void successConditionNotAchieved() {
|
||||
|
||||
final int amountTargetsForRollout = 10;
|
||||
@@ -927,7 +926,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
Rollout rolloutOne = createAndStartRollout(amountTargetsForRollout, amountOtherTargets, amountGroups,
|
||||
successCondition, errorCondition);
|
||||
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
changeStatusForRunningActions(rolloutOne, Status.ERROR, 2);
|
||||
changeStatusForRunningActions(rolloutOne, Status.FINISHED, 3);
|
||||
rolloutManagement.handleRollouts();
|
||||
@@ -952,12 +951,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
Rollout rolloutOne = createAndStartRollout(amountTargetsForRollout, amountOtherTargets, amountGroups,
|
||||
successCondition, errorCondition);
|
||||
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
changeStatusForRunningActions(rolloutOne, Status.ERROR, 2);
|
||||
changeStatusForRunningActions(rolloutOne, Status.FINISHED, 3);
|
||||
rolloutManagement.handleRollouts();
|
||||
// verify: 40% error -> should pause because errorCondition is 20%
|
||||
rolloutOne = rolloutManagement.get(rolloutOne.getId()).get();
|
||||
rolloutOne = reloadRollout(rolloutOne);
|
||||
assertThat(rolloutOne.getStatus()).isEqualTo(RolloutStatus.PAUSED);
|
||||
}
|
||||
|
||||
@@ -1138,7 +1137,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
changeStatusForRunningActions(myRollout, Status.FINISHED, 2);
|
||||
rolloutManagement.handleRollouts();
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = reloadRollout(myRollout);
|
||||
|
||||
float percent = rolloutGroupManagement
|
||||
.getWithDetailedStatus(
|
||||
@@ -1191,7 +1190,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
final Condition<String> targetBelongsInRollout = new Condition<>(s -> s.startsWith(rolloutName),
|
||||
"Target belongs into rollout");
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = reloadRollout(myRollout);
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(PAGE, myRollout.getId())
|
||||
.getContent();
|
||||
|
||||
@@ -1258,22 +1257,22 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify the creation and the start of a Rollout with more groups than targets.")
|
||||
void createAndStartRolloutWithEmptyGroups() throws Exception {
|
||||
void createAndStartRolloutWithEmptyGroups() {
|
||||
final int amountTargetsForRollout = 3;
|
||||
final int amountGroups = 5;
|
||||
final String successCondition = "50";
|
||||
final String errorCondition = "80";
|
||||
final String rolloutName = "rolloutTestG";
|
||||
final String targetPrefixName = rolloutName;
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName);
|
||||
|
||||
Rollout myRollout = testdataFactory.createRolloutByVariables(rolloutName, "desc", amountGroups,
|
||||
"controllerId==" + targetPrefixName + "-*", distributionSet, successCondition, errorCondition);
|
||||
"controllerId==" + rolloutName + "-*", distributionSet, successCondition, errorCondition);
|
||||
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
|
||||
final List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(PAGE, myRollout.getId()).getContent();
|
||||
final Long myRolloutId = myRollout.getId();
|
||||
final List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(PAGE, myRolloutId).getContent();
|
||||
|
||||
assertThat(groups.get(0).getStatus()).isEqualTo(RolloutGroupStatus.READY);
|
||||
assertThat(groups.get(0).getTotalTargets()).isEqualTo(1);
|
||||
@@ -1286,69 +1285,62 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(groups.get(4).getStatus()).isEqualTo(RolloutGroupStatus.READY);
|
||||
assertThat(groups.get(4).getTotalTargets()).isZero();
|
||||
|
||||
rolloutManagement.start(myRollout.getId());
|
||||
rolloutManagement.start(myRolloutId);
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
final SuccessConditionRolloutStatus conditionRolloutStatus = new SuccessConditionRolloutStatus(
|
||||
RolloutStatus.RUNNING);
|
||||
assertThat(MultipleInvokeHelper.doWithTimeout(new RolloutStatusCallable(myRollout.getId()),
|
||||
conditionRolloutStatus, 15000, 500)).as("Rollout status").isNotNull();
|
||||
awaitRunningState(myRolloutId);
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRolloutId);
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING);
|
||||
final Map<TotalTargetCountStatus.Status, Long> expectedTargetCountStatus = createInitStatusMap();
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 1L);
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.SCHEDULED, 2L);
|
||||
validateRolloutActionStatus(myRollout.getId(), expectedTargetCountStatus);
|
||||
|
||||
validateRolloutActionStatus(myRolloutId, expectedTargetCountStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the creation and the start of a rollout.")
|
||||
void createAndStartRollout() throws Exception {
|
||||
void createAndStartRollout() {
|
||||
|
||||
final int amountTargetsForRollout = 50;
|
||||
final int amountGroups = 5;
|
||||
final String successCondition = "50";
|
||||
final String errorCondition = "80";
|
||||
final String rolloutName = "rolloutTest";
|
||||
final String targetPrefixName = rolloutName;
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName);
|
||||
|
||||
Rollout myRollout = testdataFactory.createRolloutByVariables(rolloutName, "desc", amountGroups,
|
||||
"controllerId==" + targetPrefixName + "-*", distributionSet, successCondition, errorCondition);
|
||||
"controllerId==" + rolloutName + "-*", distributionSet, successCondition, errorCondition);
|
||||
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
final Long myRolloutId = myRollout.getId();
|
||||
myRollout = getRollout(myRolloutId);
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
|
||||
rolloutManagement.start(myRollout.getId());
|
||||
rolloutManagement.start(myRolloutId);
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
final SuccessConditionRolloutStatus conditionRolloutTargetCount = new SuccessConditionRolloutStatus(
|
||||
RolloutStatus.RUNNING);
|
||||
assertThat(MultipleInvokeHelper.doWithTimeout(new RolloutStatusCallable(myRollout.getId()),
|
||||
conditionRolloutTargetCount, 15000, 500)).as("Rollout status").isNotNull();
|
||||
awaitRunningState(myRolloutId);
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = reloadRollout(myRollout);
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING);
|
||||
final Map<TotalTargetCountStatus.Status, Long> expectedTargetCountStatus = createInitStatusMap();
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 10L);
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.SCHEDULED, 40L);
|
||||
validateRolloutActionStatus(myRollout.getId(), expectedTargetCountStatus);
|
||||
validateRolloutActionStatus(myRolloutId, expectedTargetCountStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a rollout cannot be created if the 'max targets per rollout group' quota is violated.")
|
||||
void createRolloutFailsIfQuotaGroupQuotaIsViolated() throws Exception {
|
||||
void createRolloutFailsIfQuotaGroupQuotaIsViolated() {
|
||||
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerRolloutGroup();
|
||||
|
||||
@@ -1375,15 +1367,14 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that a rollout cannot be created based on group definitions if the 'max targets per rollout group' quota is violated for one of the groups.")
|
||||
void createRolloutWithGroupDefinitionsFailsIfQuotaGroupQuotaIsViolated() throws Exception {
|
||||
void createRolloutWithGroupDefinitionsFailsIfQuotaGroupQuotaIsViolated() {
|
||||
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerRolloutGroup();
|
||||
|
||||
final int amountTargetsForRollout = maxTargets * 2 + 2;
|
||||
final String rolloutName = "rolloutTest";
|
||||
final String targetPrefixName = rolloutName;
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName);
|
||||
|
||||
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
|
||||
|
||||
@@ -1395,9 +1386,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// group1 exceeds the quota
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create(
|
||||
entityFactory.rollout().create().name(rolloutName).description(rolloutName)
|
||||
.targetFilterQuery("controllerId==" + targetPrefixName + "-*").set(distributionSet),
|
||||
Arrays.asList(group1, group2), conditions));
|
||||
entityFactory.rollout()
|
||||
.create()
|
||||
.name(rolloutName)
|
||||
.description(rolloutName)
|
||||
.targetFilterQuery("controllerId==" + rolloutName + "-*")
|
||||
.set(distributionSet), Arrays.asList(group1, group2), conditions));
|
||||
|
||||
// create group definitions
|
||||
final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3")
|
||||
@@ -1407,74 +1401,93 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// group4 exceeds the quota
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create(
|
||||
entityFactory.rollout().create().name(rolloutName).description(rolloutName)
|
||||
.targetFilterQuery("controllerId==" + targetPrefixName + "-*").set(distributionSet),
|
||||
Arrays.asList(group3, group4), conditions));
|
||||
entityFactory.rollout()
|
||||
.create()
|
||||
.name(rolloutName)
|
||||
.description(rolloutName)
|
||||
.targetFilterQuery("controllerId==" + rolloutName + "-*")
|
||||
.set(distributionSet), Arrays.asList(group3, group4), conditions));
|
||||
|
||||
// create group definitions
|
||||
final RolloutGroupCreate group5 = entityFactory.rolloutGroup().create().conditions(conditions).name("group5")
|
||||
final RolloutGroupCreate group5 = entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.conditions(conditions)
|
||||
.name("group5")
|
||||
.targetPercentage(33.3F);
|
||||
final RolloutGroupCreate group6 = entityFactory.rolloutGroup().create().conditions(conditions).name("group6")
|
||||
final RolloutGroupCreate group6 = entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.conditions(conditions)
|
||||
.name("group6")
|
||||
.targetPercentage(66.6F);
|
||||
final RolloutGroupCreate group7 = entityFactory.rolloutGroup().create().conditions(conditions).name("group7")
|
||||
final RolloutGroupCreate group7 = entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.conditions(conditions)
|
||||
.name("group7")
|
||||
.targetPercentage(100.0F);
|
||||
|
||||
// should work fine
|
||||
assertThat(rolloutManagement.create(
|
||||
entityFactory.rollout().create().name(rolloutName).description(rolloutName)
|
||||
.targetFilterQuery("controllerId==" + targetPrefixName + "-*").set(distributionSet),
|
||||
Arrays.asList(group5, group6, group7), conditions)).isNotNull();
|
||||
assertThat(rolloutManagement.create(entityFactory.rollout()
|
||||
.create()
|
||||
.name(rolloutName)
|
||||
.description(rolloutName)
|
||||
.targetFilterQuery("controllerId==" + rolloutName + "-*")
|
||||
.set(distributionSet), Arrays.asList(group5, group6, group7), conditions)).isNotNull();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the creation and the automatic start of a rollout.")
|
||||
void createAndAutoStartRollout() throws Exception {
|
||||
void createAndAutoStartRollout() {
|
||||
|
||||
final int amountTargetsForRollout = 50;
|
||||
final int amountGroups = 5;
|
||||
final String successCondition = "50";
|
||||
final String errorCondition = "80";
|
||||
final String rolloutName = "rolloutTest8";
|
||||
final String targetPrefixName = rolloutName;
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName);
|
||||
|
||||
Rollout myRollout = testdataFactory.createRolloutByVariables(rolloutName, "desc", amountGroups,
|
||||
"controllerId==" + targetPrefixName + "-*", distributionSet, successCondition, errorCondition);
|
||||
"controllerId==" + rolloutName + "-*", distributionSet, successCondition, errorCondition);
|
||||
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
|
||||
// schedule rollout auto start into the future
|
||||
final Long myRolloutId = myRollout.getId();
|
||||
rolloutManagement
|
||||
.update(entityFactory.rollout().update(myRollout.getId()).startAt(System.currentTimeMillis() + 60000));
|
||||
.update(entityFactory.rollout().update(myRolloutId).startAt(System.currentTimeMillis() + 60000));
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
// rollout should not have been started
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRolloutId);
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
|
||||
// schedule to now
|
||||
rolloutManagement.update(entityFactory.rollout().update(myRollout.getId()).startAt(System.currentTimeMillis()));
|
||||
rolloutManagement.update(entityFactory.rollout().update(myRolloutId).startAt(System.currentTimeMillis()));
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRolloutId);
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.STARTING);
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
final SuccessConditionRolloutStatus conditionRolloutTargetCount = new SuccessConditionRolloutStatus(
|
||||
RolloutStatus.RUNNING);
|
||||
assertThat(MultipleInvokeHelper.doWithTimeout(new RolloutStatusCallable(myRollout.getId()),
|
||||
conditionRolloutTargetCount, 15000, 500)).as("Rollout status").isNotNull();
|
||||
awaitRunningState(myRolloutId);
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRolloutId);
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING);
|
||||
final Map<TotalTargetCountStatus.Status, Long> expectedTargetCountStatus = createInitStatusMap();
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 10L);
|
||||
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.SCHEDULED, 40L);
|
||||
validateRolloutActionStatus(myRollout.getId(), expectedTargetCountStatus);
|
||||
validateRolloutActionStatus(myRolloutId, expectedTargetCountStatus);
|
||||
}
|
||||
|
||||
private Rollout reloadRollout(final Rollout r) {
|
||||
return getRollout(r.getId());
|
||||
}
|
||||
|
||||
private Rollout getRollout(final Long myRolloutId) {
|
||||
return rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1506,7 +1519,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
rolloutGroups.add(generateRolloutGroup(2, percentTargetsInGroup3, null));
|
||||
|
||||
Rollout myRollout = rolloutManagement.create(rolloutcreate, rolloutGroups, conditions);
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRollout.getId());
|
||||
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.CREATING);
|
||||
for (final RolloutGroup group : rolloutGroupManagement.findByRollout(PAGE, myRollout.getId()).getContent()) {
|
||||
@@ -1520,7 +1533,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRollout.getId());
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
assertThat(myRollout.getTotalTargets()).isEqualTo(amountTargetsInGroup1and2 + amountTargetsInGroup1);
|
||||
|
||||
@@ -1539,7 +1552,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify rollout creation fails if group definition does not address all targets")
|
||||
void createRolloutWithGroupsNotMatchingTargets() throws Exception {
|
||||
void createRolloutWithGroupsNotMatchingTargets() {
|
||||
final String rolloutName = "rolloutTest4";
|
||||
final int amountTargetsForRollout = 500;
|
||||
final int percentTargetsInGroup1 = 20;
|
||||
@@ -1560,7 +1573,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify rollout creation fails if group definition specifies illegal target percentage")
|
||||
void createRolloutWithIllegalPercentage() throws Exception {
|
||||
void createRolloutWithIllegalPercentage() {
|
||||
final String rolloutName = "rolloutTest6";
|
||||
final int amountTargetsForRollout = 10;
|
||||
final int percentTargetsInGroup1 = 101;
|
||||
@@ -1581,7 +1594,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify rollout creation fails if the 'max rollout groups per rollout' quota is violated.")
|
||||
void createRolloutWithIllegalAmountOfGroups() throws Exception {
|
||||
void createRolloutWithIllegalAmountOfGroups() {
|
||||
final String rolloutName = "rolloutTest5";
|
||||
final int targets = 10;
|
||||
final int maxGroups = quotaManagement.getMaxRolloutGroupsPerRollout();
|
||||
@@ -1589,34 +1602,33 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
|
||||
final RolloutCreate rollout = generateTargetsAndRollout(rolloutName, targets);
|
||||
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> rolloutManagement.create(rollout, maxGroups + 1, conditions))
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(
|
||||
() -> rolloutManagement.create(rollout, maxGroups + 1, conditions))
|
||||
.withMessageContaining("not be greater than " + maxGroups);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the start of a Rollout does not work during creation phase.")
|
||||
void createAndStartRolloutDuringCreationFails() throws Exception {
|
||||
void createAndStartRolloutDuringCreationFails() {
|
||||
final int amountTargetsForRollout = 3;
|
||||
final int amountGroups = 5;
|
||||
final String successCondition = "50";
|
||||
final String errorCondition = "80";
|
||||
final String rolloutName = "rolloutTestGC";
|
||||
final String targetPrefixName = rolloutName;
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, targetPrefixName + "-", targetPrefixName);
|
||||
testdataFactory.createTargets(amountTargetsForRollout, rolloutName + "-", rolloutName);
|
||||
|
||||
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, successCondition)
|
||||
.errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition)
|
||||
.errorAction(RolloutGroupErrorAction.PAUSE, null).build();
|
||||
final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName)
|
||||
.description("some description").targetFilterQuery("id==" + targetPrefixName + "-*")
|
||||
.description("some description").targetFilterQuery("id==" + rolloutName + "-*")
|
||||
.set(distributionSet);
|
||||
|
||||
Rollout myRollout = rolloutManagement.create(rolloutToCreate, amountGroups, conditions);
|
||||
myRollout = rolloutManagement.get(myRollout.getId()).get();
|
||||
myRollout = getRollout(myRollout.getId());
|
||||
|
||||
assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.CREATING);
|
||||
|
||||
@@ -1640,7 +1652,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Creating a rollout without approver role and approval enabled leads to transition to "
|
||||
@Description("Creating a rollout without approve role and approval enabled leads to transition to "
|
||||
+ "WAITING_FOR_APPROVAL state.")
|
||||
void createdRolloutWithoutApprovalRoleTransitionsToWaitingForApprovalState() {
|
||||
approvalStrategy.setApprovalNeeded(true);
|
||||
@@ -1770,7 +1782,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Creating a rollout without weight value when multi assignment in enabled.")
|
||||
void weightNotRequiredInMultiAssignmentMode() {
|
||||
enableMultiAssignments();
|
||||
createSimpleTestRolloutWithTargetsAndDistributionSet(10, 10, 2, "50", "80", ActionType.FORCED, null);
|
||||
final Rollout rollout = createSimpleTestRolloutWithTargetsAndDistributionSet(
|
||||
10, 10, 2, "50", "80", ActionType.FORCED, null);
|
||||
assertThat(rollout).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1805,7 +1819,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("A Rollout with weight creats actions with weights")
|
||||
@Description("A Rollout with weight creates actions with weights")
|
||||
void actionsWithWeightAreCreated() {
|
||||
final int amountOfTargets = 5;
|
||||
final int weight = 99;
|
||||
@@ -1815,8 +1829,9 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
rolloutManagement.start(rolloutId);
|
||||
rolloutManagement.handleRollouts();
|
||||
final List<Action> actions = deploymentManagement.findActionsAll(PAGE).getContent();
|
||||
assertThat(actions).hasSize(amountOfTargets);
|
||||
assertThat(actions).allMatch(action -> action.getWeight().get() == weight);
|
||||
assertThat(actions) //
|
||||
.hasSize(amountOfTargets) //
|
||||
.allMatch(action -> action.getWeight().get() == weight);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1830,57 +1845,58 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
rolloutManagement.start(rolloutId);
|
||||
rolloutManagement.handleRollouts();
|
||||
final List<Action> actions = deploymentManagement.findActionsAll(PAGE).getContent();
|
||||
assertThat(actions).hasSize(amountOfTargets);
|
||||
assertThat(actions).allMatch(action -> !action.getWeight().isPresent());
|
||||
assertThat(actions).hasSize(amountOfTargets).allMatch(action -> !action.getWeight().isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to create a rollout with an invalidated distribution set.")
|
||||
public void createRolloutWithInvalidDistributionSet() {
|
||||
void createRolloutWithInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class).as(
|
||||
"Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithInvalidDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to create a rollout with an incomplete distribution set.")
|
||||
public void createRolloutWithIncompleteDistributionSet() {
|
||||
void createRolloutWithIncompleteDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class).as(
|
||||
"Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithIncompleteDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update a rollout with an invalidated distribution set.")
|
||||
public void updateRolloutWithInvalidDistributionSet() {
|
||||
void updateRolloutWithInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
testdataFactory.createTarget();
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("updateRolloutWithInvalidDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80");
|
||||
final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> rolloutManagement
|
||||
.update(entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId())));
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class).as(
|
||||
"Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> rolloutManagement.update(
|
||||
entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update a rollout with an incomplete distribution set.")
|
||||
public void updateRolloutWithIncompleteDistributionSet() {
|
||||
void updateRolloutWithIncompleteDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
testdataFactory.createTarget();
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("updateRolloutWithIncompleteDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80");
|
||||
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception").isThrownBy(() -> rolloutManagement.update(
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class).as(
|
||||
"Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> rolloutManagement.update(
|
||||
entityFactory.rollout().update(rollout.getId()).set(incompleteDistributionSet.getId())));
|
||||
}
|
||||
|
||||
@@ -1903,27 +1919,31 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
targets.addAll(targetsWithoutType);
|
||||
|
||||
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
|
||||
final RolloutCreate rolloutToCreate = entityFactory.rollout().create().name(rolloutName)
|
||||
.targetFilterQuery("name==*").set(testDs);
|
||||
final RolloutCreate rolloutToCreate = entityFactory.rollout()
|
||||
.create()
|
||||
.name(rolloutName)
|
||||
.targetFilterQuery("name==*")
|
||||
.set(testDs);
|
||||
|
||||
final Rollout createdRollout = rolloutManagement.create(rolloutToCreate, 1, conditions);
|
||||
|
||||
// Let the executor handle created Rollout
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
final Rollout testRollout = rolloutManagement.get(createdRollout.getId()).get();
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement
|
||||
.findByRollout(Pageable.unpaged(), testRollout.getId()).getContent();
|
||||
final Rollout testRollout = reloadRollout(createdRollout);
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(Pageable.unpaged(),
|
||||
testRollout.getId()).getContent();
|
||||
|
||||
assertThat(testRollout.getStatus()).isEqualTo(RolloutStatus.READY);
|
||||
assertThat(testRollout.getTotalTargets()).isEqualTo(targets.size());
|
||||
assertThat(rolloutGroups).hasSize(1);
|
||||
assertThat(rolloutGroups.get(0).getTotalTargets()).isEqualTo(targets.size());
|
||||
|
||||
final List<Target> rolloutGroupTargets = rolloutGroupManagement
|
||||
.findTargetsOfRolloutGroup(Pageable.unpaged(), rolloutGroups.get(0).getId()).getContent();
|
||||
final List<Target> rolloutGroupTargets = rolloutGroupManagement.findTargetsOfRolloutGroup(Pageable.unpaged(),
|
||||
rolloutGroups.get(0).getId()).getContent();
|
||||
|
||||
assertThat(rolloutGroupTargets).hasSize(targets.size()).containsExactlyInAnyOrderElementsOf(targets)
|
||||
assertThat(rolloutGroupTargets).hasSize(targets.size())
|
||||
.containsExactlyInAnyOrderElementsOf(targets)
|
||||
.doesNotContainAnyElementsOf(incompatibleTargets);
|
||||
}
|
||||
|
||||
@@ -2027,35 +2047,14 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
return map;
|
||||
}
|
||||
|
||||
private static class SuccessConditionRolloutStatus implements SuccessCondition<RolloutStatus> {
|
||||
|
||||
private final RolloutStatus rolloutStatus;
|
||||
|
||||
public SuccessConditionRolloutStatus(final RolloutStatus rolloutStatus) {
|
||||
this.rolloutStatus = rolloutStatus;
|
||||
private void awaitRunningState(final Long myRolloutId) {
|
||||
Awaitility.await()
|
||||
.atMost(Duration.TEN_SECONDS)
|
||||
.pollInterval(Duration.FIVE_HUNDRED_MILLISECONDS)
|
||||
.with()
|
||||
.until(() -> WithSpringAuthorityRule.runAsPrivileged(
|
||||
() -> rolloutManagement.get(myRolloutId).orElseThrow(NoSuchElementException::new))
|
||||
.getStatus()
|
||||
.equals(RolloutStatus.RUNNING));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean success(final RolloutStatus result) {
|
||||
return result.equals(rolloutStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private class RolloutStatusCallable implements Callable<RolloutStatus> {
|
||||
|
||||
final Long rolloutId;
|
||||
|
||||
RolloutStatusCallable(final Long rolloutId) {
|
||||
this.rolloutId = rolloutId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RolloutStatus call() throws Exception {
|
||||
|
||||
final Rollout myRollout = rolloutManagement.get(rolloutId).get();
|
||||
return myRollout.getStatus();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
|
||||
@@ -57,7 +59,7 @@ import io.qameta.allure.Story;
|
||||
public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access reacts as specfied on calls for non existing entities by means "
|
||||
@Description("Verifies that management get access reacts as specified on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
@@ -80,7 +82,8 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> softwareModuleManagement
|
||||
.create(Arrays.asList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))),
|
||||
.create(Collections
|
||||
.singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))),
|
||||
"SoftwareModuleType");
|
||||
verifyThrownExceptionBy(
|
||||
() -> softwareModuleManagement
|
||||
@@ -92,12 +95,13 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx")),
|
||||
"SoftwareModule");
|
||||
verifyThrownExceptionBy(
|
||||
() -> softwareModuleManagement.createMetaData(Arrays
|
||||
.asList(entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx"))),
|
||||
() -> softwareModuleManagement.createMetaData(Collections.singletonList(
|
||||
entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx"))),
|
||||
"SoftwareModule");
|
||||
|
||||
verifyThrownExceptionBy(() -> softwareModuleManagement.delete(NOT_EXIST_IDL), "SoftwareModule");
|
||||
verifyThrownExceptionBy(() -> softwareModuleManagement.delete(Arrays.asList(NOT_EXIST_IDL)), "SoftwareModule");
|
||||
verifyThrownExceptionBy(() -> softwareModuleManagement.delete(Collections.singletonList(NOT_EXIST_IDL)),
|
||||
"SoftwareModule");
|
||||
verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(NOT_EXIST_IDL, "xxx"), "SoftwareModule");
|
||||
verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(module.getId(), NOT_EXIST_ID),
|
||||
"SoftwareModuleMetadata");
|
||||
@@ -141,13 +145,13 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
.update(entityFactory.softwareModule().update(ah.getId()));
|
||||
|
||||
assertThat(updated.getOptLockRevision())
|
||||
.as("Expected version number of updated entitity to be equal to created version")
|
||||
.as("Expected version number of updated entity to be equal to created version")
|
||||
.isEqualTo(ah.getOptLockRevision());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Calling update for changed fields results in change in the repository.")
|
||||
public void updateSoftareModuleFieldsToNewValue() {
|
||||
public void updateSoftwareModuleFieldsToNewValue() {
|
||||
final SoftwareModule ah = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final SoftwareModule updated = softwareModuleManagement
|
||||
@@ -213,7 +217,9 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
assignDistributionSet(ds.getId(), target.getControllerId());
|
||||
assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(ds);
|
||||
final Optional<DistributionSet> assignedDistributionSet = deploymentManagement
|
||||
.getAssignedDistributionSet(target.getControllerId());
|
||||
assertThat(assignedDistributionSet).contains(ds);
|
||||
final Action action = actionRepository.findByTargetAndDistributionSet(PAGE, target, ds).getContent().get(0);
|
||||
assertThat(action).isNotNull();
|
||||
return action;
|
||||
@@ -273,13 +279,13 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// [VERIFY EXPECTED RESULT]:
|
||||
// verify: SoftwareModule is deleted
|
||||
assertThat(softwareModuleRepository.findAll()).hasSize(0);
|
||||
assertThat(softwareModuleRepository.findAll()).isEmpty();
|
||||
assertThat(softwareModuleManagement.get(unassignedModule.getId())).isNotPresent();
|
||||
|
||||
// verify: binary data of artifact is deleted
|
||||
assertArtifactNull(artifact1, artifact2);
|
||||
|
||||
// verify: meta data of artifact is deleted
|
||||
// verify: metadata of artifact is deleted
|
||||
assertThat(artifactRepository.findById(artifact1.getId())).isNotPresent();
|
||||
assertThat(artifactRepository.findById(artifact2.getId())).isNotPresent();
|
||||
}
|
||||
@@ -301,7 +307,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
// verify: assignedModule is marked as deleted
|
||||
assignedModule = softwareModuleManagement.get(assignedModule.getId()).get();
|
||||
assertTrue(assignedModule.isDeleted(), "The module should be flagged as deleted");
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).isEmpty();
|
||||
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
||||
|
||||
// verify: binary data is deleted
|
||||
@@ -329,7 +335,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet disSet = testdataFactory.createDistributionSet(Sets.newHashSet(assignedModule));
|
||||
|
||||
// [STEP3]: Assign DistributionSet to a Device
|
||||
assignDistributionSet(disSet, Arrays.asList(target));
|
||||
assignDistributionSet(disSet, Collections.singletonList(target));
|
||||
|
||||
// [STEP4]: Delete the DistributionSet
|
||||
distributionSetManagement.delete(disSet.getId());
|
||||
@@ -341,7 +347,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
// verify: assignedModule is marked as deleted
|
||||
assignedModule = softwareModuleManagement.get(assignedModule.getId()).get();
|
||||
assertTrue(assignedModule.isDeleted(), "The found module should be flagged deleted");
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).isEmpty();
|
||||
assertThat(softwareModuleRepository.findAll()).hasSize(1);
|
||||
|
||||
// verify: binary data is deleted
|
||||
@@ -356,8 +362,8 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Delete an softwaremodule with an artifact, which is alsoused by another softwaremodule.")
|
||||
public void deleteSoftwareModulesWithSharedArtifact() throws IOException {
|
||||
@Description("Delete an software module with an artifact, which is also used by another software module.")
|
||||
public void deleteSoftwareModulesWithSharedArtifact() {
|
||||
|
||||
// Init artifact binary data, target and DistributionSets
|
||||
final int artifactSize = 1024;
|
||||
@@ -428,11 +434,11 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// [STEP3]: Assign SoftwareModuleX to DistributionSetX and to target
|
||||
final DistributionSet disSetX = testdataFactory.createDistributionSet(Sets.newHashSet(moduleX), "X");
|
||||
assignDistributionSet(disSetX, Arrays.asList(target));
|
||||
assignDistributionSet(disSetX, Collections.singletonList(target));
|
||||
|
||||
// [STEP4]: Assign SoftwareModuleY to DistributionSet and to target
|
||||
final DistributionSet disSetY = testdataFactory.createDistributionSet(Sets.newHashSet(moduleY), "Y");
|
||||
assignDistributionSet(disSetY, Arrays.asList(target));
|
||||
assignDistributionSet(disSetY, Collections.singletonList(target));
|
||||
|
||||
// [STEP5]: Delete SoftwareModuleX
|
||||
softwareModuleManagement.delete(moduleX.getId());
|
||||
@@ -444,12 +450,12 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
moduleX = softwareModuleManagement.get(moduleX.getId()).get();
|
||||
moduleY = softwareModuleManagement.get(moduleY.getId()).get();
|
||||
|
||||
// verify: SoftwareModuleX and SofwtareModule are marked as deleted
|
||||
// verify: SoftwareModuleX and SoftwareModule are marked as deleted
|
||||
assertThat(moduleX).isNotNull();
|
||||
assertThat(moduleY).isNotNull();
|
||||
assertTrue(moduleX.isDeleted(), "The module should be flagged deleted");
|
||||
assertTrue(moduleY.isDeleted(), "The module should be flagged deleted");
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).isEmpty();
|
||||
assertThat(softwareModuleRepository.findAll()).hasSize(2);
|
||||
|
||||
// verify: binary data of artifact is deleted
|
||||
@@ -506,7 +512,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test verfies that results are returned based on given filter parameters and in the specified order.")
|
||||
@Description("Test verifies that results are returned based on given filter parameters and in the specified order.")
|
||||
public void findSoftwareModuleOrderByDistributionModuleNameAscModuleVersionAsc() {
|
||||
// test meta data
|
||||
final SoftwareModuleType testType = softwareModuleTypeManagement
|
||||
@@ -515,9 +521,9 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
.create(entityFactory.distributionSetType().create().key("key").name("name"));
|
||||
|
||||
distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(testDsType.getId(),
|
||||
Arrays.asList(osType.getId()));
|
||||
Collections.singletonList(osType.getId()));
|
||||
testDsType = distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(testDsType.getId(),
|
||||
Arrays.asList(testType.getId()));
|
||||
Collections.singletonList(testType.getId()));
|
||||
|
||||
// found in test
|
||||
final SoftwareModule unassigned = testdataFactory.createSoftwareModule("thetype", "unassignedfound", false);
|
||||
@@ -567,9 +573,9 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
.create(entityFactory.distributionSetType().create().key("key").name("name"));
|
||||
|
||||
distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(testDsType.getId(),
|
||||
Arrays.asList(osType.getId()));
|
||||
Collections.singletonList(osType.getId()));
|
||||
testDsType = distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(testDsType.getId(),
|
||||
Arrays.asList(testType.getId()));
|
||||
Collections.singletonList(testType.getId()));
|
||||
|
||||
// found in test
|
||||
testdataFactory.createSoftwareModule("thetype", "unassignedfound", false);
|
||||
@@ -602,7 +608,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// one soft deleted
|
||||
final SoftwareModule deleted = testdataFactory.createSoftwareModuleApp();
|
||||
testdataFactory.createDistributionSet(Arrays.asList(deleted));
|
||||
testdataFactory.createDistributionSet(Collections.singletonList(deleted));
|
||||
softwareModuleManagement.delete(deleted.getId());
|
||||
|
||||
assertThat(softwareModuleManagement.count()).as("Number of undeleted modules").isEqualTo(1);
|
||||
@@ -610,7 +616,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that software modules are resturned that are assigned to given DS.")
|
||||
@Description("Verfies that software modules are returned that are assigned to given DS.")
|
||||
public void findSoftwareModuleByAssignedTo() {
|
||||
// test modules
|
||||
final SoftwareModule one = testdataFactory.createSoftwareModuleOs();
|
||||
@@ -688,7 +694,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// add some meta data entries
|
||||
final SoftwareModule module3 = testdataFactory.createSoftwareModuleApp("m3");
|
||||
final int firstHalf = Math.round(maxMetaData / 2);
|
||||
final int firstHalf = Math.round(((float) maxMetaData) / 2.f);
|
||||
for (int i = 0; i < firstHalf; ++i) {
|
||||
softwareModuleManagement.createMetaData(
|
||||
entityFactory.softwareModuleMetadata().create(module3.getId()).key("k" + i).value("v" + i));
|
||||
@@ -735,7 +741,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that metadata for a software module can be updated.")
|
||||
public void updateSoftwareModuleMetadata() throws InterruptedException {
|
||||
public void updateSoftwareModuleMetadata() {
|
||||
final String knownKey = "myKnownKey";
|
||||
final String knownValue = "myKnownValue";
|
||||
final String knownUpdateValue = "myNewUpdatedValue";
|
||||
@@ -752,18 +758,16 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(softwareModuleMetadata.getValue()).isEqualTo(knownValue);
|
||||
|
||||
// base software module should have now the opt lock revision one
|
||||
// because we are modifying the
|
||||
// base software module
|
||||
// because we are modifying the base software module
|
||||
SoftwareModule changedLockRevisionModule = softwareModuleManagement.get(ah.getId()).get();
|
||||
assertThat(changedLockRevisionModule.getOptLockRevision()).isEqualTo(2);
|
||||
|
||||
// update the software module metadata
|
||||
Thread.sleep(100);
|
||||
final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetaData(entityFactory
|
||||
.softwareModuleMetadata().update(ah.getId(), knownKey).value(knownUpdateValue).targetVisible(true));
|
||||
// we are updating the sw meta data so also modiying the base software
|
||||
// module so opt lock
|
||||
// revision must be two
|
||||
|
||||
// we are updating the sw metadata so also modifying the base software
|
||||
// module so opt lock revision must be two
|
||||
changedLockRevisionModule = softwareModuleManagement.get(ah.getId()).get();
|
||||
assertThat(changedLockRevisionModule.getOptLockRevision()).isEqualTo(3);
|
||||
|
||||
@@ -776,7 +780,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that existing metadata can be deleted.")
|
||||
@Description("Verifies that existing metadata can be deleted.")
|
||||
public void deleteSoftwareModuleMetadata() {
|
||||
final String knownKey1 = "myKnownKey1";
|
||||
final String knownValue1 = "myKnownValue1";
|
||||
@@ -796,11 +800,11 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
softwareModuleManagement.deleteMetaData(ah.getId(), knownKey1);
|
||||
assertThat(
|
||||
softwareModuleManagement.findMetaDataBySoftwareModuleId(PageRequest.of(0, 10), ah.getId()).getContent())
|
||||
.as("Metadata elemenets are").isEmpty();
|
||||
.as("Metadata elements are").isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that non existing metadata find results in exception.")
|
||||
@Description("Verifies that non existing metadata find results in exception.")
|
||||
public void findSoftwareModuleMetadataFailsIfEntryDoesNotExist() {
|
||||
final String knownKey1 = "myKnownKey1";
|
||||
final String knownValue1 = "myKnownValue1";
|
||||
@@ -854,7 +858,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(metadataSw1.getNumberOfElements()).isEqualTo(metadataCountSw1);
|
||||
assertThat(metadataSw1.getTotalElements()).isEqualTo(metadataCountSw1);
|
||||
|
||||
assertThat(metadataSw2.getNumberOfElements()).isEqualTo(0);
|
||||
assertThat(metadataSw2.getTotalElements()).isEqualTo(0);
|
||||
assertThat(metadataSw2.getNumberOfElements()).isZero();
|
||||
assertThat(metadataSw2.getTotalElements()).isZero();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,14 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.FilterParams;
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
@@ -77,7 +79,7 @@ import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Target Management")
|
||||
public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private static final String WHITESPACE_ERROR = "target with whitespaces in controller id should not be created";
|
||||
|
||||
@@ -85,7 +87,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Verifies that management get access react as specified on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
assertThat(targetManagement.getByControllerID(NOT_EXIST_ID)).isNotPresent();
|
||||
assertThat(targetManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
@@ -97,7 +99,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
+ " by means of throwing EntityNotFoundException.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetTagCreatedEvent.class, count = 1) })
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
final TargetTag tag = targetTagManagement.create(entityFactory.tag().create().name("A"));
|
||||
final Target target = testdataFactory.createTarget();
|
||||
|
||||
@@ -153,14 +155,15 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
verifyThrownExceptionBy(() -> targetManagement.update(entityFactory.target().update(NOT_EXIST_ID)), "Target");
|
||||
|
||||
verifyThrownExceptionBy(() -> targetManagement.createMetaData(NOT_EXIST_ID,
|
||||
Arrays.asList(entityFactory.generateTargetMetadata("123", "123"))), "Target");
|
||||
Collections.singletonList(entityFactory.generateTargetMetadata("123", "123"))), "Target");
|
||||
verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(NOT_EXIST_ID, "xxx"), "Target");
|
||||
verifyThrownExceptionBy(() -> targetManagement.deleteMetaData(target.getControllerId(), NOT_EXIST_ID),
|
||||
"TargetMetadata");
|
||||
verifyThrownExceptionBy(() -> targetManagement.getMetaDataByControllerId(NOT_EXIST_ID, "xxx"), "Target");
|
||||
verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerId(PAGE, NOT_EXIST_ID), "Target");
|
||||
verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerIdAndRsql(PAGE, NOT_EXIST_ID, "key==*"),
|
||||
verifyThrownExceptionBy(() -> targetManagement.findMetaDataByControllerId(PAGE, NOT_EXIST_ID),
|
||||
"Target");
|
||||
verifyThrownExceptionBy(
|
||||
() -> targetManagement.findMetaDataByControllerIdAndRsql(PAGE, NOT_EXIST_ID, "key==*"), "Target");
|
||||
verifyThrownExceptionBy(
|
||||
() -> targetManagement.updateMetadata(NOT_EXIST_ID, entityFactory.generateTargetMetadata("xxx", "xxx")),
|
||||
"Target");
|
||||
@@ -171,7 +174,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Ensures that retrieving the target security is only permitted with the necessary permissions.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
|
||||
public void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception {
|
||||
void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception {
|
||||
final Target createdTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("targetWithSecurityToken").securityToken("token"));
|
||||
|
||||
@@ -197,8 +200,8 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists.")
|
||||
@WithUser(tenantId = "tenantWhichDoesNotExists", allSpPermissions = true, autoCreateTenant = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void createTargetForTenantWhichDoesNotExistThrowsTenantNotExistException() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void createTargetForTenantWhichDoesNotExistThrowsTenantNotExistException() {
|
||||
try {
|
||||
targetManagement.create(entityFactory.target().create().controllerId("targetId123"));
|
||||
fail("should not be possible as the tenant does not exist");
|
||||
@@ -210,7 +213,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verify that a target with same controller ID than another device cannot be created.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
|
||||
public void createTargetThatViolatesUniqueConstraintFails() {
|
||||
void createTargetThatViolatesUniqueConstraintFails() {
|
||||
targetManagement.create(entityFactory.target().create().controllerId("123"));
|
||||
|
||||
assertThatExceptionOfType(EntityAlreadyExistsException.class)
|
||||
@@ -220,8 +223,8 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verify that a target with with invalid properties cannot be created or updated")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 0) })
|
||||
public void createAndUpdateTargetWithInvalidFields() {
|
||||
@Expect(type = TargetUpdatedEvent.class) })
|
||||
void createAndUpdateTargetWithInvalidFields() {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
|
||||
createTargetWithInvalidControllerId();
|
||||
@@ -235,54 +238,53 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void createAndUpdateTargetWithInvalidDescription(final Target target) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long description should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a")
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("target with too long description should not be created");
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid description should not be created")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid description should not be created");
|
||||
.create(entityFactory.target().create().controllerId("a").description(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long description should not be updated")
|
||||
.isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId())
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("target with too long description should not be updated");
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid description should not be updated")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.update(entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid description should not be updated");
|
||||
|
||||
.update(entityFactory.target().update(target.getControllerId()).description(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTargetWithInvalidName(final Target target) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long name should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a")
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("target with too long name should not be created");
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid name should not be created")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid name should not be created");
|
||||
.create(entityFactory.target().create().controllerId("a").name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long name should not be updated")
|
||||
.isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId())
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("target with too long name should not be updated");
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid name should not be updated")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid name should not be updated");
|
||||
.update(entityFactory.target().update(target.getControllerId()).name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too short name should not be updated")
|
||||
.isThrownBy(
|
||||
() -> targetManagement.update(entityFactory.target().update(target.getControllerId()).name("")))
|
||||
.as("target with too short name should not be updated");
|
||||
() -> targetManagement.update(entityFactory.target().update(target.getControllerId()).name("")));
|
||||
|
||||
}
|
||||
|
||||
@@ -290,90 +292,90 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void createAndUpdateTargetWithInvalidSecurityToken(final Target target) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long token should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a")
|
||||
.securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1))))
|
||||
.as("target with too long token should not be created");
|
||||
.securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid token should not be created")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid token should not be created");
|
||||
.create(entityFactory.target().create().controllerId("a").securityToken(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long token should not be updated")
|
||||
.isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId())
|
||||
.securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1))))
|
||||
.as("target with too long token should not be updated");
|
||||
.securityToken(RandomStringUtils.randomAlphanumeric(Target.SECURITY_TOKEN_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid token should not be updated")
|
||||
.isThrownBy(() -> targetManagement.update(
|
||||
entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid token should not be updated");
|
||||
entityFactory.target().update(target.getControllerId()).securityToken(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too short token should not be updated")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.update(entityFactory.target().update(target.getControllerId()).securityToken("")))
|
||||
.as("target with too short token should not be updated");
|
||||
.update(entityFactory.target().update(target.getControllerId()).securityToken("")));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTargetWithInvalidAddress(final Target target) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long address should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a")
|
||||
.address(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("target with too long address should not be created");
|
||||
.address(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAddressException.class)
|
||||
.as("target with invalid should not be created")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid should not be created");
|
||||
.create(entityFactory.target().create().controllerId("a").address(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long address should not be updated")
|
||||
.isThrownBy(() -> targetManagement.update(entityFactory.target().update(target.getControllerId())
|
||||
.address(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("target with too long address should not be updated");
|
||||
.address(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(InvalidTargetAddressException.class)
|
||||
.as("target with invalid address should not be updated")
|
||||
.isThrownBy(() -> targetManagement
|
||||
.update(entityFactory.target().update(target.getControllerId()).address(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid address should not be updated");
|
||||
.update(entityFactory.target().update(target.getControllerId()).address(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createTargetWithInvalidControllerId() {
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("")))
|
||||
.as("target with empty controller id should not be created");
|
||||
.as("target with empty controller id should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(null)))
|
||||
.as("target with null controller id should not be created");
|
||||
.as("target with null controller id should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(null)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with too long controller id should not be created")
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create()
|
||||
.controllerId(RandomStringUtils.randomAlphanumeric(Target.CONTROLLER_ID_MAX_SIZE + 1))))
|
||||
.as("target with too long controller id should not be created");
|
||||
.controllerId(RandomStringUtils.randomAlphanumeric(Target.CONTROLLER_ID_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("target with invalid controller id should not be created")
|
||||
.isThrownBy(
|
||||
() -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML)))
|
||||
.as("target with invalid controller id should not be created");
|
||||
() -> targetManagement.create(entityFactory.target().create().controllerId(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" ")))
|
||||
.as(WHITESPACE_ERROR);
|
||||
.as(WHITESPACE_ERROR)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" ")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b")))
|
||||
.as(WHITESPACE_ERROR);
|
||||
.as(WHITESPACE_ERROR)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("a b")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" ")))
|
||||
.as(WHITESPACE_ERROR);
|
||||
.as(WHITESPACE_ERROR)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId(" ")));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb")))
|
||||
.as(WHITESPACE_ERROR);
|
||||
.as(WHITESPACE_ERROR)
|
||||
.isThrownBy(() -> targetManagement.create(entityFactory.target().create().controllerId("aaa bbb")));
|
||||
|
||||
}
|
||||
|
||||
@@ -382,7 +384,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 4),
|
||||
@Expect(type = TargetTagCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 5) })
|
||||
public void assignAndUnassignTargetsToTag() {
|
||||
void assignAndUnassignTargetsToTag() {
|
||||
final List<String> assignTarget = new ArrayList<>();
|
||||
assignTarget.add(
|
||||
targetManagement.create(entityFactory.target().create().controllerId("targetId123")).getControllerId());
|
||||
@@ -400,7 +402,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assignedTargets.forEach(target -> assertThat(
|
||||
targetTagManagement.findByTarget(PAGE, target.getControllerId()).getNumberOfElements()).isEqualTo(1));
|
||||
|
||||
TargetTag findTargetTag = targetTagManagement.getByName("Tag1").get();
|
||||
TargetTag findTargetTag = targetTagManagement.getByName("Tag1").orElseThrow(IllegalStateException::new);
|
||||
assertThat(assignedTargets.size()).as("Assigned targets are wrong")
|
||||
.isEqualTo(targetManagement.findByTag(PAGE, targetTag.getId()).getNumberOfElements());
|
||||
|
||||
@@ -408,7 +410,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(unAssignTarget.getControllerId()).as("Controller id is wrong").isEqualTo("targetId123");
|
||||
assertThat(targetTagManagement.findByTarget(PAGE, unAssignTarget.getControllerId())).as("Tag size is wrong")
|
||||
.isEmpty();
|
||||
findTargetTag = targetTagManagement.getByName("Tag1").get();
|
||||
targetTagManagement.getByName("Tag1").orElseThrow(NoSuchElementException::new);
|
||||
assertThat(targetManagement.findByTag(PAGE, targetTag.getId())).as("Assigned targets are wrong").hasSize(3);
|
||||
assertThat(targetManagement.findByRsqlAndTag(PAGE, "controllerId==targetId123", targetTag.getId()))
|
||||
.as("Assigned targets are wrong").isEmpty();
|
||||
@@ -421,17 +423,17 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Ensures that targets can deleted e.g. test all cascades")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 12),
|
||||
@Expect(type = TargetDeletedEvent.class, count = 12), @Expect(type = TargetUpdatedEvent.class, count = 6) })
|
||||
public void deleteAndCreateTargets() {
|
||||
void deleteAndCreateTargets() {
|
||||
Target target = targetManagement.create(entityFactory.target().create().controllerId("targetId123"));
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(1);
|
||||
targetManagement.delete(Collections.singletonList(target.getId()));
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(0);
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isZero();
|
||||
|
||||
target = createTargetWithAttributes("4711");
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(1);
|
||||
assertThat(targetManagement.existsByControllerId("4711")).isTrue();
|
||||
targetManagement.delete(Collections.singletonList(target.getId()));
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(0);
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isZero();
|
||||
assertThat(targetManagement.existsByControllerId("4711")).isFalse();
|
||||
|
||||
final List<Long> targets = new ArrayList<>();
|
||||
@@ -442,7 +444,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(10);
|
||||
targetManagement.delete(targets);
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(0);
|
||||
assertThat(targetManagement.count()).as("target count is wrong").isZero();
|
||||
}
|
||||
|
||||
private Target createTargetWithAttributes(final String controllerId) {
|
||||
@@ -466,60 +468,72 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void findTargetByControllerIDWithDetails() {
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("test");
|
||||
final DistributionSet set2 = testdataFactory.createDistributionSet("test2");
|
||||
void findTargetByControllerIDWithDetails() {
|
||||
final DistributionSet testDs1 = testdataFactory.createDistributionSet("test");
|
||||
final DistributionSet testDs2 = testdataFactory.createDistributionSet("test2");
|
||||
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId()))
|
||||
.as("For newly created distributions sets the assigned target count should be zero")
|
||||
.isZero();
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId()))
|
||||
.as("For newly created distributions sets the installed target count should be zero")
|
||||
.isZero();
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
|
||||
.as("Exists assigned or installed query should return false for new distribution sets")
|
||||
.isFalse();
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(set2.getId()))
|
||||
.as("Target count is wrong").isFalse();
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId()))
|
||||
.as("For newly created distributions sets the assigned target count should be zero")
|
||||
.isZero();
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId()))
|
||||
.as("For newly created distributions sets the installed target count should be zero")
|
||||
.isZero();
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
|
||||
.as("For newly created distributions sets the assigned target count should be zero").isFalse();
|
||||
|
||||
Target target = createTargetWithAttributes("4711");
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist("4711", LOCALHOST);
|
||||
|
||||
final DistributionSetAssignmentResult result = assignDistributionSet(set.getId(), "4711");
|
||||
final DistributionSetAssignmentResult result = assignDistributionSet(testDs1.getId(), "4711");
|
||||
|
||||
controllerManagement.addUpdateActionStatus(
|
||||
entityFactory.actionStatus().create(getFirstAssignedActionId(result)).status(Status.FINISHED));
|
||||
assignDistributionSet(set2.getId(), "4711");
|
||||
assignDistributionSet(testDs2.getId(), "4711");
|
||||
|
||||
target = targetManagement.getByControllerID("4711").get();
|
||||
target = targetManagement.getByControllerID("4711").orElseThrow(IllegalStateException::new);
|
||||
// read data
|
||||
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(set.getId())).as("Target count is wrong")
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId())).as("Target count is wrong")
|
||||
.isZero();
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())).as("Target count is wrong")
|
||||
.isEqualTo(1);
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId())).as("Target count is wrong")
|
||||
.isTrue();
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(1);
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(set2.getId()))
|
||||
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())).as("Target count is wrong")
|
||||
.isZero();
|
||||
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
|
||||
.as("Target count is wrong").isTrue();
|
||||
assertThat(target.getLastTargetQuery()).as("Target query is not work").isGreaterThanOrEqualTo(current);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet("4711").get()).as("Assigned ds size is wrong")
|
||||
.isEqualTo(set2);
|
||||
assertThat(deploymentManagement.getInstalledDistributionSet("4711").get()).as("Installed ds is wrong")
|
||||
.isEqualTo(set);
|
||||
|
||||
final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711")
|
||||
.orElseThrow(NoSuchElementException::new);
|
||||
assertThat(assignedDs).as("Assigned ds size is wrong")
|
||||
.isEqualTo(testDs2);
|
||||
|
||||
final DistributionSet installedDs = deploymentManagement.getInstalledDistributionSet("4711")
|
||||
.orElseThrow(NoSuchElementException::new);
|
||||
assertThat(installedDs)
|
||||
.as("Installed ds is wrong")
|
||||
.isEqualTo(testDs1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Checks if the EntityAlreadyExistsException is thrown if the targets with the same controller ID are created twice.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 5) })
|
||||
public void createMultipleTargetsDuplicate() {
|
||||
void createMultipleTargetsDuplicate() {
|
||||
testdataFactory.createTargets(5, "mySimpleTargs", "my simple targets");
|
||||
try {
|
||||
testdataFactory.createTargets(5, "mySimpleTargs", "my simple targets");
|
||||
@@ -532,7 +546,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Checks if the EntityAlreadyExistsException is thrown if a single target with the same controller ID are created twice.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
|
||||
public void createTargetDuplicate() {
|
||||
void createTargetDuplicate() {
|
||||
targetManagement.create(entityFactory.target().create().controllerId("4711"));
|
||||
try {
|
||||
targetManagement.create(entityFactory.target().create().controllerId("4711"));
|
||||
@@ -554,8 +568,6 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
* targets to be verified
|
||||
* @param tags
|
||||
* are contained within tags of all targets.
|
||||
* @param tags
|
||||
* to be found in the tags of the targets
|
||||
*/
|
||||
private void checkTargetHasTags(final boolean strict, final Iterable<Target> targets, final TargetTag... tags) {
|
||||
_target: for (final Target tl : targets) {
|
||||
@@ -592,34 +604,29 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Creates and updates a target and verifies the changes in the repository.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void singleTargetIsInsertedIntoRepo() throws Exception {
|
||||
void singleTargetIsInsertedIntoRepo() throws Exception {
|
||||
|
||||
final String myCtrlID = "myCtrlID";
|
||||
|
||||
Target savedTarget = testdataFactory.createTarget(myCtrlID);
|
||||
assertThat(savedTarget).isNotNull().as("The target should not be null");
|
||||
final Long createdAt = savedTarget.getCreatedAt();
|
||||
Long modifiedAt = savedTarget.getLastModifiedAt();
|
||||
assertThat(savedTarget).as("The target should not be null").isNotNull();
|
||||
final long createdAt = savedTarget.getCreatedAt();
|
||||
long modifiedAt = savedTarget.getLastModifiedAt();
|
||||
|
||||
assertThat(createdAt).as("CreatedAt compared with modifiedAt").isEqualTo(modifiedAt);
|
||||
assertThat(savedTarget.getCreatedAt()).isNotNull()
|
||||
.as("The createdAt attribute of the target should no be null");
|
||||
assertThat(savedTarget.getLastModifiedAt()).isNotNull()
|
||||
.as("The lastModifiedAt attribute of the target should no be null");
|
||||
|
||||
Thread.sleep(1);
|
||||
Awaitility.await().until( () -> System.currentTimeMillis() > createdAt + 1);
|
||||
|
||||
savedTarget = targetManagement.update(
|
||||
entityFactory.target().update(savedTarget.getControllerId()).description("changed description"));
|
||||
assertThat(savedTarget.getLastModifiedAt()).isNotNull()
|
||||
.as("The lastModifiedAt attribute of the target should not be null");
|
||||
assertThat(createdAt).as("CreatedAt compared with saved modifiedAt")
|
||||
.isNotEqualTo(savedTarget.getLastModifiedAt());
|
||||
assertThat(modifiedAt).as("ModifiedAt compared with saved modifiedAt")
|
||||
.isNotEqualTo(savedTarget.getLastModifiedAt());
|
||||
modifiedAt = savedTarget.getLastModifiedAt();
|
||||
|
||||
final Target foundTarget = targetManagement.getByControllerID(savedTarget.getControllerId()).get();
|
||||
assertThat(foundTarget).isNotNull().as("The target should not be null");
|
||||
final Target foundTarget = targetManagement.getByControllerID(savedTarget.getControllerId()).orElseThrow(IllegalStateException::new);
|
||||
assertThat(foundTarget).as("The target should not be null").isNotNull();
|
||||
assertThat(myCtrlID).as("ControllerId compared with saved controllerId")
|
||||
.isEqualTo(foundTarget.getControllerId());
|
||||
assertThat(savedTarget).as("Target compared with saved target").isEqualTo(foundTarget);
|
||||
@@ -634,7 +641,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 101),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 100),
|
||||
@Expect(type = TargetDeletedEvent.class, count = 51) })
|
||||
public void bulkTargetCreationAndDelete() throws Exception {
|
||||
void bulkTargetCreationAndDelete() {
|
||||
final String myCtrlID = "myCtrlID";
|
||||
List<Target> firstList = testdataFactory.createTargets(100, myCtrlID, "first description");
|
||||
|
||||
@@ -699,7 +706,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetTagCreatedEvent.class, count = 7),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 7) })
|
||||
public void targetTagAssignment() {
|
||||
void targetTagAssignment() {
|
||||
final Target t1 = testdataFactory.createTarget("id-1");
|
||||
final int noT2Tags = 4;
|
||||
final int noT1Tags = 3;
|
||||
@@ -711,13 +718,13 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final List<TargetTag> t2Tags = testdataFactory.createTargetTags(noT2Tags, "tag2");
|
||||
t2Tags.forEach(tag -> targetManagement.assignTag(Collections.singletonList(t2.getControllerId()), tag.getId()));
|
||||
|
||||
final Target t11 = targetManagement.getByControllerID(t1.getControllerId()).get();
|
||||
final Target t11 = targetManagement.getByControllerID(t1.getControllerId()).orElseThrow(IllegalStateException::new);
|
||||
assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong")
|
||||
.hasSize(noT1Tags).containsAll(t1Tags);
|
||||
assertThat(targetTagManagement.findByTarget(PAGE, t11.getControllerId()).getContent()).as("Tag size is wrong")
|
||||
.hasSize(noT1Tags).doesNotContain(Iterables.toArray(t2Tags, TargetTag.class));
|
||||
|
||||
final Target t21 = targetManagement.getByControllerID(t2.getControllerId()).get();
|
||||
final Target t21 = targetManagement.getByControllerID(t2.getControllerId()).orElseThrow(IllegalStateException::new);
|
||||
assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong")
|
||||
.hasSize(noT2Tags).containsAll(t2Tags);
|
||||
assertThat(targetTagManagement.findByTarget(PAGE, t21.getControllerId()).getContent()).as("Tag size is wrong")
|
||||
@@ -729,7 +736,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 50),
|
||||
@Expect(type = TargetTagCreatedEvent.class, count = 4),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 80) })
|
||||
public void targetTagBulkAssignments() {
|
||||
void targetTagBulkAssignments() {
|
||||
final List<Target> tagATargets = testdataFactory.createTargets(10, "tagATargets", "first description");
|
||||
final List<Target> tagBTargets = testdataFactory.createTargets(10, "tagBTargets", "first description");
|
||||
final List<Target> tagCTargets = testdataFactory.createTargets(10, "tagCTargets", "first description");
|
||||
@@ -756,7 +763,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
toggleTagAssignment(tagABCTargets, tagC);
|
||||
|
||||
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "X")))
|
||||
.as("Target count is wrong").isEqualTo(0);
|
||||
.as("Target count is wrong").isZero();
|
||||
|
||||
// search for targets with tag tagA
|
||||
final List<Target> targetWithTagA = new ArrayList<>();
|
||||
@@ -798,7 +805,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetTagCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetCreatedEvent.class, count = 109),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 227) })
|
||||
public void targetTagBulkUnassignments() {
|
||||
void targetTagBulkUnassignments() {
|
||||
final TargetTag targTagA = targetTagManagement.create(entityFactory.tag().create().name("Targ-A-Tag"));
|
||||
final TargetTag targTagB = targetTagManagement.create(entityFactory.tag().create().name("Targ-B-Tag"));
|
||||
final TargetTag targTagC = targetTagManagement.create(entityFactory.tag().create().name("Targ-C-Tag"));
|
||||
@@ -856,7 +863,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetTagCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetCreatedEvent.class, count = 50),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 25) })
|
||||
public void findTargetsWithNoTag() {
|
||||
void findTargetsWithNoTag() {
|
||||
|
||||
final TargetTag targTagA = targetTagManagement.create(entityFactory.tag().create().name("Targ-A-Tag"));
|
||||
final List<Target> targAs = testdataFactory.createTargets(25, "target-id-A", "first description");
|
||||
@@ -868,8 +875,8 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final List<Target> targetsListWithNoTag = targetManagement
|
||||
.findByFilters(PAGE, new FilterParams(null, null, null, null, Boolean.TRUE, tagNames)).getContent();
|
||||
|
||||
assertThat(50L).as("Total targets").isEqualTo(targetManagement.count());
|
||||
assertThat(25).as("Targets with no tag").isEqualTo(targetsListWithNoTag.size());
|
||||
assertThat(targetManagement.count()).as("Total targets").isEqualTo(50L);
|
||||
assertThat(targetsListWithNoTag.size()).as("Targets with no tag").isEqualTo(25);
|
||||
|
||||
}
|
||||
|
||||
@@ -877,12 +884,13 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Description("Tests the a target can be read with only the read target permission")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void targetCanBeReadWithOnlyReadTargetPermission() throws Exception {
|
||||
void targetCanBeReadWithOnlyReadTargetPermission() throws Exception {
|
||||
final String knownTargetControllerId = "readTarget";
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist(knownTargetControllerId, new URI("http://127.0.0.1"));
|
||||
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("bumlux", "READ_TARGET"), () -> {
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId).get();
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId)
|
||||
.orElseThrow(IllegalStateException::new);
|
||||
assertThat(findTargetByControllerID).isNotNull();
|
||||
assertThat(findTargetByControllerID.getPollStatus()).isNotNull();
|
||||
return null;
|
||||
@@ -892,7 +900,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test that RSQL filter finds targets with tags or specific ids.")
|
||||
public void findTargetsWithTagOrId() {
|
||||
void findTargetsWithTagOrId() {
|
||||
final String rsqlFilter = "tag==Targ-A-Tag,id==target-id-B-00001,id==target-id-B-00008";
|
||||
final TargetTag targTagA = targetTagManagement.create(entityFactory.tag().create().name("Targ-A-Tag"));
|
||||
final List<String> targAs = testdataFactory.createTargets(25, "target-id-A", "first description").stream()
|
||||
@@ -910,7 +918,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verify that the find all targets by ids method contains the entities that we are looking for")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 12) })
|
||||
public void verifyFindTargetAllById() {
|
||||
void verifyFindTargetAllById() {
|
||||
final List<Long> searchIds = Arrays.asList(testdataFactory.createTarget("target-4").getId(),
|
||||
testdataFactory.createTarget("target-5").getId(), testdataFactory.createTarget("target-6").getId());
|
||||
for (int i = 0; i < 9; i++) {
|
||||
@@ -927,7 +935,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that the flag for requesting controller attributes is set correctly.")
|
||||
public void verifyRequestControllerAttributes() {
|
||||
void verifyRequestControllerAttributes() {
|
||||
final String knownControllerId = "KnownControllerId";
|
||||
final Target target = createTargetWithAttributes(knownControllerId);
|
||||
|
||||
@@ -945,7 +953,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Checks that metadata for a target can be created.")
|
||||
public void createTargetMetadata() {
|
||||
void createTargetMetadata() {
|
||||
final String knownKey = "targetMetaKnownKey";
|
||||
final String knownValue = "targetMetaKnownValue";
|
||||
|
||||
@@ -968,7 +976,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies the enforcement of the metadata quota per target.")
|
||||
public void createTargetMetadataUntilQuotaIsExceeded() {
|
||||
void createTargetMetadataUntilQuotaIsExceeded() {
|
||||
|
||||
// add meta data one by one
|
||||
final Target target1 = testdataFactory.createTarget("target1");
|
||||
@@ -1012,7 +1020,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that metadata for a target can be updated.")
|
||||
public void updateTargetMetadata() throws InterruptedException {
|
||||
void updateTargetMetadata() throws InterruptedException {
|
||||
final String knownKey = "myKnownKey";
|
||||
final String knownValue = "myKnownValue";
|
||||
final String knownUpdateValue = "myNewUpdatedValue";
|
||||
@@ -1025,21 +1033,20 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
// create target meta data entry
|
||||
insertTargetMetadata(knownKey, knownValue, target);
|
||||
|
||||
Target changedLockRevisionTarget = targetManagement.get(target.getId()).get();
|
||||
Target changedLockRevisionTarget = targetManagement.get(target.getId()).orElseThrow(NoSuchElementException::new);
|
||||
assertThat(changedLockRevisionTarget.getOptLockRevision()).isEqualTo(2);
|
||||
|
||||
Thread.sleep(100);
|
||||
// Unsure if needed maybe to wait for a db flush?
|
||||
// Thread.sleep(100);
|
||||
|
||||
// update the target metadata
|
||||
final JpaTargetMetadata updated = (JpaTargetMetadata) targetManagement.updateMetadata(target.getControllerId(),
|
||||
entityFactory.generateTargetMetadata(knownKey, knownUpdateValue));
|
||||
// we are updating the target meta data so also modifying the base
|
||||
// software
|
||||
// module so opt lock
|
||||
// revision must be three
|
||||
changedLockRevisionTarget = targetManagement.get(target.getId()).get();
|
||||
// software module so opt lock revision must be three
|
||||
changedLockRevisionTarget = targetManagement.get(target.getId()).orElseThrow(NoSuchElementException::new);
|
||||
assertThat(changedLockRevisionTarget.getOptLockRevision()).isEqualTo(3);
|
||||
assertThat(changedLockRevisionTarget.getLastModifiedAt()).isGreaterThan(0L);
|
||||
assertThat(changedLockRevisionTarget.getLastModifiedAt()).isPositive();
|
||||
|
||||
// verify updated meta data contains the updated value
|
||||
assertThat(updated).isNotNull();
|
||||
@@ -1052,7 +1059,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that target type for a target can be created, updated and unassigned.")
|
||||
public void createAndUpdateTargetTypeInTarget() {
|
||||
void createAndUpdateTargetTypeInTarget() {
|
||||
// create a target type
|
||||
final List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype", 2);
|
||||
assertThat(targetTypes).hasSize(2);
|
||||
@@ -1088,7 +1095,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that target type to a target can be assigned.")
|
||||
public void assignTargetTypeInTarget() {
|
||||
void assignTargetTypeInTarget() {
|
||||
// create a target
|
||||
final Target target = testdataFactory.createTarget("target1", "testtarget");
|
||||
// initial opt lock revision must be one
|
||||
@@ -1117,7 +1124,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 20),
|
||||
@Expect(type = TargetTypeCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 29), @Expect(type = TargetDeletedEvent.class, count = 1) })
|
||||
public void targetTypeBulkAssignments() {
|
||||
void targetTypeBulkAssignments() {
|
||||
final List<Target> typeATargets = testdataFactory.createTargets(10, "typeATargets", "first description");
|
||||
final List<Target> typeBTargets = testdataFactory.createTargets(10, "typeBTargets", "first description");
|
||||
|
||||
@@ -1163,7 +1170,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Queries and loads the metadata related to a given target.")
|
||||
public void findAllTargetMetadataByControllerId() {
|
||||
void findAllTargetMetadataByControllerId() {
|
||||
// create targets
|
||||
final Target target1 = createTargetWithMetadata("target1", 10);
|
||||
final Target target2 = createTargetWithMetadata("target2", 8);
|
||||
@@ -1194,7 +1201,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that target type is not assigned to target if invalid.")
|
||||
public void assignInvalidTargetTypeToTarget() {
|
||||
void assignInvalidTargetTypeToTarget() {
|
||||
// create a target
|
||||
final Target target = testdataFactory.createTarget("target1", "testtarget");
|
||||
// initial opt lock revision must be one
|
||||
@@ -1205,12 +1212,12 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// assign target type to target
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), null))
|
||||
.as("target type with id=null cannot be assigned");
|
||||
.as("target type with id=null cannot be assigned")
|
||||
.isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), null));
|
||||
|
||||
assertThatExceptionOfType(EntityNotFoundException.class)
|
||||
.isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), 114L))
|
||||
.as("target type with id that does not exists cannot be assigned");
|
||||
.as("target type with id that does not exists cannot be assigned")
|
||||
.isThrownBy(() -> targetManagement.assignType(targetFound.get().getControllerId(), 114L));
|
||||
|
||||
// opt lock revision is not changed
|
||||
Optional<JpaTarget> targetFound1 = targetRepository.findById(target.getId());
|
||||
@@ -1221,7 +1228,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that target type can be unassigned from target.")
|
||||
public void unAssignTargetTypeFromTarget() {
|
||||
void unAssignTargetTypeFromTarget() {
|
||||
// create a target type
|
||||
TargetType targetType = testdataFactory.findOrCreateTargetType("targettype");
|
||||
assertThat(targetType).isNotNull();
|
||||
@@ -1245,7 +1252,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test that RSQL filter finds targets with metadata and/or controllerId.")
|
||||
public void findTargetsByRsqlWithMetadata() {
|
||||
void findTargetsByRsqlWithMetadata() {
|
||||
final String controllerId1 = "target1";
|
||||
final String controllerId2 = "target2";
|
||||
createTargetWithMetadata(controllerId1, 2);
|
||||
|
||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -34,12 +33,12 @@ import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test class for {@link TargetTagManagement}.
|
||||
@@ -47,13 +46,13 @@ import org.junit.jupiter.api.Test;
|
||||
*/
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Target Tag Management")
|
||||
public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access reacts as specfied on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
assertThat(targetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent();
|
||||
assertThat(targetTagManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
}
|
||||
@@ -61,9 +60,8 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Verifies that management queries react as specfied on calls for non existing entities "
|
||||
+ " by means of throwing EntityNotFoundException.")
|
||||
@ExpectEvents({ @Expect(type = DistributionSetTagUpdatedEvent.class, count = 0),
|
||||
@Expect(type = TargetTagUpdatedEvent.class, count = 0) })
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
@ExpectEvents({ @Expect(type = DistributionSetTagUpdatedEvent.class), @Expect(type = TargetTagUpdatedEvent.class) })
|
||||
void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
verifyThrownExceptionBy(() -> targetTagManagement.delete(NOT_EXIST_ID), "TargetTag");
|
||||
|
||||
verifyThrownExceptionBy(() -> targetTagManagement.update(entityFactory.tag().update(NOT_EXIST_IDL)),
|
||||
@@ -74,7 +72,7 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that a tag with with invalid properties cannot be created or updated")
|
||||
public void createAndUpdateTagWithInvalidFields() {
|
||||
void createAndUpdateTagWithInvalidFields() {
|
||||
final TargetTag tag = targetTagManagement
|
||||
.create(entityFactory.tag().create().name("tag1").description("tagdesc1"));
|
||||
|
||||
@@ -87,80 +85,81 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void createAndUpdateTagWithInvalidDescription(final Tag tag) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with too long description should not be created")
|
||||
.isThrownBy(() -> targetTagManagement.create(
|
||||
entityFactory.tag().create().name("a").description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("tag with too long description should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTagManagement.create(entityFactory.tag().create().name("a").description(INVALID_TEXT_HTML)))
|
||||
.as("tag with invalid description should not be created");
|
||||
entityFactory.tag().create().name("a").description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with invalid description should not be created").isThrownBy(() -> targetTagManagement
|
||||
.create(entityFactory.tag().create().name("a").description(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with too long description should not be updated")
|
||||
.isThrownBy(() -> targetTagManagement.update(
|
||||
entityFactory.tag().update(tag.getId()).description(RandomStringUtils.randomAlphanumeric(513))))
|
||||
.as("tag with too long description should not be updated");
|
||||
entityFactory.tag().update(tag.getId())
|
||||
.description(RandomStringUtils.randomAlphanumeric(513))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with invalid description should not be updated")
|
||||
.isThrownBy(() -> targetTagManagement
|
||||
.update(entityFactory.tag().update(tag.getId()).description(INVALID_TEXT_HTML)))
|
||||
.as("tag with invalid description should not be updated");
|
||||
.update(entityFactory.tag().update(tag.getId()).description(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTagWithInvalidColour(final Tag tag) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with too long colour should not be created")
|
||||
.isThrownBy(() -> targetTagManagement.create(
|
||||
entityFactory.tag().create().name("a").colour(RandomStringUtils.randomAlphanumeric(17))))
|
||||
.as("tag with too long colour should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTagManagement.create(entityFactory.tag().create().name("a").colour(INVALID_TEXT_HTML)))
|
||||
.as("tag with invalid colour should not be created");
|
||||
entityFactory.tag().create().name("a").colour(RandomStringUtils.randomAlphanumeric(17))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetTagManagement.update(
|
||||
entityFactory.tag().update(tag.getId()).colour(RandomStringUtils.randomAlphanumeric(17))))
|
||||
.as("tag with too long colour should not be updated");
|
||||
.as("tag with invalid colour should not be created").isThrownBy(() -> targetTagManagement
|
||||
.create(entityFactory.tag().create().name("a").colour(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).colour(INVALID_TEXT_HTML)))
|
||||
.as("tag with invalid colour should not be updated");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with too long colour should not be updated")
|
||||
.isThrownBy(() -> targetTagManagement.update(
|
||||
entityFactory.tag().update(tag.getId()).colour(RandomStringUtils.randomAlphanumeric(17))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with invalid colour should not be updated").isThrownBy(() -> targetTagManagement
|
||||
.update(entityFactory.tag().update(tag.getId()).colour(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTagWithInvalidName(final Tag tag) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with too long name should not be created")
|
||||
.isThrownBy(() -> targetTagManagement
|
||||
.create(entityFactory.tag().create().name(RandomStringUtils.randomAlphanumeric(
|
||||
NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("tag with too long name should not be created");
|
||||
NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetTagManagement.create(entityFactory.tag().create().name(INVALID_TEXT_HTML)))
|
||||
.as("tag with invalidname should not be created");
|
||||
.as("tag with invalidname should not be created")
|
||||
.isThrownBy(() -> targetTagManagement.create(entityFactory.tag().create().name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("tag with too long name should not be updated")
|
||||
.isThrownBy(() -> targetTagManagement
|
||||
.update(entityFactory.tag().update(tag.getId()).name(RandomStringUtils.randomAlphanumeric(
|
||||
NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("tag with too long name should not be updated");
|
||||
NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name(INVALID_TEXT_HTML)))
|
||||
.as("tag with invalid name should not be updated");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).as("tag with invalid name should not be updated")
|
||||
.isThrownBy(() -> targetTagManagement
|
||||
.update(entityFactory.tag().update(tag.getId()).name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name("")))
|
||||
.as("tag with too short name should not be updated");
|
||||
.as("tag with too short name should not be updated")
|
||||
.isThrownBy(() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name("")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies the toogle mechanism by means on assigning tag if at least on target in the list does not have"
|
||||
+ "the tag yet. Unassign if all of them have the tag already.")
|
||||
public void assignAndUnassignTargetTags() {
|
||||
void assignAndUnassignTargetTags() {
|
||||
final List<Target> groupA = testdataFactory.createTargets(20);
|
||||
final List<Target> groupB = testdataFactory.createTargets(20, "groupb", "groupb");
|
||||
|
||||
@@ -169,11 +168,11 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// toggle A only -> A is now assigned
|
||||
TargetTagAssignmentResult result = toggleTagAssignment(groupA, tag);
|
||||
assertThat(result.getAlreadyAssigned()).isEqualTo(0);
|
||||
assertThat(result.getAlreadyAssigned()).isZero();
|
||||
assertThat(result.getAssigned()).isEqualTo(20);
|
||||
assertThat(result.getAssignedEntity()).containsAll(targetManagement
|
||||
.getByControllerID(groupA.stream().map(Target::getControllerId).collect(Collectors.toList())));
|
||||
assertThat(result.getUnassigned()).isEqualTo(0);
|
||||
assertThat(result.getUnassigned()).isZero();
|
||||
assertThat(result.getUnassignedEntity()).isEmpty();
|
||||
assertThat(result.getTargetTag()).isEqualTo(tag);
|
||||
|
||||
@@ -183,14 +182,14 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(result.getAssigned()).isEqualTo(20);
|
||||
assertThat(result.getAssignedEntity()).containsAll(targetManagement
|
||||
.getByControllerID(groupB.stream().map(Target::getControllerId).collect(Collectors.toList())));
|
||||
assertThat(result.getUnassigned()).isEqualTo(0);
|
||||
assertThat(result.getUnassigned()).isZero();
|
||||
assertThat(result.getUnassignedEntity()).isEmpty();
|
||||
assertThat(result.getTargetTag()).isEqualTo(tag);
|
||||
|
||||
// toggle A+B -> both unassigned
|
||||
result = toggleTagAssignment(concat(groupA, groupB), tag);
|
||||
assertThat(result.getAlreadyAssigned()).isEqualTo(0);
|
||||
assertThat(result.getAssigned()).isEqualTo(0);
|
||||
assertThat(result.getAlreadyAssigned()).isZero();
|
||||
assertThat(result.getAssigned()).isZero();
|
||||
assertThat(result.getAssignedEntity()).isEmpty();
|
||||
assertThat(result.getUnassigned()).isEqualTo(40);
|
||||
assertThat(result.getUnassignedEntity()).containsAll(targetManagement.getByControllerID(
|
||||
@@ -208,7 +207,7 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that all tags are retrieved through repository.")
|
||||
public void findAllTargetTags() {
|
||||
void findAllTargetTags() {
|
||||
final List<JpaTargetTag> tags = createTargetsWithTags();
|
||||
|
||||
assertThat(targetTagRepository.findAll()).isEqualTo(targetTagRepository.findAll()).isEqualTo(tags)
|
||||
@@ -217,7 +216,7 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a created tag is persisted in the repository as defined.")
|
||||
public void createTargetTag() {
|
||||
void createTargetTag() {
|
||||
final Tag tag = targetTagManagement
|
||||
.create(entityFactory.tag().create().name("kai1").description("kai2").colour("colour"));
|
||||
|
||||
@@ -229,7 +228,7 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a deleted tag is removed from the repository as defined.")
|
||||
public void deleteTargetTags() {
|
||||
void deleteTargetTags() {
|
||||
|
||||
// create test data
|
||||
final Iterable<JpaTargetTag> tags = createTargetsWithTags();
|
||||
@@ -254,7 +253,7 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Tests the name update of a target tag.")
|
||||
public void updateTargetTag() {
|
||||
void updateTargetTag() {
|
||||
final List<JpaTargetTag> tags = createTargetsWithTags();
|
||||
|
||||
// change data
|
||||
@@ -273,29 +272,20 @@ public class TargetTagManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a tag cannot be created if one exists already with that name (ecpects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateTargetTagNameException() {
|
||||
void failedDuplicateTargetTagNameException() {
|
||||
targetTagManagement.create(entityFactory.tag().create().name("A"));
|
||||
|
||||
try {
|
||||
targetTagManagement.create(entityFactory.tag().create().name("A"));
|
||||
fail("should not have worked as tag already exists");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
|
||||
}
|
||||
assertThatExceptionOfType(EntityAlreadyExistsException.class)
|
||||
.isThrownBy(() -> targetTagManagement.create(entityFactory.tag().create().name("A")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a tag cannot be updated to a name that already exists on another tag (ecpects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateTargetTagNameExceptionAfterUpdate() {
|
||||
void failedDuplicateTargetTagNameExceptionAfterUpdate() {
|
||||
targetTagManagement.create(entityFactory.tag().create().name("A"));
|
||||
final TargetTag tag = targetTagManagement.create(entityFactory.tag().create().name("B"));
|
||||
|
||||
try {
|
||||
targetTagManagement.update(entityFactory.tag().update(tag.getId()).name("A"));
|
||||
fail("should not have worked as tag already exists");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
|
||||
}
|
||||
assertThatExceptionOfType(EntityAlreadyExistsException.class)
|
||||
.isThrownBy(() -> targetTagManagement.update(entityFactory.tag().update(tag.getId()).name("A")));
|
||||
}
|
||||
|
||||
private List<JpaTargetTag> createTargetsWithTags() {
|
||||
|
||||
@@ -8,10 +8,15 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeUpdatedEvent;
|
||||
@@ -24,23 +29,20 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Target Type Management")
|
||||
public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
class TargetTypeManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access react as specified on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = TargetTypeCreatedEvent.class, count = 0) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
@ExpectEvents({ @Expect(type = TargetTypeCreatedEvent.class) })
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
assertThat(targetTypeManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(targetTypeManagement.getByName(NOT_EXIST_ID)).isNotPresent();
|
||||
}
|
||||
@@ -48,8 +50,8 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
@Test
|
||||
@Description("Verifies that management queries react as specified on calls for non existing entities "
|
||||
+ " by means of throwing EntityNotFoundException.")
|
||||
@ExpectEvents({ @Expect(type = TargetTypeUpdatedEvent.class, count = 0) })
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
@ExpectEvents({ @Expect(type = TargetTypeUpdatedEvent.class) })
|
||||
void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
verifyThrownExceptionBy(() -> targetTypeManagement.delete(NOT_EXIST_IDL), "TargetType");
|
||||
verifyThrownExceptionBy(() -> targetTypeManagement.update(entityFactory.targetType().update(NOT_EXIST_IDL)),
|
||||
"TargetType");
|
||||
@@ -57,7 +59,7 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
|
||||
@Test
|
||||
@Description("Verify that a target type with invalid properties cannot be created or updated")
|
||||
public void createAndUpdateTargetTypeWithInvalidFields() {
|
||||
void createAndUpdateTargetTypeWithInvalidFields() {
|
||||
final TargetType targetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("targettype1").description("targettypedes1"));
|
||||
|
||||
@@ -67,82 +69,86 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTargetTypeWithInvalidDescription(final TargetType targetType) {
|
||||
void createAndUpdateTargetTypeWithInvalidDescription(final TargetType targetType) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too long description should not be created")
|
||||
.isThrownBy(() -> targetTypeManagement.create(
|
||||
entityFactory.targetType().create().name("a").description(RandomStringUtils.randomAlphanumeric(TargetType.DESCRIPTION_MAX_SIZE + 1))))
|
||||
.as("targetType with too long description should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTypeManagement.create(entityFactory.targetType().create().name("a").description(INVALID_TEXT_HTML)))
|
||||
.as("targetType with invalid description should not be created");
|
||||
entityFactory.targetType().create().name("a").description(
|
||||
RandomStringUtils.randomAlphanumeric(TargetType.DESCRIPTION_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with invalid description should not be created").isThrownBy(() -> targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("a").description(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too long description should not be updated")
|
||||
.isThrownBy(() -> targetTypeManagement.update(
|
||||
entityFactory.targetType().update(targetType.getId()).description(RandomStringUtils.randomAlphanumeric(TargetType.DESCRIPTION_MAX_SIZE + 1))))
|
||||
.as("targetType with too long description should not be updated");
|
||||
entityFactory.targetType().update(targetType.getId()).description(
|
||||
RandomStringUtils.randomAlphanumeric(TargetType.DESCRIPTION_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with invalid description should not be updated")
|
||||
.isThrownBy(() -> targetTypeManagement
|
||||
.update(entityFactory.targetType().update(targetType.getId()).description(INVALID_TEXT_HTML)))
|
||||
.as("targetType with invalid description should not be updated");
|
||||
.update(entityFactory.targetType().update(targetType.getId()).description(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTargetTypeWithInvalidColour(final TargetType targetType) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too long colour should not be created")
|
||||
.isThrownBy(() -> targetTypeManagement.create(
|
||||
entityFactory.targetType().create().name("a").colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1))))
|
||||
.as("targetType with too long colour should not be created");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTypeManagement.create(entityFactory.targetType().create().name("a").colour(INVALID_TEXT_HTML)))
|
||||
.as("targetType with invalid colour should not be created");
|
||||
entityFactory.targetType().create().name("a")
|
||||
.colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetTypeManagement.update(
|
||||
entityFactory.targetType().update(targetType.getId()).colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1))))
|
||||
.as("targetType with too long colour should not be updated");
|
||||
.as("targetType with invalid colour should not be created").isThrownBy(() -> targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("a").colour(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTypeManagement.update(entityFactory.targetType().update(targetType.getId()).colour(INVALID_TEXT_HTML)))
|
||||
.as("targetType with invalid colour should not be updated");
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too long colour should not be updated")
|
||||
.isThrownBy(() -> targetTypeManagement.update(
|
||||
entityFactory.targetType().update(targetType.getId())
|
||||
.colour(RandomStringUtils.randomAlphanumeric(TargetType.COLOUR_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with invalid colour should not be updated").isThrownBy(() -> targetTypeManagement
|
||||
.update(entityFactory.targetType().update(targetType.getId()).colour(INVALID_TEXT_HTML)));
|
||||
}
|
||||
|
||||
@Step
|
||||
private void createAndUpdateTargetTypeWithInvalidName(final TargetType targetType) {
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too long name should not be created")
|
||||
.isThrownBy(() -> targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name(RandomStringUtils.randomAlphanumeric(
|
||||
NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("targetType with too long name should not be created");
|
||||
NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetTypeManagement.create(entityFactory.targetType().create().name(INVALID_TEXT_HTML)))
|
||||
.as("targetType with invalid name should not be created");
|
||||
.as("targetType with invalid name should not be created").isThrownBy(
|
||||
() -> targetTypeManagement.create(entityFactory.targetType().create().name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too long name should not be updated")
|
||||
.isThrownBy(() -> targetTypeManagement
|
||||
.update(entityFactory.targetType().update(targetType.getId()).name(RandomStringUtils.randomAlphanumeric(
|
||||
NamedEntity.NAME_MAX_SIZE + 1))))
|
||||
.as("targetType with too long name should not be updated");
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
|
||||
() -> targetTypeManagement.update(entityFactory.targetType().update(targetType.getId()).name(INVALID_TEXT_HTML)))
|
||||
.as("targetType with invalid name should not be updated");
|
||||
NamedEntity.NAME_MAX_SIZE + 1))));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.isThrownBy(() -> targetTypeManagement.update(entityFactory.targetType().update(targetType.getId()).name("")))
|
||||
.as("targetType with too short name should not be updated");
|
||||
.as("targetType with invalid name should not be updated").isThrownBy(() -> targetTypeManagement
|
||||
.update(entityFactory.targetType().update(targetType.getId()).name(INVALID_TEXT_HTML)));
|
||||
|
||||
assertThatExceptionOfType(ConstraintViolationException.class)
|
||||
.as("targetType with too short name should not be updated").isThrownBy(() -> targetTypeManagement
|
||||
.update(entityFactory.targetType().update(targetType.getId()).name("")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the successful assignment of compatible distribution set types to a target type")
|
||||
public void assignCompatibleDistributionSetTypesToTargetType(){
|
||||
void assignCompatibleDistributionSetTypesToTargetType() {
|
||||
final TargetType targetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("targettype1").description("targettypedes1"));
|
||||
DistributionSetType distributionSetType = testdataFactory.findOrCreateDistributionSetType("testDst", "dst1");
|
||||
@@ -155,7 +161,7 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
|
||||
@Test
|
||||
@Description("Tests the successful removal of compatible distribution set types to a target type")
|
||||
public void unassignCompatibleDistributionSetTypesToTargetType(){
|
||||
void unassignCompatibleDistributionSetTypesToTargetType() {
|
||||
final TargetType targetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("targettype11").description("targettypedes11"));
|
||||
DistributionSetType distributionSetType = testdataFactory.findOrCreateDistributionSetType("testDst1", "dst11");
|
||||
@@ -166,19 +172,19 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
targetTypeManagement.unassignDistributionSetType(targetType.getId(),distributionSetType.getId());
|
||||
Optional<JpaTargetType> targetTypeWithDsTypes1 = targetTypeRepository.findById(targetType.getId());
|
||||
assertThat(targetTypeWithDsTypes1).isPresent();
|
||||
assertThat(targetTypeWithDsTypes1.get().getCompatibleDistributionSetTypes()).hasSize(0);
|
||||
assertThat(targetTypeWithDsTypes1.get().getCompatibleDistributionSetTypes()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that all types are retrieved through repository.")
|
||||
public void findAllTargetTypes() {
|
||||
void findAllTargetTypes() {
|
||||
testdataFactory.createTargetTypes("targettype", 10);
|
||||
assertThat(targetTypeRepository.findAll()).as("Target type size").hasSize(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a created target type is persisted in the repository as defined.")
|
||||
public void createTargetType() {
|
||||
void createTargetType() {
|
||||
final TargetType targetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("targettype1").description("targettypedes1").colour("colour1"));
|
||||
|
||||
@@ -190,7 +196,7 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a deleted target type is removed from the repository as defined.")
|
||||
public void deleteTargetType() {
|
||||
void deleteTargetType() {
|
||||
// create test data
|
||||
final TargetType targetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("targettype11").description("targettypedes11"));
|
||||
@@ -203,7 +209,7 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
|
||||
@Test
|
||||
@Description("Tests the name update of a target type.")
|
||||
public void updateTargetType() {
|
||||
void updateTargetType() {
|
||||
final TargetType targetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("targettype111").description("targettypedes111"));
|
||||
assertThat(targetTypeRepository.findByName("targettype111").get().getDescription()).as("type found")
|
||||
@@ -214,14 +220,14 @@ public class TargetTypeManagementTest extends AbstractJpaIntegrationTest{
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a target type cannot be created if one exists already with that name (expects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateTargetTypeNameException() {
|
||||
void failedDuplicateTargetTypeNameException() {
|
||||
targetTypeManagement.create(entityFactory.targetType().create().name("targettype123"));
|
||||
assertThrows(EntityAlreadyExistsException.class, () -> targetTypeManagement.create(entityFactory.targetType().create().name("targettype123")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a target type cannot be updated to a name that already exists (expects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateTargetTypeNameExceptionAfterUpdate() {
|
||||
void failedDuplicateTargetTypeNameExceptionAfterUpdate() {
|
||||
targetTypeManagement.create(entityFactory.targetType().create().name("targettype1234"));
|
||||
TargetType targetType = targetTypeManagement.create(entityFactory.targetType().create().name("targettype12345"));
|
||||
assertThrows(EntityAlreadyExistsException.class, () -> targetTypeManagement.update(entityFactory.targetType().update(targetType.getId()).name("targettype1234")));
|
||||
|
||||
@@ -36,7 +36,7 @@ import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("RSQL filter target")
|
||||
public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private Target target;
|
||||
private Target target2;
|
||||
@@ -47,7 +47,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
private static final String AND = ";";
|
||||
|
||||
@BeforeEach
|
||||
public void setupBeforeTest() throws InterruptedException {
|
||||
void setupBeforeTest() {
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("AssignedDs");
|
||||
|
||||
@@ -63,7 +63,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
target2 = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("targetId1234").description("targetId1234"));
|
||||
attributes.put("revision", "1.2");
|
||||
Thread.sleep(1);
|
||||
|
||||
target2 = controllerManagement.updateControllerAttributes(target2.getControllerId(), attributes, null);
|
||||
target2 = controllerManagement.findOrRegisterTargetIfItDoesNotExist(target2.getControllerId(), LOCALHOST);
|
||||
createTargetMetadata(target2.getControllerId(), entityFactory.generateTargetMetadata("metaKey", "value"));
|
||||
@@ -97,7 +97,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by (controller) id")
|
||||
public void testFilterByParameterId() {
|
||||
void testFilterByParameterId() {
|
||||
assertRSQLQuery(TargetFields.ID.name() + "==targetId123", 1);
|
||||
assertRSQLQuery(TargetFields.ID.name() + "==target*", 5);
|
||||
assertRSQLQuery(TargetFields.ID.name() + "==noExist*", 0);
|
||||
@@ -108,7 +108,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by name")
|
||||
public void testFilterByParameterName() {
|
||||
void testFilterByParameterName() {
|
||||
assertRSQLQuery(TargetFields.NAME.name() + "==targetName123", 1);
|
||||
assertRSQLQuery(TargetFields.NAME.name() + "==target*", 5);
|
||||
assertRSQLQuery(TargetFields.NAME.name() + "==noExist*", 0);
|
||||
@@ -119,7 +119,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by description")
|
||||
public void testFilterByParameterDescription() {
|
||||
void testFilterByParameterDescription() {
|
||||
assertRSQLQuery(TargetFields.DESCRIPTION.name() + "==''", 3);
|
||||
assertRSQLQuery(TargetFields.DESCRIPTION.name() + "!=''", 2);
|
||||
assertRSQLQuery(TargetFields.DESCRIPTION.name() + "==targetDesc123", 1);
|
||||
@@ -132,7 +132,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by controller id")
|
||||
public void testFilterByParameterControllerId() {
|
||||
void testFilterByParameterControllerId() {
|
||||
assertRSQLQuery(TargetFields.CONTROLLERID.name() + "==targetId123", 1);
|
||||
assertRSQLQuery(TargetFields.CONTROLLERID.name() + "==target*", 5);
|
||||
assertRSQLQuery(TargetFields.CONTROLLERID.name() + "==noExist*", 0);
|
||||
@@ -143,7 +143,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by status")
|
||||
public void testFilterByParameterUpdateStatus() {
|
||||
void testFilterByParameterUpdateStatus() {
|
||||
assertRSQLQuery(TargetFields.UPDATESTATUS.name() + "==pending", 1);
|
||||
assertRSQLQuery(TargetFields.UPDATESTATUS.name() + "!=pending", 4);
|
||||
try {
|
||||
@@ -158,8 +158,9 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by attribute")
|
||||
public void testFilterByAttribute() {
|
||||
createTargetWithAttributes("test.dot", "value.dot");
|
||||
void testFilterByAttribute() {
|
||||
controllerManagement.updateControllerAttributes(testdataFactory.createTarget().getControllerId(),
|
||||
Maps.newHashMap("test.dot", "value.dot"), null);
|
||||
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision==1.1", 1);
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".revision!=1.1", 1);
|
||||
@@ -174,17 +175,14 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".key*==value.dot", 0);
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + ".*==value.dot", 0);
|
||||
assertRSQLQuery(TargetFields.ATTRIBUTE.name() + "..==value.dot", 0);
|
||||
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + ".==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + "*==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + "==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + ".==value.dot");
|
||||
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + "*==value.dot");
|
||||
assertRSQLQueryThrowsException(TargetFields.ATTRIBUTE.name() + "==value.dot");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by assigned ds name")
|
||||
public void testFilterByAssignedDsName() {
|
||||
void testFilterByAssignedDsName() {
|
||||
assertRSQLQuery(TargetFields.ASSIGNEDDS.name() + ".name==AssignedDs", 1);
|
||||
assertRSQLQuery(TargetFields.ASSIGNEDDS.name() + ".name==A*", 1);
|
||||
assertRSQLQuery(TargetFields.ASSIGNEDDS.name() + ".name==noExist*", 0);
|
||||
@@ -194,7 +192,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by assigned ds version")
|
||||
public void testFilterByAssignedDsVersion() {
|
||||
void testFilterByAssignedDsVersion() {
|
||||
assertRSQLQuery(TargetFields.ASSIGNEDDS.name() + ".version==" + TestdataFactory.DEFAULT_VERSION, 1);
|
||||
assertRSQLQuery(TargetFields.ASSIGNEDDS.name() + ".version==*1*", 1);
|
||||
assertRSQLQuery(TargetFields.ASSIGNEDDS.name() + ".version==noExist*", 0);
|
||||
@@ -206,7 +204,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by tag name")
|
||||
public void testFilterByTag() {
|
||||
void testFilterByTag() {
|
||||
assertRSQLQuery(TargetFields.TAG.name() + "==Tag1", 2);
|
||||
assertRSQLQuery(TargetFields.TAG.name() + "!=Tag1", 3);
|
||||
assertRSQLQuery(TargetFields.TAG.name() + "==T*", 4);
|
||||
@@ -226,7 +224,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by lastTargetQuery")
|
||||
public void testFilterByLastTargetQuery() throws InterruptedException {
|
||||
void testFilterByLastTargetQuery() {
|
||||
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "==" + target.getLastTargetQuery(), 1);
|
||||
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "!=" + target.getLastTargetQuery(), 4);
|
||||
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "=lt=" + target.getLastTargetQuery(), 0);
|
||||
@@ -239,8 +237,9 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter target by metadata")
|
||||
public void testFilterByMetadata() {
|
||||
createTargetWithMetadata("key.dot", "value.dot");
|
||||
void testFilterByMetadata() {
|
||||
createTargetMetadata(testdataFactory.createTarget().getControllerId(),
|
||||
entityFactory.generateTargetMetadata("key.dot", "value.dot"));
|
||||
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".metaKey==*v*", 2);
|
||||
@@ -258,17 +257,14 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".key*==value.dot", 0);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + ".*==value.dot", 0);
|
||||
assertRSQLQuery(TargetFields.METADATA.name() + "..==value.dot", 0);
|
||||
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + ".==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + "*==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + "==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + ".==value.dot");
|
||||
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + "*==value.dot");
|
||||
assertRSQLQueryThrowsException(TargetFields.METADATA.name() + "==value.dot");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter based on more complex RSQL queries")
|
||||
public void testFilterByComplexQueries() {
|
||||
void testFilterByComplexQueries() {
|
||||
assertRSQLQuery(
|
||||
TargetFields.NAME.name() + "!=targetName123" + AND + TargetFields.METADATA.name() + ".metaKey!=value",
|
||||
0);
|
||||
@@ -278,7 +274,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Testing allowed RSQL keys based on TargetFields definition")
|
||||
public void rsqlValidTargetFields() {
|
||||
void rsqlValidTargetFields() {
|
||||
final String rsql1 = "ID == '0123' and NAME == abcd and DESCRIPTION == absd"
|
||||
+ " and CREATEDAT =lt= 0123 and LASTMODIFIEDAT =gt= 0123"
|
||||
+ " and CONTROLLERID == 0123 and UPDATESTATUS == PENDING"
|
||||
@@ -308,7 +304,7 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test filter by target type")
|
||||
public void shouldFilterTargetsByTypeIdNameAndDescription() {
|
||||
void shouldFilterTargetsByTypeIdNameAndDescription() {
|
||||
assertRSQLQuery("targettype." + TargetTypeFields.NAME.name() + "==" + targetType1.getName(), 1);
|
||||
assertRSQLQuery("targettype." + TargetTypeFields.NAME.name() + "==*1", 1);
|
||||
assertRSQLQuery("targettype." + TargetTypeFields.NAME.name() + "!=" + targetType2.getName(), 4);
|
||||
@@ -327,23 +323,8 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(countTargetsAll).isEqualTo(expectedTargets);
|
||||
}
|
||||
|
||||
private <T extends Throwable> void assertRSQLQueryThrowsException(final String rsqlParam,
|
||||
final Class<T> expectedException) {
|
||||
assertThatExceptionOfType(expectedException)
|
||||
private void assertRSQLQueryThrowsException(final String rsqlParam) {
|
||||
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class)
|
||||
.isThrownBy(() -> RSQLUtility.validateRsqlFor(rsqlParam, TargetFields.class));
|
||||
}
|
||||
|
||||
private Target createTargetWithMetadata(final String metadataKeyName, final String metadataValue) {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
createTargetMetadata(target.getControllerId(),
|
||||
entityFactory.generateTargetMetadata(metadataKeyName, metadataValue));
|
||||
return target;
|
||||
}
|
||||
|
||||
private Target createTargetWithAttributes(final String attributeName, final String attributeValue) {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
controllerManagement.updateControllerAttributes(target.getControllerId(),
|
||||
Maps.newHashMap(attributeName, attributeValue), null);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.commons.lang3.text.StrSubstitutor;
|
||||
@@ -23,6 +20,8 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.T
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Spy;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -70,34 +69,15 @@ public class VirtualPropertyResolverTest {
|
||||
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "${NOW_TS}", "${OVERDUE_TS}", "${overdue_ts}" })
|
||||
@Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.")
|
||||
public void resolveNowTimestampPlaceholder() {
|
||||
final String placeholder = "${NOW_TS}";
|
||||
void resolveNowTimestampPlaceholder(final String placeholder) {
|
||||
final String testString = "lhs=lt=" + placeholder;
|
||||
|
||||
final String resolvedPlaceholders = substitutor.replace(testString);
|
||||
assertThat("NOW_TS has to be resolved!", resolvedPlaceholders, not(containsString(placeholder)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests resolution of OVERDUE_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.")
|
||||
public void resolveOverdueTimestampPlaceholder() {
|
||||
final String placeholder = "${OVERDUE_TS}";
|
||||
final String testString = "lhs=lt=" + placeholder;
|
||||
|
||||
final String resolvedPlaceholders = substitutor.replace(testString);
|
||||
assertThat("OVERDUE_TS has to be resolved!", resolvedPlaceholders, not(containsString(placeholder)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests case insensititity of VirtualPropertyResolver.")
|
||||
public void resolveOverdueTimestampPlaceholderLowerCase() {
|
||||
final String placeholder = "${overdue_ts}";
|
||||
final String testString = "lhs=lt=" + placeholder;
|
||||
|
||||
final String resolvedPlaceholders = substitutor.replace(testString);
|
||||
assertThat("overdue_ts has to be resolved!", resolvedPlaceholders, not(containsString(placeholder)));
|
||||
assertThat(resolvedPlaceholders).as("'%s' placeholder was not replaced", placeholder)
|
||||
.doesNotContain(placeholder);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -107,7 +87,7 @@ public class VirtualPropertyResolverTest {
|
||||
final String testString = "lhs=lt=" + placeholder;
|
||||
|
||||
final String resolvedPlaceholders = substitutor.replace(testString);
|
||||
assertThat("unknown should not be resolved!", resolvedPlaceholders, containsString(placeholder));
|
||||
assertThat(resolvedPlaceholders).as("unknown should not be resolved!").contains(placeholder);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,6 +98,6 @@ public class VirtualPropertyResolverTest {
|
||||
final String testString = "lhs=lt=" + escaptedPlaceholder;
|
||||
|
||||
final String resolvedPlaceholders = substitutor.replace(testString);
|
||||
assertThat("Escaped OVERDUE_TS should not be resolved!", resolvedPlaceholders, containsString(placeholder));
|
||||
assertThat(resolvedPlaceholders).as("Escaped OVERDUE_TS should not be resolved!").contains(placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.utils;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Helper to call a request multiple times regarding a given condition until
|
||||
* timeout is reached.
|
||||
*
|
||||
*/
|
||||
public final class MultipleInvokeHelper {
|
||||
|
||||
/**
|
||||
* Call with timeout until result is not null.
|
||||
*
|
||||
* @param callable
|
||||
* class
|
||||
* @param timeout
|
||||
* value
|
||||
* @param pollInterval
|
||||
* value
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <T> T doWithTimeoutUntilResultIsNotNull(final Callable<T> callable, final long timeout,
|
||||
final long pollInterval) throws Exception // NOPMD
|
||||
{
|
||||
return doWithTimeout(callable, new SuccessCondition<T>() {
|
||||
@Override
|
||||
public boolean success(final T result) {
|
||||
return result != null;
|
||||
};
|
||||
}, timeout, pollInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call with timeout.
|
||||
*
|
||||
* @param callable
|
||||
* class
|
||||
* @param successCondition
|
||||
* class
|
||||
* @param timeout
|
||||
* value
|
||||
* @param pollInterval
|
||||
* value
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <T> T doWithTimeout(final Callable<T> callable, final SuccessCondition<T> successCondition,
|
||||
final long timeout, final long pollInterval) throws Exception // NOPMD
|
||||
{
|
||||
|
||||
if (pollInterval < 0) {
|
||||
throw new IllegalArgumentException("pollInterval must non negative");
|
||||
}
|
||||
|
||||
long duration = 0;
|
||||
Exception exception = null;
|
||||
T returnValue = null;
|
||||
while (untilTimeoutReached(timeout, duration)) {
|
||||
try {
|
||||
returnValue = callable.call();
|
||||
// clear exception
|
||||
exception = null;
|
||||
} catch (final Exception ex) {
|
||||
exception = ex;
|
||||
}
|
||||
Thread.sleep(pollInterval);
|
||||
duration += pollInterval > 0 ? pollInterval : 1;
|
||||
if (exception == null && successCondition.success(returnValue)) {
|
||||
return returnValue;
|
||||
} else {
|
||||
returnValue = null;
|
||||
}
|
||||
}
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private static boolean untilTimeoutReached(final long timeout, final long duration) {
|
||||
return duration <= timeout || timeout < 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.utils;
|
||||
|
||||
/**
|
||||
* SuccessCondition Interface.
|
||||
*
|
||||
* @param <T>
|
||||
* type of the value to get verified
|
||||
*/
|
||||
public interface SuccessCondition<T> {
|
||||
|
||||
/**
|
||||
* The implementation of the success condition.
|
||||
*
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
boolean success(final T result);
|
||||
|
||||
}
|
||||
@@ -17,11 +17,10 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
@@ -59,7 +58,6 @@ import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||
import org.eclipse.hawkbit.repository.test.TestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.EventVerifier;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
@@ -103,7 +101,7 @@ import org.springframework.test.context.TestPropertySource;
|
||||
// Cleaning repository will fire "delete" events. We won't count them to the
|
||||
// test execution. So, the order execution between EventVerifier and Cleanup is
|
||||
// important!
|
||||
@TestExecutionListeners(inheritListeners = true, listeners = { EventVerifier.class, CleanupTestExecutionListener.class,
|
||||
@TestExecutionListeners(listeners = { EventVerifier.class, CleanupTestExecutionListener.class,
|
||||
MySqlTestDatabase.class, MsSqlTestDatabase.class,
|
||||
PostgreSqlTestDatabase.class }, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
|
||||
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
|
||||
@@ -302,7 +300,7 @@ public abstract class AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
protected DistributionSetAssignmentResult assignDistributionSet(final DistributionSet pset, final Target target) {
|
||||
return assignDistributionSet(pset, Arrays.asList(target));
|
||||
return assignDistributionSet(pset, Collections.singletonList(target));
|
||||
}
|
||||
|
||||
protected DistributionSetAssignmentResult assignDistributionSet(final long dsId, final String targetId,
|
||||
@@ -322,16 +320,16 @@ public abstract class AbstractIntegrationTest {
|
||||
return distributionSetManagement.createMetaData(dsId, md);
|
||||
}
|
||||
|
||||
protected TargetMetadata createTargetMetadata(final String controllerId, final MetaData md) {
|
||||
return createTargetMetadata(controllerId, Collections.singletonList(md)).get(0);
|
||||
protected void createTargetMetadata(final String controllerId, final MetaData md) {
|
||||
createTargetMetadata(controllerId, Collections.singletonList(md));
|
||||
}
|
||||
|
||||
protected List<TargetMetadata> createTargetMetadata(final String controllerId, final List<MetaData> md) {
|
||||
return targetManagement.createMetaData(controllerId, md);
|
||||
private void createTargetMetadata(final String controllerId, final List<MetaData> md) {
|
||||
targetManagement.createMetaData(controllerId, md);
|
||||
}
|
||||
|
||||
protected Long getOsModule(final DistributionSet ds) {
|
||||
return ds.findFirstModuleByType(osType).get().getId();
|
||||
return ds.findFirstModuleByType(osType).orElseThrow(NoSuchElementException::new).getId();
|
||||
}
|
||||
|
||||
protected Action prepareFinishedUpdate() {
|
||||
@@ -386,7 +384,7 @@ public abstract class AbstractIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
private static String artifactDirectory = createTempDir();
|
||||
private static final String ARTIFACT_DIRECTORY = createTempDir();
|
||||
|
||||
private static String createTempDir() {
|
||||
try {
|
||||
@@ -398,9 +396,9 @@ public abstract class AbstractIntegrationTest {
|
||||
|
||||
@AfterEach
|
||||
public void cleanUp() {
|
||||
if (new File(artifactDirectory).exists()) {
|
||||
if (new File(ARTIFACT_DIRECTORY).exists()) {
|
||||
try {
|
||||
FileUtils.cleanDirectory(new File(artifactDirectory));
|
||||
FileUtils.cleanDirectory(new File(ARTIFACT_DIRECTORY));
|
||||
} catch (final IOException | IllegalArgumentException e) {
|
||||
LOG.warn("Cannot cleanup file-directory", e);
|
||||
}
|
||||
@@ -409,14 +407,14 @@ public abstract class AbstractIntegrationTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeClass() {
|
||||
System.setProperty("org.eclipse.hawkbit.repository.file.path", artifactDirectory);
|
||||
System.setProperty("org.eclipse.hawkbit.repository.file.path", ARTIFACT_DIRECTORY);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterClass() {
|
||||
if (new File(artifactDirectory).exists()) {
|
||||
if (new File(ARTIFACT_DIRECTORY).exists()) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(new File(artifactDirectory));
|
||||
FileUtils.deleteDirectory(new File(ARTIFACT_DIRECTORY));
|
||||
} catch (final IOException | IllegalArgumentException e) {
|
||||
LOG.warn("Cannot delete file-directory", e);
|
||||
}
|
||||
@@ -449,20 +447,6 @@ public abstract class AbstractIntegrationTest {
|
||||
return currentTime.getOffset().getId().replace("Z", "+00:00");
|
||||
}
|
||||
|
||||
protected static String generateRandomStringWithLength(final int length) {
|
||||
final StringBuilder randomStringBuilder = new StringBuilder(length);
|
||||
final Random rand = new Random();
|
||||
final int lowercaseACode = 97;
|
||||
final int lowercaseZCode = 122;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
final char randomCharacter = (char) (rand.nextInt(lowercaseZCode - lowercaseACode + 1) + lowercaseACode);
|
||||
randomStringBuilder.append(randomCharacter);
|
||||
}
|
||||
|
||||
return randomStringBuilder.toString();
|
||||
}
|
||||
|
||||
protected static Action getFirstAssignedAction(
|
||||
final DistributionSetAssignmentResult distributionSetAssignmentResult) {
|
||||
return distributionSetAssignmentResult.getAssignedEntity().stream().findFirst()
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.test.util;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
public class TargetTestData {
|
||||
public static final String ATTRIBUTE_KEY_TOO_LONG;
|
||||
public static final String ATTRIBUTE_KEY_VALID;
|
||||
public static final String ATTRIBUTE_VALUE_TOO_LONG;
|
||||
public static final String ATTRIBUTE_VALUE_VALID;
|
||||
|
||||
static {
|
||||
final Random rand = new Random();
|
||||
ATTRIBUTE_KEY_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE + 1, rand);
|
||||
ATTRIBUTE_KEY_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE, rand);
|
||||
ATTRIBUTE_VALUE_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE + 1, rand);
|
||||
ATTRIBUTE_VALUE_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE, rand);
|
||||
}
|
||||
|
||||
private static String generateRandomStringWithLength(final int length, final Random rand) {
|
||||
final StringBuilder randomStringBuilder = new StringBuilder(length);
|
||||
final int lowercaseACode = 97;
|
||||
final int lowercaseZCode = 122;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
final char randomCharacter = (char) (rand.nextInt(lowercaseZCode - lowercaseACode + 1) + lowercaseACode);
|
||||
randomStringBuilder.append(randomCharacter);
|
||||
}
|
||||
return randomStringBuilder.toString();
|
||||
}
|
||||
|
||||
private TargetTestData() {
|
||||
// nothing to do here
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,7 @@
|
||||
package org.eclipse.hawkbit.repository.test.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -29,6 +27,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
public class WithSpringAuthorityRule implements BeforeEachCallback, AfterEachCallback {
|
||||
|
||||
public static final String DEFAULT_TENANT = "default";
|
||||
private SecurityContext oldContext;
|
||||
|
||||
@Override
|
||||
@@ -64,7 +63,7 @@ public class WithSpringAuthorityRule implements BeforeEachCallback, AfterEachCal
|
||||
|
||||
@Override
|
||||
public void setAuthentication(final Authentication authentication) {
|
||||
// nothing todo
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,35 +84,14 @@ public class WithSpringAuthorityRule implements BeforeEachCallback, AfterEachCal
|
||||
}
|
||||
|
||||
private String[] getAllAuthorities(final String[] additionalAuthorities, final String[] notInclude) {
|
||||
final List<String> allPermissions = new ArrayList<>();
|
||||
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
|
||||
for (final Field field : declaredFields) {
|
||||
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
boolean addPermission = true;
|
||||
final String permissionName = (String) field.get(null);
|
||||
final List<String> permissions = SpPermission.getAllAuthorities();
|
||||
if (notInclude != null) {
|
||||
for (final String notInlcudePerm : notInclude) {
|
||||
if (permissionName.equals(notInlcudePerm)) {
|
||||
addPermission = false;
|
||||
break;
|
||||
permissions.removeAll(Arrays.asList(notInclude));
|
||||
}
|
||||
if (additionalAuthorities != null) {
|
||||
permissions.addAll(Arrays.asList(additionalAuthorities));
|
||||
}
|
||||
}
|
||||
if (addPermission) {
|
||||
allPermissions.add(permissionName);
|
||||
}
|
||||
// don't want to log this exceptions.
|
||||
} catch (@SuppressWarnings("squid:S1166") IllegalArgumentException | IllegalAccessException e) {
|
||||
// nope
|
||||
}
|
||||
}
|
||||
}
|
||||
for (final String authority : additionalAuthorities) {
|
||||
allPermissions.add(authority);
|
||||
}
|
||||
return allPermissions.toArray(new String[allPermissions.size()]);
|
||||
return permissions.toArray(new String[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -146,23 +124,23 @@ public class WithSpringAuthorityRule implements BeforeEachCallback, AfterEachCal
|
||||
}
|
||||
|
||||
public static WithUser withController(final String principal, final String... authorities) {
|
||||
return withUserAndTenant(principal, "default", true, true, true, authorities);
|
||||
return withUserAndTenant(principal, DEFAULT_TENANT, true, true, true, authorities);
|
||||
}
|
||||
|
||||
public static WithUser withUser(final String principal, final String... authorities) {
|
||||
return withUserAndTenant(principal, "default", true, true, false, authorities);
|
||||
return withUserAndTenant(principal, DEFAULT_TENANT, true, true, false, authorities);
|
||||
}
|
||||
|
||||
public static WithUser withUser(final String principal, final boolean allSpPermision, final String... authorities) {
|
||||
return withUserAndTenant(principal, "default", true, allSpPermision, false, authorities);
|
||||
return withUserAndTenant(principal, DEFAULT_TENANT, true, allSpPermision, false, authorities);
|
||||
}
|
||||
|
||||
public static WithUser withUser(final boolean autoCreateTenant) {
|
||||
return withUserAndTenant("bumlux", "default", autoCreateTenant, true, false, new String[] {});
|
||||
return withUserAndTenant("bumlux", DEFAULT_TENANT, autoCreateTenant, true, false);
|
||||
}
|
||||
|
||||
public static WithUser withUserAndTenant(final String principal, final String tenant, final String... authorities) {
|
||||
return withUserAndTenant(principal, tenant, true, true, false, new String[] {});
|
||||
return withUserAndTenant(principal, tenant, true, true, false, authorities);
|
||||
}
|
||||
|
||||
public static WithUser withUserAndTenant(final String principal, final String tenant,
|
||||
@@ -172,8 +150,7 @@ public class WithSpringAuthorityRule implements BeforeEachCallback, AfterEachCal
|
||||
}
|
||||
|
||||
private static WithUser privilegedUser() {
|
||||
return createWithUser("bumlux", "default", true, true, false,
|
||||
new String[] { "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE" });
|
||||
return createWithUser("bumlux", DEFAULT_TENANT, true, true, false, "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE");
|
||||
}
|
||||
|
||||
private static WithUser createWithUser(final String principal, final String tenant, final boolean autoCreateTenant,
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
@@ -130,7 +131,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId) {
|
||||
LOG.debug("getSoftwareModulesArtifacts({})", controllerId);
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Target target = findTarget(controllerId);
|
||||
|
||||
final SoftwareModule softwareModule = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
@@ -169,20 +170,16 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@PathVariable("fileName") final String fileName) {
|
||||
final ResponseEntity<InputStream> result;
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Target target = findTarget(controllerId);
|
||||
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
|
||||
if (checkModule(fileName, module)) {
|
||||
LOG.warn("Softare module with id {} could not be found.", softwareModuleId);
|
||||
LOG.warn("Software module with id {} could not be found.", softwareModuleId);
|
||||
result = ResponseEntity.notFound().build();
|
||||
} else {
|
||||
|
||||
// Exception squid:S3655 - Optional access is checked in checkModule
|
||||
// subroutine
|
||||
@SuppressWarnings("squid:S3655")
|
||||
final Artifact artifact = module.getArtifactByFilename(fileName).get();
|
||||
|
||||
// Artifact presence is ensured in 'checkModule'
|
||||
final Artifact artifact = module.getArtifactByFilename(fileName).orElseThrow(NoSuchElementException::new);
|
||||
final DbArtifact file = artifactManagement
|
||||
.loadArtifactBinary(artifact.getSha1Hash(), module.getId(), module.isEncrypted())
|
||||
.orElseThrow(() -> new ArtifactBinaryNotFoundException(artifact.getSha1Hash()));
|
||||
@@ -239,7 +236,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@PathVariable("fileName") final String fileName) {
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Target target = findTarget(controllerId);
|
||||
|
||||
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
@@ -274,9 +271,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
|
||||
LOG.debug("getControllerBasedeploymentAction({},{})", controllerId, resource);
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
verifyActionAssignedToTarget(target, action);
|
||||
final Target target = findTarget(controllerId);
|
||||
final Action action = findActionForTarget(actionId, target);
|
||||
|
||||
checkAndCancelExpiredAction(action);
|
||||
|
||||
@@ -296,7 +292,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
private static HandlingType calculateDownloadType(final Action action) {
|
||||
if (action.isDownloadOnly() || action.isForce()) {
|
||||
if (action.isDownloadOnly() || action.isForcedOrTimeForced()) {
|
||||
return HandlingType.FORCED;
|
||||
}
|
||||
return HandlingType.ATTEMPT;
|
||||
@@ -325,9 +321,9 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId) {
|
||||
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback);
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
verifyActionAssignedToTarget(target, action);
|
||||
final Target target = findTarget(controllerId);
|
||||
final Action action = findActionForTarget(actionId, target);
|
||||
|
||||
|
||||
if (!action.isActive()) {
|
||||
LOG.warn("Updating action {} with feedback {} not possible since action not active anymore.",
|
||||
@@ -342,7 +338,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId,
|
||||
final Long actionid) {
|
||||
final Long actionId) {
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
|
||||
@@ -353,38 +349,38 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
LOG.debug("Controller confirmed cancel (actionid: {}, controllerId: {}) as we got {} report.", actionid,
|
||||
LOG.debug("Controller confirmed cancel (actionId: {}, controllerId: {}) as we got {} report.", actionId,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.CANCELED;
|
||||
addMessageIfEmpty("Target confirmed cancelation.", messages);
|
||||
addMessageIfEmpty("Target confirmed cancellation.", messages);
|
||||
break;
|
||||
case REJECTED:
|
||||
LOG.info("Controller reported internal error (actionid: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, controllerId, feedback.getStatus().getExecution());
|
||||
LOG.info("Controller reported internal error (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionId, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.WARNING;
|
||||
addMessageIfEmpty("Target REJECTED update", messages);
|
||||
break;
|
||||
case CLOSED:
|
||||
status = handleClosedCase(feedback, controllerId, actionid, messages);
|
||||
status = handleClosedCase(feedback, controllerId, actionId, messages);
|
||||
break;
|
||||
case DOWNLOAD:
|
||||
LOG.debug("Controller confirmed status of download (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, controllerId, feedback.getStatus().getExecution());
|
||||
actionId, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.DOWNLOAD;
|
||||
addMessageIfEmpty("Target confirmed download start", messages);
|
||||
break;
|
||||
case DOWNLOADED:
|
||||
LOG.debug("Controller confirmed download (actionId: {}, controllerId: {}) as we got {} report.", actionid,
|
||||
LOG.debug("Controller confirmed download (actionId: {}, controllerId: {}) as we got {} report.", actionId,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.DOWNLOADED;
|
||||
addMessageIfEmpty("Target confirmed download finished", messages);
|
||||
break;
|
||||
default:
|
||||
status = handleDefaultCase(feedback, controllerId, actionid, messages);
|
||||
status = handleDefaultCase(feedback, controllerId, actionId, messages);
|
||||
break;
|
||||
}
|
||||
|
||||
return entityFactory.actionStatus().create(actionid).status(status).messages(messages);
|
||||
return entityFactory.actionStatus().create(actionId).status(status).messages(messages);
|
||||
}
|
||||
|
||||
private static void addMessageIfEmpty(final String text, final List<String> messages) {
|
||||
@@ -393,20 +389,20 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
}
|
||||
|
||||
private Status handleDefaultCase(final DdiActionFeedback feedback, final String controllerId, final Long actionid,
|
||||
private Status handleDefaultCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId,
|
||||
final List<String> messages) {
|
||||
Status status;
|
||||
LOG.debug("Controller reported intermediate status (actionid: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, controllerId, feedback.getStatus().getExecution());
|
||||
LOG.debug("Controller reported intermediate status (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionId, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.RUNNING;
|
||||
addMessageIfEmpty("Target reported " + feedback.getStatus().getExecution(), messages);
|
||||
return status;
|
||||
}
|
||||
|
||||
private Status handleClosedCase(final DdiActionFeedback feedback, final String controllerId, final Long actionid,
|
||||
private Status handleClosedCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId,
|
||||
final List<String> messages) {
|
||||
Status status;
|
||||
LOG.debug("Controller reported closed (actionid: {}, controllerId: {}) as we got {} report.", actionid,
|
||||
LOG.debug("Controller reported closed (actionId: {}, controllerId: {}) as we got {} report.", actionId,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
status = Status.ERROR;
|
||||
@@ -432,9 +428,9 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId) {
|
||||
LOG.debug("getControllerCancelAction({})", controllerId);
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
verifyActionAssignedToTarget(target, action);
|
||||
final Target target = findTarget(controllerId);
|
||||
final Action action = findActionForTarget(actionId, target);
|
||||
|
||||
|
||||
if (action.isCancelingOrCanceled()) {
|
||||
final DdiCancel cancel = new DdiCancel(String.valueOf(action.getId()),
|
||||
@@ -443,7 +439,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
LOG.debug("Found an active CancelAction for target {}. returning cancel: {}", controllerId, cancel);
|
||||
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved cancel action and should start now the cancelation.");
|
||||
+ "Target retrieved cancel action and should start now the cancellation.");
|
||||
|
||||
return new ResponseEntity<>(cancel, HttpStatus.OK);
|
||||
}
|
||||
@@ -458,12 +454,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId) {
|
||||
LOG.debug("provideCancelActionFeedback for target [{}]: {}", controllerId, feedback);
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
verifyActionAssignedToTarget(target, action);
|
||||
final Target target = findTarget(controllerId);
|
||||
final Action action = findActionForTarget(actionId, target);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(generateActionCancelStatus(feedback, target, actionId, entityFactory));
|
||||
.addCancelActionStatus(generateActionCancelStatus(feedback, target, action.getId(), entityFactory));
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@@ -473,9 +468,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
|
||||
LOG.debug("getControllerInstalledAction({})", controllerId);
|
||||
|
||||
final Target target = findTargetWithExceptionIfNotFound(controllerId);
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
verifyActionAssignedToTarget(target, action);
|
||||
final Target target = findTarget(controllerId);
|
||||
final Action action = findActionForTarget(actionId, target);
|
||||
|
||||
if (action.isActive() || action.isCancelingOrCanceled()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
@@ -511,19 +505,19 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
private static ActionStatusCreate generateActionCancelStatus(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionid, final EntityFactory entityFactory) {
|
||||
final Long actionId, final EntityFactory entityFactory) {
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
status = handleCaseCancelCanceled(feedback, target, actionid, messages);
|
||||
status = handleCaseCancelCanceled(feedback, target, actionId, messages);
|
||||
break;
|
||||
case REJECTED:
|
||||
LOG.info("Target rejected the cancelation request (actionid: {}, controllerId: {}).", actionid,
|
||||
LOG.info("Target rejected the cancellation request (actionId: {}, controllerId: {}).", actionId,
|
||||
target.getControllerId());
|
||||
status = Status.CANCEL_REJECTED;
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancelation request.");
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancellation request.");
|
||||
break;
|
||||
case CLOSED:
|
||||
status = handleCancelClosedCase(feedback, messages);
|
||||
@@ -537,7 +531,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
messages.addAll(feedback.getStatus().getDetails());
|
||||
}
|
||||
|
||||
return entityFactory.actionStatus().create(actionid).status(status).messages(messages);
|
||||
return entityFactory.actionStatus().create(actionId).status(status).messages(messages);
|
||||
|
||||
}
|
||||
|
||||
@@ -545,41 +539,44 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
Status status;
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
status = Status.ERROR;
|
||||
addMessageIfEmpty("Target was not able to complete cancelation", messages);
|
||||
addMessageIfEmpty("Target was not able to complete cancellation", messages);
|
||||
} else {
|
||||
status = Status.CANCELED;
|
||||
addMessageIfEmpty("Cancelation confirmed", messages);
|
||||
addMessageIfEmpty("Cancellation confirmed", messages);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
private static Status handleCaseCancelCanceled(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionid, final List<String> messages) {
|
||||
final Long actionId, final List<String> messages) {
|
||||
Status status;
|
||||
LOG.error(
|
||||
"Target reported cancel for a cancel which is not supported by the server (actionid: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, target.getControllerId(), feedback.getStatus().getExecution());
|
||||
"Target reported cancel for a cancel which is not supported by the server (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionId, target.getControllerId(), feedback.getStatus().getExecution());
|
||||
status = Status.WARNING;
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target reported cancel for a cancel which is not supported by the server.");
|
||||
return status;
|
||||
}
|
||||
|
||||
private Target findTargetWithExceptionIfNotFound(final String controllerId) {
|
||||
private Target findTarget(final String controllerId) {
|
||||
return controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
}
|
||||
|
||||
private Action findActionWithExceptionIfNotFound(final Long actionId) {
|
||||
return controllerManagement.findActionWithDetails(actionId)
|
||||
private Action findActionForTarget(final Long actionId, final Target target) {
|
||||
final Action action = controllerManagement.findActionWithDetails(actionId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
return verifyActionBelongsToTarget(action, target);
|
||||
}
|
||||
|
||||
private void verifyActionAssignedToTarget(final Target target, final Action action) {
|
||||
private Action verifyActionBelongsToTarget(Action action, Target target) {
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
LOG.warn(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
throw new EntityNotFoundException(Action.class, action.getId());
|
||||
LOG.debug(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
throw new EntityNotFoundException(
|
||||
"Not a valid action (" + action.getId() + ") for target: " + target.getControllerId(), null);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,7 +591,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
try {
|
||||
controllerManagement.cancelAction(action.getId());
|
||||
} catch (final CancelActionNotAllowedException e) {
|
||||
LOG.info("Cancel action not allowed exception :{}", e);
|
||||
LOG.info("Cancel action not allowed: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,11 @@ import io.qameta.allure.Story;
|
||||
*/
|
||||
@Feature("Component Tests - Direct Device Integration API")
|
||||
@Story("Cancel Action Resource")
|
||||
public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Tests that the cancel action resource can be used with CBOR.")
|
||||
public void cancelActionCbor() throws Exception {
|
||||
void cancelActionCbor() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
@@ -75,7 +75,7 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test of the controller can continue a started update even after a cancel command if it so desires.")
|
||||
public void rootRsCancelActionButContinueAnyway() throws Exception {
|
||||
void rootRsCancelActionButContinueAnyway() throws Exception {
|
||||
// prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget();
|
||||
@@ -130,14 +130,14 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test for cancel operation of a update action.")
|
||||
public void rootRsCancelAction() throws Exception {
|
||||
void rootRsCancelAction() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget();
|
||||
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
|
||||
long current = System.currentTimeMillis();
|
||||
final long timeBeforeFirstPoll = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -146,13 +146,9 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId)));
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
final long timeAfterFirstPoll = System.currentTimeMillis() + 1;
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
.isBetween(timeBeforeFirstPoll, timeAfterFirstPoll);
|
||||
|
||||
// Retrieved is reported
|
||||
|
||||
@@ -171,7 +167,7 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(activeActionsByTarget).hasSize(1);
|
||||
assertThat(activeActionsByTarget.get(0).getStatus()).isEqualTo(Status.CANCELING);
|
||||
|
||||
current = System.currentTimeMillis();
|
||||
final long timeBefore2ndPoll = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
@@ -179,17 +175,10 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId())));
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
final long timeAfter2ndPoll = System.currentTimeMillis() + 1;
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
.isBetween(timeBefore2ndPoll, timeAfter2ndPoll);
|
||||
|
||||
current = System.currentTimeMillis();
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -208,7 +197,7 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent();
|
||||
assertThat(activeActionsByTarget).hasSize(0);
|
||||
assertThat(activeActionsByTarget).isEmpty();
|
||||
final Action canceledAction = deploymentManagement.findAction(cancelAction.getId()).get();
|
||||
assertThat(canceledAction.isActive()).isFalse();
|
||||
assertThat(canceledAction.getStatus()).isEqualTo(Status.CANCELED);
|
||||
@@ -217,7 +206,7 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Tests various bad requests and if the server handles them as expected.")
|
||||
public void badCancelAction() throws Exception {
|
||||
void badCancelAction() throws Exception {
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||
@@ -258,7 +247,7 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Tests the feedback channel of the cancel operation.")
|
||||
public void rootRsCancelActionFeedback() throws Exception {
|
||||
void rootRsCancelActionFeedback() throws Exception {
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
@@ -327,12 +316,12 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(0);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the feeback chanel of for multiple open cancel operations on the same target.")
|
||||
public void multipleCancelActionFeedback() throws Exception {
|
||||
void multipleCancelActionFeedback() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("3", true);
|
||||
@@ -443,13 +432,13 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(13);
|
||||
|
||||
// final status
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(0);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the feeback channel closing for too many feedbacks, i.e. denial of service prevention.")
|
||||
public void tooMuchCancelActionFeedback() throws Exception {
|
||||
void tooMuchCancelActionFeedback() throws Exception {
|
||||
testdataFactory.createTarget();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
@@ -477,9 +466,9 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("test the correct rejection of various invalid feedback requests")
|
||||
public void badCancelActionFeedback() throws Exception {
|
||||
void badCancelActionFeedback() throws Exception {
|
||||
final Action cancelAction = createCancelAction(TestdataFactory.DEFAULT_CONTROLLER_ID);
|
||||
final Action cancelAction2 = createCancelAction("4715");
|
||||
createCancelAction("4715");
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
@@ -524,12 +513,11 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
|
||||
// finally get it right :)
|
||||
// finaly, get it right :)
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
package org.eclipse.hawkbit.ddi.rest.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.repository.test.util.TargetTestData.ATTRIBUTE_KEY_TOO_LONG;
|
||||
import static org.eclipse.hawkbit.repository.test.util.TargetTestData.ATTRIBUTE_KEY_VALID;
|
||||
import static org.eclipse.hawkbit.repository.test.util.TargetTestData.ATTRIBUTE_VALUE_TOO_LONG;
|
||||
import static org.eclipse.hawkbit.repository.test.util.TargetTestData.ATTRIBUTE_VALUE_VALID;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
@@ -21,6 +25,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
@@ -40,41 +45,39 @@ import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Step;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
/**
|
||||
* Test config data from the controller.
|
||||
*/
|
||||
@ActiveProfiles({ "im", "test" })
|
||||
@Feature("Component Tests - Direct Device Integration API")
|
||||
@Story("Config Data Resource")
|
||||
public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
private static final String KEY_TOO_LONG = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE + 1);
|
||||
private static final String KEY_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_KEY_SIZE);
|
||||
private static final String VALUE_TOO_LONG = generateRandomStringWithLength(
|
||||
Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE + 1);
|
||||
private static final String VALUE_VALID = generateRandomStringWithLength(Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE);
|
||||
public static final String TARGET1_ID = "4717";
|
||||
public static final String TARGET1_CONFIGDATA_PATH = "/{tenant}/controller/v1/" + TARGET1_ID + "/configData";
|
||||
public static final String TARGET2_ID = "4718";
|
||||
public static final String TARGET2_CONFIGDATA_PATH = "/{tenant}/controller/v1/" + TARGET2_ID + "/configData";
|
||||
|
||||
@Test
|
||||
@Description("Verify that config data can be uploaded as CBOR")
|
||||
public void putConfigDataAsCbor() throws Exception {
|
||||
testdataFactory.createTarget("4717");
|
||||
void putConfigDataAsCbor() throws Exception {
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(KEY_VALID, VALUE_VALID);
|
||||
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(jsonToCbor(JsonBuilder.configData(attributes).toString()))
|
||||
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(targetManagement.getControllerAttributes("4717")).isEqualTo(attributes);
|
||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "are requested only once from the device.")
|
||||
@SuppressWarnings("squid:S2925")
|
||||
public void requestConfigDataIfEmpty() throws Exception {
|
||||
void requestConfigDataIfEmpty() throws Exception {
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
@@ -88,9 +91,11 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new)
|
||||
.getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new)
|
||||
.getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
final Map<String, String> attributes = Maps.newHashMapWithExpectedSize(1);
|
||||
@@ -113,44 +118,44 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "can be uploaded correctly by the controller.")
|
||||
public void putConfigData() throws Exception {
|
||||
testdataFactory.createTarget("4717");
|
||||
void putConfigData() throws Exception {
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
// initial
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(KEY_VALID, VALUE_VALID);
|
||||
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(targetManagement.getControllerAttributes("4717")).isEqualTo(attributes);
|
||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||
|
||||
// update
|
||||
attributes.put("sdsds", "123412");
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(targetManagement.getControllerAttributes("4717")).isEqualTo(attributes);
|
||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "upload quota is enforced to protect the server from malicious attempts.")
|
||||
public void putTooMuchConfigData() throws Exception {
|
||||
testdataFactory.createTarget("4717");
|
||||
void putTooMuchConfigData() throws Exception {
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
// initial
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) {
|
||||
attributes.put("dsafsdf" + i, "sdsds" + i);
|
||||
}
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
attributes = new HashMap<>();
|
||||
attributes.put("on too many", "sdsds");
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
|
||||
@@ -161,7 +166,7 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "resource behaves as expected in case of invalid request attempts.")
|
||||
public void badConfigData() throws Exception {
|
||||
void badConfigData() throws Exception {
|
||||
testdataFactory.createTarget("4712");
|
||||
|
||||
// not allowed methods
|
||||
@@ -195,23 +200,17 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that invalid config data attributes are handled correctly.")
|
||||
public void putConfigDataWithInvalidAttributes() throws Exception {
|
||||
void putConfigDataWithInvalidAttributes() throws Exception {
|
||||
// create a target
|
||||
final String controllerId = "4718";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
final String configDataPath = "/{tenant}/controller/v1/" + controllerId + "/configData";
|
||||
|
||||
putAndVerifyConfigDataWithKeyTooLong(configDataPath);
|
||||
|
||||
putAndVerifyConfigDataWithValueTooLong(configDataPath);
|
||||
testdataFactory.createTarget(TARGET2_ID);
|
||||
putAndVerifyConfigDataWithKeyTooLong();
|
||||
putAndVerifyConfigDataWithValueTooLong();
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putAndVerifyConfigDataWithKeyTooLong(final String configDataPath) throws Exception {
|
||||
|
||||
final Map<String, String> attributes = Collections.singletonMap(KEY_TOO_LONG, VALUE_VALID);
|
||||
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
private void putAndVerifyConfigDataWithKeyTooLong() throws Exception {
|
||||
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_TOO_LONG, ATTRIBUTE_VALUE_VALID);
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
||||
@@ -219,11 +218,9 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putAndVerifyConfigDataWithValueTooLong(final String configDataPath) throws Exception {
|
||||
|
||||
final Map<String, String> attributes = Collections.singletonMap(KEY_VALID, VALUE_TOO_LONG);
|
||||
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
private void putAndVerifyConfigDataWithValueTooLong() throws Exception {
|
||||
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_TOO_LONG);
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
||||
@@ -232,139 +229,133 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).")
|
||||
public void putConfigDataWithDifferentUpdateModes() throws Exception {
|
||||
void putConfigDataWithDifferentUpdateModes() throws Exception {
|
||||
|
||||
// create a target
|
||||
final String controllerId = "4717";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
final String configDataPath = "/{tenant}/controller/v1/" + controllerId + "/configData";
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
// no update mode
|
||||
putConfigDataWithoutUpdateMode(controllerId, configDataPath);
|
||||
putConfigDataWithoutUpdateMode();
|
||||
|
||||
// update mode REPLACE
|
||||
putConfigDataWithUpdateModeReplace(controllerId, configDataPath);
|
||||
putConfigDataWithUpdateModeReplace();
|
||||
|
||||
// update mode MERGE
|
||||
putConfigDataWithUpdateModeMerge(controllerId, configDataPath);
|
||||
putConfigDataWithUpdateModeMerge();
|
||||
|
||||
// update mode REMOVE
|
||||
putConfigDataWithUpdateModeRemove(controllerId, configDataPath);
|
||||
putConfigDataWithUpdateModeRemove();
|
||||
|
||||
// invalid update mode
|
||||
putConfigDataWithInvalidUpdateMode(configDataPath);
|
||||
|
||||
putConfigDataWithInvalidUpdateMode();
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithInvalidUpdateMode(final String configDataPath) throws Exception {
|
||||
|
||||
private void putConfigDataWithInvalidUpdateMode() throws Exception {
|
||||
// create some attriutes
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("k0", "v0");
|
||||
attributes.put("k1", "v1");
|
||||
|
||||
// use an invalid update mode
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeRemove(final String controllerId, final String configDataPath)
|
||||
throws Exception {
|
||||
|
||||
private void putConfigDataWithUpdateModeRemove() throws Exception {
|
||||
// get the current attributes
|
||||
final int previousSize = targetManagement.getControllerAttributes(controllerId).size();
|
||||
final int previousSize = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID).size();
|
||||
|
||||
// update the attributes using update mode REMOVE
|
||||
final Map<String, String> removeAttributes = new HashMap<>();
|
||||
removeAttributes.put("k1", "foo");
|
||||
removeAttributes.put("k3", "bar");
|
||||
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(removeAttributes, "remove").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute removal
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(previousSize - 2);
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).hasSize(previousSize - 2);
|
||||
assertThat(updatedAttributes).doesNotContainKeys("k1", "k3");
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeMerge(final String controllerId, final String configDataPath)
|
||||
private void putConfigDataWithUpdateModeMerge()
|
||||
throws Exception {
|
||||
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(controllerId));
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
|
||||
|
||||
// update the attributes using update mode MERGE
|
||||
final Map<String, String> mergeAttributes = new HashMap<>();
|
||||
mergeAttributes.put("k1", "v1_modified_again");
|
||||
mergeAttributes.put("k4", "v4");
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(mergeAttributes, "merge").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute merge
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(4);
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).hasSize(4);
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes);
|
||||
assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified_again");
|
||||
assertThat(updatedAttributes).containsEntry("k1", "v1_modified_again");
|
||||
attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeReplace(final String controllerId, final String configDataPath)
|
||||
private void putConfigDataWithUpdateModeReplace()
|
||||
throws Exception {
|
||||
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(controllerId));
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
|
||||
|
||||
// update the attributes using update mode REPLACE
|
||||
final Map<String, String> replacementAttributes = new HashMap<>();
|
||||
replacementAttributes.put("k1", "v1_modified");
|
||||
replacementAttributes.put("k2", "v2");
|
||||
replacementAttributes.put("k3", "v3");
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(replacementAttributes, "replace").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute replacement
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(replacementAttributes.size());
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).hasSize(replacementAttributes.size());
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes);
|
||||
assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified");
|
||||
assertThat(updatedAttributes).containsEntry("k1", "v1_modified");
|
||||
attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithoutUpdateMode(final String controllerId, final String configDataPath)
|
||||
private void putConfigDataWithoutUpdateMode()
|
||||
throws Exception {
|
||||
|
||||
// create some attriutes
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("k0", "v0");
|
||||
attributes.put("k1", "v1");
|
||||
|
||||
// set the initial attributes
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
// verify the initial parameters
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(attributes.size());
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(attributes);
|
||||
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).containsExactlyEntriesOf(attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ import io.qameta.allure.Story;
|
||||
*/
|
||||
@Feature("Component Tests - Direct Device Integration API")
|
||||
@Story("Root Poll Resource")
|
||||
public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
private static final String TARGET_COMPLETED_INSTALLATION_MSG = "Target completed installation.";
|
||||
private static final String TARGET_PROCEEDING_INSTALLATION_MSG = "Target proceeding installation.";
|
||||
@@ -87,7 +87,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensure that the root poll resource is available as CBOR")
|
||||
public void rootPollResourceCbor() throws Exception {
|
||||
void rootPollResourceCbor() throws Exception {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)
|
||||
.accept(DdiRestConstants.MEDIA_TYPE_CBOR)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andExpect(status().isOk());
|
||||
@@ -95,7 +95,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the API returns JSON when no Accept header is specified by the client.")
|
||||
public void apiReturnsJSONByDefault() throws Exception {
|
||||
void apiReturnsJSONByDefault() throws Exception {
|
||||
final MvcResult result = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
|
||||
@@ -113,7 +113,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetTypeCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleTypeCreatedEvent.class, count = 2) })
|
||||
public void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception {
|
||||
void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception {
|
||||
|
||||
mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
@@ -137,14 +137,13 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
SpPermission.CREATE_TARGET }, allSpPermissions = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void targetPollDoesNotModifyAuditData() throws Exception {
|
||||
void targetPollDoesNotModifyAuditData() throws Exception {
|
||||
// create target first with "knownPrincipal" user and audit data
|
||||
final String knownTargetControllerId = "target1";
|
||||
final String knownCreatedBy = "knownPrincipal";
|
||||
testdataFactory.createTarget(knownTargetControllerId);
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId).get();
|
||||
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
|
||||
assertThat(findTargetByControllerID.getCreatedAt()).isNotNull();
|
||||
|
||||
// make a poll, audit information should not be changed, run as
|
||||
// controller principal!
|
||||
@@ -165,7 +164,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Test
|
||||
@Description("Ensures that server returns a not found response in case of empty controller ID.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void rootRsWithoutId() throws Exception {
|
||||
void rootRsWithoutId() throws Exception {
|
||||
mvc.perform(get("/controller/v1/")).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@@ -173,7 +172,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensures that the system creates a new target in plug and play manner, i.e. target is authenticated but does not exist yet.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsPlugAndPlay() throws Exception {
|
||||
void rootRsPlugAndPlay() throws Exception {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
String controllerId = "4711";
|
||||
@@ -204,7 +203,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
public void pollWithModifiedGlobalPollingTime() throws Exception {
|
||||
void pollWithModifiedGlobalPollingTime() throws Exception {
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:02:00");
|
||||
@@ -230,7 +229,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6) })
|
||||
public void rootRsNotModified() throws Exception {
|
||||
void rootRsNotModified() throws Exception {
|
||||
String controllerId = "4711";
|
||||
final String etag = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -308,7 +307,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
+ "UNKNOWN to REGISTERED when the target polls for the first time.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsPrecommissioned() throws Exception {
|
||||
void rootRsPrecommissioned() throws Exception {
|
||||
String controllerId = "4711";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
|
||||
@@ -334,7 +333,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensures that the source IP address of the polling target is correctly stored in repository")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsPlugAndPlayIpAddress() throws Exception {
|
||||
void rootRsPlugAndPlayIpAddress() throws Exception {
|
||||
// test
|
||||
final String knownControllerId1 = "0815";
|
||||
final long create = System.currentTimeMillis();
|
||||
@@ -361,7 +360,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensures that the source IP address of the polling target is not stored in repository if disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsIpAddressNotStoredIfDisabled() throws Exception {
|
||||
void rootRsIpAddressNotStoredIfDisabled() throws Exception {
|
||||
securityProperties.getClients().setTrackRemoteIp(false);
|
||||
|
||||
// test
|
||||
@@ -384,7 +383,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception {
|
||||
void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
@@ -409,7 +408,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 6), @Expect(type = TargetPollEvent.class, count = 4),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
|
||||
public void attributeUpdateRequestSendingAfterSuccessfulDeployment() throws Exception {
|
||||
void attributeUpdateRequestSendingAfterSuccessfulDeployment() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("1");
|
||||
final Target savedTarget = testdataFactory.createTarget("922");
|
||||
final Map<String, String> attributes = Collections.singletonMap("AttributeKey", "AttributeValue");
|
||||
@@ -487,7 +486,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void testActionHistoryCount() throws Exception {
|
||||
void testActionHistoryCount() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
@@ -524,7 +523,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void testActionHistoryZeroInput() throws Exception {
|
||||
void testActionHistoryZeroInput() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
@@ -561,7 +560,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void testActionHistoryNegativeInput() throws Exception {
|
||||
void testActionHistoryNegativeInput() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
@@ -591,7 +590,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test the polling time based on different maintenance window start and end time.")
|
||||
public void sleepTimeResponseForDifferentMaintenanceWindowParameters() throws Exception {
|
||||
void sleepTimeResponseForDifferentMaintenanceWindowParameters() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> {
|
||||
@@ -638,7 +637,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test download and update values before maintenance window start time.")
|
||||
public void downloadAndUpdateStatusBeforeMaintenanceWindowStartTime() throws Exception {
|
||||
void downloadAndUpdateStatusBeforeMaintenanceWindowStartTime() throws Exception {
|
||||
Target savedTarget = testdataFactory.createTarget("1911");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(),
|
||||
@@ -658,7 +657,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test download and update values after maintenance window start time.")
|
||||
public void downloadAndUpdateStatusDuringMaintenanceWindow() throws Exception {
|
||||
void downloadAndUpdateStatusDuringMaintenanceWindow() throws Exception {
|
||||
Target savedTarget = testdataFactory.createTarget("1911");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(),
|
||||
@@ -678,7 +677,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Assign multiple DS in multi-assignment mode. The earliest active Action is exposed to the controller.")
|
||||
public void earliestActionIsExposedToControllerInMultiAssignMode() throws Exception {
|
||||
void earliestActionIsExposedToControllerInMultiAssignMode() throws Exception {
|
||||
enableMultiAssignments();
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
@@ -695,7 +694,7 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("The system should not create a new target because of a too long controller id.")
|
||||
public void rootRsWithInvalidControllerId() throws Exception {
|
||||
void rootRsWithInvalidControllerId() throws Exception {
|
||||
final String invalidControllerId = RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1);
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), invalidControllerId))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
@@ -42,7 +42,7 @@ import io.qameta.allure.Story;
|
||||
@ActiveProfiles({ "test" })
|
||||
@Feature("Component Tests - REST Security")
|
||||
@Story("Denial of Service protection filter")
|
||||
public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Override
|
||||
protected DefaultMockMvcBuilder createMvcWebAppContext(final WebApplicationContext context) {
|
||||
@@ -52,14 +52,14 @@ public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that clients that are on the blacklist are forbidded ")
|
||||
public void blackListedClientIsForbidden() throws Exception {
|
||||
void blackListedClientIsForbidden() throws Exception {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 ")).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a READ DoS attempt is blocked ")
|
||||
public void getFloddingAttackThatisPrevented() throws Exception {
|
||||
void getFloddingAttackThatisPrevented() throws Exception {
|
||||
|
||||
MvcResult result = null;
|
||||
|
||||
@@ -79,7 +79,7 @@ public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an assumed READ DoS attempt is not blocked as the client (with IPv4 address) is on a whitelist")
|
||||
public void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
|
||||
void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "127.0.0.1")).andExpect(status().isOk());
|
||||
@@ -88,7 +88,7 @@ public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an assumed READ DoS attempt is not blocked as the client (with IPv6 address) is on a whitelist")
|
||||
public void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
|
||||
void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "0:0:0:0:0:0:0:1")).andExpect(status().isOk());
|
||||
@@ -97,7 +97,8 @@ public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
|
||||
public void acceptableGetLoad() throws Exception {
|
||||
@SuppressWarnings("squid:S2925") // No idea how to get rid of the Thread.sleep here
|
||||
void acceptableGetLoad() throws Exception {
|
||||
|
||||
for (int x = 0; x < 3; x++) {
|
||||
// sleep for one second
|
||||
@@ -111,7 +112,7 @@ public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a WRITE DoS attempt is blocked ")
|
||||
public void putPostFloddingAttackThatisPrevented() throws Exception {
|
||||
void putPostFloddingAttackThatisPrevented() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
|
||||
@@ -135,7 +136,8 @@ public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
|
||||
public void acceptablePutPostLoad() throws Exception {
|
||||
@SuppressWarnings("squid:S2925") // No idea how to get rid of the Thread.sleep here
|
||||
void acceptablePutPostLoad() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.ValidationException;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||
@@ -29,6 +28,7 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
@@ -108,17 +108,22 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
|
||||
|
||||
// first check the given RSQL query if it's well formed, otherwise and
|
||||
// exception is thrown
|
||||
targetFilterQueryManagement.verifyTargetFilterQuerySyntax(rolloutRequestBody.getTargetFilterQuery());
|
||||
|
||||
final DistributionSet distributionSet = distributionSetManagement
|
||||
.getValidAndComplete(rolloutRequestBody.getDistributionSetId());
|
||||
final String targetFilterQuery = rolloutRequestBody.getTargetFilterQuery();
|
||||
if (targetFilterQuery == null) {
|
||||
// Use RSQLParameterSyntaxException due to backwards compatibility
|
||||
throw new RSQLParameterSyntaxException("Cannot create a Rollout with an empty target query filter!");
|
||||
}
|
||||
targetFilterQueryManagement.verifyTargetFilterQuerySyntax(targetFilterQuery);
|
||||
final DistributionSet distributionSet = distributionSetManagement.getValidAndComplete(
|
||||
rolloutRequestBody.getDistributionSetId());
|
||||
final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true);
|
||||
|
||||
final RolloutCreate create = MgmtRolloutMapper.fromRequest(entityFactory, rolloutRequestBody, distributionSet);
|
||||
|
||||
Rollout rollout;
|
||||
if (rolloutRequestBody.getGroups() != null) {
|
||||
final List<RolloutGroupCreate> rolloutGroups = rolloutRequestBody.getGroups().stream()
|
||||
final List<RolloutGroupCreate> rolloutGroups = rolloutRequestBody.getGroups()
|
||||
.stream()
|
||||
.map(mgmtRolloutGroup -> MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup))
|
||||
.collect(Collectors.toList());
|
||||
rollout = rolloutManagement.create(create, rolloutGroups, rolloutGroupConditions);
|
||||
|
||||
@@ -25,8 +25,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
@@ -40,10 +43,10 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.eclipse.hawkbit.rest.util.SuccessCondition;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@@ -60,21 +63,21 @@ import io.qameta.allure.Story;
|
||||
*/
|
||||
@Feature("Component Tests - Management API")
|
||||
@Story("Rollout Resource")
|
||||
public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
|
||||
private static final String HREF_ROLLOUT_PREFIX = "http://localhost/rest/v1/rollouts/";
|
||||
|
||||
@Autowired
|
||||
private RolloutManagement rolloutManagement;
|
||||
@Autowired private RolloutManagement rolloutManagement;
|
||||
|
||||
@Autowired
|
||||
private RolloutGroupManagement rolloutGroupManagement;
|
||||
@Autowired private RolloutGroupManagement rolloutGroupManagement;
|
||||
|
||||
@Test
|
||||
@Description("Testing that creating rollout with wrong body returns bad request")
|
||||
public void createRolloutWithInvalidBodyReturnsBadRequest() throws Exception {
|
||||
mvc.perform(post("/rest/v1/rollouts").content("invalid body").contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
void createRolloutWithInvalidBodyReturnsBadRequest() throws Exception {
|
||||
mvc.perform(post("/rest/v1/rollouts").content("invalid body")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("errorCode", equalTo("hawkbit.server.error.rest.body.notReadable")));
|
||||
}
|
||||
@@ -82,36 +85,45 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
@Test
|
||||
@Description("Testing that creating rollout with insufficient permission returns forbidden")
|
||||
@WithUser(allSpPermissions = true, removeFromAllPermission = "CREATE_ROLLOUT")
|
||||
public void createRolloutWithInsufficientPermissionReturnsForbidden() throws Exception {
|
||||
void createRolloutWithInsufficientPermissionReturnsForbidden() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("name", "desc", 10, dsA.getId(), "name==test", null))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().is(403)).andReturn();
|
||||
mvc.perform(post("/rest/v1/rollouts").content(
|
||||
JsonBuilder.rollout("name", "desc", 10, dsA.getId(), "name==test", null))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().is(403))
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that creating rollout with not exisiting distribution set returns not found")
|
||||
public void createRolloutWithNotExistingDistributionSetReturnsNotFound() throws Exception {
|
||||
@Description("Testing that creating rollout with not existing distribution set returns not found")
|
||||
void createRolloutWithNotExistingDistributionSetReturnsNotFound() throws Exception {
|
||||
mvc.perform(post("/rest/v1/rollouts").content(JsonBuilder.rollout("name", "desc", 10, 1234, "name==test", null))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound()).andReturn();
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that creating rollout with not valid formed target filter query returns bad request")
|
||||
public void createRolloutWithNotWellFormedFilterReturnsBadRequest() throws Exception {
|
||||
void createRolloutWithNotWellFormedFilterReturnsBadRequest() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("name", "desc", 10, dsA.getId(), "name=test", null))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest())
|
||||
mvc.perform(post("/rest/v1/rollouts").content(
|
||||
JsonBuilder.rollout("name", "desc", 10, dsA.getId(), "name=test", null))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("errorCode", equalTo("hawkbit.server.error.rest.param.rsqlParamSyntax")))
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the repository refuses to create rollout without a defined target filter set.")
|
||||
public void missingTargetFilterQueryInRollout() throws Exception {
|
||||
void missingTargetFilterQueryInRollout() throws Exception {
|
||||
|
||||
final String targetFilterQuery = null;
|
||||
|
||||
@@ -127,7 +139,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout can be created")
|
||||
public void createRollout() throws Exception {
|
||||
void createRollout() throws Exception {
|
||||
testdataFactory.createTargets(20, "target", "rollout");
|
||||
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
@@ -136,17 +148,18 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Verifies that rollout cannot be created if too many rollout groups are specified.")
|
||||
public void createRolloutWithTooManyRolloutGroups() throws Exception {
|
||||
void createRolloutWithTooManyRolloutGroups() throws Exception {
|
||||
|
||||
final int maxGroups = quotaManagement.getMaxRolloutGroupsPerRollout();
|
||||
testdataFactory.createTargets(20, "target", "rollout");
|
||||
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout1", "rollout1Desc", maxGroups + 1,
|
||||
mvc.perform(post("/rest/v1/rollouts").content(JsonBuilder.rollout("rollout1", "rollout1Desc", maxGroups + 1,
|
||||
testdataFactory.createDistributionSet("ds").getId(), "id==target*",
|
||||
new RolloutGroupConditionBuilder().withDefaults().build()))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
@@ -154,17 +167,18 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Verifies that rollout cannot be created if the 'max targets per rollout group' quota would be violated for one of the groups.")
|
||||
public void createRolloutFailsIfRolloutGroupQuotaIsViolated() throws Exception {
|
||||
void createRolloutFailsIfRolloutGroupQuotaIsViolated() throws Exception {
|
||||
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerRolloutGroup();
|
||||
testdataFactory.createTargets(maxTargets + 1, "target", "rollout");
|
||||
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout1", "rollout1Desc", 1,
|
||||
testdataFactory.createDistributionSet("ds").getId(), "id==target*",
|
||||
new RolloutGroupConditionBuilder().withDefaults().build()))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
mvc.perform(post("/rest/v1/rollouts").content(
|
||||
JsonBuilder.rollout("rollout1", "rollout1Desc", 1, testdataFactory.createDistributionSet("ds").getId(),
|
||||
"id==target*", new RolloutGroupConditionBuilder().withDefaults().build()))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
@@ -172,7 +186,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout can be created with groups")
|
||||
public void createRolloutWithGroupDefinitions() throws Exception {
|
||||
void createRolloutWithGroupDefinitions() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro");
|
||||
|
||||
final int amountTargets = 10;
|
||||
@@ -199,16 +213,22 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that no rollout with groups that have illegal percentages can be created")
|
||||
public void createRolloutWithTooLowPercentage() throws Exception {
|
||||
void createRolloutWithTooLowPercentage() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro2");
|
||||
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "ro-target", "rollout");
|
||||
|
||||
final List<RolloutGroup> rolloutGroups = Arrays.asList(
|
||||
entityFactory.rolloutGroup().create().name("Group1").description("Group1desc").targetPercentage(0F)
|
||||
.build(),
|
||||
entityFactory.rolloutGroup().create().name("Group2").description("Group2desc").targetPercentage(100F)
|
||||
final List<RolloutGroup> rolloutGroups = Arrays.asList(entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.name("Group1")
|
||||
.description("Group1desc")
|
||||
.targetPercentage(0F)
|
||||
.build(), entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.name("Group2")
|
||||
.description("Group2desc")
|
||||
.targetPercentage(100F)
|
||||
.build());
|
||||
|
||||
final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().withDefaults().build();
|
||||
@@ -224,16 +244,22 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that no rollout with groups that have illegal percentages can be created")
|
||||
public void createRolloutWithTooHighPercentage() throws Exception {
|
||||
void createRolloutWithTooHighPercentage() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro2");
|
||||
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "ro-target", "rollout");
|
||||
|
||||
final List<RolloutGroup> rolloutGroups = Arrays.asList(
|
||||
entityFactory.rolloutGroup().create().name("Group1").description("Group1desc").targetPercentage(1F)
|
||||
.build(),
|
||||
entityFactory.rolloutGroup().create().name("Group2").description("Group2desc").targetPercentage(101F)
|
||||
final List<RolloutGroup> rolloutGroups = Arrays.asList(entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.name("Group1")
|
||||
.description("Group1desc")
|
||||
.targetPercentage(1F)
|
||||
.build(), entityFactory.rolloutGroup()
|
||||
.create()
|
||||
.name("Group2")
|
||||
.description("Group2desc")
|
||||
.targetPercentage(101F)
|
||||
.build());
|
||||
|
||||
final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().withDefaults().build();
|
||||
@@ -249,24 +275,29 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing the empty list is returned if no rollout exists")
|
||||
public void noRolloutReturnsEmptyList() throws Exception {
|
||||
mvc.perform(get("/rest/v1/rollouts").accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(0))).andExpect(jsonPath("$.total", equalTo(0)));
|
||||
void noRolloutReturnsEmptyList() throws Exception {
|
||||
mvc.perform(get("/rest/v1/rollouts").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(0)))
|
||||
.andExpect(jsonPath("$.total", equalTo(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Retrieves single rollout from management API including extra data that is delivered only for single rollout access.")
|
||||
public void retrieveSingleRollout() throws Exception {
|
||||
void retrieveSingleRollout() throws Exception {
|
||||
testdataFactory.createTargets(20, "rollout", "rollout");
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
// create rollout including the created targets with prefix 'rollout'
|
||||
final Rollout rollout = rolloutManagement.create(
|
||||
entityFactory.rollout().create().name("rollout1").set(dsA.getId())
|
||||
.targetFilterQuery("controllerId==rollout*"),
|
||||
4, new RolloutGroupConditionBuilder().withDefaults()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build());
|
||||
final Rollout rollout = rolloutManagement.create(entityFactory.rollout()
|
||||
.create()
|
||||
.name("rollout1")
|
||||
.set(dsA.getId())
|
||||
.targetFilterQuery("controllerId==rollout*"), 4, new RolloutGroupConditionBuilder().withDefaults()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100")
|
||||
.build());
|
||||
|
||||
retrieveAndVerifyRolloutInCreating(dsA, rollout);
|
||||
retrieveAndVerifyRolloutInReady(rollout);
|
||||
@@ -362,7 +393,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout paged list contains rollouts")
|
||||
public void rolloutPagedListContainsAllRollouts() throws Exception {
|
||||
void rolloutPagedListContainsAllRollouts() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
testdataFactory.createTargets(20, "target", "rollout");
|
||||
@@ -403,7 +434,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout paged list is limited by the query param limit")
|
||||
public void rolloutPagedListIsLimitedToQueryParam() throws Exception {
|
||||
void rolloutPagedListIsLimitedToQueryParam() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
testdataFactory.createTargets(20, "target", "rollout");
|
||||
@@ -423,7 +454,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout paged list is limited by the query param limit")
|
||||
public void retrieveRolloutGroupsForSpecificRollout() throws Exception {
|
||||
void retrieveRolloutGroupsForSpecificRollout() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -446,7 +477,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that starting the rollout switches the state to starting and then to running")
|
||||
public void startingRolloutSwitchesIntoRunningState() throws Exception {
|
||||
void startingRolloutSwitchesIntoRunningState() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -479,7 +510,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that pausing the rollout switches the state to paused")
|
||||
public void pausingRolloutSwitchesIntoPausedState() throws Exception {
|
||||
void pausingRolloutSwitchesIntoPausedState() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -509,7 +540,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that resuming the rollout switches the state to running")
|
||||
public void resumingRolloutSwitchesIntoRunningState() throws Exception {
|
||||
void resumingRolloutSwitchesIntoRunningState() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -543,7 +574,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that an already started rollout cannot be started again and returns bad request")
|
||||
public void startingAlreadyStartedRolloutReturnsBadRequest() throws Exception {
|
||||
void startingAlreadyStartedRolloutReturnsBadRequest() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -567,7 +598,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that resuming a rollout which is not started leads to bad request")
|
||||
public void resumingNotStartedRolloutReturnsBadRequest() throws Exception {
|
||||
void resumingNotStartedRolloutReturnsBadRequest() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -584,7 +615,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that starting rollout the first rollout group is in running state")
|
||||
public void startingRolloutFirstRolloutGroupIsInRunningState() throws Exception {
|
||||
void startingRolloutFirstRolloutGroupIsInRunningState() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -612,17 +643,18 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that a single rollout group can be retrieved")
|
||||
public void retrieveSingleRolloutGroup() throws Exception {
|
||||
void retrieveSingleRolloutGroup() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
// create rollout including the created targets with prefix 'rollout'
|
||||
final Rollout rollout = rolloutManagement.create(
|
||||
entityFactory.rollout().create().name("rollout1").set(dsA.getId())
|
||||
.targetFilterQuery("controllerId==rollout*"),
|
||||
4, new RolloutGroupConditionBuilder().withDefaults()
|
||||
final Rollout rollout = rolloutManagement.create(entityFactory.rollout()
|
||||
.create()
|
||||
.name("rollout1")
|
||||
.set(dsA.getId())
|
||||
.targetFilterQuery("controllerId==rollout*"), 4, new RolloutGroupConditionBuilder().withDefaults()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build());
|
||||
|
||||
final RolloutGroup firstGroup = rolloutGroupManagement
|
||||
@@ -711,7 +743,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that the targets of rollout group can be retrieved")
|
||||
public void retrieveTargetsFromRolloutGroup() throws Exception {
|
||||
void retrieveTargetsFromRolloutGroup() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -720,8 +752,8 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
// create rollout including the created targets with prefix 'rollout'
|
||||
final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*");
|
||||
|
||||
final RolloutGroup firstGroup = rolloutGroupManagement
|
||||
.findByRollout(PageRequest.of(0, 1, Direction.ASC, "id"), rollout.getId()).getContent().get(0);
|
||||
final RolloutGroup firstGroup = rolloutGroupManagement.findByRollout(PageRequest.of(0, 1, Direction.ASC, "id"),
|
||||
rollout.getId()).getContent().get(0);
|
||||
|
||||
// retrieve targets from the first rollout group with known ID
|
||||
mvc.perform(
|
||||
@@ -734,7 +766,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that the targets of rollout group can be retrieved with rsql query param")
|
||||
public void retrieveTargetsFromRolloutGroupWithQuery() throws Exception {
|
||||
void retrieveTargetsFromRolloutGroupWithQuery() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -743,8 +775,8 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
// create rollout including the created targets with prefix 'rollout'
|
||||
final Rollout rollout = createRollout("rollout1", 2, dsA.getId(), "controllerId==rollout*");
|
||||
|
||||
final RolloutGroup firstGroup = rolloutGroupManagement
|
||||
.findByRollout(PageRequest.of(0, 1, Direction.ASC, "id"), rollout.getId()).getContent().get(0);
|
||||
final RolloutGroup firstGroup = rolloutGroupManagement.findByRollout(PageRequest.of(0, 1, Direction.ASC, "id"),
|
||||
rollout.getId()).getContent().get(0);
|
||||
|
||||
final String targetInGroup = rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, firstGroup.getId())
|
||||
.getContent().get(0).getControllerId();
|
||||
@@ -760,7 +792,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that the targets of rollout group can be retrieved after the rollout has been started")
|
||||
public void retrieveTargetsFromRolloutGroupAfterRolloutIsStarted() throws Exception {
|
||||
void retrieveTargetsFromRolloutGroupAfterRolloutIsStarted() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -788,7 +820,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Start the rollout in async mode")
|
||||
public void startingRolloutSwitchesIntoRunningStateAsync() throws Exception {
|
||||
void startingRolloutSwitchesIntoRunningStateAsync() throws Exception {
|
||||
|
||||
final int amountTargets = 1000;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -798,19 +830,31 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*");
|
||||
|
||||
// starting rollout
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
// check if running
|
||||
assertThat(doWithTimeout(() -> getRollout(rollout.getId()), this::success, 60_000, 100)).isNotNull();
|
||||
awaitRunningState(rollout.getId());
|
||||
}
|
||||
|
||||
private void awaitRunningState(final Long rolloutId) {
|
||||
Awaitility.await()
|
||||
.atMost(Duration.ONE_MINUTE)
|
||||
.pollInterval(Duration.ONE_HUNDRED_MILLISECONDS)
|
||||
.with()
|
||||
.until(() -> WithSpringAuthorityRule.runAsPrivileged(
|
||||
() -> rolloutManagement.get(rolloutId).orElseThrow(NoSuchElementException::new))
|
||||
.getStatus()
|
||||
.equals(RolloutStatus.RUNNING));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Deletion of a rollout")
|
||||
public void deleteRollout() throws Exception {
|
||||
void deleteRollout() throws Exception {
|
||||
final int amountTargets = 10;
|
||||
testdataFactory.createTargets(amountTargets, "rolloutDelete", "rolloutDelete");
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
@@ -818,26 +862,34 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
// create rollout including the created targets with prefix 'rollout'
|
||||
final Rollout rollout = createRollout("rolloutDelete", 4, dsA.getId(), "controllerId==rolloutDelete*");
|
||||
|
||||
// delete rollout
|
||||
mvc.perform(delete("/rest/v1/rollouts/{rolloutid}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(delete("/rest/v1/rollouts/{rolloutid}", rollout.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(getRollout(rollout.getId()).getStatus()).isEqualTo(RolloutStatus.DELETING);
|
||||
assertStatusIs(rollout, RolloutStatus.DELETING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Soft deletion of a rollout: soft deletion appears when already running rollout is being deleted")
|
||||
public void deleteRunningRollout() throws Exception {
|
||||
void deleteRunningRollout() throws Exception {
|
||||
final Rollout rollout = testdataFactory.createSoftDeletedRollout("softDeletedRollout");
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutid}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.deleted", equalTo(true)));
|
||||
assertThat(getRollout(rollout.getId()).getStatus()).isEqualTo(RolloutStatus.DELETED);
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutid}", rollout.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.deleted", equalTo(true)));
|
||||
|
||||
assertStatusIs(rollout, RolloutStatus.DELETED);
|
||||
}
|
||||
|
||||
private void assertStatusIs(final Rollout rollout, RolloutStatus expected) {
|
||||
final Optional<Rollout> updatedRollout = rolloutManagement.get(rollout.getId());
|
||||
assertThat(updatedRollout).get().extracting(Rollout::getStatus).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout paged list with rsql parameter")
|
||||
public void getRolloutWithRSQLParam() throws Exception {
|
||||
void getRolloutWithRSQLParam() throws Exception {
|
||||
|
||||
final int amountTargetsRollout1 = 25;
|
||||
final int amountTargetsRollout2 = 25;
|
||||
@@ -875,7 +927,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that rolloutgroup paged list with rsql parameter")
|
||||
public void retrieveRolloutGroupsForSpecificRolloutWithRSQLParam() throws Exception {
|
||||
void retrieveRolloutGroupsForSpecificRolloutWithRSQLParam() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
testdataFactory.createTargets(amountTargets, "rollout", "rollout");
|
||||
@@ -909,7 +961,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a DOWNLOAD_ONLY rollout is possible")
|
||||
public void createDownloadOnlyRollout() throws Exception {
|
||||
void createDownloadOnlyRollout() throws Exception {
|
||||
testdataFactory.createTargets(20, "target", "rollout");
|
||||
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
@@ -917,8 +969,8 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("A rollout create request containing a weight is only accepted when weight is valide and multi assignment is on.")
|
||||
public void weightValidation() throws Exception {
|
||||
@Description("A rollout create request containing a weight is only accepted when weight is valid and multi assignment is on.")
|
||||
void weightValidation() throws Exception {
|
||||
testdataFactory.createTargets(4, "rollout", "description");
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
final int weight = 66;
|
||||
@@ -946,43 +998,6 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
assertThat(rollouts.get(0).getWeight()).get().isEqualTo(weight);
|
||||
}
|
||||
|
||||
protected <T> T doWithTimeout(final Callable<T> callable, final SuccessCondition<T> successCondition,
|
||||
final long timeout, final long pollInterval) throws Exception // NOPMD
|
||||
{
|
||||
|
||||
if (pollInterval < 0) {
|
||||
throw new IllegalArgumentException("pollInterval must non negative");
|
||||
}
|
||||
|
||||
long duration = 0;
|
||||
Exception exception = null;
|
||||
T returnValue = null;
|
||||
while (untilTimeoutReached(timeout, duration)) {
|
||||
try {
|
||||
returnValue = callable.call();
|
||||
// clear exception
|
||||
exception = null;
|
||||
} catch (final Exception ex) {
|
||||
exception = ex;
|
||||
}
|
||||
Thread.sleep(pollInterval);
|
||||
duration += pollInterval > 0 ? pollInterval : 1;
|
||||
if (exception == null && successCondition.success(returnValue)) {
|
||||
return returnValue;
|
||||
} else {
|
||||
returnValue = null;
|
||||
}
|
||||
}
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
protected boolean untilTimeoutReached(final long timeout, final long duration) {
|
||||
return duration <= timeout || timeout < 0;
|
||||
}
|
||||
|
||||
private void postRollout(final String name, final int groupSize, final Long distributionSetId,
|
||||
final String targetFilterQuery, final int targets, final Action.ActionType type) throws Exception {
|
||||
final String actionType = MgmtRestModelMapper.convertActionType(type).getName();
|
||||
@@ -1026,15 +1041,6 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
// Run here, because Scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
return rolloutManagement.get(rollout.getId()).get();
|
||||
return rolloutManagement.get(rollout.getId()).orElseThrow(NoSuchElementException::new);
|
||||
}
|
||||
|
||||
protected boolean success(final Rollout result) {
|
||||
return result != null && result.getStatus() == RolloutStatus.RUNNING;
|
||||
}
|
||||
|
||||
public Rollout getRollout(final Long rolloutId) throws Exception {
|
||||
return rolloutManagement.get(rolloutId).get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,9 +31,12 @@ import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
@@ -72,23 +75,22 @@ import io.qameta.allure.Story;
|
||||
|
||||
/**
|
||||
* Tests for {@link MgmtSoftwareModuleResource} {@link RestController}.
|
||||
*
|
||||
*/
|
||||
@Feature("Component Tests - Management API")
|
||||
@Story("Software Module Resource")
|
||||
@TestPropertySource(properties = { "hawkbit.server.security.dos.maxArtifactSize=100000",
|
||||
"hawkbit.server.security.dos.maxArtifactStorage=500000" })
|
||||
public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
|
||||
@BeforeEach
|
||||
public void assertPreparationOfRepo() {
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("no softwaremodule should be founded").hasSize(0);
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("no softwaremodule should be founded").isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the update of software module metadata. It is verfied that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at).")
|
||||
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
|
||||
public void updateSoftwareModuleOnlyDescriptionAndVendorNameUntouched() throws Exception {
|
||||
void updateSoftwareModuleOnlyDescriptionAndVendorNameUntouched() throws Exception {
|
||||
final String knownSWName = "name1";
|
||||
final String knownSWVersion = "version1";
|
||||
final String knownSWDescription = "description1";
|
||||
@@ -97,101 +99,122 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
final String updateVendor = "newVendor1";
|
||||
final String updateDescription = "newDescription1";
|
||||
|
||||
SoftwareModule sm = softwareModuleManagement.create(entityFactory.softwareModule().create().type(osType)
|
||||
.name(knownSWName).version(knownSWVersion).description(knownSWDescription).vendor(knownSWVendor));
|
||||
final SoftwareModule sm = softwareModuleManagement.create(entityFactory.softwareModule()
|
||||
.create()
|
||||
.type(osType)
|
||||
.name(knownSWName)
|
||||
.version(knownSWVersion)
|
||||
.description(knownSWDescription)
|
||||
.vendor(knownSWVendor));
|
||||
|
||||
assertThat(sm.getName()).as("Wrong name of the software module").isEqualTo(knownSWName);
|
||||
|
||||
final String body = new JSONObject().put("vendor", updateVendor).put("description", updateDescription)
|
||||
.put("name", "nameShouldNotBeChanged").toString();
|
||||
final String body = new JSONObject().put("vendor", updateVendor)
|
||||
.put("description", updateDescription)
|
||||
.put("name", "nameShouldNotBeChanged")
|
||||
.toString();
|
||||
|
||||
// ensures that we are not to fast so that last modified is not set
|
||||
// correctly
|
||||
Thread.sleep(1);
|
||||
// ensures that we are not to fast so that last modified is not set correctly
|
||||
Awaitility.await()
|
||||
.atMost(Duration.ONE_HUNDRED_MILLISECONDS)
|
||||
.pollInterval(10L, TimeUnit.MILLISECONDS)
|
||||
.until(() -> sm.getLastModifiedAt() > 0L && sm.getLastModifiedBy() != null);
|
||||
|
||||
mvc.perform(put("/rest/v1/softwaremodules/{smId}", sm.getId()).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id", equalTo(sm.getId().intValue())))
|
||||
.andExpect(jsonPath("$.vendor", equalTo(updateVendor)))
|
||||
.andExpect(jsonPath("$.lastModifiedBy", equalTo("smUpdateTester")))
|
||||
.andExpect(jsonPath("$.lastModifiedAt", not(equalTo(sm.getLastModifiedAt()))))
|
||||
.andExpect(jsonPath("$.description", equalTo(updateDescription)))
|
||||
.andExpect(jsonPath("$.name", equalTo(knownSWName))).andReturn();
|
||||
.andExpect(jsonPath("$.name", equalTo(knownSWName)))
|
||||
.andReturn();
|
||||
|
||||
sm = softwareModuleManagement.get(sm.getId()).get();
|
||||
assertThat(sm.getName()).isEqualTo(knownSWName);
|
||||
assertThat(sm.getVendor()).isEqualTo(updateVendor);
|
||||
assertThat(sm.getLastModifiedBy()).isEqualTo("smUpdateTester");
|
||||
assertThat(sm.getDescription()).isEqualTo(updateDescription);
|
||||
final SoftwareModule updatedSm = softwareModuleManagement.get(sm.getId()).get();
|
||||
assertThat(updatedSm.getName()).isEqualTo(knownSWName);
|
||||
assertThat(updatedSm.getVendor()).isEqualTo(updateVendor);
|
||||
assertThat(updatedSm.getLastModifiedBy()).isEqualTo("smUpdateTester");
|
||||
assertThat(updatedSm.getDescription()).isEqualTo(updateDescription);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the update of the deletion flag. It is verfied that the software module can't be marked as deleted through update operation.")
|
||||
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
|
||||
public void updateSoftwareModuleDeletedFlag() throws Exception {
|
||||
void updateSoftwareModuleDeletedFlag() throws Exception {
|
||||
final String knownSWName = "name1";
|
||||
final String knownSWVersion = "version1";
|
||||
|
||||
SoftwareModule sm = softwareModuleManagement
|
||||
.create(entityFactory.softwareModule().create().type(osType).name(knownSWName).version(knownSWVersion));
|
||||
final SoftwareModule sm = softwareModuleManagement.create(
|
||||
entityFactory.softwareModule().create().type(osType).name(knownSWName).version(knownSWVersion));
|
||||
|
||||
assertThat(sm.isDeleted()).as("Created software module should not be deleted").isEqualTo(false);
|
||||
assertThat(sm.isDeleted()).as("Created software module should not be deleted").isFalse();
|
||||
|
||||
final String body = new JSONObject().put("deleted", true).toString();
|
||||
|
||||
// ensures that we are not to fast so that last modified is not set
|
||||
// correctly
|
||||
Thread.sleep(1);
|
||||
// ensures that we are not to fast so that last modified is not set correctly
|
||||
Awaitility.await()
|
||||
.atMost(Duration.ONE_HUNDRED_MILLISECONDS)
|
||||
.pollInterval(10L, TimeUnit.MILLISECONDS)
|
||||
.until(() -> sm.getLastModifiedAt() > 0L && sm.getLastModifiedBy() != null);
|
||||
|
||||
mvc.perform(put("/rest/v1/softwaremodules/{smId}", sm.getId()).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id", equalTo(sm.getId().intValue())))
|
||||
.andExpect(jsonPath("$.lastModifiedBy", equalTo("smUpdateTester")))
|
||||
.andExpect(jsonPath("$.lastModifiedAt", equalTo(sm.getLastModifiedAt())))
|
||||
.andExpect(jsonPath("$.deleted", equalTo(false)));
|
||||
|
||||
sm = softwareModuleManagement.get(sm.getId()).get();
|
||||
final SoftwareModule updatedSm = softwareModuleManagement.get(sm.getId()).get();
|
||||
assertThat(sm.getLastModifiedBy()).isEqualTo("smUpdateTester");
|
||||
assertThat(sm.getLastModifiedAt()).isEqualTo(sm.getLastModifiedAt());
|
||||
assertThat(sm.isDeleted()).isEqualTo(false);
|
||||
assertThat(sm.isDeleted()).isFalse();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the upload of an artifact binary. The upload is executed and the content checked in the repository for completeness.")
|
||||
public void uploadArtifact() throws Exception {
|
||||
void uploadArtifact() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
// create test file
|
||||
final byte random[] = randomBytes(5 * 1024);
|
||||
final byte[] random = randomBytes(5 * 1024);
|
||||
final String md5sum = HashGeneratorUtils.generateMD5(random);
|
||||
final String sha1sum = HashGeneratorUtils.generateSHA1(random);
|
||||
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random);
|
||||
|
||||
// upload
|
||||
final MvcResult mvcResult = mvc
|
||||
.perform(multipart("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
final MvcResult mvcResult = mvc.perform(
|
||||
multipart("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
|
||||
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
|
||||
.andExpect(jsonPath("$.hashes.sha256", equalTo(sha256sum)))
|
||||
.andExpect(jsonPath("$.size", equalTo(random.length)))
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("origFilename"))).andReturn();
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("origFilename")))
|
||||
.andReturn();
|
||||
|
||||
// check rest of response compared to DB
|
||||
final MgmtArtifact artResult = ResourceUtility
|
||||
.convertArtifactResponse(mvcResult.getResponse().getContentAsString());
|
||||
final MgmtArtifact artResult = ResourceUtility.convertArtifactResponse(
|
||||
mvcResult.getResponse().getContentAsString());
|
||||
final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getId();
|
||||
assertThat(artResult.getArtifactId()).as("Wrong artifact id").isEqualTo(artId);
|
||||
assertThat(JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
.as("Link contains no self url")
|
||||
assertThat(JsonPath.compile("$._links.self.href")
|
||||
.read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).as("Link contains no self url")
|
||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId);
|
||||
assertThat(JsonPath.compile("$._links.download.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).as("response contains no download url ").isEqualTo(
|
||||
assertThat(JsonPath.compile("$._links.download.href")
|
||||
.read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).as("response contains no download url ")
|
||||
.isEqualTo(
|
||||
"http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId + "/download");
|
||||
|
||||
assertArtifact(sm, random);
|
||||
@@ -199,7 +222,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies that artifacts which exceed the configured maximum size cannot be uploaded.")
|
||||
public void uploadArtifactFailsIfTooLarge() throws Exception {
|
||||
void uploadArtifactFailsIfTooLarge() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModule("quota", "quota", false);
|
||||
final long maxSize = quotaManagement.getMaxArtifactSize();
|
||||
|
||||
@@ -218,7 +241,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies that artifact with invalid filename cannot be uploaded to prevent cross site scripting.")
|
||||
public void uploadArtifactFailsIfFilenameInvalide() throws Exception {
|
||||
void uploadArtifactFailsIfFilenameInvalide() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModule("quota", "quota", false);
|
||||
final String illegalFilename = "<img src=ernw onerror=alert(1)>.xml";
|
||||
|
||||
@@ -226,7 +249,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
final MockMultipartFile file = new MockMultipartFile("file", illegalFilename, null, randomBytes);
|
||||
|
||||
mvc.perform(multipart("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.message", containsString("Invalid characters in string")));
|
||||
}
|
||||
@@ -261,26 +285,27 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system does not accept empty artifact uploads. Expected response: BAD REQUEST")
|
||||
public void emptyUploadArtifact() throws Exception {
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
|
||||
assertThat(artifactManagement.count()).isEqualTo(0);
|
||||
@Description("Verifies that the system does not accept empty artifact uploads. Expected response: BAD REQUEST")
|
||||
void emptyUploadArtifact() throws Exception {
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).isEmpty();
|
||||
assertThat(artifactManagement.count()).isZero();
|
||||
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "orig", null, new byte[0]);
|
||||
|
||||
mvc.perform(multipart("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system does not accept identical artifacts uploads for the same software module. Expected response: CONFLICT")
|
||||
public void duplicateUploadArtifact() throws Exception {
|
||||
@Description("Verifies that the system does not accept identical artifacts uploads for the same software module. Expected response: CONFLICT")
|
||||
void duplicateUploadArtifact() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final byte random[] = randomBytes(5 * 1024);
|
||||
final byte[] random = randomBytes(5 * 1024);
|
||||
final String md5sum = HashGeneratorUtils.generateMD5(random);
|
||||
final String sha1sum = HashGeneratorUtils.generateSHA1(random);
|
||||
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
|
||||
@@ -299,20 +324,23 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("verfies that option to upload artifacts with a custom defined by metadata, i.e. not the file name of the binary itself.")
|
||||
public void uploadArtifactWithCustomName() throws Exception {
|
||||
@Description("verifies that option to upload artifacts with a custom defined by metadata, i.e. not the file name of the binary itself.")
|
||||
void uploadArtifactWithCustomName() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
assertThat(artifactManagement.count()).isEqualTo(0);
|
||||
assertThat(artifactManagement.count()).isZero();
|
||||
|
||||
// create test file
|
||||
final byte random[] = randomBytes(5 * 1024);
|
||||
final byte[] random = randomBytes(5 * 1024);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random);
|
||||
|
||||
// upload
|
||||
mvc.perform(multipart("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file).param("filename",
|
||||
"customFilename")).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
mvc.perform(multipart("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.param("filename", "customFilename"))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("customFilename"))).andExpect(status().isCreated());
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("customFilename")))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
// check result in db...
|
||||
// repo
|
||||
@@ -323,13 +351,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system refuses upload of an artifact where the provided hash sums do not match. Expected result: BAD REQUEST")
|
||||
public void uploadArtifactWithHashCheck() throws Exception {
|
||||
@Description("Verifies that the system refuses upload of an artifact where the provided hash sums do not match. Expected result: BAD REQUEST")
|
||||
void uploadArtifactWithHashCheck() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
assertThat(artifactManagement.count()).isEqualTo(0);
|
||||
assertThat(artifactManagement.count()).isZero();
|
||||
|
||||
// create test file
|
||||
final byte random[] = randomBytes(5 * 1024);
|
||||
final byte[] random = randomBytes(5 * 1024);
|
||||
final String md5sum = HashGeneratorUtils.generateMD5(random);
|
||||
final String sha1sum = HashGeneratorUtils.generateSHA1(random);
|
||||
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
|
||||
@@ -379,13 +407,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies that only a limited number of artifacts can be uploaded for one software module.")
|
||||
public void uploadArtifactsUntilQuotaExceeded() throws Exception {
|
||||
void uploadArtifactsUntilQuotaExceeded() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
final long maxArtifacts = quotaManagement.getMaxArtifactsPerSoftwareModule();
|
||||
|
||||
for (int i = 0; i < maxArtifacts; ++i) {
|
||||
// create test file
|
||||
final byte random[] = randomBytes(5 * 1024);
|
||||
final byte[] random = randomBytes(5 * 1024);
|
||||
final String md5sum = HashGeneratorUtils.generateMD5(random);
|
||||
final String sha1sum = HashGeneratorUtils.generateSHA1(random);
|
||||
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
|
||||
@@ -403,7 +431,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
// upload one more file to cause the quota to be exceeded
|
||||
final byte random[] = randomBytes(5 * 1024);
|
||||
final byte[] random = randomBytes(5 * 1024);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random);
|
||||
|
||||
// upload
|
||||
@@ -417,7 +445,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies that artifacts can only be added as long as the artifact storage quota is not exceeded.")
|
||||
public void uploadArtifactsUntilStorageQuotaExceeded() throws Exception {
|
||||
void uploadArtifactsUntilStorageQuotaExceeded() throws Exception {
|
||||
|
||||
final long storageLimit = quotaManagement.getMaxArtifactStorage();
|
||||
|
||||
@@ -427,7 +455,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
for (int i = 0; i < numArtifacts; ++i) {
|
||||
// create test file
|
||||
final byte random[] = randomBytes(artifactSize);
|
||||
final byte[] random = randomBytes(artifactSize);
|
||||
final String md5sum = HashGeneratorUtils.generateMD5(random);
|
||||
final String sha1sum = HashGeneratorUtils.generateSHA1(random);
|
||||
final String sha256sum = HashGeneratorUtils.generateSHA256(random);
|
||||
@@ -446,7 +474,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
// upload one more file to cause the quota to be exceeded
|
||||
final byte random[] = randomBytes(artifactSize);
|
||||
final byte[] random = randomBytes(artifactSize);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random);
|
||||
|
||||
// upload
|
||||
@@ -461,16 +489,16 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Tests binary download of an artifact including verfication that the downloaded binary is consistent and that the etag header is as expected identical to the SHA1 hash of the file.")
|
||||
public void downloadArtifact() throws Exception {
|
||||
void downloadArtifact() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = randomBytes(artifactSize);
|
||||
final byte[] random = randomBytes(artifactSize);
|
||||
|
||||
final Artifact artifact = artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
final Artifact artifact2 = artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize));
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
final Artifact artifact2 = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize));
|
||||
|
||||
downloadAndVerify(sm, random, artifact);
|
||||
downloadAndVerify(sm, random, artifact2);
|
||||
@@ -492,19 +520,21 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies the listing of one defined artifact assigned to a given software module. That includes the artifact metadata and download links.")
|
||||
public void getArtifact() throws Exception {
|
||||
void getArtifact() throws Exception {
|
||||
// prepare data for test
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = randomBytes(artifactSize);
|
||||
|
||||
final Artifact artifact = artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
|
||||
// perform test
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()).accept(
|
||||
MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(artifact.getId().intValue())))
|
||||
.andExpect(jsonPath("$.size", equalTo(random.length)))
|
||||
@@ -521,16 +551,18 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies the listing of an artifact that belongs to a soft deleted software module.")
|
||||
public void getArtifactSoftDeleted() throws Exception {
|
||||
void getArtifactSoftDeleted() throws Exception {
|
||||
// prepare data for test
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs("softDeleted");
|
||||
final Artifact artifact = testdataFactory.createArtifacts(sm.getId()).get(0);
|
||||
testdataFactory.createDistributionSet(Arrays.asList(sm));
|
||||
testdataFactory.createDistributionSet(Collections.singletonList(sm));
|
||||
softwareModuleManagement.delete(sm.getId());
|
||||
|
||||
// perform test
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()).accept(
|
||||
MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(artifact.getId().intValue())))
|
||||
.andExpect(jsonPath("$.size", equalTo((int) artifact.getSize())))
|
||||
@@ -546,19 +578,20 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Verifies the listing of all artifacts assigned to a software module. That includes the artifact metadata and download links.")
|
||||
public void getArtifacts() throws Exception {
|
||||
void getArtifacts() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = randomBytes(artifactSize);
|
||||
final byte[] random = randomBytes(artifactSize);
|
||||
|
||||
final Artifact artifact = artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
final Artifact artifact2 = artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize));
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
final Artifact artifact2 = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize));
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.[0].id", equalTo(artifact.getId().intValue())))
|
||||
.andExpect(jsonPath("$.[0].size", equalTo(random.length)))
|
||||
@@ -579,11 +612,11 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system refuses unsupported request types and answers as defined to them, e.g. NOT FOUND on a non existing resource. Or a HTTP POST for updating a resource results in METHOD NOT ALLOWED etc.")
|
||||
public void invalidRequestsOnArtifactResource() throws Exception {
|
||||
@Description("Verifies that the system refuses unsupported request types and answers as defined to them, e.g. NOT FOUND on a non existing resource. Or a HTTP POST for updating a resource results in METHOD NOT ALLOWED etc.")
|
||||
void invalidRequestsOnArtifactResource() throws Exception {
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = randomBytes(artifactSize);
|
||||
final byte[] random = randomBytes(artifactSize);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random);
|
||||
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
@@ -626,22 +659,25 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system refuses unsupported request types and answers as defined to them, e.g. NOT FOUND on a non existing resource. Or a HTTP POST for updating a resource results in METHOD NOT ALLOWED etc.")
|
||||
public void invalidRequestsOnSoftwaremodulesResource() throws Exception {
|
||||
@Description("Verifies that the system refuses unsupported request types and answers as defined to them, e.g. NOT FOUND on a non existing resource. Or a HTTP POST for updating a resource results in METHOD NOT ALLOWED etc.")
|
||||
void invalidRequestsOnSoftwaremodulesResource() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final List<SoftwareModule> modules = Arrays.asList(sm);
|
||||
|
||||
// SM does not exist
|
||||
mvc.perform(get("/rest/v1/softwaremodules/12345678")).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(get("/rest/v1/softwaremodules/12345678"))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/12345678")).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/12345678"))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// bad request - no content
|
||||
mvc.perform(post("/rest/v1/softwaremodules").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// bad request - bad content
|
||||
mvc.perform(post("/rest/v1/softwaremodules").content("sdfjsdlkjfskdjf".getBytes())
|
||||
@@ -683,10 +719,11 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Test of modules retrieval without any parameters. Will return all modules in the system as defined by standard page size.")
|
||||
public void getSoftwareModulesWithoutAddtionalRequestParameters() throws Exception {
|
||||
void getSoftwareModulesWithoutAddtionalRequestParameters() throws Exception {
|
||||
final int modules = 5;
|
||||
createSoftwareModulesAlphabetical(modules);
|
||||
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(modules)))
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(modules)))
|
||||
@@ -695,13 +732,14 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Test of modules retrieval with paging limit parameter. Will return all modules in the system as defined by given page size.")
|
||||
public void detSoftwareModulesWithPagingLimitRequestParameter() throws Exception {
|
||||
void detSoftwareModulesWithPagingLimitRequestParameter() throws Exception {
|
||||
final int modules = 5;
|
||||
final int limitSize = 1;
|
||||
createSoftwareModulesAlphabetical(modules);
|
||||
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING).param(
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(modules)))
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)));
|
||||
@@ -709,15 +747,16 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Test of modules retrieval with paging limit offset parameters. Will return all modules in the system as defined by given page size starting from given offset.")
|
||||
public void getSoftwareModulesWithPagingLimitAndOffsetRequestParameter() throws Exception {
|
||||
void getSoftwareModulesWithPagingLimitAndOffsetRequestParameter() throws Exception {
|
||||
final int modules = 5;
|
||||
final int offsetParam = 2;
|
||||
final int expectedSize = modules - offsetParam;
|
||||
createSoftwareModulesAlphabetical(modules);
|
||||
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(offsetParam))
|
||||
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING).param(
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(offsetParam))
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(modules)))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(modules)))
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(expectedSize)))
|
||||
.andExpect(jsonPath(MgmtTargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(expectedSize)));
|
||||
@@ -726,12 +765,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Test retrieval of all software modules the user has access to.")
|
||||
public void getSoftwareModules() throws Exception {
|
||||
void getSoftwareModules() throws Exception {
|
||||
final SoftwareModule os = testdataFactory.createSoftwareModuleOs();
|
||||
final SoftwareModule app = testdataFactory.createSoftwareModuleApp();
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].name", contains(os.getName())))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].version", contains(os.getVersion())))
|
||||
@@ -759,7 +799,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Test the various filter parameters, e.g. filter by name or type of the module.")
|
||||
public void getSoftwareModulesWithFilterParameters() throws Exception {
|
||||
void getSoftwareModulesWithFilterParameters() throws Exception {
|
||||
final SoftwareModule os1 = testdataFactory.createSoftwareModuleOs("1");
|
||||
final SoftwareModule app1 = testdataFactory.createSoftwareModuleApp("1");
|
||||
testdataFactory.createSoftwareModuleOs("2");
|
||||
@@ -769,7 +809,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
// only by name, only one exists per name
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=name==" + os1.getName()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].name", contains(os1.getName())))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].version", contains(os1.getVersion())))
|
||||
@@ -816,29 +857,32 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system answers as defined in case of a wrong filter parameter syntax. Expected result: BAD REQUEST with error description.")
|
||||
public void getSoftwareModulesWithSyntaxErrorFilterParameter() throws Exception {
|
||||
@Description("Verifies that the system answers as defined in case of a wrong filter parameter syntax. Expected result: BAD REQUEST with error description.")
|
||||
void getSoftwareModulesWithSyntaxErrorFilterParameter() throws Exception {
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=wrongFIQLSyntax").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.errorCode", equalTo("hawkbit.server.error.rest.param.rsqlParamSyntax")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the system answers as defined in case of a non existing field used in filter. Expected result: BAD REQUEST with error description.")
|
||||
public void getSoftwareModulesWithUnknownFieldErrorFilterParameter() throws Exception {
|
||||
@Description("Verifies that the system answers as defined in case of a non existing field used in filter. Expected result: BAD REQUEST with error description.")
|
||||
void getSoftwareModulesWithUnknownFieldErrorFilterParameter() throws Exception {
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=wrongField==abc").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.errorCode", equalTo("hawkbit.server.error.rest.param.rsqlInvalidField")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Tests GET request on /rest/v1/softwaremodules/{smId}.")
|
||||
public void getSoftwareModule() throws Exception {
|
||||
void getSoftwareModule() throws Exception {
|
||||
final SoftwareModule os = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}", os.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.name", equalTo(os.getName())))
|
||||
.andExpect(jsonPath("$.version", equalTo(os.getVersion())))
|
||||
@@ -861,26 +905,41 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Verfies that the create request actually results in the creation of the modules in the repository.")
|
||||
public void createSoftwareModules() throws Exception {
|
||||
final SoftwareModule os = entityFactory.softwareModule().create().name("name1").type(osType).version("version1")
|
||||
.vendor("vendor1").description("description1").build();
|
||||
final SoftwareModule ah = entityFactory.softwareModule().create().name("name3").type(appType)
|
||||
.version("version3").vendor("vendor3").description("description3").build();
|
||||
@Description("Verifies that the create request actually results in the creation of the modules in the repository.")
|
||||
void createSoftwareModules() throws Exception {
|
||||
final SoftwareModule os = entityFactory.softwareModule()
|
||||
.create()
|
||||
.name("name1")
|
||||
.type(osType)
|
||||
.version("version1")
|
||||
.vendor("vendor1")
|
||||
.description("description1")
|
||||
.build();
|
||||
final SoftwareModule ah = entityFactory.softwareModule()
|
||||
.create()
|
||||
.name("name3")
|
||||
.type(appType)
|
||||
.version("version3")
|
||||
.vendor("vendor3")
|
||||
.description("description3")
|
||||
.build();
|
||||
|
||||
final List<SoftwareModule> modules = Arrays.asList(os, ah);
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
|
||||
final MvcResult mvcResult = mvc
|
||||
.perform(post("/rest/v1/softwaremodules/").accept(MediaType.APPLICATION_JSON_VALUE)
|
||||
.content(JsonBuilder.softwareModules(modules)).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
final MvcResult mvcResult = mvc.perform(
|
||||
post("/rest/v1/softwaremodules/").accept(MediaType.APPLICATION_JSON_VALUE)
|
||||
.content(JsonBuilder.softwareModules(modules))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo("name1")))
|
||||
.andExpect(jsonPath("[0].version", equalTo("version1")))
|
||||
.andExpect(jsonPath("[0].description", equalTo("description1")))
|
||||
.andExpect(jsonPath("[0].vendor", equalTo("vendor1"))).andExpect(jsonPath("[0].type", equalTo("os")))
|
||||
.andExpect(jsonPath("[0].vendor", equalTo("vendor1")))
|
||||
.andExpect(jsonPath("[0].type", equalTo("os")))
|
||||
.andExpect(jsonPath("[0].createdBy", equalTo("uploadTester")))
|
||||
.andExpect(jsonPath("[1].name", equalTo("name3")))
|
||||
.andExpect(jsonPath("[1].version", equalTo("version3")))
|
||||
@@ -888,60 +947,62 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
.andExpect(jsonPath("[1].vendor", equalTo("vendor3")))
|
||||
.andExpect(jsonPath("[1].type", equalTo("application")))
|
||||
.andExpect(jsonPath("[1].createdBy", equalTo("uploadTester")))
|
||||
.andExpect(jsonPath("[1].createdAt", not(equalTo(0)))).andReturn();
|
||||
.andExpect(jsonPath("[1].createdAt", not(equalTo(0))))
|
||||
.andReturn();
|
||||
|
||||
final SoftwareModule osCreated = softwareModuleManagement
|
||||
.getByNameAndVersionAndType("name1", "version1", osType.getId()).get();
|
||||
final SoftwareModule appCreated = softwareModuleManagement
|
||||
.getByNameAndVersionAndType("name3", "version3", appType.getId()).get();
|
||||
final SoftwareModule osCreated = softwareModuleManagement.getByNameAndVersionAndType("name1", "version1",
|
||||
osType.getId()).get();
|
||||
final SoftwareModule appCreated = softwareModuleManagement.getByNameAndVersionAndType("name3", "version3",
|
||||
appType.getId()).get();
|
||||
|
||||
assertThat(
|
||||
JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
.as("Response contains invalid self href")
|
||||
assertThat(JsonPath.compile("[0]._links.self.href")
|
||||
.read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).as("Response contains invalid self href")
|
||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + osCreated.getId());
|
||||
|
||||
assertThat(
|
||||
JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
.as("Response contains links self href")
|
||||
assertThat(JsonPath.compile("[1]._links.self.href")
|
||||
.read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).as("Response contains links self href")
|
||||
.isEqualTo("http://localhost/rest/v1/softwaremodules/" + appCreated.getId());
|
||||
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("Wrong softwaremodule size").hasSize(2);
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getName())
|
||||
.as("Softwaremoudle name is wrong").isEqualTo(os.getName());
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedBy())
|
||||
.as("Softwaremoudle created by is wrong").isEqualTo("uploadTester");
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedAt())
|
||||
.as("Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current);
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, appType.getId()).getContent().get(0).getName())
|
||||
.as("Softwaremoudle name is wrong").isEqualTo(ah.getName());
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getName()).as(
|
||||
"Softwaremoudle name is wrong").isEqualTo(os.getName());
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedBy()).as(
|
||||
"Softwaremoudle created by is wrong").isEqualTo("uploadTester");
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedAt()).as(
|
||||
"Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current);
|
||||
assertThat(softwareModuleManagement.findByType(PAGE, appType.getId()).getContent().get(0).getName()).as(
|
||||
"Softwaremoudle name is wrong").isEqualTo(ah.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies successfull deletion of software modules that are not in use, i.e. assigned to a DS.")
|
||||
public void deleteUnassignedSoftwareModule() throws Exception {
|
||||
void deleteUnassignedSoftwareModule() throws Exception {
|
||||
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("Softwaremoudle size is wrong").hasSize(1);
|
||||
assertThat(artifactManagement.count()).isEqualTo(1);
|
||||
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId())).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("After delete no softwarmodule should be available")
|
||||
.isEmpty();
|
||||
assertThat(artifactManagement.count()).isEqualTo(0);
|
||||
assertThat(artifactManagement.count()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies successfull deletion of a software module that is in use, i.e. assigned to a DS which should result in movinf the module to the archive.")
|
||||
public void deleteAssignedSoftwareModule() throws Exception {
|
||||
void deleteAssignedSoftwareModule() throws Exception {
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("a");
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
@@ -969,8 +1030,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the deletion of an artifact including verfication that the artifact is actually erased in the repository and removed from the software module.")
|
||||
public void deleteArtifact() throws Exception {
|
||||
@Description("Tests the deletion of an artifact including verification that the artifact is actually erased in the repository and removed from the software module.")
|
||||
void deleteArtifact() throws Exception {
|
||||
// Create 1 SM
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
@@ -978,10 +1039,10 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
// Create 2 artifacts
|
||||
final Artifact artifact = artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
artifactManagement
|
||||
.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize));
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize));
|
||||
artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize));
|
||||
|
||||
// check repo before delete
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(1);
|
||||
@@ -991,7 +1052,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
// delete
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// check that only one artifact is still alive and still assigned
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("After the sm should be marked as deleted").hasSize(1);
|
||||
@@ -1002,8 +1064,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies the successful creation of metadata and the enforcement of the meta data quota.")
|
||||
public void createMetadata() throws Exception {
|
||||
@Description("Verifies the successful creation of metadata and the enforcement of the meta data quota.")
|
||||
void createMetadata() throws Exception {
|
||||
|
||||
final String knownKey1 = "knownKey1";
|
||||
final String knownValue1 = "knownValue1";
|
||||
@@ -1020,18 +1082,17 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData1.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[0]targetVisible", equalTo(false)))
|
||||
.andExpect(jsonPath("[1]key", equalTo(knownKey2))).andExpect(jsonPath("[1]value", equalTo(knownValue2)))
|
||||
.andExpect(jsonPath("[1]targetVisible", equalTo(true)));
|
||||
.andExpect(jsonPath("[0].key", equalTo(knownKey1)))
|
||||
.andExpect(jsonPath("[0].value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[0].targetVisible", equalTo(false)))
|
||||
.andExpect(jsonPath("[1].key", equalTo(knownKey2)))
|
||||
.andExpect(jsonPath("[1].value", equalTo(knownValue2)))
|
||||
.andExpect(jsonPath("[1].targetVisible", equalTo(true)));
|
||||
|
||||
final SoftwareModuleMetadata metaKey1 = softwareModuleManagement
|
||||
.getMetaDataBySoftwareModuleId(sm.getId(), knownKey1).get();
|
||||
final SoftwareModuleMetadata metaKey2 = softwareModuleManagement
|
||||
.getMetaDataBySoftwareModuleId(sm.getId(), knownKey2).get();
|
||||
|
||||
assertThat(metaKey1.getValue()).as("Metadata key is wrong").isEqualTo(knownValue1);
|
||||
assertThat(metaKey2.getValue()).as("Metadata key is wrong").isEqualTo(knownValue2);
|
||||
assertThat(softwareModuleManagement.getMetaDataBySoftwareModuleId(sm.getId(), knownKey1))
|
||||
.as("Metadata key is wrong").get().extracting(SoftwareModuleMetadata::getValue).isEqualTo(knownValue1);
|
||||
assertThat(softwareModuleManagement.getMetaDataBySoftwareModuleId(sm.getId(), knownKey2))
|
||||
.as("Metadata key is wrong").get().extracting(SoftwareModuleMetadata::getValue).isEqualTo(knownValue2);
|
||||
|
||||
// verify quota enforcement
|
||||
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule();
|
||||
@@ -1054,8 +1115,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies the successfull update of metadata based on given key.")
|
||||
public void updateMetadata() throws Exception {
|
||||
@Description("Verifies the successful update of metadata based on given key.")
|
||||
void updateMetadata() throws Exception {
|
||||
// prepare and create metadata for update
|
||||
final String knownKey = "knownKey";
|
||||
final String knownValue = "knownValue";
|
||||
@@ -1065,24 +1126,27 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
softwareModuleManagement.createMetaData(
|
||||
entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue));
|
||||
|
||||
final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue)
|
||||
final JSONObject jsonObject = new JSONObject().put("key", knownKey)
|
||||
.put("value", updateValue)
|
||||
.put("targetVisible", true);
|
||||
|
||||
mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey)
|
||||
.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(jsonObject.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey).accept(
|
||||
MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
|
||||
.andExpect(jsonPath("key", equalTo(knownKey)))
|
||||
.andExpect(jsonPath("value", equalTo(updateValue)));
|
||||
|
||||
final SoftwareModuleMetadata assertDS = softwareModuleManagement
|
||||
.getMetaDataBySoftwareModuleId(sm.getId(), knownKey).get();
|
||||
final SoftwareModuleMetadata assertDS = softwareModuleManagement.getMetaDataBySoftwareModuleId(sm.getId(),
|
||||
knownKey).get();
|
||||
assertThat(assertDS.getValue()).as("Metadata is wrong").isEqualTo(updateValue);
|
||||
assertThat(assertDS.isTargetVisible()).as("target visible is wrong").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies the successfull deletion of metadata entry.")
|
||||
public void deleteMetadata() throws Exception {
|
||||
@Description("Verifies the successful deletion of metadata entry.")
|
||||
void deleteMetadata() throws Exception {
|
||||
// prepare and create metadata for deletion
|
||||
final String knownKey = "knownKey";
|
||||
final String knownValue = "knownValue";
|
||||
@@ -1092,14 +1156,15 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue));
|
||||
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(softwareModuleManagement.getMetaDataBySoftwareModuleId(sm.getId(), knownKey)).isNotPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that module metadta deletion request to API on an entity that does not exist results in NOT_FOUND.")
|
||||
public void deleteModuleMetadataThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||
@Description("Ensures that module metadata deletion request to API on an entity that does not exist results in NOT_FOUND.")
|
||||
void deleteModuleMetadataThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||
// prepare and create metadata for deletion
|
||||
final String knownKey = "knownKey";
|
||||
final String knownValue = "knownValue";
|
||||
@@ -1109,7 +1174,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue));
|
||||
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/XXX", sm.getId(), knownKey))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/1234/metadata/{key}", knownKey))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
@@ -1119,22 +1185,25 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
@Test
|
||||
@Description("Ensures that module deletion request to API on an entity that does not exist results in NOT_FOUND.")
|
||||
public void deleteSoftwareModuleThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/1234")).andDo(MockMvcResultPrinter.print())
|
||||
void deleteSoftwareModuleThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||
mvc.perform(delete("/rest/v1/softwaremodules/1234"))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies the successfull search of a metadata entry based on value.")
|
||||
public void searchSoftwareModuleMetadataRsql() throws Exception {
|
||||
@Description("Verifies the successful search of a metadata entry based on value.")
|
||||
void searchSoftwareModuleMetadataRsql() throws Exception {
|
||||
final int totalMetadata = 10;
|
||||
final String knownKeyPrefix = "knownKey";
|
||||
final String knownValuePrefix = "knownValue";
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
for (int index = 0; index < totalMetadata; index++) {
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(sm.getId())
|
||||
.key(knownKeyPrefix + index).value(knownValuePrefix + index));
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata()
|
||||
.create(sm.getId())
|
||||
.key(knownKeyPrefix + index)
|
||||
.value(knownValuePrefix + index));
|
||||
}
|
||||
|
||||
final String rsqlSearchValue1 = "value==knownValue1";
|
||||
|
||||
@@ -25,25 +25,29 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Duration;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.ActionFields;
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -93,7 +97,7 @@ import io.qameta.allure.Story;
|
||||
*/
|
||||
@Feature("Component Tests - Management API")
|
||||
@Story("Target Resource")
|
||||
public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
|
||||
private static final String TARGET_DESCRIPTION_TEST = "created in test";
|
||||
|
||||
@@ -127,8 +131,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
private JpaProperties jpaProperties;
|
||||
|
||||
@Test
|
||||
@Description("Ensures that actions list is in exptected order.")
|
||||
public void getActionStatusReturnsCorrectType() throws Exception {
|
||||
@Description("Ensures that actions list is in expected order.")
|
||||
void getActionStatusReturnsCorrectType() throws Exception {
|
||||
final int limitSize = 2;
|
||||
final String knownTargetId = "targetId";
|
||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
||||
@@ -159,7 +163,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
@Test
|
||||
@Description("Ensures that security token is not returned if user does not have READ_TARGET_SEC_TOKEN permission.")
|
||||
@WithUser(allSpPermissions = false, authorities = { SpPermission.READ_TARGET, SpPermission.CREATE_TARGET })
|
||||
public void securityTokenIsNotInResponseIfMissingPermission() throws Exception {
|
||||
void securityTokenIsNotInResponseIfMissingPermission() throws Exception {
|
||||
|
||||
final String knownControllerId = "knownControllerId";
|
||||
testdataFactory.createTarget(knownControllerId);
|
||||
@@ -172,7 +176,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
@Description("Ensures that security token is returned if user does have READ_TARGET_SEC_TOKEN permission.")
|
||||
@WithUser(allSpPermissions = false, authorities = { SpPermission.READ_TARGET, SpPermission.CREATE_TARGET,
|
||||
SpPermission.READ_TARGET_SEC_TOKEN })
|
||||
public void securityTokenIsInResponseWithCorrectPermission() throws Exception {
|
||||
void securityTokenIsInResponseWithCorrectPermission() throws Exception {
|
||||
|
||||
final String knownControllerId = "knownControllerId";
|
||||
final Target createTarget = testdataFactory.createTarget(knownControllerId);
|
||||
@@ -183,7 +187,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that that IP address is in result as stored in the repository.")
|
||||
public void addressAndIpAddressInTargetResult() throws Exception {
|
||||
void addressAndIpAddressInTargetResult() throws Exception {
|
||||
// prepare targets with IP
|
||||
final String knownControllerId1 = "0815";
|
||||
final String knownControllerId2 = "4711";
|
||||
@@ -212,13 +216,13 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that actions history is returned as defined by filter status==pending,status==finished.")
|
||||
public void searchActionsRsql() throws Exception {
|
||||
void searchActionsRsql() throws Exception {
|
||||
|
||||
// prepare test
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
final Target createTarget = testdataFactory.createTarget("knownTargetId");
|
||||
|
||||
assignDistributionSet(dsA, Arrays.asList(createTarget));
|
||||
assignDistributionSet(dsA, Collections.singletonList(createTarget));
|
||||
|
||||
final String rsqlPendingStatus = "status==pending";
|
||||
final String rsqlFinishedStatus = "status==finished";
|
||||
@@ -243,8 +247,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a deletion of an active action results in cancelation triggered.")
|
||||
public void cancelActionOK() throws Exception {
|
||||
@Description("Ensures that a deletion of an active action results in cancellation triggered.")
|
||||
void cancelActionOK() throws Exception {
|
||||
// prepare test
|
||||
final Target tA = createTargetAndStartAction();
|
||||
|
||||
@@ -269,8 +273,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that method not allowed is returned if cancelation is triggered on already canceled action.")
|
||||
public void cancelAndCancelActionIsNotAllowed() throws Exception {
|
||||
@Description("Ensures that method not allowed is returned if cancellation is triggered on already canceled action.")
|
||||
void cancelAndCancelActionIsNotAllowed() throws Exception {
|
||||
// prepare test
|
||||
final Target tA = createTargetAndStartAction();
|
||||
|
||||
@@ -291,7 +295,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Force Quit an Action, which is already canceled. Expected Result is an HTTP response code 204.")
|
||||
public void forceQuitAnCanceledActionReturnsOk() throws Exception {
|
||||
void forceQuitAnCanceledActionReturnsOk() throws Exception {
|
||||
|
||||
final Target tA = createTargetAndStartAction();
|
||||
|
||||
@@ -305,7 +309,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
assertThat(cancelActions).hasSize(1);
|
||||
assertThat(cancelActions.get(0).isCancelingOrCanceled()).isTrue();
|
||||
|
||||
// test - force quit an canceled action should return 204
|
||||
// test - force quit: Canceled actions should return 204
|
||||
mvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}?force=true",
|
||||
tA.getControllerId(), cancelActions.get(0).getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNoContent());
|
||||
@@ -313,7 +317,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Force Quit an Action, which is not canceled. Expected Result is an HTTP response code 405.")
|
||||
public void forceQuitAnNotCanceledActionReturnsMethodNotAllowed() throws Exception {
|
||||
void forceQuitAnNotCanceledActionReturnsMethodNotAllowed() throws Exception {
|
||||
|
||||
final Target tA = createTargetAndStartAction();
|
||||
|
||||
@@ -327,7 +331,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that deletion is executed if permitted.")
|
||||
public void deleteTargetReturnsOK() throws Exception {
|
||||
void deleteTargetReturnsOK() throws Exception {
|
||||
final String knownControllerId = "knownControllerIdDelete";
|
||||
testdataFactory.createTarget(knownControllerId);
|
||||
|
||||
@@ -339,7 +343,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that deletion is refused with not found if target does not exist.")
|
||||
public void deleteTargetWhichDoesNotExistsLeadsToNotFound() throws Exception {
|
||||
void deleteTargetWhichDoesNotExistsLeadsToNotFound() throws Exception {
|
||||
final String knownControllerId = "knownControllerIdDelete";
|
||||
|
||||
mvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId))
|
||||
@@ -348,7 +352,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that update is refused with not found if target does not exist.")
|
||||
public void updateTargetWhichDoesNotExistsLeadsToNotFound() throws Exception {
|
||||
void updateTargetWhichDoesNotExistsLeadsToNotFound() throws Exception {
|
||||
final String knownControllerId = "knownControllerIdUpdate";
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content("{}")
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
@@ -357,37 +361,37 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target update request is reflected by repository.")
|
||||
public void updateTargetDescription() throws Exception {
|
||||
void updateTargetDescription() throws Exception {
|
||||
final String knownControllerId = "123";
|
||||
final String knownNewDescription = "a new desc updated over rest";
|
||||
final String knownNameNotModiy = "nameNotModiy";
|
||||
final String knownNameNotModify = "nameNotModify";
|
||||
final String body = new JSONObject().put("description", knownNewDescription).toString();
|
||||
|
||||
// prepare
|
||||
targetManagement.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModiy)
|
||||
targetManagement.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModify)
|
||||
.description("old description"));
|
||||
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.controllerId", equalTo(knownControllerId)))
|
||||
.andExpect(jsonPath("$.description", equalTo(knownNewDescription)))
|
||||
.andExpect(jsonPath("$.name", equalTo(knownNameNotModiy)));
|
||||
.andExpect(jsonPath("$.name", equalTo(knownNameNotModify)));
|
||||
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownControllerId).get();
|
||||
assertThat(findTargetByControllerID.getDescription()).isEqualTo(knownNewDescription);
|
||||
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy);
|
||||
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target update request fails is updated value fails against a constraint.")
|
||||
public void updateTargetDescriptionFailsIfInvalidLength() throws Exception {
|
||||
void updateTargetDescriptionFailsIfInvalidLength() throws Exception {
|
||||
final String knownControllerId = "123";
|
||||
final String knownNewDescription = RandomStringUtils.randomAlphabetic(513);
|
||||
final String knownNameNotModiy = "nameNotModiy";
|
||||
final String knownNameNotModify = "nameNotModify";
|
||||
final String body = new JSONObject().put("description", knownNewDescription).toString();
|
||||
|
||||
// prepare
|
||||
targetManagement.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModiy)
|
||||
targetManagement.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModify)
|
||||
.description("old description"));
|
||||
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content(body)
|
||||
@@ -400,53 +404,53 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target update request is reflected by repository.")
|
||||
public void updateTargetSecurityToken() throws Exception {
|
||||
void updateTargetSecurityToken() throws Exception {
|
||||
final String knownControllerId = "123";
|
||||
final String knownNewToken = "6567576565";
|
||||
final String knownNameNotModiy = "nameNotModiy";
|
||||
final String knownNameNotModify = "nameNotModify";
|
||||
final String body = new JSONObject().put("securityToken", knownNewToken).toString();
|
||||
|
||||
// prepare
|
||||
targetManagement
|
||||
.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModiy));
|
||||
.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModify));
|
||||
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.controllerId", equalTo(knownControllerId)))
|
||||
.andExpect(jsonPath("$.securityToken", equalTo(knownNewToken)))
|
||||
.andExpect(jsonPath("$.name", equalTo(knownNameNotModiy)));
|
||||
.andExpect(jsonPath("$.name", equalTo(knownNameNotModify)));
|
||||
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownControllerId).get();
|
||||
assertThat(findTargetByControllerID.getSecurityToken()).isEqualTo(knownNewToken);
|
||||
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy);
|
||||
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target update request is reflected by repository.")
|
||||
public void updateTargetAddress() throws Exception {
|
||||
void updateTargetAddress() throws Exception {
|
||||
final String knownControllerId = "123";
|
||||
final String knownNewAddress = "amqp://test123/foobar";
|
||||
final String knownNameNotModiy = "nameNotModiy";
|
||||
final String knownNameNotModify = "nameNotModify";
|
||||
final String body = new JSONObject().put("address", knownNewAddress).toString();
|
||||
|
||||
// prepare
|
||||
targetManagement.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModiy)
|
||||
targetManagement.create(entityFactory.target().create().controllerId(knownControllerId).name(knownNameNotModify)
|
||||
.address(knownNewAddress));
|
||||
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.controllerId", equalTo(knownControllerId)))
|
||||
.andExpect(jsonPath("$.address", equalTo(knownNewAddress)))
|
||||
.andExpect(jsonPath("$.name", equalTo(knownNameNotModiy)));
|
||||
.andExpect(jsonPath("$.name", equalTo(knownNameNotModify)));
|
||||
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownControllerId).get();
|
||||
assertThat(findTargetByControllerID.getAddress().toString()).isEqualTo(knownNewAddress);
|
||||
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModiy);
|
||||
assertThat(findTargetByControllerID.getAddress()).hasToString(knownNewAddress);
|
||||
assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target query returns list of targets in defined format.")
|
||||
public void getTargetWithoutAddtionalRequestParameters() throws Exception {
|
||||
void getTargetWithoutAdditionalRequestParameters() throws Exception {
|
||||
final int knownTargetAmount = 3;
|
||||
final String idA = "a";
|
||||
final String idB = "b";
|
||||
@@ -489,7 +493,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target query returns list of targets in defined format in size reduced by given limit parameter.")
|
||||
public void getTargetWithPagingLimitRequestParameter() throws Exception {
|
||||
void getTargetWithPagingLimitRequestParameter() throws Exception {
|
||||
final int knownTargetAmount = 3;
|
||||
final int limitSize = 1;
|
||||
createTargetsAlphabetical(knownTargetAmount);
|
||||
@@ -514,7 +518,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target query returns list of targets in defined format in size reduced by given limit and offset parameter.")
|
||||
public void getTargetWithPagingLimitAndOffsetRequestParameter() throws Exception {
|
||||
void getTargetWithPagingLimitAndOffsetRequestParameter() throws Exception {
|
||||
final int knownTargetAmount = 5;
|
||||
final int offsetParam = 2;
|
||||
final int expectedSize = knownTargetAmount - offsetParam;
|
||||
@@ -559,7 +563,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the get request for a target works.")
|
||||
public void getSingleTarget() throws Exception {
|
||||
void getSingleTarget() throws Exception {
|
||||
// create first a target which can be retrieved by rest interface
|
||||
final String knownControllerId = "1";
|
||||
final String knownName = "someName";
|
||||
@@ -583,7 +587,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target get request returns a not found if the target does not exits.")
|
||||
public void getSingleTargetNoExistsResponseNotFound() throws Exception {
|
||||
void getSingleTargetNoExistsResponseNotFound() throws Exception {
|
||||
|
||||
final String targetIdNotExists = "bubu";
|
||||
|
||||
@@ -600,7 +604,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that get request for asigned distribution sets returns no count if no distribution set has been assigned.")
|
||||
public void getAssignedDistributionSetOfTargetIsEmpty() throws Exception {
|
||||
void getAssignedDistributionSetOfTargetIsEmpty() throws Exception {
|
||||
// create first a target which can be retrieved by rest interface
|
||||
final String knownControllerId = "1";
|
||||
final String knownName = "someName";
|
||||
@@ -614,7 +618,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the get request for asigned distribution sets works.")
|
||||
public void getAssignedDistributionSetOfTarget() throws Exception {
|
||||
void getAssignedDistributionSetOfTarget() throws Exception {
|
||||
// create first a target which can be retrieved by rest interface
|
||||
final String knownControllerId = "1";
|
||||
final String knownName = "someName";
|
||||
@@ -671,7 +675,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that get request for installed distribution sets returns no count if no distribution set has been installed.")
|
||||
public void getInstalledDistributionSetOfTargetIsEmpty() throws Exception {
|
||||
void getInstalledDistributionSetOfTargetIsEmpty() throws Exception {
|
||||
// create first a target which can be retrieved by rest interface
|
||||
final String knownControllerId = "1";
|
||||
final String knownName = "someName";
|
||||
@@ -683,12 +687,12 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a target creation with empty name and a controllerId that exceeds the name length limitation is successful and the name gets truncated.")
|
||||
public void createTargetWithEmptyNameAndLongControllerId() throws Exception {
|
||||
void createTargetWithEmptyNameAndLongControllerId() throws Exception {
|
||||
final String randomString = RandomStringUtils.randomAlphanumeric(JpaTarget.CONTROLLER_ID_MAX_SIZE);
|
||||
|
||||
final Target target = entityFactory.target().create().controllerId(randomString).build();
|
||||
|
||||
final String targetList = JsonBuilder.targets(Arrays.asList(target), false);
|
||||
final String targetList = JsonBuilder.targets(Collections.singletonList(target), false);
|
||||
|
||||
final String expectedTargetName = randomString.substring(0,
|
||||
Math.min(JpaTarget.CONTROLLER_ID_MAX_SIZE, NamedEntity.NAME_MAX_SIZE));
|
||||
@@ -703,13 +707,13 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that post request for creating a target with no payload returns a bad request.")
|
||||
public void createTargetWithoutPayloadBadRequest() throws Exception {
|
||||
void createTargetWithoutPayloadBadRequest() throws Exception {
|
||||
|
||||
final MvcResult mvcResult = mvc
|
||||
.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
|
||||
|
||||
assertThat(targetManagement.count()).isEqualTo(0);
|
||||
assertThat(targetManagement.count()).isZero();
|
||||
|
||||
// verify response json exception message
|
||||
final ExceptionInfo exceptionInfo = ResourceUtility
|
||||
@@ -720,7 +724,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that post request for creating a target with invalid payload returns a bad request.")
|
||||
public void createTargetWithBadPayloadBadRequest() throws Exception {
|
||||
void createTargetWithBadPayloadBadRequest() throws Exception {
|
||||
final String notJson = "abc";
|
||||
|
||||
final MvcResult mvcResult = mvc
|
||||
@@ -728,7 +732,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
|
||||
|
||||
assertThat(targetManagement.count()).isEqualTo(0);
|
||||
assertThat(targetManagement.count()).isZero();
|
||||
|
||||
// verify response json exception message
|
||||
final ExceptionInfo exceptionInfo = ResourceUtility
|
||||
@@ -738,14 +742,14 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that a mandatory properties of new targets are validated as not null.")
|
||||
public void createTargetWithMissingMandatoryPropertyBadRequest() throws Exception {
|
||||
@Description("Verifies that a mandatory properties of new targets are validated as not null.")
|
||||
void createTargetWithMissingMandatoryPropertyBadRequest() throws Exception {
|
||||
final MvcResult mvcResult = mvc
|
||||
.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING).content("[{\"name\":\"id1\"}]")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
|
||||
|
||||
assertThat(targetManagement.count()).isEqualTo(0);
|
||||
assertThat(targetManagement.count()).isZero();
|
||||
|
||||
// verify response json exception message
|
||||
final ExceptionInfo exceptionInfo = ResourceUtility
|
||||
@@ -756,15 +760,16 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verfies that a properties of new targets are validated as in allowed size range.")
|
||||
public void createTargetWithInvalidPropertyBadRequest() throws Exception {
|
||||
void createTargetWithInvalidPropertyBadRequest() throws Exception {
|
||||
final Target test1 = entityFactory.target().create().controllerId("id1")
|
||||
.name(RandomStringUtils.randomAlphanumeric(NamedEntity.NAME_MAX_SIZE + 1)).build();
|
||||
|
||||
final MvcResult mvcResult = mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING)
|
||||
.content(JsonBuilder.targets(Arrays.asList(test1), true)).contentType(MediaType.APPLICATION_JSON))
|
||||
.content(JsonBuilder.targets(Collections.singletonList(test1), true))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
|
||||
|
||||
assertThat(targetManagement.count()).isEqualTo(0);
|
||||
assertThat(targetManagement.count()).isZero();
|
||||
|
||||
// verify response json exception message
|
||||
final ExceptionInfo exceptionInfo = ResourceUtility
|
||||
@@ -775,7 +780,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for creating multiple targets works.")
|
||||
public void createTargetsListReturnsSuccessful() throws Exception {
|
||||
void createTargetsListReturnsSuccessful() throws Exception {
|
||||
final Target test1 = entityFactory.target().create().controllerId("id1").name("testname1")
|
||||
.securityToken("token").address("amqp://test123/foobar").description("testid1").build();
|
||||
final Target test2 = entityFactory.target().create().controllerId("id2").name("testname2")
|
||||
@@ -810,32 +815,35 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
.andExpect(jsonPath("[2].createdBy", equalTo("bumlux"))).andReturn();
|
||||
|
||||
assertThat(
|
||||
JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
JsonPath.compile("[0]._links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
.isEqualTo("http://localhost/rest/v1/targets/id1");
|
||||
assertThat(
|
||||
JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
JsonPath.compile("[1]._links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
.isEqualTo("http://localhost/rest/v1/targets/id2");
|
||||
assertThat(
|
||||
JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
JsonPath.compile("[2]._links.self.href").read(mvcResult.getResponse().getContentAsString()).toString())
|
||||
.isEqualTo("http://localhost/rest/v1/targets/id3");
|
||||
|
||||
assertThat(targetManagement.getByControllerID("id1")).isNotNull();
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getName()).isEqualTo("testname1");
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getDescription()).isEqualTo("testid1");
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getSecurityToken()).isEqualTo("token");
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getAddress().toString())
|
||||
.isEqualTo("amqp://test123/foobar");
|
||||
assertThat(targetManagement.getByControllerID("id2")).isNotNull();
|
||||
assertThat(targetManagement.getByControllerID("id2").get().getName()).isEqualTo("testname2");
|
||||
assertThat(targetManagement.getByControllerID("id2").get().getDescription()).isEqualTo("testid2");
|
||||
assertThat(targetManagement.getByControllerID("id3")).isNotNull();
|
||||
assertThat(targetManagement.getByControllerID("id3").get().getName()).isEqualTo("testname3");
|
||||
assertThat(targetManagement.getByControllerID("id3").get().getDescription()).isEqualTo("testid3");
|
||||
final Target t1 = assertTarget("id1", "testname1", "testid1");
|
||||
assertThat(t1.getSecurityToken()).isEqualTo("token");
|
||||
assertThat(t1.getAddress()).hasToString("amqp://test123/foobar");
|
||||
|
||||
assertTarget("id2", "testname2", "testid2");
|
||||
assertTarget("id3", "testname3", "testid3");
|
||||
}
|
||||
|
||||
private Target assertTarget(final String controllerId, final String name, final String description) {
|
||||
final Optional<Target> target1 = targetManagement.getByControllerID(controllerId);
|
||||
assertThat(target1).isPresent();
|
||||
final Target t = target1.get();
|
||||
assertThat(t.getName()).isEqualTo(name);
|
||||
assertThat(t.getDescription()).isEqualTo(description);
|
||||
return t;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for creating one target within a list works.")
|
||||
public void createTargetsSingleEntryListReturnsSuccessful() throws Exception {
|
||||
void createTargetsSingleEntryListReturnsSuccessful() throws Exception {
|
||||
final String knownName = "someName";
|
||||
final String knownControllerId = "controllerId1";
|
||||
final String knownDescription = "someDescription";
|
||||
@@ -855,7 +863,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for creating the same target again leads to a conflict response.")
|
||||
public void createTargetsSingleEntryListDoubleReturnConflict() throws Exception {
|
||||
void createTargetsSingleEntryListDoubleReturnConflict() throws Exception {
|
||||
final String knownName = "someName";
|
||||
final String knownControllerId = "controllerId1";
|
||||
final String knownDescription = "someDescription";
|
||||
@@ -885,7 +893,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the get request for action of a target returns no actions if nothing has happened.")
|
||||
public void getActionWithEmptyResult() throws Exception {
|
||||
void getActionWithEmptyResult() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
testdataFactory.createTarget(knownTargetId);
|
||||
|
||||
@@ -897,7 +905,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the expected response is returned for update action.")
|
||||
public void getUpdateAction() throws Exception {
|
||||
void getUpdateAction() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
||||
|
||||
@@ -918,7 +926,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the expected response is returned for update action with maintenance window.")
|
||||
public void getUpdateActionWithMaintenanceWindow() throws Exception {
|
||||
void getUpdateActionWithMaintenanceWindow() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final String schedule = getTestSchedule(10);
|
||||
final String duration = getTestDuration(10);
|
||||
@@ -947,7 +955,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the expected response is returned when update action was cancelled.")
|
||||
public void getCancelAction() throws Exception {
|
||||
void getCancelAction() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
||||
|
||||
@@ -968,7 +976,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the expected response is returned when update action with maintenance window was cancelled.")
|
||||
public void getCancelActionWithMaintenanceWindow() throws Exception {
|
||||
void getCancelActionWithMaintenanceWindow() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final String schedule = getTestSchedule(10);
|
||||
final String duration = getTestDuration(10);
|
||||
@@ -997,7 +1005,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the expected response of geting actions of a target is returned.")
|
||||
public void getMultipleActions() throws Exception {
|
||||
void getMultipleActions() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
||||
|
||||
@@ -1021,7 +1029,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the expected response of getting actions with maintenance window of a target is returned.")
|
||||
public void getMultipleActionsWithMaintenanceWindow() throws Exception {
|
||||
void getMultipleActionsWithMaintenanceWindow() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final String schedule = getTestSchedule(10);
|
||||
final String duration = getTestDuration(10);
|
||||
@@ -1059,7 +1067,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the API returns the status list with expected content.")
|
||||
public void getMultipleActionStatus() throws Exception {
|
||||
void getMultipleActionStatus() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
|
||||
// retrieve list in default descending order for actionstaus entries
|
||||
@@ -1087,11 +1095,11 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the API returns the status list with expected content sorted by reportedAt field.")
|
||||
public void getMultipleActionStatusSortedByReportedAt() throws Exception {
|
||||
void getMultipleActionStatusSortedByReportedAt() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
|
||||
final List<ActionStatus> actionStatus = deploymentManagement.findActionStatusByAction(PAGE, action.getId())
|
||||
.getContent().stream().sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId()))
|
||||
.getContent().stream().sorted(Comparator.comparingLong(Identifiable::getId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// descending order
|
||||
@@ -1133,7 +1141,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the API returns the status list with expected content split into two pages.")
|
||||
public void getMultipleActionStatusWithPagingLimitRequestParameter() throws Exception {
|
||||
void getMultipleActionStatusWithPagingLimitRequestParameter() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
|
||||
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
|
||||
@@ -1173,7 +1181,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verifies getting multiple actions with the paging request parameter.")
|
||||
public void getMultipleActionsWithPagingLimitRequestParameter() throws Exception {
|
||||
void getMultipleActionsWithPagingLimitRequestParameter() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
|
||||
|
||||
@@ -1230,13 +1238,12 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
+ "?offset=0&limit=50&sort=id:DESC";
|
||||
}
|
||||
|
||||
private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId)
|
||||
throws InterruptedException {
|
||||
private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId) {
|
||||
return generateTargetWithTwoUpdatesWithOneOverrideWithMaintenanceWindow(knownTargetId, null, null, null);
|
||||
}
|
||||
|
||||
private List<Action> generateTargetWithTwoUpdatesWithOneOverrideWithMaintenanceWindow(final String knownTargetId,
|
||||
final String schedule, final String duration, final String timezone) throws InterruptedException {
|
||||
final String schedule, final String duration, final String timezone) {
|
||||
final Target target = testdataFactory.createTarget(knownTargetId);
|
||||
|
||||
final Iterator<DistributionSet> sets = testdataFactory.createDistributionSets(2).iterator();
|
||||
@@ -1245,11 +1252,14 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
// Update
|
||||
if (schedule == null) {
|
||||
final List<Target> updatedTargets = assignDistributionSet(one, Arrays.asList(target)).getAssignedEntity()
|
||||
final List<Target> updatedTargets = assignDistributionSet(one, Collections.singletonList(target))
|
||||
.getAssignedEntity()
|
||||
.stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
// 2nd update
|
||||
// sleep 10ms to ensure that we can sort by reportedAt
|
||||
Thread.sleep(10);
|
||||
Awaitility.await().atMost(Duration.ONE_HUNDRED_MILLISECONDS).atLeast(5, TimeUnit.MILLISECONDS)
|
||||
.pollInterval(10, TimeUnit.MILLISECONDS)
|
||||
.until(() -> updatedTargets.stream().allMatch(t -> t.getLastModifiedAt() > 0L));
|
||||
assignDistributionSet(two, updatedTargets);
|
||||
} else {
|
||||
final List<Target> updatedTargets = assignDistributionSetWithMaintenanceWindow(one.getId(),
|
||||
@@ -1257,7 +1267,9 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
.map(Action::getTarget).collect(Collectors.toList());
|
||||
// 2nd update
|
||||
// sleep 10ms to ensure that we can sort by reportedAt
|
||||
Thread.sleep(10);
|
||||
Awaitility.await().atMost(Duration.ONE_HUNDRED_MILLISECONDS).atLeast(5, TimeUnit.MILLISECONDS)
|
||||
.pollInterval(10, TimeUnit.MILLISECONDS)
|
||||
.until(() -> updatedTargets.stream().allMatch(t -> t.getLastModifiedAt() > 0L));
|
||||
assignDistributionSetWithMaintenanceWindow(two.getId(), updatedTargets.get(0).getControllerId(), schedule,
|
||||
duration, timezone);
|
||||
}
|
||||
@@ -1272,7 +1284,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verfies that an action is switched from soft to forced if requested by management API")
|
||||
public void updateAction() throws Exception {
|
||||
void updateAction() throws Exception {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
@@ -1299,7 +1311,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
@Test
|
||||
@Description("Verfies that a DS to target assignment is reflected by the repository and that repeating "
|
||||
+ "the assignment does not change the target.")
|
||||
public void assignDistributionSetToTarget() throws Exception {
|
||||
void assignDistributionSetToTarget() throws Exception {
|
||||
|
||||
Target target = testdataFactory.createTarget();
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1326,7 +1338,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Verfies that a DOWNLOAD_ONLY DS to target assignment is properly handled")
|
||||
public void assignDownloadOnlyDistributionSetToTarget() throws Exception {
|
||||
void assignDownloadOnlyDistributionSetToTarget() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1339,15 +1351,14 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set);
|
||||
final Slice<Action> actions = deploymentManagement.findActionsByTarget("targetExist", PageRequest.of(0, 100));
|
||||
assertThat(actions.getSize()).isGreaterThan(0);
|
||||
actions.stream().filter(a -> a.getDistributionSet().equals(set))
|
||||
.forEach(a -> ActionType.DOWNLOAD_ONLY.equals(a.getActionType()));
|
||||
assertThat(actions).isNotEmpty().filteredOn(a -> a.getDistributionSet().equals(set))
|
||||
.extracting(Action::getActionType).containsOnly(ActionType.DOWNLOAD_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that an offline DS to target assignment is reflected by the repository and that repeating "
|
||||
+ "the assignment does not change the target.")
|
||||
public void offlineAssignDistributionSetToTarget() throws Exception {
|
||||
void offlineAssignDistributionSetToTarget() throws Exception {
|
||||
|
||||
Target target = testdataFactory.createTarget();
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1377,7 +1388,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assignDistributionSetToTargetWithActionTimeForcedAndTime() throws Exception {
|
||||
void assignDistributionSetToTargetWithActionTimeForcedAndTime() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("fsdfsd");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1400,7 +1411,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Assigns distribution set to target with only maintenance schedule.")
|
||||
public void assignDistributionSetToTargetWithMaintenanceWindowStartTimeOnly() throws Exception {
|
||||
void assignDistributionSetToTargetWithMaintenanceWindowStartTimeOnly() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("fsdfsd");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1415,7 +1426,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Assigns distribution set to target with only maintenance window duration.")
|
||||
public void assignDistributionSetToTargetWithMaintenanceWindowEndTimeOnly() throws Exception {
|
||||
void assignDistributionSetToTargetWithMaintenanceWindowEndTimeOnly() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("fsdfsd");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1430,7 +1441,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Assigns distribution set to target with valid maintenance window.")
|
||||
public void assignDistributionSetToTargetWithValidMaintenanceWindow() throws Exception {
|
||||
void assignDistributionSetToTargetWithValidMaintenanceWindow() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("fsdfsd");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1447,7 +1458,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Assigns distribution set to target with maintenance window next execution start (should be ignored, calculated automaticaly based on schedule, duration and timezone)")
|
||||
public void assignDistributionSetToTargetWithMaintenanceWindowNextExecutionStart() throws Exception {
|
||||
void assignDistributionSetToTargetWithMaintenanceWindowNextExecutionStart() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("fsdfsd");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1469,7 +1480,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Assigns distribution set to target with last maintenance window scheduled before current time.")
|
||||
public void assignDistributionSetToTargetWithMaintenanceWindowEndTimeBeforeStartTime() throws Exception {
|
||||
void assignDistributionSetToTargetWithMaintenanceWindowEndTimeBeforeStartTime() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("fsdfsd");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
@@ -1485,7 +1496,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidRequestsOnAssignDistributionSetToTarget() throws Exception {
|
||||
void invalidRequestsOnAssignDistributionSetToTarget() throws Exception {
|
||||
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
|
||||
@@ -1514,7 +1525,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidRequestsOnActionResource() throws Exception {
|
||||
void invalidRequestsOnActionResource() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
|
||||
// target does not exist
|
||||
@@ -1546,7 +1557,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidRequestsOnActionStatusResource() throws Exception {
|
||||
void invalidRequestsOnActionStatusResource() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
|
||||
// target does not exist
|
||||
@@ -1579,7 +1590,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerAttributesViaTargetResourceReturnsAttributesWithOk() throws Exception {
|
||||
void getControllerAttributesViaTargetResourceReturnsAttributesWithOk() throws Exception {
|
||||
// create target with attributes
|
||||
final String knownTargetId = "targetIdWithAttributes";
|
||||
final Map<String, String> knownControllerAttrs = new HashMap<>();
|
||||
@@ -1595,7 +1606,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerEmptyAttributesReturnsNoContent() throws Exception {
|
||||
void getControllerEmptyAttributesReturnsNoContent() throws Exception {
|
||||
// create target with attributes
|
||||
final String knownTargetId = "targetIdWithAttributes";
|
||||
testdataFactory.createTarget(knownTargetId);
|
||||
@@ -1607,7 +1618,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Request update of Controller Attributes.")
|
||||
public void triggerControllerAttributesUpdate() throws Exception {
|
||||
void triggerControllerAttributesUpdate() throws Exception {
|
||||
// create target with attributes
|
||||
final String knownTargetId = "targetIdNeedsUpdate";
|
||||
final Map<String, String> knownControllerAttrs = new HashMap<>();
|
||||
@@ -1656,7 +1667,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchTargetsUsingRsqlQuery() throws Exception {
|
||||
void searchTargetsUsingRsqlQuery() throws Exception {
|
||||
final int amountTargets = 10;
|
||||
createTargetsAlphabetical(amountTargets);
|
||||
|
||||
@@ -1686,7 +1697,6 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
*
|
||||
* @param amount
|
||||
* The number of targets to create
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
private void createTargetsAlphabetical(final int amount) {
|
||||
char character = 'a';
|
||||
@@ -1717,7 +1727,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the metadata creation through API is reflected by the repository.")
|
||||
public void createMetadata() throws Exception {
|
||||
void createMetadata() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
testdataFactory.createTarget(knownControllerId);
|
||||
|
||||
@@ -1735,9 +1745,10 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData1.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[1]key", equalTo(knownKey2)))
|
||||
.andExpect(jsonPath("[1]value", equalTo(knownValue2)));
|
||||
.andExpect(jsonPath("[0].key", equalTo(knownKey1)))
|
||||
.andExpect(jsonPath("[0].value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[1].key", equalTo(knownKey2)))
|
||||
.andExpect(jsonPath("[1].value", equalTo(knownValue2)));
|
||||
|
||||
final TargetMetadata metaKey1 = targetManagement.getMetaDataByControllerId(knownControllerId, knownKey1).get();
|
||||
final TargetMetadata metaKey2 = targetManagement.getMetaDataByControllerId(knownControllerId, knownKey2).get();
|
||||
@@ -1766,7 +1777,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata update through API is reflected by the repository.")
|
||||
public void updateMetadata() throws Exception {
|
||||
void updateMetadata() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
|
||||
// prepare and create metadata for update
|
||||
@@ -1799,7 +1810,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry deletion through API is reflected by the repository.")
|
||||
public void deleteMetadata() throws Exception {
|
||||
void deleteMetadata() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
|
||||
// prepare and create metadata for deletion
|
||||
@@ -1816,7 +1827,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target metadata deletion request to API on an entity that does not exist results in NOT_FOUND.")
|
||||
public void deleteMetadataThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||
void deleteMetadataThatDoesNotExistLeadsToNotFound() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
|
||||
// prepare and create metadata for deletion
|
||||
@@ -1836,7 +1847,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry selection through API reflectes the repository content.")
|
||||
public void getSingleMetadata() throws Exception {
|
||||
void getSingleMetadata() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
|
||||
// prepare and create metadata for deletion
|
||||
@@ -1852,7 +1863,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry paged list selection through API reflectes the repository content.")
|
||||
public void getPagedListOfMetadata() throws Exception {
|
||||
void getPagedListOfMetadata() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
|
||||
final int totalMetadata = 10;
|
||||
@@ -1885,7 +1896,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a target metadata filtered query with value==knownValue1 parameter returns only the metadata entries with that value.")
|
||||
public void searchDistributionSetMetadataRsql() throws Exception {
|
||||
void searchDistributionSetMetadataRsql() throws Exception {
|
||||
final String knownControllerId = "targetIdWithMetadata";
|
||||
|
||||
final int totalMetadata = 10;
|
||||
@@ -1904,7 +1915,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("A request for assigning multiple DS to a target results in a Bad Request when multiassignment in disabled.")
|
||||
public void multiassignmentRequestNotAllowedIfDisabled() throws Exception {
|
||||
void multiassignmentRequestNotAllowedIfDisabled() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final List<Long> dsIds = testdataFactory.createDistributionSets(2).stream().map(DistributionSet::getId)
|
||||
.collect(Collectors.toList());
|
||||
@@ -1919,7 +1930,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Passing an array in assignment request is allowed if multiassignment is disabled and array size in 1.")
|
||||
public void multiassignmentRequestAllowedIfDisabledButHasSizeOne() throws Exception {
|
||||
void multiassignmentRequestAllowedIfDisabledButHasSizeOne() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
|
||||
@@ -1931,7 +1942,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Identical assignments in a single request are removed when multiassignment in disabled.")
|
||||
public void identicalAssignmentInRequestAreRemovedIfMultiassignmentsDisabled() throws Exception {
|
||||
void identicalAssignmentInRequestAreRemovedIfMultiassignmentsDisabled() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
|
||||
@@ -1945,7 +1956,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Assign multiple DSs to a target in one request with multiassignments enabled.")
|
||||
public void multiAssignment() throws Exception {
|
||||
void multiAssignment() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final List<Long> dsIds = testdataFactory.createDistributionSets(2).stream().map(DistributionSet::getId)
|
||||
.collect(Collectors.toList());
|
||||
@@ -1960,8 +1971,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("An assignment request containing a weight is only accepted when weight is valide and multi assignment is on.")
|
||||
public void weightValidation() throws Exception {
|
||||
@Description("An assignment request containing a weight is only accepted when weight is valid and multi assignment is on.")
|
||||
void weightValidation() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
final int weight = 98;
|
||||
@@ -1985,7 +1996,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("An assignment request containing a valid weight when multi assignment is off.")
|
||||
public void weightWithSingleAssignment() throws Exception {
|
||||
void weightWithSingleAssignment() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
|
||||
@@ -1999,7 +2010,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("An assignment request containing a valid weight when multi assignment is on.")
|
||||
public void weightWithMultiAssignment() throws Exception {
|
||||
void weightWithMultiAssignment() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
final int weight = 98;
|
||||
@@ -2018,7 +2029,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Get weight of action")
|
||||
public void getActionWeight() throws Exception {
|
||||
void getActionWeight() throws Exception {
|
||||
final String targetId = testdataFactory.createTarget().getControllerId();
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
final int customWeightHigh = 800;
|
||||
@@ -2049,7 +2060,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("An action provides information of the rollout it was created for (if any).")
|
||||
public void getActionWithRolloutInfo() throws Exception {
|
||||
void getActionWithRolloutInfo() throws Exception {
|
||||
|
||||
// setup
|
||||
final int amountTargets = 10;
|
||||
@@ -2082,7 +2093,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for creating targets with target type works.")
|
||||
public void createTargetsWithTargetType() throws Exception {
|
||||
void createTargetsWithTargetType() throws Exception {
|
||||
final TargetType type1 = testdataFactory.createTargetType("typeWithDs", Collections.singletonList(standardDsType));
|
||||
final TargetType type2 = testdataFactory.createTargetType("typeWithOutDs", Collections.singletonList(standardDsType));
|
||||
|
||||
@@ -2132,26 +2143,21 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
.andExpect(jsonPath(JSON_PATH_DESCRIPTION, equalTo("testid2")))
|
||||
.andExpect(jsonPath("$._links.targetType.href", equalTo(hrefType1))).andReturn();
|
||||
|
||||
assertThat(targetManagement.getByControllerID("id1")).isNotNull();
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getName()).isEqualTo("targetWithoutType");
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getDescription()).isEqualTo("testid1");
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getTargetType()).isNull();
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getSecurityToken()).isEqualTo("token");
|
||||
assertThat(targetManagement.getByControllerID("id1").get().getAddress().toString())
|
||||
.isEqualTo("amqp://test123/foobar");
|
||||
assertThat(targetManagement.getByControllerID("id2")).isNotNull();
|
||||
assertThat(targetManagement.getByControllerID("id2").get().getName()).isEqualTo("targetOfType1");
|
||||
assertThat(targetManagement.getByControllerID("id2").get().getDescription()).isEqualTo("testid2");
|
||||
assertThat(targetManagement.getByControllerID("id2").get().getTargetType().getName()).isEqualTo("typeWithDs");
|
||||
assertThat(targetManagement.getByControllerID("id3")).isNotNull();
|
||||
assertThat(targetManagement.getByControllerID("id3").get().getName()).isEqualTo("targetOfType2");
|
||||
assertThat(targetManagement.getByControllerID("id3").get().getDescription()).isEqualTo("testid3");
|
||||
assertThat(targetManagement.getByControllerID("id3").get().getTargetType().getName()).isEqualTo("typeWithOutDs");
|
||||
final Target target1 = assertTarget("id1", "targetWithoutType", "testid1");
|
||||
assertThat(target1.getTargetType()).isNull();
|
||||
assertThat(target1.getSecurityToken()).isEqualTo("token");
|
||||
assertThat(target1.getAddress()).hasToString("amqp://test123/foobar");
|
||||
|
||||
final Target target2 = assertTarget("id2", "targetOfType1", "testid2");
|
||||
assertThat(target2.getTargetType()).extracting(TargetType::getName).isEqualTo("typeWithDs");
|
||||
|
||||
final Target target3 = assertTarget("id3", "targetOfType2", "testid3");
|
||||
assertThat(target3.getTargetType()).extracting(TargetType::getName).isEqualTo("typeWithOutDs");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for creating target with target type works.")
|
||||
public void createTargetWithExistingTargetType() throws Exception {
|
||||
void createTargetWithExistingTargetType() throws Exception {
|
||||
// create target type
|
||||
List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype",1);
|
||||
assertThat(targetTypes).hasSize(1);
|
||||
@@ -2171,7 +2177,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a put request for updating targets with target type works.")
|
||||
public void updateTargetTypeInTarget() throws Exception {
|
||||
void updateTargetTypeInTarget() throws Exception {
|
||||
// create target type
|
||||
List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype",2);
|
||||
assertThat(targetTypes).hasSize(2);
|
||||
@@ -2193,7 +2199,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for creating targets with unknown target type fails.")
|
||||
public void addingNonExistingTargetTypeInTargetShouldFail() throws Exception {
|
||||
void addingNonExistingTargetTypeInTargetShouldFail() throws Exception {
|
||||
long unknownTargetTypeId = 999;
|
||||
String errorMsg = String.format("TargetType with given identifier {%s} does not exist.", unknownTargetTypeId);
|
||||
|
||||
@@ -2213,7 +2219,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for assign target type to target works.")
|
||||
public void assignTargetTypeToTarget() throws Exception {
|
||||
void assignTargetTypeToTarget() throws Exception {
|
||||
// create target type
|
||||
TargetType targetType = testdataFactory.findOrCreateTargetType("targettype");
|
||||
assertThat(targetType).isNotNull();
|
||||
@@ -2233,7 +2239,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a post request for assign a invalid target type to target fails.")
|
||||
public void assignInvalidTargetTypeToTargetFails() throws Exception {
|
||||
void assignInvalidTargetTypeToTargetFails() throws Exception {
|
||||
// Invalid target type ID
|
||||
long invalidTargetTypeId = 999;
|
||||
|
||||
@@ -2260,7 +2266,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a delete request for unassign target type from target works.")
|
||||
public void unassignTargetTypeFromTarget() throws Exception {
|
||||
void unassignTargetTypeFromTarget() throws Exception {
|
||||
// create target type
|
||||
List<TargetType> targetTypes = testdataFactory.createTargetTypes("targettype",1);
|
||||
assertThat(targetTypes).hasSize(1);
|
||||
@@ -2279,10 +2285,10 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidRequestsOnTargetTypeResource() throws Exception {
|
||||
void invalidRequestsOnTargetTypeResource() throws Exception {
|
||||
final String knownTargetId = "targetId";
|
||||
final Target target = testdataFactory.createTarget(knownTargetId);
|
||||
final TargetType targettype = testdataFactory.createTargetType("targettype", Collections.emptyList());
|
||||
testdataFactory.createTarget(knownTargetId);
|
||||
testdataFactory.createTargetType("targettype", Collections.emptyList());
|
||||
|
||||
// GET is not allowed
|
||||
mvc.perform(get(
|
||||
|
||||
@@ -74,9 +74,9 @@ public class RestConfiguration {
|
||||
* filter in the filter chain
|
||||
*/
|
||||
@Bean
|
||||
FilterRegistrationBean eTagFilter() {
|
||||
FilterRegistrationBean<ExcludePathAwareShallowETagFilter> eTagFilter() {
|
||||
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
final FilterRegistrationBean<ExcludePathAwareShallowETagFilter> filterRegBean = new FilterRegistrationBean<>();
|
||||
// Exclude the URLs for downloading artifacts, so no eTag is generated
|
||||
// in the ShallowEtagHeaderFilter, just using the SH1 hash of the
|
||||
// artifact itself as 'ETag', because otherwise the file will be copied
|
||||
|
||||
@@ -151,7 +151,7 @@ public final class FileStreamingUtil {
|
||||
LOG.debug("range header for filename ({}) is: {}", filename, range);
|
||||
|
||||
// Range header matches"bytes=n-n,n-n,n-n..."
|
||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
|
||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*+$")) {
|
||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length);
|
||||
LOG.debug("range header for filename ({}) is not satisfiable: ", filename);
|
||||
return new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.rest.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Management API")
|
||||
@Story("File streaming")
|
||||
class FileStreamingUtilTest {
|
||||
private final static String CONTENT = "This is some very long string which is intended to test";
|
||||
private final static byte[] CONTENT_BYTES = CONTENT.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private static final DbArtifact TEST_ARTIFACT = new DbArtifact() {
|
||||
|
||||
@Override
|
||||
public String getArtifactId() {
|
||||
return "1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbArtifactHash getHashes() {
|
||||
return new DbArtifactHash("sha1-111", "md5-123", "sha256-123");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return CONTENT_BYTES.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getFileInputStream() {
|
||||
return new ByteArrayInputStream(CONTENT_BYTES);
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void shouldProcessRangeHeaderForMultipartRequests() throws IOException {
|
||||
final HttpServletResponse servletResponse = Mockito.mock(HttpServletResponse.class);
|
||||
final ServletOutputStream outputStream = Mockito.mock(ServletOutputStream.class);
|
||||
|
||||
Mockito.when(servletResponse.getOutputStream()).thenReturn(outputStream);
|
||||
final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10,9-15,16-");
|
||||
long lastModified = System.currentTimeMillis();
|
||||
|
||||
final ResponseEntity<InputStream> responseEntity = FileStreamingUtil.writeFileResponse(TEST_ARTIFACT,
|
||||
"test.file", lastModified, servletResponse, servletRequest, null);
|
||||
|
||||
assertThat(responseEntity).isNotNull();
|
||||
verify(servletResponse).setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified);
|
||||
final ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
|
||||
final ArgumentCaptor<Integer> lenCaptor = ArgumentCaptor.forClass(Integer.class);
|
||||
|
||||
verify(outputStream).print(stringCaptor.capture());
|
||||
assertThat(stringCaptor.getValue()).contains("--THIS_STRING_SEPARATES_MULTIPART--");
|
||||
verify(outputStream, times(3)).write(any(), anyInt(), lenCaptor.capture());
|
||||
assertThat(lenCaptor.getAllValues()).containsExactly(11, 7, 39); // Range lengths
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldValidateRangeHeaderForMultipartRequests() throws IOException {
|
||||
long lastModified = System.currentTimeMillis();
|
||||
final HttpServletResponse servletResponse = Mockito.mock(HttpServletResponse.class);
|
||||
final ServletOutputStream outputStream = Mockito.mock(ServletOutputStream.class);
|
||||
Mockito.when(servletResponse.getOutputStream()).thenReturn(outputStream);
|
||||
|
||||
final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10***,9-15,16-");
|
||||
|
||||
final ResponseEntity<InputStream> responseEntity = FileStreamingUtil.writeFileResponse(TEST_ARTIFACT,
|
||||
"test.file", lastModified, servletResponse, servletRequest, null);
|
||||
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
verify(outputStream, times(0)).print(anyString());
|
||||
verify(outputStream, times(0)).write(any(), anyInt(), anyInt());
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
package org.eclipse.hawkbit.rest.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,24 +42,21 @@ public class SortUtilityTest {
|
||||
@Description("Ascending sorting based on name.")
|
||||
public void parseSortParam1() {
|
||||
final List<Order> parse = SortUtility.parse(TargetFields.class, SORT_PARAM_1);
|
||||
assertThat(1).as("Count of parsing parameter").isEqualTo(parse.size());
|
||||
assertThat(parse).as("Count of parsing parameter").hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ascending sorting based on name and descending sorting based on description.")
|
||||
public void parseSortParam2() {
|
||||
final List<Order> parse = SortUtility.parse(TargetFields.class, SORT_PARAM_2);
|
||||
assertThat(2).as("Count of parsing parameter").isEqualTo(parse.size());
|
||||
assertThat(parse).as("Count of parsing parameter").hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Sorting with wrong syntax leads to SortParameterSyntaxErrorException.")
|
||||
public void parseWrongSyntaxParam() {
|
||||
try {
|
||||
SortUtility.parse(TargetFields.class, SYNTAX_FAILURE_SORT_PARAM);
|
||||
fail("SortParameterSyntaxErrorException expected because of wrong syntax");
|
||||
} catch (final SortParameterSyntaxErrorException e) {
|
||||
}
|
||||
assertThrows(SortParameterSyntaxErrorException.class,
|
||||
() -> SortUtility.parse(TargetFields.class, SYNTAX_FAILURE_SORT_PARAM));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,22 +69,14 @@ public class SortUtilityTest {
|
||||
@Test
|
||||
@Description("Sorting with unknown direction order leads to SortParameterUnsupportedDirectionException.")
|
||||
public void parseWrongDirectionParam() {
|
||||
try {
|
||||
SortUtility.parse(TargetFields.class, WRONG_DIRECTION_PARAM);
|
||||
fail("SortParameterUnsupportedDirectionException expected because of unknown direction order");
|
||||
} catch (final SortParameterUnsupportedDirectionException e) {
|
||||
}
|
||||
|
||||
assertThrows(SortParameterUnsupportedDirectionException.class,
|
||||
() -> SortUtility.parse(TargetFields.class, WRONG_DIRECTION_PARAM));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Sorting with unknown field leads to SortParameterUnsupportedFieldException.")
|
||||
public void parseWrongFieldParam() {
|
||||
try {
|
||||
SortUtility.parse(TargetFields.class, WRONG_FIELD_PARAM);
|
||||
fail("SortParameterUnsupportedFieldException expected because of unknown field");
|
||||
} catch (final SortParameterUnsupportedFieldException e) {
|
||||
}
|
||||
|
||||
assertThrows(SortParameterUnsupportedFieldException.class,
|
||||
() -> SortUtility.parse(TargetFields.class, WRONG_FIELD_PARAM));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.im.authentication;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
@@ -22,16 +21,14 @@ import org.springframework.security.core.GrantedAuthority;
|
||||
/**
|
||||
* <p>
|
||||
* Software provisioning permissions that are technically available as
|
||||
* {@link GrantedAuthority} based on the authenticated users identity context.
|
||||
* {@linkplain GrantedAuthority} based on the authenticated users identity
|
||||
* context.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The Permissions cover CRUD for two data areas:
|
||||
*
|
||||
* XX_Target_CRUD which covers the following entities: {@link Target} entities
|
||||
* including metadata, {@link TargetTag}s, {@link TargetRegistrationRule}s
|
||||
* XX_Repository CRUD which covers: {@link DistributionSet}s,
|
||||
* {@link SoftwareModule}s, DS Tags
|
||||
* The permissions cover CRUD operations for various areas within eclipse
|
||||
* hawkBit, like targets, software-artifacts, distribution sets, config-options
|
||||
* etc.
|
||||
* </p>
|
||||
*/
|
||||
public final class SpPermission {
|
||||
@@ -39,69 +36,50 @@ public final class SpPermission {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SpPermission.class);
|
||||
|
||||
/**
|
||||
* Permission to read the targets from the
|
||||
* {@link ProvisioningTargetRepository} including their meta information,
|
||||
* {@link ProvisioningTargetFilter}s and target changing entities (
|
||||
* {@link DistributionSetApplier} and {@link TargetRegistrationRule}). That
|
||||
* corresponds in REST API to GET.
|
||||
* Permission to read the targets (list and filter).
|
||||
*/
|
||||
public static final String READ_TARGET = "READ_TARGET";
|
||||
|
||||
/**
|
||||
* Permission to read the target security token. The security token is
|
||||
* security concerned and should be protected. So the combination
|
||||
* {@link #READ_TARGET} and {@link #READ_TARGET_SEC_TOKEN} is necessary to
|
||||
* able to read the security token of an target.
|
||||
* Permission to read the target security token. The security token is security
|
||||
* concerned and should be protected. So the combination
|
||||
* {@linkplain #READ_TARGET} and {@code READ_TARGET_SEC_TOKEN} is necessary to
|
||||
* be able to read the security token of a target.
|
||||
*/
|
||||
public static final String READ_TARGET_SEC_TOKEN = "READ_TARGET_SECURITY_TOKEN";
|
||||
|
||||
/**
|
||||
* Permission to change/edit/update targets in the
|
||||
* {@link ProvisioningTargetRepository} including their meta information and
|
||||
* or/relations or {@link DistributionSet} assignment,
|
||||
* {@link ProvisioningTargetFilter}s and target changing entities (
|
||||
* {@link DistributionSetApplier} and {@link TargetRegistrationRule}). That
|
||||
* corresponds in REST API to POST.
|
||||
* Permission to change/edit/update targets and to assign updates.
|
||||
*/
|
||||
public static final String UPDATE_TARGET = "UPDATE_TARGET";
|
||||
|
||||
/**
|
||||
* Permission to add new targets to the {@link ProvisioningTargetRepository}
|
||||
* including their meta information and or/relations or
|
||||
* {@link DistributionSet} assignment.That corresponds in REST API to PUT.
|
||||
* Permission to add new targets including their meta information.
|
||||
*/
|
||||
public static final String CREATE_TARGET = "CREATE_TARGET";
|
||||
|
||||
/**
|
||||
* Permission to delete targets in the {@link ProvisioningTargetRepository},
|
||||
* {@link ProvisioningTargetFilter}s and target changing entities (
|
||||
* {@link DistributionSetApplier} and {@link TargetRegistrationRule}). That
|
||||
* corresponds in REST API to DELETE.
|
||||
* Permission to delete targets.
|
||||
*/
|
||||
public static final String DELETE_TARGET = "DELETE_TARGET";
|
||||
|
||||
/**
|
||||
* Permission to read {@link DistributionSet}s and/or {@link OsPackage}s.
|
||||
* That corresponds in REST API to GET.
|
||||
* Permission to read distributions and artifacts.
|
||||
*/
|
||||
public static final String READ_REPOSITORY = "READ_REPOSITORY";
|
||||
|
||||
/**
|
||||
* Permission to edit/update {@link DistributionSet}s including their
|
||||
* {@link OsPackage} assignment and/or {@link OsPackage}s. That corresponds
|
||||
* in REST API to POST.
|
||||
* Permission to edit/update distributions and artifacts.
|
||||
*/
|
||||
public static final String UPDATE_REPOSITORY = "UPDATE_REPOSITORY";
|
||||
|
||||
/**
|
||||
* Permission to add {@link DistributionSet}s and/or {@link OsPackage}s to
|
||||
* the repository. That corresponds in REST API to PUT.
|
||||
* Permission to add distributions and artifacts.
|
||||
*/
|
||||
public static final String CREATE_REPOSITORY = "CREATE_REPOSITORY";
|
||||
|
||||
/**
|
||||
* Permission to delete {@link DistributionSet}s and/or {@link OsPackage}s
|
||||
* from the repository. That corresponds in REST API to DELETE.
|
||||
* Permission to delete distributions and artifacts.
|
||||
*/
|
||||
public static final String DELETE_REPOSITORY = "DELETE_REPOSITORY";
|
||||
|
||||
@@ -112,7 +90,7 @@ public final class SpPermission {
|
||||
public static final String SYSTEM_ADMIN = "SYSTEM_ADMIN";
|
||||
|
||||
/**
|
||||
* Permission to download repository artifact of an software module.
|
||||
* Permission to download repository artifacts of a software module.
|
||||
*/
|
||||
public static final String DOWNLOAD_REPOSITORY_ARTIFACT = "DOWNLOAD_REPOSITORY_ARTIFACT";
|
||||
|
||||
@@ -157,9 +135,6 @@ public final class SpPermission {
|
||||
|
||||
/**
|
||||
* Return all permission.
|
||||
*
|
||||
* @param exclusionRoles
|
||||
* roles which will excluded
|
||||
* @return all permissions
|
||||
*/
|
||||
public static List<String> getAllAuthorities() {
|
||||
@@ -167,7 +142,6 @@ public final class SpPermission {
|
||||
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
|
||||
for (final Field field : declaredFields) {
|
||||
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
final String role = (String) field.get(null);
|
||||
allPermissions.add(role);
|
||||
@@ -219,8 +193,8 @@ public final class SpPermission {
|
||||
public static final String CONTROLLER_ROLE = "ROLE_CONTROLLER";
|
||||
|
||||
/**
|
||||
* The role which contains in the spring security context in case an
|
||||
* controller is authenticated but only as anonymous.
|
||||
* The role which contained in the spring security context in case that a
|
||||
* controller is authenticated, but only as 'anonymous'.
|
||||
*/
|
||||
public static final String CONTROLLER_ROLE_ANONYMOUS = "ROLE_CONTROLLER_ANONYMOUS";
|
||||
|
||||
@@ -359,7 +333,7 @@ public final class SpPermission {
|
||||
|
||||
/**
|
||||
* Spring security eval hasAnyRole expression to check if the spring
|
||||
* context contains the anoynmous role or the controller specific role
|
||||
* context contains the anonymous role or the controller specific role
|
||||
* {@link SpringEvalExpressions#CONTROLLER_ROLE}.
|
||||
*/
|
||||
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
|
||||
|
||||
@@ -46,7 +46,7 @@ public class UserPrincipal extends User {
|
||||
*/
|
||||
public UserPrincipal(final String username, final String firstname, final String lastname, final String loginname,
|
||||
final String email, final String tenant) {
|
||||
this(username, "***", lastname, firstname, loginname, email, tenant, Collections.emptyList());
|
||||
this(username, "***", firstname, lastname, loginname, email, tenant, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,11 +11,13 @@ package org.eclipse.hawkbit.im.authentication;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -26,7 +28,7 @@ import io.qameta.allure.Story;
|
||||
*/
|
||||
@Feature("Unit Tests - Security")
|
||||
@Story("Permission Test")
|
||||
public final class PermissionTest {
|
||||
public final class SpPermissionTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify the get permission function")
|
||||
@@ -38,6 +40,21 @@ public final class PermissionTest {
|
||||
assertThat(allAuthoritiesList).hasSize(allPermission);
|
||||
assertThat(allAuthoritiesList.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList()))
|
||||
.containsAll(allAuthorities);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Try to double check if all permissions works as expected")
|
||||
void shouldReturnAllPermissions() {
|
||||
List<String> expected = new LinkedList<>();
|
||||
ReflectionUtils.doWithFields(SpPermission.class, f -> {
|
||||
if (ReflectionUtils.isPublicStaticFinal(f) && String.class.equals(f.getType())) {
|
||||
try {
|
||||
expected.add((String) f.get(null));
|
||||
} catch (IllegalAccessException | IllegalArgumentException e) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
});
|
||||
assertThat(SpPermission.getAllAuthorities()).containsAll(expected);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An pre-authenticated processing filter which extracts the principal from a
|
||||
* A pre-authenticated processing filter which extracts the principal from a
|
||||
* request URI and the credential from a request header in a the
|
||||
* {@link DmfTenantSecurityToken}.
|
||||
*
|
||||
@@ -44,9 +44,8 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
// X-Ssl-Issuer-Dn-1: CN=Bosch-CA-DE,CN=PKI,DC=Bosch,DC=com
|
||||
// X-Ssl-Issuer-Hash-1: ae:11:f5:6a:0a:e8:74:50:81:0e:0c:37:ec:c5:22:fc
|
||||
private final String caCommonNameHeader;
|
||||
// the X-Ssl-Issuer-Hash basic header header which contains the x509
|
||||
// fingerprint hash, this
|
||||
// header exists multiple in the request for all trusted chain.
|
||||
// the X-Ssl-Issuer-Hash basic header: Contains the x509 fingerprint hash, this
|
||||
// header exists multiple times in the request for all trusted chains.
|
||||
private final String sslIssuerHashBasicHeader;
|
||||
|
||||
/**
|
||||
@@ -76,18 +75,18 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final DmfTenantSecurityToken secruityToken) {
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final DmfTenantSecurityToken securityToken) {
|
||||
// retrieve the common name header and the authority name header from
|
||||
// the http request and combine them together
|
||||
final String commonNameValue = secruityToken.getHeader(caCommonNameHeader);
|
||||
final String knownSslIssuerConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||
final String commonNameValue = securityToken.getHeader(caCommonNameHeader);
|
||||
final String knownSslIssuerConfigurationValue = tenantAware.runAsTenant(securityToken.getTenant(),
|
||||
sslIssuerNameConfigTenantRunner);
|
||||
final String sslIssuerHashValue = getIssuerHashHeader(secruityToken, knownSslIssuerConfigurationValue);
|
||||
final String sslIssuerHashValue = getIssuerHashHeader(securityToken, knownSslIssuerConfigurationValue);
|
||||
if (commonNameValue != null && LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Found commonNameHeader {}={}, using as credentials", caCommonNameHeader, commonNameValue);
|
||||
}
|
||||
if (sslIssuerHashValue != null && LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Found sslIssuerHash ****, using as credentials for tenant {}", secruityToken.getTenant());
|
||||
LOGGER.trace("Found sslIssuerHash ****, using as credentials for tenant {}", securityToken.getTenant());
|
||||
}
|
||||
|
||||
if (commonNameValue != null && sslIssuerHashValue != null) {
|
||||
@@ -97,37 +96,36 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPreAuthenticatedCredentials(final DmfTenantSecurityToken secruityToken) {
|
||||
final String authorityNameConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||
public Object getPreAuthenticatedCredentials(final DmfTenantSecurityToken securityToken) {
|
||||
final String authorityNameConfigurationValue = tenantAware.runAsTenant(securityToken.getTenant(),
|
||||
sslIssuerNameConfigTenantRunner);
|
||||
String controllerId = secruityToken.getControllerId();
|
||||
|
||||
// in case of legacy download artifact, the controller ID is not in the
|
||||
// URL path, so then we just use the common name header
|
||||
if (controllerId == null || "anonymous".equals(controllerId)) {
|
||||
controllerId = secruityToken.getHeader(caCommonNameHeader);
|
||||
}
|
||||
final String controllerId = //
|
||||
(securityToken.getControllerId() == null || "anonymous".equals(securityToken.getControllerId()) //
|
||||
? securityToken.getHeader(caCommonNameHeader)
|
||||
: securityToken.getControllerId());
|
||||
|
||||
final List<String> knownHashes = splitMultiHashBySemicolon(authorityNameConfigurationValue);
|
||||
|
||||
final String cntlId = controllerId;
|
||||
return knownHashes.stream().map(hashItem -> new HeaderAuthentication(cntlId, hashItem))
|
||||
return knownHashes.stream().map(hashItem -> new HeaderAuthentication(controllerId, hashItem))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the {@link #sslIssuerHashBasicHeader} basic header
|
||||
* {@code X-Ssl-Issuer-Hash-%d} and try to finds the same hash as known.
|
||||
* It's ok if we find the the hash in any the trusted CA chain to accept
|
||||
* this request for this tenant.
|
||||
* {@code X-Ssl-Issuer-Hash-%d} and try to find the same hash as known. It's ok
|
||||
* if we find the hash in any the trusted CA chain to accept this request for
|
||||
* this tenant.
|
||||
*/
|
||||
private String getIssuerHashHeader(final DmfTenantSecurityToken secruityToken, final String knownIssuerHashes) {
|
||||
private String getIssuerHashHeader(final DmfTenantSecurityToken securityToken, final String knownIssuerHashes) {
|
||||
// there may be several knownIssuerHashes configured for the tenant
|
||||
final List<String> knownHashes = splitMultiHashBySemicolon(knownIssuerHashes);
|
||||
|
||||
// iterate over the headers until we get a null header.
|
||||
int iHeader = 1;
|
||||
String foundHash;
|
||||
while ((foundHash = secruityToken.getHeader(String.format(sslIssuerHashBasicHeader, iHeader))) != null) {
|
||||
while ((foundHash = securityToken.getHeader(String.format(sslIssuerHashBasicHeader, iHeader))) != null) {
|
||||
if (knownHashes.contains(foundHash.toLowerCase())) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Found matching ssl issuer hash at position {}", iHeader);
|
||||
@@ -137,8 +135,8 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
iHeader++;
|
||||
}
|
||||
LOG_SECURITY_AUTH.debug(
|
||||
"Certifacte request but no matching hash found in headers {} for common name {} in request",
|
||||
sslIssuerHashBasicHeader, secruityToken.getHeader(caCommonNameHeader));
|
||||
"Certificate request but no matching hash found in headers {} for common name {} in request",
|
||||
sslIssuerHashBasicHeader, securityToken.getHeader(caCommonNameHeader));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -156,6 +154,6 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
}
|
||||
|
||||
private static List<String> splitMultiHashBySemicolon(final String knownIssuerHashes) {
|
||||
return Arrays.stream(knownIssuerHashes.split(";|,")).map(String::toLowerCase).collect(Collectors.toList());
|
||||
return Arrays.stream(knownIssuerHashes.split("[;,]")).map(String::toLowerCase).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -23,11 +22,11 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@Feature("Unit Tests - Security")
|
||||
@Story("Issuer hash based authentication")
|
||||
@@ -57,8 +56,6 @@ public class ControllerPreAuthenticatedSecurityHeaderFilterTest {
|
||||
@Mock
|
||||
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
||||
@Mock
|
||||
private DmfTenantSecurityToken tenantSecurityTokenMock;
|
||||
@Mock
|
||||
private UserAuthoritiesResolver authoritiesResolver;
|
||||
|
||||
@BeforeEach
|
||||
@@ -74,7 +71,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilterTest {
|
||||
final DmfTenantSecurityToken securityToken = prepareSecurityToken(SINGLE_HASH);
|
||||
// use single known hash
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME), eq(String.class)))
|
||||
TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME, String.class))
|
||||
.thenReturn(CONFIG_VALUE_SINGLE_HASH);
|
||||
assertThat(underTest.getPreAuthenticatedPrincipal(securityToken)).isNotNull();
|
||||
}
|
||||
@@ -84,7 +81,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilterTest {
|
||||
public void testIssuerHashBasedAuthenticationWithMultipleKnownHashes() {
|
||||
// use multiple known hashes
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME), eq(String.class)))
|
||||
TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME, String.class))
|
||||
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
||||
assertThat(underTest.getPreAuthenticatedPrincipal(prepareSecurityToken(SINGLE_HASH))).isNotNull();
|
||||
assertThat(underTest.getPreAuthenticatedPrincipal(prepareSecurityToken(SECOND_HASH))).isNotNull();
|
||||
@@ -97,7 +94,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilterTest {
|
||||
final DmfTenantSecurityToken securityToken = prepareSecurityToken(UNKNOWN_HASH);
|
||||
// use single known hash
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME), eq(String.class)))
|
||||
TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME, String.class))
|
||||
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
||||
assertThat(underTest.getPreAuthenticatedPrincipal(securityToken)).isNull();
|
||||
}
|
||||
@@ -112,7 +109,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilterTest {
|
||||
final HeaderAuthentication expected2 = new HeaderAuthentication(CA_COMMON_NAME_VALUE, SECOND_HASH);
|
||||
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME), eq(String.class)))
|
||||
TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME, String.class))
|
||||
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
||||
|
||||
final Collection<HeaderAuthentication> credentials1 = (Collection<HeaderAuthentication>) underTest
|
||||
@@ -123,8 +120,8 @@ public class ControllerPreAuthenticatedSecurityHeaderFilterTest {
|
||||
final Object principal1 = underTest.getPreAuthenticatedPrincipal(securityToken1);
|
||||
final Object principal2 = underTest.getPreAuthenticatedPrincipal(securityToken2);
|
||||
|
||||
assertThat(credentials1.contains(expected1)).isTrue();
|
||||
assertThat(credentials2.contains(expected2)).isTrue();
|
||||
assertThat(credentials1).contains(expected1);
|
||||
assertThat(credentials2).contains(expected2);
|
||||
|
||||
assertThat(expected1).as("hash1 expected in principal!").isEqualTo(principal1);
|
||||
assertThat(expected2).as("hash2 expected in principal!").isEqualTo(principal2);
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
<phase>process-classes</phase>
|
||||
<configuration>
|
||||
<!-- if you don't specify any modules, the plugin will find them -->
|
||||
<!-- <modules> <module>com.vaadin.demo.mobilemail.gwt.ColorPickerWidgetSet</module> </modules> -->
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>resources</goal>
|
||||
|
||||
@@ -91,18 +91,18 @@ public class FileTransferHandlerStreamVariable extends AbstractFileTransferHandl
|
||||
return ByteStreams.nullOutputStream();
|
||||
}
|
||||
|
||||
// we return the outputstream so we cannot close it here
|
||||
// we return the output stream - we cannot close it here
|
||||
@SuppressWarnings("squid:S2095")
|
||||
final PipedOutputStream outputStream = new PipedOutputStream();
|
||||
PipedInputStream inputStream = null;
|
||||
final PipedInputStream inputStream;
|
||||
try {
|
||||
inputStream = new PipedInputStream(outputStream);
|
||||
publishUploadProgressEvent(fileUploadId, 0, fileSize);
|
||||
startTransferToRepositoryThread(inputStream, fileUploadId, mimeType);
|
||||
} catch (final IOException e) {
|
||||
LOG.warn("Creating piped Stream failed {}.", e);
|
||||
LOG.warn("Creating piped Stream failed {}.", e.getMessage());
|
||||
tryToCloseIOStream(outputStream);
|
||||
tryToCloseIOStream(inputStream);
|
||||
// input stream is not created in case of and IOException here
|
||||
interruptUploadDueToUploadFailed();
|
||||
publishUploadFailedAndFinishedEvent(fileUploadId);
|
||||
return ByteStreams.nullOutputStream();
|
||||
|
||||
@@ -54,7 +54,7 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
|
||||
private final transient SoftwareModuleManagement softwareModuleManagement;
|
||||
private final long maxSize;
|
||||
|
||||
private volatile FileUploadId fileUploadId;
|
||||
private FileUploadId fileUploadId;
|
||||
|
||||
FileTransferHandlerVaadinUpload(final long maxSize, final SoftwareModuleManagement softwareManagement,
|
||||
final ArtifactManagement artifactManagement, final VaadinMessageSource i18n, final Lock uploadLock) {
|
||||
@@ -64,6 +64,11 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
|
||||
this.softwareModuleManagement = softwareManagement;
|
||||
}
|
||||
|
||||
private synchronized FileUploadId setFileUploadId(final String fileName, final SoftwareModule softwareModule) {
|
||||
this.fileUploadId = new FileUploadId(fileName, softwareModule);
|
||||
return fileUploadId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload started for {@link Upload} variant.
|
||||
*
|
||||
@@ -75,8 +80,7 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
|
||||
resetState();
|
||||
|
||||
final SoftwareModule softwareModule = getSelectedSoftwareModule();
|
||||
|
||||
this.fileUploadId = new FileUploadId(event.getFilename(), softwareModule);
|
||||
final FileUploadId fupId = setFileUploadId(event.getFilename(), softwareModule);
|
||||
|
||||
if (getUploadState().isFileInUploadState(this.fileUploadId)) {
|
||||
// actual interrupt will happen a bit late so setting the below
|
||||
@@ -84,15 +88,14 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
|
||||
interruptUploadDueToDuplicateFile();
|
||||
event.getUpload().interruptUpload();
|
||||
} else {
|
||||
publishUploadStarted(fileUploadId);
|
||||
publishUploadStarted(fupId);
|
||||
|
||||
if (RegexCharacterCollection.stringContainsCharacter(event.getFilename(), ILLEGAL_FILENAME_CHARACTERS)) {
|
||||
LOG.debug("Filename contains illegal characters {} for upload {}", fileUploadId.getFilename(),
|
||||
fileUploadId);
|
||||
LOG.debug("Filename contains illegal characters {} for upload {}", fupId.getFilename(), fupId);
|
||||
interruptUploadDueToIllegalFilename();
|
||||
event.getUpload().interruptUpload();
|
||||
} else if (isFileAlreadyContainedInSoftwareModule(fileUploadId, softwareModule)) {
|
||||
LOG.debug("File {} already contained in Software Module {}", fileUploadId.getFilename(),
|
||||
} else if (isFileAlreadyContainedInSoftwareModule(fupId, softwareModule)) {
|
||||
LOG.debug("File {} already contained in Software Module {}", fupId.getFilename(),
|
||||
softwareModule);
|
||||
interruptUploadDueToDuplicateFile();
|
||||
event.getUpload().interruptUpload();
|
||||
@@ -115,7 +118,6 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
|
||||
*/
|
||||
@Override
|
||||
public OutputStream receiveUpload(final String fileName, final String mimeType) {
|
||||
|
||||
if (isUploadInterrupted()) {
|
||||
return ByteStreams.nullOutputStream();
|
||||
}
|
||||
@@ -123,15 +125,14 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
|
||||
// we return the outputstream so we cannot close it here
|
||||
@SuppressWarnings("squid:S2095")
|
||||
final PipedOutputStream outputStream = new PipedOutputStream();
|
||||
PipedInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new PipedInputStream(outputStream);
|
||||
PipedInputStream inputStream = new PipedInputStream(outputStream);
|
||||
publishUploadProgressEvent(fileUploadId, 0, 0);
|
||||
startTransferToRepositoryThread(inputStream, fileUploadId, mimeType);
|
||||
} catch (final IOException e) {
|
||||
LOG.warn("Creating piped Stream failed {}.", e);
|
||||
LOG.warn("Creating piped Stream failed!", e);
|
||||
tryToCloseIOStream(outputStream);
|
||||
tryToCloseIOStream(inputStream);
|
||||
// input stream is not created in case of an IOException
|
||||
interruptUploadDueToUploadFailed();
|
||||
publishUploadFailedAndFinishedEvent(fileUploadId);
|
||||
return ByteStreams.nullOutputStream();
|
||||
|
||||
@@ -29,7 +29,7 @@ public abstract class AbstractAddEntityWindowController<T, E, R> extends Abstrac
|
||||
* @param uiDependencies
|
||||
* {@link CommonUiDependencies}
|
||||
*/
|
||||
public AbstractAddEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
protected AbstractAddEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
super(uiDependencies);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public abstract class AbstractAddNamedEntityWindowController<T, E extends ProxyN
|
||||
* @param uiDependencies
|
||||
* {@link CommonUiDependencies}
|
||||
*/
|
||||
public AbstractAddNamedEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
protected AbstractAddNamedEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
super(uiDependencies);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public abstract class AbstractUpdateEntityWindowController<T, E, R> extends Abst
|
||||
* @param uiDependencies
|
||||
* {@link CommonUiDependencies}
|
||||
*/
|
||||
public AbstractUpdateEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
protected AbstractUpdateEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
super(uiDependencies);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public abstract class AbstractUpdateNamedEntityWindowController<T, E extends Pro
|
||||
* @param uiDependencies
|
||||
* {@link CommonUiDependencies}
|
||||
*/
|
||||
public AbstractUpdateNamedEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
protected AbstractUpdateNamedEntityWindowController(final CommonUiDependencies uiDependencies) {
|
||||
super(uiDependencies);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.common.data.proxies;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
|
||||
/**
|
||||
* Proxy entity representing the {@link Identifiable} entity, fetched from
|
||||
@@ -23,7 +25,7 @@ public abstract class ProxyIdentifiableEntity implements Serializable {
|
||||
/**
|
||||
* Constructor to initialize the id with null
|
||||
*/
|
||||
public ProxyIdentifiableEntity() {
|
||||
protected ProxyIdentifiableEntity() {
|
||||
this.id = null;
|
||||
}
|
||||
|
||||
@@ -32,7 +34,7 @@ public abstract class ProxyIdentifiableEntity implements Serializable {
|
||||
* @param id
|
||||
* Id of entity
|
||||
*/
|
||||
public ProxyIdentifiableEntity(final Long id) {
|
||||
protected ProxyIdentifiableEntity(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -64,25 +66,13 @@ public abstract class ProxyIdentifiableEntity implements Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ProxyIdentifiableEntity other = (ProxyIdentifiableEntity) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
final ProxyIdentifiableEntity that = (ProxyIdentifiableEntity) o;
|
||||
return Objects.equals(id, that.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,7 +32,7 @@ public abstract class ProxyNamedEntity extends ProxyIdentifiableEntity implement
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ProxyNamedEntity() {
|
||||
protected ProxyNamedEntity() {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,7 +41,7 @@ public abstract class ProxyNamedEntity extends ProxyIdentifiableEntity implement
|
||||
* @param id
|
||||
* Id of named entity
|
||||
*/
|
||||
public ProxyNamedEntity(final Long id) {
|
||||
protected ProxyNamedEntity(final Long id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract class AbstractGridDetailsLayout<T extends ProxyNamedEntity> exte
|
||||
* @param i18n
|
||||
* VaadinMessageSource
|
||||
*/
|
||||
public AbstractGridDetailsLayout(final VaadinMessageSource i18n) {
|
||||
protected AbstractGridDetailsLayout(final VaadinMessageSource i18n) {
|
||||
this.i18n = i18n;
|
||||
|
||||
this.binder = new Binder<>();
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.vaadin.server.Sizeable.Unit;
|
||||
import com.vaadin.ui.Window;
|
||||
|
||||
/**
|
||||
* Abstract builder for Meta data window
|
||||
* Abstract builder for metadata window
|
||||
*
|
||||
* @param <F>
|
||||
* Generic type
|
||||
@@ -31,7 +31,7 @@ public abstract class AbstractMetaDataWindowBuilder<F> extends AbstractEntityWin
|
||||
* @param uiDependencies
|
||||
* {@link CommonUiDependencies}
|
||||
*/
|
||||
public AbstractMetaDataWindowBuilder(final CommonUiDependencies uiDependencies) {
|
||||
protected AbstractMetaDataWindowBuilder(final CommonUiDependencies uiDependencies) {
|
||||
super(uiDependencies);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract class AbstractMetaDataWindowLayout<F> extends HorizontalLayout {
|
||||
* @param uiDependencies
|
||||
* {@link CommonUiDependencies}
|
||||
*/
|
||||
public AbstractMetaDataWindowLayout(final CommonUiDependencies uiDependencies) {
|
||||
protected AbstractMetaDataWindowLayout(final CommonUiDependencies uiDependencies) {
|
||||
this.uiDependencies = uiDependencies;
|
||||
this.i18n = uiDependencies.getI18n();
|
||||
this.eventBus = uiDependencies.getEventBus();
|
||||
|
||||
@@ -46,7 +46,7 @@ public abstract class AbstractBreadcrumbGridHeader extends AbstractGridHeader {
|
||||
* @param eventBus
|
||||
* UIEventBus
|
||||
*/
|
||||
public AbstractBreadcrumbGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
protected AbstractBreadcrumbGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
final UIEventBus eventBus) {
|
||||
super(i18n, permChecker, eventBus);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public abstract class AbstractDetailsHeader<T> extends AbstractMasterAwareGridHe
|
||||
* @param uiNotification
|
||||
* UINotification
|
||||
*/
|
||||
public AbstractDetailsHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
protected AbstractDetailsHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
final UIEventBus eventBus, final UINotification uiNotification) {
|
||||
super(i18n, permChecker, eventBus);
|
||||
|
||||
@@ -67,7 +67,7 @@ public abstract class AbstractDetailsHeader<T> extends AbstractMasterAwareGridHe
|
||||
addHeaderSupports(Arrays.asList(editDetailsHeaderSupport, metaDataDetailsHeaderSupport));
|
||||
}
|
||||
|
||||
// can be overriden in child classes for entity-specific permission
|
||||
// can be overridden in child classes for entity-specific permission
|
||||
protected boolean hasEditPermission() {
|
||||
return permChecker.hasUpdateRepositoryPermission();
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public abstract class AbstractDetailsHeader<T> extends AbstractMasterAwareGridHe
|
||||
return true;
|
||||
}
|
||||
|
||||
// can be overriden in child classes for entity-specific permission
|
||||
// can be overridden in child classes for entity-specific permission
|
||||
protected boolean hasMetadataReadPermission() {
|
||||
return permChecker.hasReadRepositoryPermission();
|
||||
}
|
||||
|
||||
@@ -68,7 +68,8 @@ public abstract class AbstractEntityGridHeader extends AbstractGridHeader {
|
||||
* @param view
|
||||
* EventView
|
||||
*/
|
||||
public AbstractEntityGridHeader(final CommonUiDependencies uiDependencies, final HidableLayoutUiState filterLayoutUiState,
|
||||
protected AbstractEntityGridHeader(final CommonUiDependencies uiDependencies,
|
||||
final HidableLayoutUiState filterLayoutUiState,
|
||||
final GridLayoutUiState gridLayoutUiState, final EventLayout filterLayout, final EventView view) {
|
||||
super(uiDependencies.getI18n(), uiDependencies.getPermChecker(), uiDependencies.getEventBus());
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public abstract class AbstractFilterHeader extends AbstractGridHeader {
|
||||
* @param eventBus
|
||||
* UIEventBus
|
||||
*/
|
||||
public AbstractFilterHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
protected AbstractFilterHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
final UIEventBus eventBus) {
|
||||
super(i18n, permChecker, eventBus);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
||||
* @param eventBus
|
||||
* UIEventBus
|
||||
*/
|
||||
public AbstractGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
protected AbstractGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
final UIEventBus eventBus) {
|
||||
this.i18n = i18n;
|
||||
this.permChecker = permChecker;
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class AbstractMasterAwareGridHeader<T> extends AbstractGridHeade
|
||||
* @param eventBus
|
||||
* UIEventBus
|
||||
*/
|
||||
public AbstractMasterAwareGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
protected AbstractMasterAwareGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
final UIEventBus eventBus) {
|
||||
super(i18n, permChecker, eventBus);
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public class TargetFilterAddUpdateLayout extends AbstractEntityWindowLayout<Prox
|
||||
* @param rsqlValidationOracle
|
||||
* RsqlValidationOracle
|
||||
*/
|
||||
public TargetFilterAddUpdateLayout(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
protected TargetFilterAddUpdateLayout(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
|
||||
final UiProperties uiProperties, final TargetFilterDetailsLayoutUiState uiState, final UIEventBus eventBus,
|
||||
final RsqlValidationOracle rsqlValidationOracle) {
|
||||
super();
|
||||
@@ -140,7 +140,8 @@ public class TargetFilterAddUpdateLayout extends AbstractEntityWindowLayout<Prox
|
||||
autoCompleteComponent.addValidationListener((valid, message) -> searchButton.setEnabled(valid));
|
||||
autoCompleteComponent.addTextfieldChangedListener(this::onFilterQueryTextfieldChanged);
|
||||
autoCompleteComponent
|
||||
.addShortcutListener(new ShortcutListener("List Filtered Targets", ShortcutAction.KeyCode.ENTER, null) {
|
||||
.addShortcutListener(
|
||||
new ShortcutListener("List Filtered Targets", ShortcutAction.KeyCode.ENTER, (int[]) null) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
@@ -200,13 +201,6 @@ public class TargetFilterAddUpdateLayout extends AbstractEntityWindowLayout<Prox
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable search button
|
||||
*/
|
||||
public void disableSearchButton() {
|
||||
searchButton.setEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validity of target filter query.
|
||||
*
|
||||
|
||||
@@ -95,7 +95,7 @@ public class DeploymentAssignmentWindowController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given distribution sets to targets assignments
|
||||
* Save the given distribution sets to target assignments
|
||||
*
|
||||
* @param proxyTargets
|
||||
* to assign the given distribution sets to
|
||||
@@ -140,7 +140,7 @@ public class DeploymentAssignmentWindowController {
|
||||
EntityModifiedEventType.ENTITY_UPDATED, ProxyTarget.class, assignedTargetIds));
|
||||
} catch (final MultiAssignmentIsNotEnabledException e) {
|
||||
notification.displayValidationError(i18n.getMessage("message.target.ds.multiassign.error"));
|
||||
LOG.error("UI allowed multiassignment although it is not enabled: {}", e);
|
||||
LOG.error("UI allowed multi-assignment although it is not enabled", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,14 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.vaadin.data.Binder;
|
||||
import com.vaadin.ui.CustomComponent;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.ui.common.data.proxies.ProxySystemConfigWindow;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import com.vaadin.data.Binder;
|
||||
import com.vaadin.ui.CustomComponent;
|
||||
|
||||
/**
|
||||
* Base class for all configuration views. This class implements the logic for
|
||||
* the handling of the configurations in a consistent way.
|
||||
@@ -33,7 +34,7 @@ public abstract class BaseConfigurationView<B extends ProxySystemConfigWindow> e
|
||||
private final transient TenantConfigurationManagement tenantConfigurationManagement;
|
||||
private final Binder<B> binder;
|
||||
|
||||
public BaseConfigurationView(final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||
protected BaseConfigurationView(final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||
binder = new Binder<>();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.TimeZone;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyNamedEntity;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
@@ -99,10 +98,10 @@ public final class SPDateTimeUtil {
|
||||
*
|
||||
* @param lastQueryDate
|
||||
* Last query date
|
||||
* @return String formatted date
|
||||
* @return String formatted date or {@code null} when the provided {@code lastQueryDate} was {@code null}
|
||||
*/
|
||||
public static String getFormattedDate(final Long lastQueryDate) {
|
||||
return formatDate(lastQueryDate, null);
|
||||
return getFormattedDate(lastQueryDate, SPUIDefinitions.LAST_QUERY_DATE_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,67 +111,15 @@ public final class SPDateTimeUtil {
|
||||
* Last query date
|
||||
* @param datePattern
|
||||
* pattern how to format the date (cp. {@code SimpleDateFormat})
|
||||
* @return String formatted date
|
||||
* @return String formatted date or {@code null} when the provided {@code lastQueryDate} was {@code null}
|
||||
*/
|
||||
public static String getFormattedDate(final Long lastQueryDate, final String datePattern) {
|
||||
return formatDate(lastQueryDate, null, datePattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted date 'created at' by entity.
|
||||
*
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @return String formatted date
|
||||
*/
|
||||
public static String formatCreatedAt(final ProxyNamedEntity baseEntity) {
|
||||
if (baseEntity == null) {
|
||||
return "";
|
||||
}
|
||||
return formatDate(baseEntity.getCreatedAt(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted date 'last modified at' by entity.
|
||||
*
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @return String formatted date
|
||||
*/
|
||||
public static String formatLastModifiedAt(final ProxyNamedEntity baseEntity) {
|
||||
if (baseEntity == null) {
|
||||
return "";
|
||||
}
|
||||
return formatDate(baseEntity.getLastModifiedAt(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted date 'last modified at' by entity.
|
||||
*
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @param datePattern
|
||||
* pattern how to format the date (cp. {@code SimpleDateFormat})
|
||||
* @return String formatted date
|
||||
*/
|
||||
public static String formatLastModifiedAt(final ProxyNamedEntity baseEntity, final String datePattern) {
|
||||
if (baseEntity == null) {
|
||||
return "";
|
||||
}
|
||||
return formatDate(baseEntity.getLastModifiedAt(), "", datePattern);
|
||||
}
|
||||
|
||||
private static String formatDate(final Long lastQueryDate, final String defaultString, final String datePattern) {
|
||||
if (lastQueryDate != null) {
|
||||
final SimpleDateFormat format = new SimpleDateFormat(datePattern);
|
||||
format.setTimeZone(getBrowserTimeZone());
|
||||
return format.format(new Date(lastQueryDate));
|
||||
}
|
||||
return defaultString;
|
||||
}
|
||||
|
||||
private static String formatDate(final Long lastQueryDate, final String defaultString) {
|
||||
return formatDate(lastQueryDate, defaultString, SPUIDefinitions.LAST_QUERY_DATE_FORMAT);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,10 +173,10 @@ public final class SPDateTimeUtil {
|
||||
* Get time zone of the browser client to be used as default.
|
||||
*/
|
||||
public static String getClientTimeZoneOffsetId() {
|
||||
return getCurentZonedDateTime().getOffset().getId().replaceAll("Z", "+00:00");
|
||||
return getCurrentZonedDateTime().getOffset().getId().replace("Z", "+00:00");
|
||||
}
|
||||
|
||||
private static ZonedDateTime getCurentZonedDateTime() {
|
||||
private static ZonedDateTime getCurrentZonedDateTime() {
|
||||
return ZonedDateTime.now(getBrowserTimeZoneId());
|
||||
}
|
||||
|
||||
@@ -243,7 +190,7 @@ public final class SPDateTimeUtil {
|
||||
* @return Two weeks from current date and time in epoc milliseconds
|
||||
*/
|
||||
public static Long twoWeeksFromNowEpochMilli() {
|
||||
return getCurentZonedDateTime().plusWeeks(2).toInstant().toEpochMilli();
|
||||
return getCurrentZonedDateTime().plusWeeks(2).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,7 +199,7 @@ public final class SPDateTimeUtil {
|
||||
* @return Half an hour from current date and time in epoc milliseconds
|
||||
*/
|
||||
public static Long halfAnHourFromNowEpochMilli() {
|
||||
return getCurentZonedDateTime().plusMinutes(30).toInstant().toEpochMilli();
|
||||
return getCurrentZonedDateTime().plusMinutes(30).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,11 +46,11 @@ public class HawkbitCommonUtilTest {
|
||||
// WHEN
|
||||
final Locale currentLocale2 = HawkbitCommonUtil.getCurrentLocale();
|
||||
// THEN
|
||||
assertThat(Locale.GERMAN).isEqualTo(currentLocale2);
|
||||
assertThat(currentLocale2).isEqualTo(Locale.GERMAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("If a default locale is set in the environment, then it should take perceedence over requested browser locale")
|
||||
@Description("If a default locale is set in the environment, then it should take precedence over requested browser locale")
|
||||
public void getLocaleToBeUsedShouldReturnDefaultLocalIfSet() {
|
||||
final UiProperties.Localization localizationProperties = Mockito.mock(UiProperties.Localization.class);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class HawkbitCommonUtilTest {
|
||||
// WHEN
|
||||
final Locale localeToBeUsed = HawkbitCommonUtil.getLocaleToBeUsed(localizationProperties, Locale.CHINESE);
|
||||
// THEN
|
||||
assertThat(Locale.GERMAN).isEqualTo(localeToBeUsed);
|
||||
assertThat(localeToBeUsed).isEqualTo(Locale.GERMAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,7 +74,7 @@ public class HawkbitCommonUtilTest {
|
||||
// WHEN
|
||||
final Locale localeToBeUsed = HawkbitCommonUtil.getLocaleToBeUsed(localizationProperties, Locale.GERMAN);
|
||||
// THEN
|
||||
assertThat(Locale.GERMAN).isEqualTo(localeToBeUsed);
|
||||
assertThat(localeToBeUsed).isEqualTo(Locale.GERMAN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
3
pom.xml
3
pom.xml
@@ -129,8 +129,7 @@
|
||||
<properties>
|
||||
|
||||
<java.version>1.8</java.version>
|
||||
<!-- Developer preview -->
|
||||
<!-- <java.version>11</java.version> -->
|
||||
<!-- Developer preview: java.version = 11 -->
|
||||
|
||||
<spring.boot.version>2.3.7.RELEASE</spring.boot.version>
|
||||
<spring.cloud.version>Hoxton.SR7</spring.cloud.version>
|
||||
|
||||
Reference in New Issue
Block a user