DDI supports sha256 (#869)

* Add SHA256 file hash to ddi GET outputs

Signed-off-by: Alexander Dobler <alexander.dobler3@bosch-si.com>

* Integrate review findings for SHA256 changes

Signed-off-by: Alexander Dobler <alexander.dobler3@bosch-si.com>

* Renamed hashes to base16hases in store() parameters

Signed-off-by: Alexander Dobler <alexander.dobler3@bosch-si.com>

* Added missing javadoc according to sonarqube findings

Signed-off-by: Alexander Dobler <alexander.dobler3@bosch-si.com>
This commit is contained in:
Alexander Dobler
2019-07-29 14:11:40 +02:00
committed by Dominic Schabel
parent fba6cf9787
commit bde3548846
20 changed files with 131 additions and 53 deletions

View File

@@ -62,16 +62,14 @@ public class ArtifactFilesystemRepository extends AbstractArtifactRepository {
return null;
}
return new ArtifactFilesystem(file, sha1, new DbArtifactHash(sha1, null), file.length(), null);
return new ArtifactFilesystem(file, sha1, new DbArtifactHash(sha1, null, null), file.length(), null);
}
@Override
protected AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
final String contentType, final String tempFile) throws IOException {
protected AbstractDbArtifact store(final String tenant, final DbArtifactHash base16Hashes, final String contentType, final String tempFile) throws IOException {
final File file = new File(tempFile);
return renameFileToSHA1Naming(tenant, file, new ArtifactFilesystem(file, sha1Hash16,
new DbArtifactHash(sha1Hash16, mdMD5Hash16), file.length(), contentType));
return renameFileToSHA1Naming(tenant, file, new ArtifactFilesystem(file, base16Hashes.getSha1(), base16Hashes, file.length(), contentType));
}
private ArtifactFilesystem renameFileToSHA1Naming(final String tenant, final File file,

View File

@@ -32,7 +32,7 @@ public class ArtifactFilesystemTest {
public void getInputStreamOfNonExistingFileThrowsException() {
final File file = new File("fileWhichTotalDoesNotExists");
final ArtifactFilesystem underTest = new ArtifactFilesystem(file, "fileWhichTotalDoesNotExists",
new DbArtifactHash("1", "2"), 0L, null);
new DbArtifactHash("1", "2", "3"), 0L, null);
try {
underTest.getFileInputStream();
Assertions.fail("Expected a FileNotFoundException because file does not exists");
@@ -48,7 +48,7 @@ public class ArtifactFilesystemTest {
createTempFile.deleteOnExit();
final ArtifactFilesystem underTest = new ArtifactFilesystem(createTempFile,
ArtifactFilesystemTest.class.getSimpleName(), new DbArtifactHash("1", "2"), 0L, null);
ArtifactFilesystemTest.class.getSimpleName(), new DbArtifactHash("1", "2", "3"), 0L, null);
final byte[] buffer = new byte[1024];
IOUtils.read(underTest.getFileInputStream(), buffer);
}

View File

@@ -42,27 +42,31 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
// is not used security related
@SuppressWarnings("squid:S2070")
public AbstractDbArtifact store(final String tenant, final InputStream content, final String filename,
final String contentType, final DbArtifactHash hash) {
final String contentType, final DbArtifactHash providedHashes) {
final MessageDigest mdSHA1;
final MessageDigest mdMD5;
final MessageDigest mdSHA256;
try {
mdSHA1 = MessageDigest.getInstance("SHA1");
mdMD5 = MessageDigest.getInstance("MD5");
mdSHA256 = MessageDigest.getInstance("SHA-256");
} catch (final NoSuchAlgorithmException e) {
throw new ArtifactStoreException(e.getMessage(), e);
}
String tempFile = null;
try (final DigestInputStream inputstream = wrapInDigestInputStream(content, mdSHA1, mdMD5)) {
try (final DigestInputStream inputstream = wrapInDigestInputStream(content, mdSHA1, mdMD5, mdSHA256)) {
tempFile = storeTempFile(inputstream);
final String sha1Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
final String md5Hash16 = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
final String sha256Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA256.digest());
checkHashes(sha1Hash16, md5Hash16, hash);
checkHashes(sha1Hash16, md5Hash16, sha256Hash16, providedHashes);
return store(sanitizeTenant(tenant), sha1Hash16, md5Hash16, contentType, tempFile);
return store(sanitizeTenant(tenant), new DbArtifactHash(sha1Hash16, md5Hash16, sha256Hash16), contentType,
tempFile);
} catch (final IOException e) {
throw new ArtifactStoreException(e.getMessage(), e);
} finally {
@@ -100,27 +104,35 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
}
}
private static void checkHashes(final String sha1Hash16, final String md5Hash16, final DbArtifactHash hash) {
if (hash == null) {
private static void checkHashes(final String sha1Hash16, final String md5Hash16, final String sha256Hash16,
final DbArtifactHash providedHashes) {
if (providedHashes == null) {
return;
}
if (hash.getSha1() != null && !sha1Hash16.equals(hash.getSha1())) {
throw new HashNotMatchException("The given sha1 hash " + hash.getSha1()
+ " does not match with the calcualted sha1 hash " + sha1Hash16, HashNotMatchException.SHA1);
if (areHashesNotMatching(providedHashes.getSha1(), sha1Hash16)) {
throw new HashNotMatchException("The given sha1 hash " + providedHashes.getSha1()
+ " does not match the calculated sha1 hash " + sha1Hash16, HashNotMatchException.SHA1);
}
if (hash.getMd5() != null && !md5Hash16.equals(hash.getMd5())) {
throw new HashNotMatchException(
"The given md5 hash " + hash.getMd5() + " does not match with the calcualted md5 hash " + md5Hash16,
HashNotMatchException.MD5);
if (areHashesNotMatching(providedHashes.getMd5(), md5Hash16)) {
throw new HashNotMatchException("The given md5 hash " + providedHashes.getMd5()
+ " does not match the calculated md5 hash " + md5Hash16, HashNotMatchException.MD5);
}
if (areHashesNotMatching(providedHashes.getSha256(), sha256Hash16)) {
throw new HashNotMatchException("The given sha256 hash " + providedHashes.getSha256()
+ " does not match the calculated sha256 hash " + sha256Hash16, HashNotMatchException.SHA256);
}
}
protected abstract AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
private static boolean areHashesNotMatching(String providedHashValue, String hashValue) {
return providedHashValue != null && !hashValue.equals(providedHashValue);
}
protected abstract AbstractDbArtifact store(final String tenant, final DbArtifactHash base16Hashes,
final String contentType, final String tempFile) throws IOException;
private static DigestInputStream wrapInDigestInputStream(final InputStream input, final MessageDigest mdSHA1,
final MessageDigest mdMD5) {
return new DigestInputStream(new DigestInputStream(input, mdMD5), mdSHA1);
final MessageDigest mdMD5, final MessageDigest mdSHA256) {
return new DigestInputStream(new DigestInputStream(new DigestInputStream(input, mdSHA256), mdMD5), mdSHA1);
}
protected static String sanitizeTenant(final String tenant) {

View File

@@ -21,6 +21,7 @@ public class HashNotMatchException extends RuntimeException {
public static final String SHA1 = "SHA-1";
public static final String MD5 = "MD5";
public static final String SHA256 = "SHA-256";
private final String hashFunction;

View File

@@ -18,6 +18,8 @@ public class DbArtifactHash {
private final String md5;
private final String sha256;
/**
* Constructor.
*
@@ -25,10 +27,13 @@ public class DbArtifactHash {
* the sha1 hash
* @param md5
* the md5 hash
* @param sha256
* the sha256 hash
*/
public DbArtifactHash(final String sha1, final String md5) {
public DbArtifactHash(final String sha1, final String md5, final String sha256) {
this.sha1 = sha1;
this.md5 = md5;
this.sha256 = sha256;
}
public String getSha1() {
@@ -39,4 +44,7 @@ public class DbArtifactHash {
return md5;
}
public String getSha256() {
return sha256;
}
}

View File

@@ -167,14 +167,14 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
}
@Test
@Description("Verifies that download and install event with software moduls and artifacts works")
@Description("Verifies that download and install event with software modules and artifacts works")
public void testSendDownloadRequest() {
DistributionSet dsA = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
SoftwareModule module = dsA.getModules().iterator().next();
final List<AbstractDbArtifact> receivedList = new ArrayList<>();
for (final Artifact artifact : testdataFactory.createArtifacts(module.getId())) {
receivedList.add(new ArtifactFilesystem(new File("./test"), artifact.getSha1Hash(),
new DbArtifactHash(artifact.getSha1Hash(), null), artifact.getSize(), null));
new DbArtifactHash(artifact.getSha1Hash(), null, null), artifact.getSize(), null));
}
module = softwareModuleManagement.get(module.getId()).get();
dsA = distributionSetManagement.get(dsA.getId()).get();

View File

@@ -38,6 +38,11 @@ public interface Artifact extends TenantAwareBaseEntity {
*/
String getSha1Hash();
/**
* @return SHA-256 hash of the artifact.
*/
String getSha256Hash();
/**
* @return size of the artifact in bytes.
*/

View File

@@ -35,6 +35,8 @@ public class ArtifactUpload {
private final String providedSha1Sum;
private final String providedSha256Sum;
private final boolean overrideExisting;
private final String contentType;
@@ -90,6 +92,7 @@ public class ArtifactUpload {
this.filename = filename;
this.providedMd5Sum = providedMd5Sum;
this.providedSha1Sum = providedSha1Sum;
this.providedSha256Sum = null;
this.overrideExisting = overrideExisting;
this.contentType = contentType;
this.filesize = filesize;
@@ -115,6 +118,10 @@ public class ArtifactUpload {
return providedSha1Sum;
}
public String getProvidedSha256Sum() {
return providedSha256Sum;
}
public boolean overrideExisting() {
return overrideExisting;
}

View File

@@ -128,7 +128,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
try {
return artifactRepository.store(tenantAware.getCurrentTenant(), artifactUpload.getInputStream(),
artifactUpload.getFilename(), artifactUpload.getContentType(),
new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum()));
new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum(), artifactUpload.getProvidedSha256Sum()));
} catch (final ArtifactStoreException e) {
throw new ArtifactUploadFailedException(e);
} catch (final HashNotMatchException e) {
@@ -256,6 +256,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
artifact = new JpaArtifact(result.getHashes().getSha1(), providedFilename, softwareModule);
}
artifact.setMd5Hash(result.getHashes().getMd5());
artifact.setSha256Hash(result.getHashes().getSha256());
artifact.setSha1Hash(result.getHashes().getSha1());
artifact.setSize(result.getSize());

View File

@@ -57,6 +57,9 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art
@Column(name = "md5_hash", length = 32, updatable = false, nullable = true)
private String md5Hash;
@Column(name = "sha256_hash", length = 64, updatable = false, nullable = true)
private String sha256Hash;
@Column(name = "file_size", updatable = false)
private long size;
@@ -94,6 +97,11 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art
return sha1Hash;
}
@Override
public String getSha256Hash() {
return sha256Hash;
}
public void setMd5Hash(final String md5Hash) {
this.md5Hash = md5Hash;
}
@@ -102,6 +110,11 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art
this.sha1Hash = sha1Hash;
}
public void setSha256Hash(final String sha256Hash) {
this.sha256Hash = sha256Hash;
}
@Override
public long getSize() {
return size;

View File

@@ -0,0 +1 @@
ALTER TABLE sp_artifact ADD COLUMN sha256_hash CHAR(64);

View File

@@ -0,0 +1 @@
ALTER TABLE sp_artifact ADD COLUMN sha256_hash CHAR(64);

View File

@@ -0,0 +1 @@
ALTER TABLE sp_artifact ADD COLUMN sha256_hash CHAR(64);

View File

@@ -0,0 +1 @@
ALTER TABLE sp_artifact ADD sha256_hash CHAR(64);

View File

@@ -139,6 +139,8 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
.isEqualTo(HashGeneratorUtils.generateSHA1(randomBytes));
assertThat(artifactManagement.getByFilename("file1").get().getMd5Hash())
.isEqualTo(HashGeneratorUtils.generateMD5(randomBytes));
assertThat(artifactManagement.getByFilename("file1").get().getSha256Hash())
.isEqualTo(HashGeneratorUtils.generateSHA256(randomBytes));
assertThat(artifactRepository.findAll()).hasSize(4);
assertThat(softwareModuleRepository.findAll()).hasSize(3);

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.ddi.json.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
@@ -23,6 +25,10 @@ public class DdiArtifactHash {
@JsonProperty
private String md5;
@JsonProperty
@JsonInclude(Include.NON_NULL)
private String sha256;
/**
* Default constructor.
*/
@@ -34,11 +40,16 @@ public class DdiArtifactHash {
* Public constructor.
*
* @param sha1
* sha1 hash of the artifact
* @param md5
* md5 hash of the artifact
* @param sha256
* sha256 hash of the artifact
*/
public DdiArtifactHash(final String sha1, final String md5) {
public DdiArtifactHash(final String sha1, final String md5, final String sha256) {
this.sha1 = sha1;
this.md5 = md5;
this.sha256 = sha256;
}
/**
@@ -55,4 +66,10 @@ public class DdiArtifactHash {
return md5;
}
/**
* @return the sha256
*/
public String getSha256() {
return sha256;
}
}

View File

@@ -92,7 +92,7 @@ public final class DataConversionHelper {
private static DdiArtifact createArtifact(final Target target, final ArtifactUrlHandler artifactUrlHandler,
final Artifact artifact, final SystemManagement systemManagement, final HttpRequest request) {
final DdiArtifact file = new DdiArtifact();
file.setHashes(new DdiArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash()));
file.setHashes(new DdiArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash(), artifact.getSha256Hash()));
file.setFilename(artifact.getFilename());
file.setSize(artifact.getSize());

View File

@@ -153,8 +153,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
final Target savedTarget = createTargetAndAssertNoActiveActions();
List<Target> targetsAssignedToDs = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.FORCED,
RepositoryModelConstants.NO_FORCE_TIME, Collections.singletonList(savedTarget.getControllerId()))
final List<Target> targetsAssignedToDs = deploymentManagement
.assignDistributionSet(ds.getId(), ActionType.FORCED, RepositoryModelConstants.NO_FORCE_TIME,
Collections.singletonList(savedTarget.getControllerId()))
.getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -172,7 +173,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
// Run test
long current = System.currentTimeMillis();
final long current = System.currentTimeMillis();
performGet(CONTROLLER_BY_ID, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
@@ -255,7 +256,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = createTargetAndAssertNoActiveActions();
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.SOFT,
final List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.SOFT,
RepositoryModelConstants.NO_FORCE_TIME, Collections.singletonList(savedTarget.getControllerId()))
.getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -315,7 +316,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = createTargetAndAssertNoActiveActions();
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.TIMEFORCED,
final List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.TIMEFORCED,
System.currentTimeMillis(), Collections.singletonList(savedTarget.getControllerId()))
.getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -334,7 +335,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Run test
long current = System.currentTimeMillis();
final long current = System.currentTimeMillis();
performGet(CONTROLLER_BY_ID, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
@@ -383,7 +384,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = createTargetAndAssertNoActiveActions();
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.DOWNLOAD_ONLY,
final List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.DOWNLOAD_ONLY,
RepositoryModelConstants.NO_FORCE_TIME, Collections.singletonList(savedTarget.getControllerId()))
.getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -465,6 +466,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
contains(artifact.getMd5Hash())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0].hashes.sha1",
contains(artifact.getSha1Hash())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[0].hashes.sha256",
contains(artifact.getSha256Hash())))
.andExpect(jsonPath(
"$.deployment.chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/"
@@ -480,6 +483,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
contains(artifactSignature.getMd5Hash())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1].hashes.sha1",
contains(artifactSignature.getSha1Hash())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1].hashes.sha256",
contains(artifactSignature.getSha256Hash())))
.andExpect(
jsonPath("$.deployment.chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/"
@@ -710,7 +715,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
postFeedback(MediaType.APPLICATION_JSON, DEFAULT_CONTROLLER_ID, 1234L,
JsonBuilder.deploymentActionInProgressFeedback("1234"), status().isNotFound());
Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
// Action does not exists
postFeedback(MediaType.APPLICATION_JSON, "4713", 1234L, JsonBuilder.deploymentActionInProgressFeedback("1234"),
@@ -774,9 +779,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final String missingResultInFeedback = JsonBuilder.missingResultInFeedback(action.getId().toString(), "closed",
"test");
postFeedback(MediaType.APPLICATION_JSON, "1080", action.getId(), missingResultInFeedback,
status().isBadRequest())
.andExpect(jsonPath("$.*", hasSize(3)))
.andExpect(jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
status().isBadRequest()).andExpect(jsonPath("$.*", hasSize(3))).andExpect(
jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
}
@Test
@@ -797,13 +801,12 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final String missingFinishedResultInFeedback = JsonBuilder
.missingFinishedResultInFeedback(action.getId().toString(), "closed", "test");
postFeedback(MediaType.APPLICATION_JSON, "1080", action.getId(), missingFinishedResultInFeedback,
status().isBadRequest())
.andExpect(jsonPath("$.*", hasSize(3)))
.andExpect(jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
status().isBadRequest()).andExpect(jsonPath("$.*", hasSize(3))).andExpect(
jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
}
private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) {
Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
assertTargetCountByStatus(1, 0, 0);
@@ -834,16 +837,17 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(content().contentTypeCompatibleWith(mediaType));
}
private ResultActions postFeedback(final MediaType mediaType, final String controllerId, final Long id, final String content,
final ResultMatcher statusMatcher) throws Exception {
private ResultActions postFeedback(final MediaType mediaType, final String controllerId, final Long id,
final String content, final ResultMatcher statusMatcher) throws Exception {
return postFeedback(mediaType, controllerId, id, content.getBytes(), statusMatcher);
}
private ResultActions postFeedback(final MediaType mediaType, final String controllerId, final Long id, final byte[] content,
final ResultMatcher statusMatcher) throws Exception {
return mvc.perform(post(DEPLOYMENT_BASE + id + "/feedback", tenantAware.getCurrentTenant(), controllerId)
.content(content).contentType(mediaType).accept(mediaType)).andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher);
private ResultActions postFeedback(final MediaType mediaType, final String controllerId, final Long id,
final byte[] content, final ResultMatcher statusMatcher) throws Exception {
return mvc
.perform(post(DEPLOYMENT_BASE + id + "/feedback", tenantAware.getCurrentTenant(), controllerId)
.content(content).contentType(mediaType).accept(mediaType))
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
}
private Target createTargetAndAssertNoActiveActions() {
@@ -855,7 +859,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
}
private void assertStatusMessagesCount(final int actionStatusMessagesCount) {
Iterable<ActionStatus> actionStatusMessages;
final Iterable<ActionStatus> actionStatusMessages;
actionStatusMessages = deploymentManagement.findActionStatusAll(PageRequest.of(0, 100, Direction.DESC, "id"))
.getContent();
assertThat(actionStatusMessages).hasSize(actionStatusMessagesCount);
@@ -894,7 +898,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
}
private void assertStatusAndActiveActionsCount(final TargetUpdateStatus status, final int activeActions) {
Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
assertThat(target.getUpdateStatus()).isEqualTo(status);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()))
.hasSize(activeActions);

View File

@@ -112,6 +112,8 @@ final class DdiApiModelProperties {
static final String ARTIFACT_HASHES_SHA1 = "SHA1 hash of the artifact in Base 16 format";
static final String ARTIFACT_HASHES_MD5 = "MD5 hash of the artifact";
static final String ARTIFACT_HASHES_SHA256 = "SHA-256 hash of the artifact in Base 16 format";
static final String ARTIFACT_SIZE = "size of the artifact";
static final String ACTION_HISTORY = "Optional GET parameter to retrieve a given number of messages which are previously provided by the device. "

View File

@@ -321,6 +321,8 @@ public class RootControllerDocumentationTest extends AbstractApiRestDocumentatio
.description(DdiApiModelProperties.ARTIFACT_HASHES_SHA1),
fieldWithPath("deployment.chunks[].artifacts[].hashes.md5")
.description(DdiApiModelProperties.ARTIFACT_HASHES_MD5),
fieldWithPath("deployment.chunks[].artifacts[].hashes.sha256")
.description(DdiApiModelProperties.ARTIFACT_HASHES_SHA256),
fieldWithPath("deployment.chunks[].artifacts[].size")
.description(DdiApiModelProperties.ARTIFACT_SIZE),
fieldWithPath("deployment.chunks[].artifacts[]._links.download")
@@ -451,6 +453,8 @@ public class RootControllerDocumentationTest extends AbstractApiRestDocumentatio
fieldWithPath("[]hashes").description(DdiApiModelProperties.ARTIFACTS),
fieldWithPath("[]hashes.sha1").description(DdiApiModelProperties.ARTIFACT_HASHES_SHA1),
fieldWithPath("[]hashes.md5").description(DdiApiModelProperties.ARTIFACT_HASHES_MD5),
fieldWithPath("[]hashes.sha256")
.description(DdiApiModelProperties.ARTIFACT_HASHES_SHA256),
fieldWithPath("[]size").description(DdiApiModelProperties.ARTIFACT_SIZE),
fieldWithPath("[]_links.download")
.description(DdiApiModelProperties.ARTIFACT_HTTPS_DOWNLOAD_LINK_BY_CONTROLLER),