Feature/java11 build (#1280)
* hawkBit on Java 11 Signed-off-by: Dominic Schabel <dominic.schabel@bosch.io> * Preparing java 11 build - Update eclipse-link maven plugin dependencies - Fixing warnings, adopt to java-11 style Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Preparing java 11 build - Fixing warnings, adapt to java-11 style - Added since to deprecated Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixing sonar warnings - removed deprecated API Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Fixing sonar warnings & failing test - Added suppressWarning - added WithSpringAuthorityRule to clean-up listener Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Compile warnings - Test if final causes issues in tests Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Removed deprecated code Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Reverted changes Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Removed final as this causes invalid reflective access exceptions - The eclipselink generated classes seem to modify the field directly - update plugin version Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> * Upgrade eclipselink from 2.7.9 to 2.7.10 * Remove @deprecated endpoints from MgmtTargetTagResource * Remove dependencies already defined in eclipselink-maven-plugin * Try eclipselink 2.7.11-RC1 * Set project encoding to UTF-8 * Upgrade surefire and failsafe plugins to 3.0.0-M7 * Try fixed string instead of a random generated one * Replace JsonBuilder by Jackson ObjectMapper usage * Use JsonBuilder again * Use APPLICATION_JSON_UTF8 instead of APPLICATION_JSON * Try to replace com.vaadin.external.google:android-json by org.json:json * Add debugging outputs * Improve debugging outputs * Improve debugging outputs * Use Jackson instead of JsonBuilder * Use Jackson instead of JsonBuilder 2nd part * Use Spring json dependency * Use eclipselink 2.7.11 * Fix RootControllerDocumentationTest * Improve helper methods of AbstractDDiApiIntegrationTest * Upgrade SpringBoot and SpringCloud versions * Improve deprecation notice for 0.3.0M8 * Fix BaseAmqpServiceTest * Fix SpecificationsBuilderTest * Removed deprecated code * Define maven-enforcer-plugin version * Remove com.google.code.findbugs.jsr305 Signed-off-by: Florian Ruschbaschan <florian.ruschbaschan@bosch.io> * Update circleci image to openjdk:openjdk:11.0.13-jdk-buster Signed-off-by: Florian Ruschbaschan <florian.ruschbaschan@bosch.io> * Fix javadoc generation and license check Signed-off-by: Florian Ruschbaschan <florian.ruschbaschan@bosch.io> * Fix review findings Signed-off-by: Florian Ruschbaschan <florian.ruschbaschan@bosch.io> Signed-off-by: Dominic Schabel <dominic.schabel@bosch.io> Signed-off-by: Peter Vigier <Peter.Vigier@bosch.io> Signed-off-by: Florian Ruschbaschan <florian.ruschbaschan@bosch.io> Co-authored-by: Dominic Schabel <dominic.schabel@bosch.io> Co-authored-by: Peter Vigier <Peter.Vigier@bosch.io> Co-authored-by: Markus Block <markus.block@bosch-si.com>
This commit is contained in:
committed by
GitHub
parent
537548defb
commit
32718676a4
@@ -14,7 +14,7 @@ jobs:
|
||||
working_directory: ~/hawkBit
|
||||
|
||||
docker:
|
||||
- image: circleci/openjdk:8u181-jdk-stretch
|
||||
- image: circleci/openjdk:11.0.13-jdk-buster
|
||||
auth:
|
||||
username: $DOCKERHUB_USER
|
||||
password: $DOCKERHUB_ACCESSTOKEN
|
||||
|
||||
@@ -65,7 +65,7 @@ public class BaseAmqpServiceTest {
|
||||
@Description("Tests invalid null message content")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void convertMessageWithNullContent() {
|
||||
final Message message = createMessage(null);
|
||||
final Message message = createMessage("".getBytes());
|
||||
assertThatExceptionOfType(MessageConversionException.class)
|
||||
.as("Expected MessageConversionException for invalid JSON")
|
||||
.isThrownBy(() -> baseAmqpService.convertMessage(message, DmfActionUpdateStatus.class));
|
||||
|
||||
@@ -32,6 +32,7 @@ public interface ArtifactEncryption {
|
||||
*
|
||||
* @return secrets key/value pairs
|
||||
* @throws ArtifactEncryptionFailedException
|
||||
* thrown in case of an error while generating secrets
|
||||
*/
|
||||
Map<String, String> generateSecrets();
|
||||
|
||||
@@ -44,6 +45,7 @@ public interface ArtifactEncryption {
|
||||
* artifact stream to encrypt
|
||||
* @return encrypted input stream
|
||||
* @throws ArtifactEncryptionFailedException
|
||||
* thrown in case of an error while encrypting the provided stream
|
||||
*/
|
||||
InputStream encryptStream(final Map<String, String> secrets, final InputStream stream);
|
||||
|
||||
@@ -56,6 +58,7 @@ public interface ArtifactEncryption {
|
||||
* artifact stream to decrypt
|
||||
* @return decrypted input stream
|
||||
* @throws ArtifactEncryptionFailedException
|
||||
* thrown in case of an error while decrypting the provided stream
|
||||
*/
|
||||
InputStream decryptStream(final Map<String, String> secrets, final InputStream stream);
|
||||
|
||||
|
||||
@@ -206,6 +206,7 @@ public interface TargetFilterQueryManagement {
|
||||
*
|
||||
* @return the page with the found {@link TargetFilterQuery}s
|
||||
* @param pageable
|
||||
* pagination information
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
Slice<TargetFilterQuery> findWithAutoAssignDS(@NotNull Pageable pageable);
|
||||
|
||||
@@ -66,59 +66,16 @@ public interface TargetManagement {
|
||||
List<Target> assignTag(@NotEmpty Collection<String> controllerIds, long tagId);
|
||||
|
||||
/**
|
||||
* Counts number of targets with given
|
||||
* {@link Target#getAssignedDistributionSet()}.
|
||||
*
|
||||
* @param distId
|
||||
* to search for
|
||||
* Counts number of targets with the given distribution set assigned.
|
||||
*
|
||||
* @param distId to search for
|
||||
* @return number of found {@link Target}s.
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
long countByAssignedDistributionSet(long distId);
|
||||
|
||||
/**
|
||||
* Count {@link Target}s for all the given filter parameters.
|
||||
*
|
||||
* @param status
|
||||
* find targets having one of these {@link TargetUpdateStatus}s.
|
||||
* Set to <code>null</code> in case this is not required.
|
||||
* @param overdueState
|
||||
* find targets that are overdue (targets that did not respond
|
||||
* during the configured intervals: poll_itvl + overdue_itvl).
|
||||
* Set to <code>null</code> in case this is not required.
|
||||
* @param searchText
|
||||
* to find targets having the text anywhere in name or
|
||||
* description. Set <code>null</code> in case this is not
|
||||
* required.
|
||||
* @param installedOrAssignedDistributionSetId
|
||||
* to find targets having the {@link DistributionSet} as
|
||||
* installed or assigned. Set to <code>null</code> in case this
|
||||
* is not required.
|
||||
* @param tagNames
|
||||
* to find targets which are having any one in this tag names.
|
||||
* Set <code>null</code> in case this is not required.
|
||||
* @param selectTargetWithNoTag
|
||||
* flag to select targets with no tag assigned
|
||||
*
|
||||
* @return the found number of {@link Target}s
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*
|
||||
* @deprecated this method
|
||||
* {@link TargetManagement#countByFilters(FilterParams)} should
|
||||
* be used instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
long countByFilters(Collection<TargetUpdateStatus> status, Boolean overdueState, String searchText,
|
||||
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... tagNames);
|
||||
|
||||
/**
|
||||
* Count {@link Target}s for all the given filter parameters.
|
||||
*
|
||||
@@ -135,14 +92,11 @@ public interface TargetManagement {
|
||||
long countByFilters(@NotNull final FilterParams filterParams);
|
||||
|
||||
/**
|
||||
* Counts number of targets with given with given distribution set Id
|
||||
* Get the count of targets with the given distribution set id.
|
||||
*
|
||||
* @param distId
|
||||
* to search for
|
||||
* @param distId to search for
|
||||
* @return number of found {@link Target}s.
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
@@ -152,12 +106,9 @@ public interface TargetManagement {
|
||||
* Checks if there is already a {@link Target} that has the given
|
||||
* distribution set Id assigned or installed.
|
||||
*
|
||||
* @param distId
|
||||
* to search for
|
||||
* @param distId to search for
|
||||
* @return <code>true</code> if a {@link Target} exists.
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
* @throws EntityNotFoundException if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
@@ -226,8 +177,8 @@ public interface TargetManagement {
|
||||
Target create(@NotNull @Valid TargetCreate create);
|
||||
|
||||
/**
|
||||
* creates multiple {@link Target}s. If some of the given {@link Target}s
|
||||
* already exists in the DB a {@link EntityAlreadyExistsException} is
|
||||
* creates multiple {@link Target}s. If the given {@link Target}s
|
||||
* already exists in the DB an {@link EntityAlreadyExistsException} is
|
||||
* thrown. {@link Target}s contain all objects of the parameter targets,
|
||||
* including duplicates.
|
||||
*
|
||||
@@ -546,28 +497,27 @@ public interface TargetManagement {
|
||||
Slice<Target> findByTargetFilterQuery(@NotNull Pageable pageable, long targetFilterQueryId);
|
||||
|
||||
/**
|
||||
* method retrieves all {@link Target}s from the repo in the following
|
||||
* order:
|
||||
* method retrieves all {@link Target}s from the repo in the following order:
|
||||
* <p>
|
||||
* 1) {@link Target}s which have the given {@link DistributionSet} as
|
||||
* {@link Target#getTarget()} {@link Target#getInstalledDistributionSet()}
|
||||
* <p>
|
||||
* 2) {@link Target}s which have the given {@link DistributionSet} as
|
||||
* {@link Target#getAssignedDistributionSet()}
|
||||
* <p>
|
||||
* 3) {@link Target}s which have no connection to the given
|
||||
* {@link DistributionSet}.
|
||||
* <ol>
|
||||
* <li>{@link Target}s which have the given {@link DistributionSet} as installed
|
||||
* distribution set</li>
|
||||
* <li>{@link Target}s which have the given {@link DistributionSet} as assigned
|
||||
* distribution set</li>
|
||||
* <li>{@link Target}s which have no connection to the given
|
||||
* {@link DistributionSet}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param pageable
|
||||
* the page request to page the result set
|
||||
* @param orderByDistributionId
|
||||
* {@link DistributionSet#getId()} to be ordered by
|
||||
* @param filterParams
|
||||
* the filters to apply; only filters are enabled that have
|
||||
* non-null value; filters are AND-gated
|
||||
* the filters to apply; only filters are enabled that have non-null
|
||||
* value; filters are AND-gated
|
||||
* @return a paged result {@link Page} of the {@link Target}s in a defined
|
||||
* order.
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*/
|
||||
@@ -614,17 +564,16 @@ public interface TargetManagement {
|
||||
Page<Target> findByRsqlAndTag(@NotNull Pageable pageable, @NotNull String rsqlParam, long tagId);
|
||||
|
||||
/**
|
||||
* Toggles {@link TargetTag} assignment to given {@link Target}s by means
|
||||
* that if some (or all) of the targets in the list have the {@link Tag} not
|
||||
* yet assigned, they will be. Only if all of theme have the tag already
|
||||
* assigned they will be removed instead.
|
||||
* Toggles {@link TargetTag} assignment to given {@link Target}s by means that
|
||||
* if some (or all) of the targets in the list have the {@link Tag} not yet
|
||||
* assigned, they will be. Only if all of them have the tag already assigned
|
||||
* they will be removed instead.
|
||||
*
|
||||
* @param controllerIds
|
||||
* to toggle for
|
||||
* @param tagName
|
||||
* to toggle
|
||||
* @return TagAssigmentResult with all meta data of the assignment outcome.
|
||||
*
|
||||
* @return TagAssigmentResult with all metadata of the assignment outcome.
|
||||
* @throws EntityNotFoundException
|
||||
* if tag with given name does not exist
|
||||
*/
|
||||
@@ -641,7 +590,7 @@ public interface TargetManagement {
|
||||
* to set the type to
|
||||
* @param typeId
|
||||
* to assign targets to
|
||||
* @return {@link TargetTypeAssignmentResult} with all meta data of the
|
||||
* @return {@link TargetTypeAssignmentResult} with all metadata of the
|
||||
* assignment outcome.
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
@@ -656,7 +605,7 @@ public interface TargetManagement {
|
||||
*
|
||||
* @param controllerIds
|
||||
* to remove the type from
|
||||
* @return {@link TargetTypeAssignmentResult} with all meta data of the
|
||||
* @return {@link TargetTypeAssignmentResult} with all metadata of the
|
||||
* assignment outcome.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
||||
@@ -827,15 +776,15 @@ public interface TargetManagement {
|
||||
* for
|
||||
* @param metadata
|
||||
* the meta data entries to create or update
|
||||
* @return the updated or created target meta data entries
|
||||
*
|
||||
* @return the updated or created target metadata entries
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if given target does not exist
|
||||
*
|
||||
*
|
||||
* @throws EntityAlreadyExistsException
|
||||
* in case one of the meta data entry already exists for the
|
||||
* in case one of the metadata entry already exists for the
|
||||
* specific key
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of {@link MetaData} entries is exceeded
|
||||
* for the addressed {@link Target}
|
||||
@@ -847,10 +796,10 @@ public interface TargetManagement {
|
||||
* Deletes a target meta data entry.
|
||||
*
|
||||
* @param controllerId
|
||||
* where meta data has to be deleted
|
||||
* where metadata has to be deleted
|
||||
* @param key
|
||||
* of the meta data element
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if given target does not exist
|
||||
*/
|
||||
@@ -863,10 +812,10 @@ public interface TargetManagement {
|
||||
* @param pageable
|
||||
* the page request to page the result
|
||||
* @param controllerId
|
||||
* the controller id to retrieve the meta data from
|
||||
* the controller id to retrieve the metadata from
|
||||
*
|
||||
* @return a paged result of all meta data entries for a given target id
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -875,12 +824,12 @@ public interface TargetManagement {
|
||||
|
||||
/**
|
||||
* Counts all meta data by the given target id.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* the controller id to retrieve the meta data from
|
||||
*
|
||||
* @return count of all meta data entries for a given target id
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -888,17 +837,17 @@ public interface TargetManagement {
|
||||
long countMetaDataByControllerId(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given target id and query.
|
||||
*
|
||||
* Finds all metadata by the given target id and query.
|
||||
*
|
||||
* @param pageable
|
||||
* the page request to page the result
|
||||
* @param controllerId
|
||||
* the controller id to retrieve the meta data from
|
||||
* the controller id to retrieve the metadata from
|
||||
* @param rsqlParam
|
||||
* rsql query string
|
||||
*
|
||||
* @return a paged result of all meta data entries for a given target id
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
@@ -932,14 +881,14 @@ public interface TargetManagement {
|
||||
* Updates a target meta data value if corresponding entry exists.
|
||||
*
|
||||
* @param controllerId
|
||||
* {@link Target} controller id of the meta data entry to be
|
||||
* {@link Target} controller id of the metadata entry to be
|
||||
* updated
|
||||
* @param metadata
|
||||
* meta data entry to be updated
|
||||
* @return the updated meta data entry
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* in case the meta data entry does not exists and cannot be
|
||||
* in case the metadata entry does not exist and cannot be
|
||||
* updated
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
|
||||
@@ -56,8 +56,10 @@ public interface TargetType extends NamedEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unassigns a distribution set type from target types
|
||||
* Unassigns a {@link DistributionSetType} from {@link TargetType}
|
||||
*
|
||||
* @param dsTypeId
|
||||
* that will be removed from {@link TargetType}
|
||||
* @return the resulting target type
|
||||
*/
|
||||
TargetType removeDistributionSetType(final Long dsTypeId);
|
||||
|
||||
@@ -29,6 +29,7 @@ public class TenantUsage {
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenantName
|
||||
* name of the tenant
|
||||
*/
|
||||
public TenantUsage(final String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
@@ -18,13 +18,11 @@
|
||||
</parent>
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<name>hawkBit :: Repository :: JPA Implementation</name>
|
||||
|
||||
|
||||
<properties>
|
||||
<apt.source.dir>${project.build.directory}/generated-sources/apt/</apt.source.dir>
|
||||
<classgraph.version>4.8.90</classgraph.version>
|
||||
<eclipselink.maven.plugin.version>2.7.5.1</eclipselink.maven.plugin.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<!-- Hawkbit -->
|
||||
<dependency>
|
||||
@@ -70,7 +68,11 @@
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
@@ -89,14 +91,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Static weaver for EclipseLink -->
|
||||
<plugin>
|
||||
<groupId>com.ethlo.persistence.tools</groupId>
|
||||
<artifactId>eclipselink-maven-plugin</artifactId>
|
||||
<version>${eclipselink.maven.plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>modelgen</id>
|
||||
@@ -117,24 +118,10 @@
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<!--
|
||||
Required for Java 11 since plugin version is build on
|
||||
EclipseLink 2.7.5 (which doesn't have latest fixes for Java 11)
|
||||
-->
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>org.eclipse.persistence.jpa</artifactId>
|
||||
<version>${eclipselink.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!--
|
||||
Required for Java 11 since plugin uses older version (4.8.21)
|
||||
which suffer from NPE while weaving. We require at least 4.8.48
|
||||
see: https://github.com/ethlo/eclipselink-maven-plugin/issues/31
|
||||
-->
|
||||
<groupId>io.github.classgraph</groupId>
|
||||
<artifactId>classgraph</artifactId>
|
||||
<version>${classgraph.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@@ -743,7 +743,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
throw new InvalidTargetAttributeException();
|
||||
}
|
||||
|
||||
final JpaTarget target = (JpaTarget) targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId))
|
||||
final JpaTarget target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId))
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
// get the modifiable attribute map
|
||||
|
||||
@@ -188,10 +188,10 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
|
||||
final JpaTarget updatedTarget = JpaManagementHelper.touch(entityManager, targetRepository, target);
|
||||
|
||||
final List<TargetMetadata> createdMetadata = Collections.unmodifiableList(md.stream()
|
||||
final List<TargetMetadata> createdMetadata = md.stream()
|
||||
.map(meta -> targetMetadataRepository
|
||||
.save(new JpaTargetMetadata(meta.getKey(), meta.getValue(), updatedTarget)))
|
||||
.collect(Collectors.toList()));
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
// TargetUpdatedEvent is not sent within the touch() method due to the
|
||||
// "lastModifiedAt" field being ignored in JpaTarget
|
||||
@@ -228,12 +228,12 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
// target indirectly
|
||||
final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository,
|
||||
getByControllerIdAndThrowIfNotFound(controllerId));
|
||||
final JpaTargetMetadata matadata = targetMetadataRepository.save(updatedMetadata);
|
||||
final JpaTargetMetadata metadata = targetMetadataRepository.save(updatedMetadata);
|
||||
// target update event is set to ignore "lastModifiedAt" field so it is
|
||||
// not send automatically within the touch() method
|
||||
eventPublisherHolder.getEventPublisher()
|
||||
.publishEvent(new TargetUpdatedEvent(target, eventPublisherHolder.getApplicationId()));
|
||||
return matadata;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -247,7 +247,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository,
|
||||
getByControllerIdAndThrowIfNotFound(controllerId));
|
||||
targetMetadataRepository.deleteById(metadata.getId());
|
||||
// target update event is set to ignore "lastModifiedAt" field so it is
|
||||
// target update event is set to ignore "lastModifiedAt" field, so it is
|
||||
// not send automatically within the touch() method
|
||||
eventPublisherHolder.getEventPublisher()
|
||||
.publishEvent(new TargetUpdatedEvent(target, eventPublisherHolder.getApplicationId()));
|
||||
@@ -419,14 +419,6 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, specList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFilters(final Collection<TargetUpdateStatus> status, final Boolean overdueState,
|
||||
final String searchText, final Long installedOrAssignedDistributionSetId,
|
||||
final Boolean selectTargetWithNoTag, final String... tagNames) {
|
||||
return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId,
|
||||
selectTargetWithNoTag, tagNames));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFilters(final FilterParams filterParams) {
|
||||
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
|
||||
@@ -590,8 +582,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
|
||||
allTargets.forEach(target -> target.addTag(tag));
|
||||
|
||||
final List<Target> result = Collections
|
||||
.unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList()));
|
||||
final List<Target> result = allTargets.stream().map(targetRepository::save)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
// No reason to save the tag
|
||||
entityManager.detach(tag);
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ParseExceptionWrapper {
|
||||
|
||||
/**
|
||||
* Get the current token
|
||||
*
|
||||
*
|
||||
* @return the current token or {@code null} if there is non.
|
||||
*/
|
||||
public TokenWrapper getCurrentToken() {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class LazyControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
controllerManagement.findOrRegisterTargetIfItDoesNotExist("AA", LOCALHOST);
|
||||
TimeUnit.MILLISECONDS.sleep(repositoryProperties.getPollPersistenceFlushTime() + 1);
|
||||
TimeUnit.MILLISECONDS.sleep(repositoryProperties.getPollPersistenceFlushTime() + 10);
|
||||
|
||||
final Target updated = targetManagement.get(target.getId()).get();
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ public class SpecificationsBuilderTest {
|
||||
|
||||
when(criteriaBuilder.equal(any(Path.class), eq("testValue1"))).thenReturn(equalPredicate1);
|
||||
when(criteriaBuilder.equal(any(Path.class), eq("testValue2"))).thenReturn(equalPredicate2);
|
||||
when(criteriaBuilder.and(eq(equalPredicate2), eq(equalPredicate1))).thenReturn(combinedPredicate);
|
||||
when(criteriaBuilder.and(eq(equalPredicate1), eq(equalPredicate2))).thenReturn(combinedPredicate);
|
||||
when(root.get("field1")).thenReturn(field1);
|
||||
when(root.get("field2")).thenReturn(field2);
|
||||
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
<artifactId>hawkbit-repository-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-security-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-artifact-repository-filesystem</artifactId>
|
||||
@@ -140,4 +145,4 @@
|
||||
<artifactId>awaitility</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -24,10 +24,12 @@ public class CleanupTestExecutionListener extends AbstractTestExecutionListener
|
||||
|
||||
@Override
|
||||
public void afterTestMethod(final TestContext testContext) throws Exception {
|
||||
|
||||
final ApplicationContext applicationContext = testContext.getApplicationContext();
|
||||
new JpaTestRepositoryManagement(applicationContext.getBean(TenantAwareCacheManager.class),
|
||||
applicationContext.getBean(SystemSecurityContext.class),
|
||||
applicationContext.getBean(SystemManagement.class)).clearTestRepository();
|
||||
WithSpringAuthorityRule.runAsPrivileged(() -> {
|
||||
final ApplicationContext applicationContext = testContext.getApplicationContext();
|
||||
new JpaTestRepositoryManagement(applicationContext.getBean(TenantAwareCacheManager.class),
|
||||
applicationContext.getBean(SystemSecurityContext.class),
|
||||
applicationContext.getBean(SystemManagement.class)).clearTestRepository();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,21 +29,15 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The answer header would look like: { "id": "51659181", "time":
|
||||
* "20140511T121314", "status": { "execution": "closed", "result": { "final":
|
||||
* "success", "progress": {} } "details": [], } }
|
||||
* The answer header would look like: { "time": "20140511T121314", "status": {
|
||||
* "execution": "closed", "result": { "final": "success", "progress": {} }
|
||||
* "details": [], } }
|
||||
* </p>
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DdiActionFeedback {
|
||||
/**
|
||||
* @deprecated
|
||||
* This ID is always given by the actionId path variable.
|
||||
* Will be removed in future versions.
|
||||
*/
|
||||
@Deprecated
|
||||
private final Long id;
|
||||
|
||||
private final String time;
|
||||
|
||||
@NotNull
|
||||
@@ -51,27 +45,20 @@ public class DdiActionFeedback {
|
||||
private final DdiStatus status;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param id
|
||||
* of the actions the feedback is for
|
||||
* Constructs an action-feedback
|
||||
*
|
||||
* @param time
|
||||
* of the feedback
|
||||
* time of feedback
|
||||
* @param status
|
||||
* is the feedback itself
|
||||
* status to be appended to the action
|
||||
*/
|
||||
@JsonCreator
|
||||
public DdiActionFeedback(@JsonProperty("id") final Long id, @JsonProperty("time") final String time,
|
||||
@JsonProperty("status") final DdiStatus status) {
|
||||
this.id = id;
|
||||
public DdiActionFeedback(@JsonProperty(value = "time", required = true) final String time,
|
||||
@JsonProperty(value = "status", required = true) final DdiStatus status) {
|
||||
this.time = time;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
@@ -82,7 +69,7 @@ public class DdiActionFeedback {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ActionFeedback [id=" + id + ", time=" + time + ", status=" + status + "]";
|
||||
return "ActionFeedback [time=" + time + ", status=" + status + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,16 +61,6 @@ public final class DdiRestConstants {
|
||||
*/
|
||||
public static final String MEDIA_TYPE_CBOR = "application/cbor";
|
||||
|
||||
/**
|
||||
* Media type for CBOR content with strings encoded as UTF-8. Technically
|
||||
* redundant since CBOR always uses UTF-8, but Spring will append it
|
||||
* regardless.
|
||||
* @deprecated Since the Spring Framework (v5.2.4.RELEASE) dropped the charset attribute
|
||||
* from content type headers, please use {@link DdiRestConstants#MEDIA_TYPE_CBOR} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String MEDIA_TYPE_CBOR_UTF8 = "application/cbor;charset=UTF-8";
|
||||
|
||||
private DdiRestConstants() {
|
||||
// constant class, private constructor.
|
||||
}
|
||||
|
||||
@@ -13,8 +13,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
|
||||
@@ -22,57 +24,41 @@ import com.fasterxml.jackson.databind.exc.MismatchedInputException;
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test serializability of DDI api model 'DdiActionFeedback'
|
||||
* Test serialization of DDI api model 'DdiActionFeedback'
|
||||
*/
|
||||
@Feature("Unit Tests - Direct Device Integration API")
|
||||
@Story("Serializability of DDI api Models")
|
||||
@Story("Serialization of DDI api Models")
|
||||
public class DdiActionFeedbackTest {
|
||||
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
@Description("Verify the correct serialization and deserialization of the model")
|
||||
public void shouldSerializeAndDeserializeObject() throws IOException {
|
||||
// Setup
|
||||
Long id = 123L;
|
||||
String time = "20190809T121314";
|
||||
DdiStatus ddiStatus = new DdiStatus(DdiStatus.ExecutionStatus.CLOSED, null, Lists.emptyList());
|
||||
DdiActionFeedback ddiActionFeedback = new DdiActionFeedback(id, time, ddiStatus);
|
||||
final String time = Instant.now().toString();
|
||||
final DdiStatus ddiStatus = new DdiStatus(DdiStatus.ExecutionStatus.CLOSED, null, Lists.emptyList());
|
||||
final DdiActionFeedback ddiActionFeedback = new DdiActionFeedback(time, ddiStatus);
|
||||
|
||||
// Test
|
||||
String serializedDdiActionFeedback = mapper.writeValueAsString(ddiActionFeedback);
|
||||
DdiActionFeedback deserializedDdiActionFeedback = mapper.readValue(serializedDdiActionFeedback,
|
||||
final String serializedDdiActionFeedback = mapper.writeValueAsString(ddiActionFeedback);
|
||||
final DdiActionFeedback deserializedDdiActionFeedback = mapper.readValue(serializedDdiActionFeedback,
|
||||
DdiActionFeedback.class);
|
||||
|
||||
assertThat(serializedDdiActionFeedback).contains(id.toString(), time);
|
||||
assertThat(deserializedDdiActionFeedback.getId()).isEqualTo(id);
|
||||
assertThat(serializedDdiActionFeedback).contains(time);
|
||||
assertThat(deserializedDdiActionFeedback.getTime()).isEqualTo(time);
|
||||
assertThat(deserializedDdiActionFeedback.getStatus().toString()).isEqualTo(ddiStatus.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify the correct deserialization of a model with a additional unknown property")
|
||||
public void shouldDeserializeObjectWithUnknownProperty() throws IOException {
|
||||
// Setup
|
||||
String serializedDdiActionFeedback = "{\"id\":1, \"time\":\"20190809T121314\", \"status\":{\"execution\":\"closed\", \"result\":null, \"details\":[]}, \"unknownProperty\": \"test\"}";
|
||||
|
||||
// Test
|
||||
DdiActionFeedback ddiActionFeedback = mapper.readValue(serializedDdiActionFeedback, DdiActionFeedback.class);
|
||||
|
||||
assertThat(ddiActionFeedback.getId()).isEqualTo(1L);
|
||||
assertThat(ddiActionFeedback.getTime()).matches("20190809T121314");
|
||||
assertThat(deserializedDdiActionFeedback.getStatus()).hasToString(ddiStatus.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that deserialization fails for known properties with a wrong datatype")
|
||||
public void shouldFailForObjectWithWrongDataTypes() throws IOException {
|
||||
// Setup
|
||||
String serializedDdiActionFeedback = "{\"id\": [1],\"time\":\"20190809T121314\",\"status\":{\"execution\":\"closed\",\"result\":null,\"details\":[]}}";
|
||||
final String serializedDdiActionFeedback = "{\"time\":\"20190809T121314\",\"status\":{\"execution\": [closed],\"result\":null,\"details\":[]}}";
|
||||
|
||||
assertThatExceptionOfType(MismatchedInputException.class).isThrownBy(
|
||||
() -> mapper.readValue(serializedDdiActionFeedback, DdiActionFeedback.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import io.qameta.allure.Story;
|
||||
* Check DDI api model classes for '@JsonIgnoreProperties' annotation
|
||||
*/
|
||||
@Feature("Unit Tests - Direct Device Integration API")
|
||||
@Story("Serializability of DDI api Models")
|
||||
@Story("Serialization of DDI api Models")
|
||||
public class JsonIgnorePropertiesAnnotationTest {
|
||||
|
||||
@Test
|
||||
@@ -35,15 +35,15 @@ public class JsonIgnorePropertiesAnnotationTest {
|
||||
"This test verifies that all model classes within the 'org.eclipse.hawkbit.ddi.json.model' package are annotated with '@JsonIgnoreProperties(ignoreUnknown = true)'")
|
||||
public void shouldCheckAnnotationsForAllModelClasses() throws IOException {
|
||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
String packageName = this.getClass().getPackage().getName();
|
||||
final String packageName = this.getClass().getPackage().getName();
|
||||
|
||||
ImmutableSet<ClassPath.ClassInfo> topLevelClasses = ClassPath.from(loader).getTopLevelClasses(packageName);
|
||||
for (ClassPath.ClassInfo classInfo : topLevelClasses) {
|
||||
Class<?> modelClass = classInfo.load();
|
||||
final ImmutableSet<ClassPath.ClassInfo> topLevelClasses = ClassPath.from(loader).getTopLevelClasses(packageName);
|
||||
for (final ClassPath.ClassInfo classInfo : topLevelClasses) {
|
||||
final Class<?> modelClass = classInfo.load();
|
||||
if (modelClass.getSimpleName().contains("Test") || modelClass.isEnum()) {
|
||||
continue;
|
||||
}
|
||||
JsonIgnoreProperties annotation = modelClass.getAnnotation(JsonIgnoreProperties.class);
|
||||
final JsonIgnoreProperties annotation = modelClass.getAnnotation(JsonIgnoreProperties.class);
|
||||
assertThat(annotation).isNotNull();
|
||||
assertThat(annotation.ignoreUnknown()).isTrue();
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
.orElseThrow(() -> new SoftwareModuleNotAssignedToTargetException(module, target.getControllerId()));
|
||||
final String range = request.getHeader("Range");
|
||||
|
||||
String message;
|
||||
final String message;
|
||||
if (range != null) {
|
||||
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads range " + range + " of: "
|
||||
+ request.getRequestURI();
|
||||
@@ -327,7 +327,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
if (!action.isActive()) {
|
||||
LOG.warn("Updating action {} with feedback {} not possible since action not active anymore.",
|
||||
action.getId(), feedback.getId());
|
||||
action.getId(), feedback.getStatus());
|
||||
return new ResponseEntity<>(HttpStatus.GONE);
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
messages.addAll(feedback.getStatus().getDetails());
|
||||
}
|
||||
|
||||
Status status;
|
||||
final Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
LOG.debug("Controller confirmed cancel (actionId: {}, controllerId: {}) as we got {} report.", actionId,
|
||||
@@ -391,7 +391,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
private Status handleDefaultCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId,
|
||||
final List<String> messages) {
|
||||
Status status;
|
||||
final Status status;
|
||||
LOG.debug("Controller reported intermediate status (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionId, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.RUNNING;
|
||||
@@ -401,7 +401,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
private Status handleClosedCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId,
|
||||
final List<String> messages) {
|
||||
Status status;
|
||||
final Status status;
|
||||
LOG.debug("Controller reported closed (actionId: {}, controllerId: {}) as we got {} report.", actionId,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
@@ -482,8 +482,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
}
|
||||
|
||||
private DdiDeploymentBase generateDdiDeploymentBase(Target target, Action action,
|
||||
Integer actionHistoryMessageCount) {
|
||||
private DdiDeploymentBase generateDdiDeploymentBase(final Target target, final Action action,
|
||||
final Integer actionHistoryMessageCount) {
|
||||
final List<DdiChunk> chunks = DataConversionHelper.createChunks(target, action, artifactUrlHandler,
|
||||
systemManagement, new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest()),
|
||||
controllerManagement);
|
||||
@@ -508,7 +508,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
final Long actionId, final EntityFactory entityFactory) {
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
Status status;
|
||||
final Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
status = handleCaseCancelCanceled(feedback, target, actionId, messages);
|
||||
@@ -536,7 +536,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
private static Status handleCancelClosedCase(final DdiActionFeedback feedback, final List<String> messages) {
|
||||
Status status;
|
||||
final Status status;
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
status = Status.ERROR;
|
||||
addMessageIfEmpty("Target was not able to complete cancellation", messages);
|
||||
@@ -549,7 +549,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
private static Status handleCaseCancelCanceled(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionId, final List<String> messages) {
|
||||
Status status;
|
||||
final 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());
|
||||
@@ -570,7 +570,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
return verifyActionBelongsToTarget(action, target);
|
||||
}
|
||||
|
||||
private Action verifyActionBelongsToTarget(Action action, Target target) {
|
||||
private Action verifyActionBelongsToTarget(final Action action, final Target target) {
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
LOG.debug(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
throw new EntityNotFoundException(
|
||||
|
||||
@@ -18,7 +18,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiProgress;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
@@ -38,6 +46,8 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
|
||||
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
|
||||
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
|
||||
@@ -59,22 +69,23 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
protected static final String CANCEL_FEEDBACK = CANCEL_ACTION + "/feedback";
|
||||
|
||||
protected static final int ARTIFACT_SIZE = 5 * 1024;
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* Convert JSON to a CBOR equivalent.
|
||||
*
|
||||
*
|
||||
* @param json
|
||||
* JSON object to convert
|
||||
* @return Equivalent CBOR data
|
||||
* @throws IOException
|
||||
* Invalid JSON input
|
||||
*/
|
||||
protected static byte[] jsonToCbor(String json) throws IOException {
|
||||
JsonFactory jsonFactory = new JsonFactory();
|
||||
JsonParser jsonParser = jsonFactory.createParser(json);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
CBORFactory cborFactory = new CBORFactory();
|
||||
CBORGenerator cborGenerator = cborFactory.createGenerator(out);
|
||||
protected static byte[] jsonToCbor(final String json) throws IOException {
|
||||
final JsonFactory jsonFactory = new JsonFactory();
|
||||
final JsonParser jsonParser = jsonFactory.createParser(json);
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final CBORFactory cborFactory = new CBORFactory();
|
||||
final CBORGenerator cborGenerator = cborFactory.createGenerator(out);
|
||||
while (jsonParser.nextToken() != null) {
|
||||
cborGenerator.copyCurrentEvent(jsonParser);
|
||||
}
|
||||
@@ -84,19 +95,19 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
|
||||
/**
|
||||
* Convert CBOR to JSON equivalent.
|
||||
*
|
||||
*
|
||||
* @param input
|
||||
* CBOR data to convert
|
||||
* @return Equivalent JSON string
|
||||
* @throws IOException
|
||||
* Invalid CBOR input
|
||||
*/
|
||||
protected static String cborToJson(byte[] input) throws IOException {
|
||||
CBORFactory cborFactory = new CBORFactory();
|
||||
CBORParser cborParser = cborFactory.createParser(input);
|
||||
JsonFactory jsonFactory = new JsonFactory();
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonGenerator jsonGenerator = jsonFactory.createGenerator(stringWriter);
|
||||
protected static String cborToJson(final byte[] input) throws IOException {
|
||||
final CBORFactory cborFactory = new CBORFactory();
|
||||
final CBORParser cborParser = cborFactory.createParser(input);
|
||||
final JsonFactory jsonFactory = new JsonFactory();
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
final JsonGenerator jsonGenerator = jsonFactory.createGenerator(stringWriter);
|
||||
while (cborParser.nextToken() != null) {
|
||||
jsonGenerator.copyCurrentEvent(cborParser);
|
||||
}
|
||||
@@ -106,7 +117,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
|
||||
protected ResultActions postDeploymentFeedback(final String controllerId, final Long actionId, final String content,
|
||||
final ResultMatcher statusMatcher) throws Exception {
|
||||
return postDeploymentFeedback(MediaType.APPLICATION_JSON, controllerId, actionId, content.getBytes(),
|
||||
return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(),
|
||||
statusMatcher);
|
||||
}
|
||||
|
||||
@@ -120,7 +131,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
|
||||
protected ResultActions postCancelFeedback(final String controllerId, final Long actionId, final String content,
|
||||
final ResultMatcher statusMatcher) throws Exception {
|
||||
return postCancelFeedback(MediaType.APPLICATION_JSON, controllerId, actionId, content.getBytes(),
|
||||
return postCancelFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(),
|
||||
statusMatcher);
|
||||
}
|
||||
|
||||
@@ -164,7 +175,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
getDownloadAndUploadType(actionType), getDownloadAndUploadType(actionType));
|
||||
}
|
||||
|
||||
private ResultActions verifyBasePayload(ResultActions resultActions, final String controllerId,
|
||||
private ResultActions verifyBasePayload(final ResultActions resultActions, final String controllerId,
|
||||
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
||||
final Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
||||
return resultActions.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
||||
@@ -234,4 +245,92 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
return "attempt";
|
||||
}
|
||||
|
||||
protected String getJsonRejectedCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("rejected"));
|
||||
}
|
||||
|
||||
protected String getJsonRejectedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("rejected"));
|
||||
}
|
||||
|
||||
protected String getJsonDownloadDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.DOWNLOAD, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("download"));
|
||||
}
|
||||
|
||||
protected String getJsonDownloadedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.DOWNLOADED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("download"));
|
||||
}
|
||||
|
||||
protected String getJsonCanceledCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("canceled"));
|
||||
}
|
||||
|
||||
protected String getJsonCanceledDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("canceled"));
|
||||
}
|
||||
|
||||
protected String getJsonScheduledCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("scheduled"));
|
||||
}
|
||||
|
||||
protected String getJsonScheduledDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("scheduled"));
|
||||
}
|
||||
|
||||
protected String getJsonResumedCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("resumed"));
|
||||
}
|
||||
|
||||
protected String getJsonResumedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("resumed"));
|
||||
}
|
||||
|
||||
protected String getJsonProceedingCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("proceeding"));
|
||||
}
|
||||
|
||||
protected String getJsonProceedingDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("proceeding"));
|
||||
}
|
||||
|
||||
protected String getJsonClosedCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("closed"));
|
||||
}
|
||||
|
||||
protected String getJsonClosedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("closed"));
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus,
|
||||
final DdiResult.FinalResult finalResult) throws JsonProcessingException {
|
||||
return getJsonActionFeedback(executionStatus, finalResult,
|
||||
Collections.singletonList(RandomStringUtils.randomAlphanumeric(1000)));
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus, final DdiResult ddiResult,
|
||||
final List<String> messages) throws JsonProcessingException {
|
||||
final DdiStatus ddiStatus = new DdiStatus(executionStatus, ddiResult, messages);
|
||||
return objectMapper.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus,
|
||||
final DdiResult.FinalResult finalResult, final List<String> messages) throws JsonProcessingException {
|
||||
final DdiStatus ddiStatus = new DdiStatus(executionStatus, new DdiResult(finalResult, new DdiProgress(2, 5)),
|
||||
messages);
|
||||
return objectMapper.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
@@ -57,18 +59,22 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
// check that we can get the cancel action as CBOR
|
||||
final byte[] result = mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
final byte[] result = mvc
|
||||
.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andReturn().getResponse().getContentAsByteArray();
|
||||
assertThat(JsonPathUtils.<String>evaluate(cborToJson(result), "$.id")).isEqualTo(String.valueOf(cancelAction.getId()));
|
||||
assertThat(JsonPathUtils.<String>evaluate(cborToJson(result), "$.cancelAction.stopId")).isEqualTo(String.valueOf(actionId));
|
||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andReturn().getResponse()
|
||||
.getContentAsByteArray();
|
||||
assertThat(JsonPathUtils.<String> evaluate(cborToJson(result), "$.id"))
|
||||
.isEqualTo(String.valueOf(cancelAction.getId()));
|
||||
assertThat(JsonPathUtils.<String> evaluate(cborToJson(result), "$.cancelAction.stopId"))
|
||||
.isEqualTo(String.valueOf(actionId));
|
||||
|
||||
// and submit feedback as CBOR
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(
|
||||
jsonToCbor(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "proceeding")))
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(jsonToCbor(getJsonProceedingCancelActionFeedback()))
|
||||
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
@@ -85,11 +91,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
// controller rejects cancelation
|
||||
// controller rejects cancellation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "rejected"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
@@ -112,8 +118,9 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// and finish it
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
||||
+ actionId + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "success"))
|
||||
+ actionId + "/feedback", tenantAware.getCurrentTenant()).content(
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("message")))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
@@ -139,9 +146,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
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())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
@@ -191,8 +197,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// controller confirmed cancelled action, should not be active anymore
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)
|
||||
.content(JsonBuilder.cancelActionFeedback(actionId.toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
@@ -263,8 +269,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "proceeding"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
@@ -272,16 +278,16 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "resumed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(4);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "scheduled"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(5);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
@@ -290,8 +296,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "canceled"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
@@ -303,8 +309,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "rejected"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(7);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
@@ -312,8 +318,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// update closed -> should remove the action from active
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonClosedCancelActionFeedback()).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())).isEmpty();
|
||||
@@ -364,8 +370,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// now lets return feedback for the first cancelation
|
||||
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))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(7);
|
||||
|
||||
@@ -391,8 +397,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// now lets return feedback for the second cancelation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction2.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(9);
|
||||
|
||||
@@ -426,8 +432,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// now lets return feedback for the third cancelation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction3.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(13);
|
||||
|
||||
@@ -447,7 +453,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
final String feedback = JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "proceeding");
|
||||
final String feedback = getJsonProceedingCancelActionFeedback();
|
||||
// assignDistributionSet creates an ActionStatus and cancel action
|
||||
// stores an action status, so
|
||||
// only 97 action status left
|
||||
@@ -473,8 +479,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// not allowed methods
|
||||
mvc.perform(put("/{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))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
@@ -488,36 +494,35 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
// bad content type
|
||||
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_ATOM_XML).accept(MediaType.APPLICATION_JSON))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||
|
||||
// bad body
|
||||
String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}";
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "546456456"))
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback())
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// invalid action
|
||||
invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback("sdfsdfsdfs", "closed"))
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
|
||||
// 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))
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
|
||||
@@ -45,7 +47,6 @@ 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.rest.exception.MessageNotReadableException;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@@ -81,8 +82,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
.getContent().get(0);
|
||||
|
||||
// get deployment base
|
||||
performGet(DEPLOYMENT_BASE,
|
||||
MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
|
||||
performGet(DEPLOYMENT_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), action.getId().toString());
|
||||
|
||||
final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId();
|
||||
@@ -92,8 +92,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
status().isOk(), tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
String.valueOf(softwareModuleId));
|
||||
|
||||
final byte[] feedback = jsonToCbor(
|
||||
JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding"));
|
||||
final byte[] feedback = jsonToCbor(getJsonProceedingDeploymentActionFeedback());
|
||||
|
||||
postDeploymentFeedback(MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), target.getControllerId(),
|
||||
action.getId(), feedback, status().isOk());
|
||||
@@ -164,8 +163,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// Run test
|
||||
final long current = System.currentTimeMillis();
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -262,8 +260,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -274,9 +271,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds,
|
||||
visibleMetadataOsKey, visibleMetadataOsValue, artifact, artifactSignature, action.getId(), "attempt",
|
||||
"attempt", getOsModule(findDistributionSetByAction));
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, visibleMetadataOsKey,
|
||||
visibleMetadataOsValue, artifact, artifactSignature, action.getId(), "attempt", "attempt",
|
||||
getOsModule(findDistributionSetByAction));
|
||||
|
||||
// Retrieved is reported
|
||||
final List<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
@@ -301,8 +298,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target savedTarget = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||
ActionType.TIMEFORCED)
|
||||
.getAssignedEntity().stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
ActionType.TIMEFORCED).getAssignedEntity().stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
@@ -321,8 +317,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -337,9 +332,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
artifactSignature, action.getId(),
|
||||
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
|
||||
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaTypes.HAL_JSON, ds, artifact,
|
||||
artifactSignature, action.getId(),
|
||||
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaTypes.HAL_JSON, ds, artifact, artifactSignature,
|
||||
action.getId(), findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced",
|
||||
"forced");
|
||||
|
||||
// Retrieved is reported
|
||||
final Iterable<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
@@ -368,8 +363,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target savedTarget = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||
ActionType.DOWNLOAD_ONLY)
|
||||
.getAssignedEntity().stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
ActionType.DOWNLOAD_ONLY).getAssignedEntity().stream().map(Action::getTarget)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
@@ -388,8 +383,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -472,7 +466,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding");
|
||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||
// assign distribution set creates an action status, so only 99 left
|
||||
for (int i = 0; i < 99; i++) {
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(), feedback, status().isOk());
|
||||
@@ -497,10 +491,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
messages.add(String.valueOf(i));
|
||||
}
|
||||
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding", "none",
|
||||
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE,
|
||||
messages);
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(), feedback,
|
||||
status().isForbidden());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(), feedback, status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -522,22 +515,22 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.UNKNOWN)).hasSize(2);
|
||||
|
||||
// action1 done
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId1,
|
||||
JsonBuilder.deploymentActionFeedback(actionId1.toString(), "closed"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId1, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 2, Optional.of(ds1));
|
||||
assertStatusMessagesCount(4);
|
||||
|
||||
// action2 done
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId2,
|
||||
JsonBuilder.deploymentActionFeedback(actionId2.toString(), "closed"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId2, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 1, Optional.of(ds2));
|
||||
assertStatusMessagesCount(5);
|
||||
|
||||
// action3 done
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId3,
|
||||
JsonBuilder.deploymentActionFeedback(actionId3.toString(), "closed"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId3, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds3));
|
||||
assertStatusMessagesCount(6);
|
||||
@@ -556,7 +549,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action action = deploymentManagement.findActionsByDistributionSet(PAGE, ds.getId()).getContent().get(0);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(),
|
||||
JsonBuilder.deploymentActionFeedback(action.getId().toString(), "closed", "failure", "error message"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.FAILURE,
|
||||
Collections.singletonList("Error message")),
|
||||
status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.empty(), TargetUpdateStatus.ERROR, 0, Optional.empty());
|
||||
@@ -569,8 +563,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
Collections.singletonList(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get()));
|
||||
final Action action2 = deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent()
|
||||
.get(0);
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(),
|
||||
JsonBuilder.deploymentActionFeedback(action2.getId().toString(), "closed", "SUCCESS"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(),
|
||||
status().isOk());
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds));
|
||||
assertTargetCountByStatus(0, 0, 1);
|
||||
assertThat(deploymentManagement.findInActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID)).hasSize(2);
|
||||
@@ -592,33 +586,33 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// Now valid Feedback
|
||||
for (int i = 0; i < 4; i++) {
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonProceedingDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
assertActionStatusCount(i + 2, i);
|
||||
|
||||
}
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "scheduled"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonScheduledDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
assertActionStatusCount(6, 5);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "resumed"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonResumedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
assertActionStatusCount(7, 6);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "canceled"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonCanceledDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1);
|
||||
assertActionStatusCount(8, 7, 0, 0, 1);
|
||||
assertTargetCountByStatus(1, 0, 0);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "rejected"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonRejectedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1);
|
||||
assertActionStatusCount(9, 6, 1, 0, 1);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed"), status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
assertStatusAndActiveActionsCount(TargetUpdateStatus.IN_SYNC, 0);
|
||||
assertActionStatusCount(10, 7, 1, 1, 1);
|
||||
assertTargetCountByStatus(0, 0, 1);
|
||||
@@ -635,14 +629,13 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// target does not exist
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, 1234L,
|
||||
JsonBuilder.deploymentActionInProgressFeedback("1234"), status().isNotFound());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, 1234L, getJsonProceedingDeploymentActionFeedback(),
|
||||
status().isNotFound());
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
|
||||
|
||||
// Action does not exist
|
||||
postDeploymentFeedback("4713", 1234L, JsonBuilder.deploymentActionInProgressFeedback("1234"),
|
||||
status().isNotFound());
|
||||
postDeploymentFeedback("4713", 1234L, getJsonProceedingDeploymentActionFeedback(), status().isNotFound());
|
||||
|
||||
assignDistributionSet(savedSet, Collections.singletonList(savedTarget)).getAssignedEntity().iterator().next();
|
||||
assignDistributionSet(savedSet2, Collections.singletonList(testdataFactory.createTarget("4713")));
|
||||
@@ -651,8 +644,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
.getContent().get(0);
|
||||
|
||||
// action exists but is not assigned to this target
|
||||
postDeploymentFeedback("4713", updateAction.getId(),
|
||||
JsonBuilder.deploymentActionInProgressFeedback(updateAction.getId().toString()), status().isNotFound());
|
||||
postDeploymentFeedback("4713", updateAction.getId(), getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING,
|
||||
DdiResult.FinalResult.NONE, Collections.singletonList("")), status().isNotFound());
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(),
|
||||
@@ -669,11 +662,11 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an invalid id in feedback body returns a bad request.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1)})
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void invalidIdInFeedbackReturnsBadRequest() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
@@ -681,17 +674,17 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
postDeploymentFeedback("1080", action.getId(),
|
||||
JsonBuilder.deploymentActionInProgressFeedback("AAAA"), status().isBadRequest());
|
||||
final String invalidFeedback = "{\"id\":\"AAAA\",\"status\":{\"execution\":\"proceeding\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
|
||||
postDeploymentFeedback("1080", action.getId(), invalidFeedback, status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a missing feedback result in feedback body returns a bad request.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1)})
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void missingResultAttributeInFeedbackReturnsBadRequest() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
@@ -700,20 +693,21 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final String missingResultInFeedback = JsonBuilder.missingResultInFeedback(action.getId().toString(), "closed",
|
||||
"test");
|
||||
postDeploymentFeedback("1080", action.getId(), missingResultInFeedback,
|
||||
status().isBadRequest()).andExpect(jsonPath("$.*", hasSize(3))).andExpect(
|
||||
jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
|
||||
|
||||
final String missingResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, (DdiResult) null,
|
||||
Collections.singletonList("test"));
|
||||
postDeploymentFeedback("1080", action.getId(), missingResultInFeedback, status().isBadRequest())
|
||||
.andExpect(jsonPath("$.*", hasSize(3)))
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a missing finished result in feedback body returns a bad request.")
|
||||
@ExpectEvents({@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1)})
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void missingFinishedAttributeInFeedbackReturnsBadRequest() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
@@ -722,11 +716,13 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final String missingFinishedResultInFeedback = JsonBuilder
|
||||
.missingFinishedResultInFeedback(action.getId().toString(), "closed", "test");
|
||||
postDeploymentFeedback("1080", action.getId(), missingFinishedResultInFeedback,
|
||||
status().isBadRequest()).andExpect(jsonPath("$.*", hasSize(3))).andExpect(
|
||||
jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
|
||||
final String missingFinishedResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED,
|
||||
new DdiResult(null, null),
|
||||
Collections.singletonList("test"));
|
||||
|
||||
postDeploymentFeedback("1080", action.getId(), missingFinishedResultInFeedback, status().isBadRequest())
|
||||
.andExpect(jsonPath("$.*", hasSize(3)))
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
|
||||
}
|
||||
|
||||
private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) {
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
|
||||
@@ -45,7 +47,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@@ -77,8 +78,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed"), status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
|
||||
// get installed base
|
||||
performGet(INSTALLED_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
|
||||
@@ -123,7 +124,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId1,
|
||||
JsonBuilder.deploymentActionFeedback(actionId1.toString(), "closed", "success", "Closed"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Closed")),
|
||||
status().isOk());
|
||||
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
|
||||
@@ -143,7 +145,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED);
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId2,
|
||||
JsonBuilder.deploymentActionFeedback(actionId2.toString(), "closed", "success", "Closed"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Closed")),
|
||||
status().isOk());
|
||||
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2,
|
||||
@@ -155,7 +158,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
startsWith(installedBaseLink(CONTROLLER_ID, actionId2.toString()))))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
||||
|
||||
// older installed action is still accessible, although not part of controller base
|
||||
// older installed action is still accessible, although not part of controller
|
||||
// base
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
|
||||
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
|
||||
}
|
||||
@@ -177,20 +181,25 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
deploymentManagement.cancelAction(actionId1);
|
||||
postCancelFeedback(target.getControllerId(), actionId1,
|
||||
JsonBuilder.cancelActionFeedback(actionId1.toString(), "closed", "Canceled"), status().isOk());
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds1, action2 - and provide cancel feedback
|
||||
final Long actionId2 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.FORCED));
|
||||
deploymentManagement.cancelAction(actionId2);
|
||||
postCancelFeedback(target.getControllerId(), actionId2,
|
||||
JsonBuilder.cancelActionFeedback(actionId2.toString(), "closed", "Canceled"), status().isOk());
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds1, action 3 - and provide success feedback
|
||||
final Long actionId3 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId3,
|
||||
JsonBuilder.deploymentActionFeedback(actionId3.toString(), "closed", "success", "Closed"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// Test: latest succeeded action is returned in installedBase
|
||||
@@ -228,7 +237,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Long actionId1 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId1,
|
||||
JsonBuilder.deploymentActionFeedback(actionId1.toString(), "closed", "success", "Success"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Success")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds2, action2 - assign ds1, action 3 - and cancel both
|
||||
@@ -238,10 +248,14 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
deploymentManagement.cancelAction(actionId2);
|
||||
postCancelFeedback(target.getControllerId(), actionId2,
|
||||
JsonBuilder.cancelActionFeedback(actionId2.toString(), "closed", "Canceled"), status().isOk());
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
deploymentManagement.cancelAction(actionId3);
|
||||
postCancelFeedback(target.getControllerId(), actionId3,
|
||||
JsonBuilder.cancelActionFeedback(actionId3.toString(), "closed", "Canceled"), status().isOk());
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// Test: the succeeded action is returned in installedBase instead of the latest
|
||||
// cancelled action
|
||||
@@ -279,7 +293,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Long actionId1 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId1,
|
||||
JsonBuilder.deploymentActionFeedback(actionId1.toString(), "closed", "success", "Success"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Success")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds2, action2 - assign ds1, action 3 - and cancel action 2
|
||||
@@ -289,7 +304,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
deploymentManagement.cancelAction(actionId2);
|
||||
postCancelFeedback(target.getControllerId(), actionId2,
|
||||
JsonBuilder.cancelActionFeedback(actionId2.toString(), "closed", "Canceled"), status().isOk());
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// Test: the succeeded action is returned in installedBase instead of the latest
|
||||
// cancelled action
|
||||
@@ -338,8 +355,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed"), status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
|
||||
final Long softwareModuleId = ds.getModules().stream().findAny().get().getId();
|
||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
||||
@@ -385,7 +402,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds.getId(), target.getControllerId(), actionType));
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "success", "Closed"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Closed")),
|
||||
status().isOk());
|
||||
|
||||
// Run test
|
||||
@@ -433,10 +451,10 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").exists())
|
||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "download"), status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "downloaded"), status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
|
||||
// Test
|
||||
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
@@ -448,7 +466,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.eclipse.hawkbit.ddi.rest.resource.DdiInstalledBaseTest#actionTypeForDeployment")
|
||||
@Description("Test a failed deployment to a controller. Checks that closed action is not represented as installedBase.")
|
||||
public void deploymentActionFailedNotInInstalledBase(Action.ActionType actionType) throws Exception {
|
||||
public void deploymentActionFailedNotInInstalledBase(final Action.ActionType actionType) throws Exception {
|
||||
// Prepare test data
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
@@ -461,9 +479,11 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding"), status().isOk());
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "failure", "Installation failed"),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.FAILURE,
|
||||
Collections.singletonList("Installation failed")),
|
||||
status().isOk());
|
||||
|
||||
// Test
|
||||
@@ -482,14 +502,20 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(), JsonBuilder.deploymentActionFeedback(
|
||||
savedAction.getId().toString(), "scheduled", "Installation scheduled"), status().isOk());
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("Installation scheduled")),
|
||||
status().isOk());
|
||||
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(), JsonBuilder.deploymentActionFeedback(
|
||||
savedAction.getId().toString(), "proceeding", "Installation proceeding"), status().isOk());
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("Installation proceeding")),
|
||||
status().isOk());
|
||||
// only this feedback triggers the ActionUpdateEvent
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(), JsonBuilder.deploymentActionFeedback(
|
||||
savedAction.getId().toString(), "closed", "success", "Installation completed"), status().isOk());
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Installation completed")),
|
||||
status().isOk());
|
||||
|
||||
// Test
|
||||
// for zero input no action history is returned
|
||||
@@ -545,8 +571,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet savedSet = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
|
||||
postDeploymentFeedback(CONTROLLER_ID, actionId,
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "success"), status().isOk());
|
||||
postDeploymentFeedback(CONTROLLER_ID, actionId, getJsonClosedCancelActionFeedback(), status().isOk());
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId)
|
||||
|
||||
@@ -33,6 +33,8 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
@@ -88,9 +90,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Test
|
||||
@Description("Ensure that the root poll resource is available as CBOR")
|
||||
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());
|
||||
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());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -147,11 +149,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// make a poll, audit information should not be changed, run as
|
||||
// controller principal!
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownTargetControllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS),
|
||||
() -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownTargetControllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
|
||||
// verify that audit information has not changed
|
||||
final Target targetVerify = targetManagement.getByControllerID(knownTargetControllerId).get();
|
||||
@@ -175,7 +178,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
void rootRsPlugAndPlay() throws Exception {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
String controllerId = "4711";
|
||||
final String controllerId = "4711";
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", controllerId)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
@@ -204,16 +207,16 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void pollWithModifiedGlobalPollingTime() throws Exception {
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:02:00");
|
||||
return null;
|
||||
});
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION),
|
||||
() -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:02:00");
|
||||
return null;
|
||||
});
|
||||
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
|
||||
return null;
|
||||
});
|
||||
@@ -230,7 +233,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6) })
|
||||
void rootRsNotModified() throws Exception {
|
||||
String controllerId = "4711";
|
||||
final String controllerId = "4711";
|
||||
final String etag = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
@@ -308,7 +311,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void rootRsPrecommissioned() throws Exception {
|
||||
String controllerId = "4711";
|
||||
final String controllerId = "4711";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
|
||||
assertThat(targetManagement.getByControllerID(controllerId).get().getUpdateStatus())
|
||||
@@ -339,12 +342,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final long create = System.currentTimeMillis();
|
||||
|
||||
// make a poll, audit information should be set on plug and play
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(
|
||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS),
|
||||
() -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
|
||||
// verify
|
||||
final Target target = targetManagement.getByControllerID(knownControllerId1).get();
|
||||
@@ -414,9 +417,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final Map<String, String> attributes = Collections.singletonMap("AttributeKey", "AttributeValue");
|
||||
assertThatAttributesUpdateIsRequested(savedTarget.getControllerId());
|
||||
|
||||
mvc.perform(put(CONTROLLER_BASE + "/configData", tenantAware.getCurrentTenant(),
|
||||
savedTarget.getControllerId()).content(JsonBuilder.configData(attributes).toString())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
mvc.perform(put(CONTROLLER_BASE + "/configData", tenantAware.getCurrentTenant(), savedTarget.getControllerId())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
assertThatAttributesUpdateIsNotRequested(savedTarget.getControllerId());
|
||||
|
||||
@@ -465,8 +467,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
if (message == null) {
|
||||
message = RandomStringUtils.randomAlphanumeric(1000);
|
||||
}
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(action.getId().toString(), execution, finished,
|
||||
message);
|
||||
|
||||
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.valueOf(execution.toUpperCase()),
|
||||
DdiResult.FinalResult.valueOf(finished.toUpperCase()), Collections.singletonList(message));
|
||||
return mvc.perform(
|
||||
post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId())
|
||||
.content(feedback).contentType(MediaType.APPLICATION_JSON));
|
||||
@@ -503,8 +506,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_COMPLETED_INSTALLATION_MSG))))
|
||||
@@ -540,8 +542,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
||||
|
||||
@@ -577,8 +578,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG))))
|
||||
@@ -593,13 +593,14 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
void sleepTimeResponseForDifferentMaintenanceWindowParameters() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:05:00");
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL,
|
||||
"00:01:00");
|
||||
return null;
|
||||
});
|
||||
WithSpringAuthorityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION),
|
||||
() -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:05:00");
|
||||
tenantConfigurationManagement
|
||||
.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL, "00:01:00");
|
||||
return null;
|
||||
});
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("1911");
|
||||
assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(), getTestSchedule(16),
|
||||
@@ -648,9 +649,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911",
|
||||
action.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("skip")))
|
||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable")));
|
||||
}
|
||||
@@ -668,9 +669,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911",
|
||||
action.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available")));
|
||||
}
|
||||
@@ -704,8 +705,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
throws Exception {
|
||||
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
|
||||
tenantAware.getCurrentTenant(), controllerId, expectedActionId);
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(
|
||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)));
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.util.List;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.security.DosFilter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -114,7 +113,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensures that a WRITE DoS attempt is blocked ")
|
||||
void putPostFloddingAttackThatisPrevented() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||
|
||||
MvcResult result = null;
|
||||
int requests = 0;
|
||||
@@ -139,7 +138,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
@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");
|
||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||
|
||||
for (int x = 0; x < 5; x++) {
|
||||
// sleep for one second
|
||||
|
||||
@@ -11,19 +11,15 @@
|
||||
hawkbit.controller.pollingTime=00:01:00
|
||||
hawkbit.controller.pollingOverdueTime=00:01:00
|
||||
hawkbit.controller.minPollingTime=00:00:30
|
||||
|
||||
hawkbit.controller.maintenanceWindowPollCount=3
|
||||
# DDI configuration - END
|
||||
|
||||
# Upload configuration - START
|
||||
spring.servlet.multipart.max-file-size=5MB
|
||||
# Upload configuration - END
|
||||
|
||||
# Quota - START
|
||||
hawkbit.server.security.dos.maxStatusEntriesPerAction=100
|
||||
hawkbit.server.security.dos.maxAttributeEntriesPerTarget=10
|
||||
# Quota - END
|
||||
|
||||
# Logging START - activate to see request/response details
|
||||
#logging.level.org.eclipse.hawkbit.rest.util.MockMvcResultPrinter=DEBUG
|
||||
# Logging END
|
||||
|
||||
@@ -73,14 +73,14 @@ public interface MgmtDistributionSetTagRestApi {
|
||||
ResponseEntity<MgmtTag> getDistributionSetTag(@PathVariable("distributionsetTagId") Long distributionsetTagId);
|
||||
|
||||
/**
|
||||
* Handles the POST request of creating new distribution set tag. The
|
||||
* request body must always be a list of tags.
|
||||
* Handles the POST request of creating new distribution set tag. The request
|
||||
* body must always be a list of tags.
|
||||
*
|
||||
* @param tags
|
||||
* the distribution set tags to be created.
|
||||
* @return In case all modules could successful created the ResponseEntity
|
||||
* with status code 201 - Created. The Response Body are the created
|
||||
* distribution set tags but without ResponseBody.
|
||||
* @return In case all modules could successful created the ResponseEntity with
|
||||
* status code 201 - Created. The Response Body contains the created
|
||||
* distribution set tags but without details.
|
||||
*/
|
||||
@PostMapping(consumes = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
@@ -93,9 +93,9 @@ public interface MgmtDistributionSetTagRestApi {
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @param restDSTagRest
|
||||
* the the request body to be updated
|
||||
* @return status OK if update is successful and the updated distribution
|
||||
* set tag.
|
||||
* the request body to be updated
|
||||
* @return status OK if update is successful and the updated distribution set
|
||||
* tag.
|
||||
*/
|
||||
@PutMapping(value = "/{distributionsetTagId}", consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
@@ -144,26 +144,6 @@ public interface MgmtDistributionSetTagRestApi {
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all assigned distribution sets by
|
||||
* the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
*
|
||||
* @return the list of assigned distribution sets.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link #getAssignedDistributionSets(Long, int, int, String, String)}
|
||||
* instead as this variant does not include paging and as result
|
||||
* returns only a limited list of distributionsets
|
||||
*/
|
||||
@Deprecated
|
||||
@GetMapping(value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSet>> getAssignedDistributionSets(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId);
|
||||
|
||||
/**
|
||||
* Handles the POST request to toggle the assignment of distribution sets by
|
||||
* the given tag id.
|
||||
@@ -182,28 +162,6 @@ public interface MgmtDistributionSetTagRestApi {
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to toggle the assignment of distribution sets by
|
||||
* the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
* @param assignedDSRequestBodies
|
||||
* list of distribution set ids to be toggled
|
||||
*
|
||||
* @return the list of assigned distribution sets and unassigned
|
||||
* distribution sets.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link MgmtDistributionSetTagRestApi#toggleTagAssignment}
|
||||
*/
|
||||
@Deprecated
|
||||
@PostMapping(value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING
|
||||
+ "/toggleTagAssignment")
|
||||
ResponseEntity<MgmtDistributionSetTagAssigmentResult> toggleTagAssignmentUnpaged(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to assign distribution sets to the given tag id.
|
||||
*
|
||||
@@ -221,27 +179,6 @@ public interface MgmtDistributionSetTagRestApi {
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to assign distribution sets to the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
* @param assignedDSRequestBodies
|
||||
* list of distribution sets ids to be assigned
|
||||
*
|
||||
* @return the list of assigned distribution set.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link MgmtDistributionSetTagRestApi#assignDistributionSets}
|
||||
*/
|
||||
@Deprecated
|
||||
@PostMapping(value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSet>> assignDistributionSetsUnpaged(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request to unassign one distribution set from the
|
||||
* given tag id.
|
||||
@@ -257,22 +194,4 @@ public interface MgmtDistributionSetTagRestApi {
|
||||
ResponseEntity<Void> unassignDistributionSet(@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
@PathVariable("distributionsetId") Long distributionsetId);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request to unassign one distribution set from the
|
||||
* given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @param distributionsetId
|
||||
* the ID of the distribution set to unassign
|
||||
* @return http status code
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link MgmtDistributionSetTagRestApi#unassignDistributionSet}
|
||||
*/
|
||||
@Deprecated
|
||||
@DeleteMapping(value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING
|
||||
+ "/{distributionsetId}")
|
||||
ResponseEntity<Void> unassignDistributionSetUnpaged(@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
@PathVariable("distributionsetId") Long distributionsetId);
|
||||
}
|
||||
|
||||
@@ -119,15 +119,6 @@ public final class MgmtRestConstants {
|
||||
*/
|
||||
public static final String TARGETTYPE_V1_DS_TYPES = "compatibledistributionsettypes";
|
||||
|
||||
/**
|
||||
* The tag URL mapping rest resource.
|
||||
*
|
||||
* @deprecated {@link #TARGET_TAG_TARGETS_REQUEST_MAPPING} is preferred as
|
||||
* this resource on GET supports paging
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String DEPRECATAED_TARGET_TAG_TARGETS_REQUEST_MAPPING = "/{targetTagId}/targets";
|
||||
|
||||
/**
|
||||
* The tag URL mapping rest resource.
|
||||
*/
|
||||
@@ -144,15 +135,6 @@ public final class MgmtRestConstants {
|
||||
*/
|
||||
public static final String TARGET_FILTER_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/targetfilters";
|
||||
|
||||
/**
|
||||
* The deprecated tag URL mapping rest resource.
|
||||
*
|
||||
* @deprecated {@link #DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING}
|
||||
* is preferred as this resource on GET supports paging
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING = "/{distributionsetTagId}/distributionsets";
|
||||
|
||||
/**
|
||||
* The tag URL mapping rest resource.
|
||||
*/
|
||||
|
||||
@@ -112,25 +112,6 @@ public interface MgmtTargetTagRestApi {
|
||||
@DeleteMapping(value = "/{targetTagId}")
|
||||
ResponseEntity<Void> deleteTargetTag(@PathVariable("targetTagId") Long targetTagId);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all assigned targets by the given
|
||||
* tag id.
|
||||
*
|
||||
* @param targetTagId
|
||||
* the ID of the target tag to retrieve
|
||||
*
|
||||
* @return the list of assigned targets.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link #getAssignedTargets(Long, int, int, String, String)}
|
||||
* instead as this variant does not include paging and as result
|
||||
* returns only a limited list of targets
|
||||
*/
|
||||
@Deprecated
|
||||
@GetMapping(value = MgmtRestConstants.DEPRECATAED_TARGET_TAG_TARGETS_REQUEST_MAPPING, produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtTarget>> getAssignedTargets(@PathVariable("targetTagId") Long targetTagId);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all assigned targets by the given
|
||||
* tag id.
|
||||
@@ -177,27 +158,6 @@ public interface MgmtTargetTagRestApi {
|
||||
ResponseEntity<MgmtTargetTagAssigmentResult> toggleTagAssignment(@PathVariable("targetTagId") Long targetTagId,
|
||||
List<MgmtAssignedTargetRequestBody> assignedTargetRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to toggle the assignment of targets by the given
|
||||
* tag id.
|
||||
*
|
||||
* @param targetTagId
|
||||
* the ID of the target tag to retrieve
|
||||
* @param assignedTargetRequestBodies
|
||||
* list of controller ids to be toggled
|
||||
*
|
||||
* @return the list of assigned targets and unassigned targets.
|
||||
* @deprecated please use {@link MgmtTargetTagRestApi#toggleTagAssignment}
|
||||
*/
|
||||
@Deprecated
|
||||
@PostMapping(value = MgmtRestConstants.DEPRECATAED_TARGET_TAG_TARGETS_REQUEST_MAPPING
|
||||
+ "/toggleTagAssignment", consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtTargetTagAssigmentResult> toggleTagAssignmentUnpaged(
|
||||
@PathVariable("targetTagId") Long targetTagId,
|
||||
List<MgmtAssignedTargetRequestBody> assignedTargetRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to assign targets to the given tag id.
|
||||
*
|
||||
@@ -214,25 +174,6 @@ public interface MgmtTargetTagRestApi {
|
||||
ResponseEntity<List<MgmtTarget>> assignTargets(@PathVariable("targetTagId") Long targetTagId,
|
||||
List<MgmtAssignedTargetRequestBody> assignedTargetRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to assign targets to the given tag id.
|
||||
*
|
||||
* @param targetTagId
|
||||
* the ID of the target tag to retrieve
|
||||
* @param assignedTargetRequestBodies
|
||||
* list of controller ids to be assigned
|
||||
*
|
||||
* @return the list of assigned targets.
|
||||
*
|
||||
* @deprecated please use {@link MgmtTargetTagRestApi#assignTargets}
|
||||
*/
|
||||
@Deprecated
|
||||
@PostMapping(value = MgmtRestConstants.DEPRECATAED_TARGET_TAG_TARGETS_REQUEST_MAPPING, consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtTarget>> assignTargetsUnpaged(@PathVariable("targetTagId") Long targetTagId,
|
||||
List<MgmtAssignedTargetRequestBody> assignedTargetRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request to unassign one target from the given tag id.
|
||||
*
|
||||
@@ -245,20 +186,4 @@ public interface MgmtTargetTagRestApi {
|
||||
@DeleteMapping(value = MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING + "/{controllerId}")
|
||||
ResponseEntity<Void> unassignTarget(@PathVariable("targetTagId") Long targetTagId,
|
||||
@PathVariable("controllerId") String controllerId);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request to unassign one target from the given tag id.
|
||||
*
|
||||
* @param targetTagId
|
||||
* the ID of the target tag
|
||||
* @param controllerId
|
||||
* the ID of the target to unassign
|
||||
* @return http status code
|
||||
*
|
||||
* @deprecated please use {@link MgmtTargetTagRestApi#unassignTarget}
|
||||
*/
|
||||
@Deprecated
|
||||
@DeleteMapping(value = MgmtRestConstants.DEPRECATAED_TARGET_TAG_TARGETS_REQUEST_MAPPING + "/{controllerId}")
|
||||
ResponseEntity<Void> unassignTargetUnpaged(@PathVariable("targetTagId") Long targetTagId,
|
||||
@PathVariable("controllerId") String controllerId);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -139,15 +138,6 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<MgmtDistributionSet>> getAssignedDistributionSets(
|
||||
@PathVariable("distributionsetTagId") final Long distributionsetTagId) {
|
||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDistributionSets(distributionSetManagement
|
||||
.findByTag(PageRequest.of(0, MgmtRestConstants.REQUEST_PARAMETER_PAGING_MAX_LIMIT),
|
||||
distributionsetTagId)
|
||||
.getContent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<PagedList<MgmtDistributionSet>> getAssignedDistributionSets(
|
||||
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
|
||||
@@ -204,7 +194,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
|
||||
LOG.debug("Assign DistributionSet {} for ds tag {}", assignedDSRequestBodies.size(), distributionsetTagId);
|
||||
final List<DistributionSet> assignedDs = this.distributionSetManagement
|
||||
.assignTag(findDistributionSetIds(assignedDSRequestBodies), distributionsetTagId);
|
||||
LOG.debug("Assignd DistributionSet {}", assignedDs.size());
|
||||
LOG.debug("Assigned DistributionSet {}", assignedDs.size());
|
||||
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponseDistributionSets(assignedDs));
|
||||
}
|
||||
|
||||
@@ -227,26 +217,4 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
|
||||
return assignedDistributionSetRequestBodies.stream()
|
||||
.map(MgmtAssignedDistributionSetRequestBody::getDistributionSetId).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<MgmtDistributionSetTagAssigmentResult> toggleTagAssignmentUnpaged(
|
||||
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
|
||||
@RequestBody final List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies) {
|
||||
return toggleTagAssignment(distributionsetTagId, assignedDSRequestBodies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<MgmtDistributionSet>> assignDistributionSetsUnpaged(
|
||||
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
|
||||
@RequestBody final List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies) {
|
||||
return assignDistributionSets(distributionsetTagId, assignedDSRequestBodies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> unassignDistributionSetUnpaged(
|
||||
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
|
||||
@PathVariable("distributionsetId") final Long distributionsetId) {
|
||||
return unassignDistributionSet(distributionsetTagId, distributionsetId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -130,14 +130,6 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<MgmtTarget>> getAssignedTargets(@PathVariable("targetTagId") final Long targetTagId) {
|
||||
|
||||
return ResponseEntity.ok(MgmtTargetMapper.toResponse(targetManagement
|
||||
.findByTag(PageRequest.of(0, MgmtRestConstants.REQUEST_PARAMETER_PAGING_MAX_LIMIT), targetTagId)
|
||||
.getContent()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<PagedList<MgmtTarget>> getAssignedTargets(@PathVariable("targetTagId") final Long targetTagId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
|
||||
@@ -205,23 +197,4 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<MgmtTargetTagAssigmentResult> toggleTagAssignmentUnpaged(
|
||||
@PathVariable("targetTagId") final Long targetTagId,
|
||||
@RequestBody final List<MgmtAssignedTargetRequestBody> assignedTargetRequestBodies) {
|
||||
return toggleTagAssignment(targetTagId, assignedTargetRequestBodies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<MgmtTarget>> assignTargetsUnpaged(@PathVariable("targetTagId") final Long targetTagId,
|
||||
@RequestBody final List<MgmtAssignedTargetRequestBody> assignedTargetRequestBodies) {
|
||||
return assignTargets(targetTagId, assignedTargetRequestBodies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> unassignTargetUnpaged(@PathVariable("targetTagId") final Long targetTagId,
|
||||
@PathVariable("controllerId") final String controllerId) {
|
||||
return unassignTarget(targetTagId, controllerId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.rest.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
@@ -186,96 +184,6 @@ public abstract class JsonBuilder {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a json string for the feedback for the execution "proceeding".
|
||||
*
|
||||
* @param id
|
||||
* of the Action feedback refers to
|
||||
* @return the built string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String deploymentActionInProgressFeedback(final String id) throws JSONException {
|
||||
return deploymentActionFeedback(id, "proceeding");
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a certain json string for a action feedback.
|
||||
*
|
||||
* @param id
|
||||
* of the action the feedback refers to
|
||||
* @param execution
|
||||
* see ExecutionStatus
|
||||
* @return the build json string
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String deploymentActionFeedback(final String id, final String execution) throws JSONException {
|
||||
return deploymentActionFeedback(id, execution, "none",
|
||||
Arrays.asList(RandomStringUtils.randomAlphanumeric(1000)));
|
||||
|
||||
}
|
||||
|
||||
public static String deploymentActionFeedback(final String id, final String execution, final String message)
|
||||
throws JSONException {
|
||||
return deploymentActionFeedback(id, execution, "none", Arrays.asList(message));
|
||||
|
||||
}
|
||||
|
||||
public static String deploymentActionFeedback(final String id, final String execution, final String finished,
|
||||
final String message) throws JSONException {
|
||||
return deploymentActionFeedback(id, execution, finished, Arrays.asList(message));
|
||||
}
|
||||
|
||||
public static String deploymentActionFeedback(final String id, final String execution, final String finished,
|
||||
final Collection<String> messages) throws JSONException {
|
||||
|
||||
return new JSONObject().put("id", id).put("status", new JSONObject().put("execution", execution)
|
||||
.put("result",
|
||||
new JSONObject().put("finished", finished).put("progress",
|
||||
new JSONObject().put("cnt", 2).put("of", 5)))
|
||||
.put("details", new JSONArray(messages))).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an invalid request body with missing result for feedback message.
|
||||
*
|
||||
* @param id
|
||||
* id of the action
|
||||
* @param execution
|
||||
* the execution
|
||||
* @param message
|
||||
* the message
|
||||
* @return a invalid request body
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String missingResultInFeedback(final String id, final String execution, final String message)
|
||||
throws JSONException {
|
||||
return new JSONObject().put("id", id).put("time", "20140511T121314")
|
||||
.put("status",
|
||||
new JSONObject().put("execution", execution).put("details", new JSONArray().put(message)))
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an invalid request body with missing finished result for feedback
|
||||
* message.
|
||||
*
|
||||
* @param id
|
||||
* id of the action
|
||||
* @param execution
|
||||
* the execution
|
||||
* @param message
|
||||
* the message
|
||||
* @return a invalid request body
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String missingFinishedResultInFeedback(final String id, final String execution, final String message)
|
||||
throws JSONException {
|
||||
return new JSONObject().put("id", id).put("time", "20140511T121314")
|
||||
.put("status", new JSONObject().put("execution", execution).put("result", new JSONObject())
|
||||
.put("details", new JSONArray().put(message)))
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static String distributionSetTypes(final List<DistributionSetType> types) throws JSONException {
|
||||
final JSONArray result = new JSONArray();
|
||||
|
||||
@@ -512,8 +420,8 @@ public abstract class JsonBuilder {
|
||||
}
|
||||
});
|
||||
|
||||
final JSONObject json = new JSONObject().put("name", type.getName()).put("description", type.getDescription())
|
||||
.put("colour", type.getColour());
|
||||
final JSONObject json = new JSONObject().put("name", type.getName())
|
||||
.put("description", type.getDescription()).put("colour", type.getColour());
|
||||
|
||||
if (dsTypes.length() != 0) {
|
||||
json.put("compatibledistributionsettypes", dsTypes);
|
||||
@@ -637,11 +545,6 @@ public abstract class JsonBuilder {
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
public static String cancelActionFeedback(final String id, final String execution) throws JSONException {
|
||||
return cancelActionFeedback(id, execution, RandomStringUtils.randomAlphanumeric(1000));
|
||||
|
||||
}
|
||||
|
||||
public static String cancelActionFeedback(final String id, final String execution, final String message)
|
||||
throws JSONException {
|
||||
return new JSONObject().put("id", id)
|
||||
|
||||
@@ -36,6 +36,8 @@ final class DdiApiModelProperties {
|
||||
|
||||
static final String FEEDBACK_ACTION_ID = "(@deprecated) id of the action";
|
||||
|
||||
static final String FEEDBACK_ACTION_TIME = "timestamp of the action";
|
||||
|
||||
static final String CANCEL_ACTION = "action that needs to be canceled";
|
||||
|
||||
static final String ACTION_ID_CANCELED = "id of the action that needs to be canceled (typically identical to id field on the cancel action itself)";
|
||||
|
||||
@@ -21,10 +21,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiProgress;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
@@ -41,6 +47,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -177,11 +184,15 @@ public class RootControllerDocumentationTest extends AbstractApiRestDocumentatio
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(set.getId(), target.getControllerId()));
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
final DdiStatus ddiStatus = new DdiStatus(DdiStatus.ExecutionStatus.CLOSED,
|
||||
new DdiResult(DdiResult.FinalResult.SUCCESS, new DdiProgress(2, 5)), List.of("Some feedback"));
|
||||
final DdiActionFeedback feedback = new DdiActionFeedback(Instant.now().toString(), ddiStatus);
|
||||
|
||||
mockMvc.perform(post(
|
||||
DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION
|
||||
+ "/{actionId}/feedback",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), cancelAction.getId()).content(
|
||||
JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed", "Some feedback"))
|
||||
objectMapper.writeValueAsString(feedback))
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(this.document.document(
|
||||
@@ -190,7 +201,10 @@ public class RootControllerDocumentationTest extends AbstractApiRestDocumentatio
|
||||
parameterWithName("actionId").description(DdiApiModelProperties.ACTION_ID_CANCELED)),
|
||||
requestFields(
|
||||
optionalRequestFieldWithPath("id")
|
||||
.description(DdiApiModelProperties.FEEDBACK_ACTION_ID),
|
||||
.description(DdiApiModelProperties.FEEDBACK_ACTION_ID)
|
||||
.type(JsonFieldType.NUMBER),
|
||||
optionalRequestFieldWithPath("time")
|
||||
.description(DdiApiModelProperties.FEEDBACK_ACTION_TIME),
|
||||
requestFieldWithPath("status").description(DdiApiModelProperties.TARGET_STATUS),
|
||||
requestFieldWithPath("status.execution")
|
||||
.description(DdiApiModelProperties.TARGET_EXEC_STATUS).type("enum")
|
||||
@@ -381,11 +395,15 @@ public class RootControllerDocumentationTest extends AbstractApiRestDocumentatio
|
||||
final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID));
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(set.getId(), target.getControllerId()));
|
||||
|
||||
mockMvc.perform(post(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/"
|
||||
+ DdiRestConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}/feedback", tenantAware.getCurrentTenant(),
|
||||
target.getControllerId(), actionId)
|
||||
.content(
|
||||
JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "Feedback message"))
|
||||
final DdiStatus ddiStatus = new DdiStatus(DdiStatus.ExecutionStatus.CLOSED,
|
||||
new DdiResult(DdiResult.FinalResult.SUCCESS, new DdiProgress(2, 5)), List.of("Feedback message"));
|
||||
final DdiActionFeedback feedback = new DdiActionFeedback(Instant.now().toString(), ddiStatus);
|
||||
|
||||
mockMvc.perform(post(
|
||||
DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION
|
||||
+ "/{actionId}/feedback",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), actionId)
|
||||
.content(objectMapper.writeValueAsString(feedback))
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaTypes.HAL_JSON_VALUE))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(this.document.document(
|
||||
@@ -395,7 +413,10 @@ public class RootControllerDocumentationTest extends AbstractApiRestDocumentatio
|
||||
|
||||
requestFields(
|
||||
optionalRequestFieldWithPath("id")
|
||||
.description(DdiApiModelProperties.FEEDBACK_ACTION_ID),
|
||||
.description(DdiApiModelProperties.FEEDBACK_ACTION_ID)
|
||||
.type(JsonFieldType.NUMBER),
|
||||
optionalRequestFieldWithPath("time")
|
||||
.description(DdiApiModelProperties.FEEDBACK_ACTION_TIME),
|
||||
requestFieldWithPath("status").description(DdiApiModelProperties.TARGET_STATUS),
|
||||
requestFieldWithPath("status.execution")
|
||||
.description(DdiApiModelProperties.TARGET_EXEC_STATUS).type("enum")
|
||||
|
||||
57
pom.xml
57
pom.xml
@@ -16,7 +16,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.7.RELEASE</version>
|
||||
<version>2.3.12.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
@@ -128,12 +128,11 @@
|
||||
|
||||
<properties>
|
||||
|
||||
<java.version>1.8</java.version>
|
||||
<!-- Developer preview: java.version = 11 -->
|
||||
<java.version>11</java.version>
|
||||
|
||||
<spring.boot.version>2.3.7.RELEASE</spring.boot.version>
|
||||
<spring-framework.version>5.2.20.RELEASE</spring-framework.version>
|
||||
<spring.cloud.version>Hoxton.SR7</spring.cloud.version>
|
||||
<spring.boot.version>2.3.12.RELEASE</spring.boot.version>
|
||||
<spring-framework.version>5.2.22.RELEASE</spring-framework.version>
|
||||
<spring.cloud.version>Hoxton.SR12</spring.cloud.version>
|
||||
<spring.plugin.core.version>2.0.0.RELEASE</spring.plugin.core.version>
|
||||
|
||||
<snapshotDependencyAllowed>true</snapshotDependencyAllowed>
|
||||
@@ -155,15 +154,27 @@
|
||||
<vaadin.gwt-user.version>2.8.2</vaadin.gwt-user.version>
|
||||
<!-- Vaadin versions - END -->
|
||||
|
||||
<!-- ************************ -->
|
||||
<!-- Maven Plugins -->
|
||||
<!-- ************************ -->
|
||||
<maven.processor.plugin.version>3.3.3</maven.processor.plugin.version>
|
||||
<maven.scm.plugin.version>1.11.1</maven.scm.plugin.version>
|
||||
<maven.site.plugin.version>3.9.0</maven.site.plugin.version>
|
||||
<maven.site.plugin.version>3.9.1</maven.site.plugin.version>
|
||||
<maven.surefire.plugin.version>3.0.0-M7</maven.surefire.plugin.version>
|
||||
<maven.failsafe.plugin.version>3.0.0-M7</maven.failsafe.plugin.version>
|
||||
<maven.enforcer.plugin.version>3.1.0</maven.enforcer.plugin.version>
|
||||
<!-- ************************ -->
|
||||
<!-- Maven Surefire settings -->
|
||||
<!-- ************************ -->
|
||||
<surefire.forkcount>1</surefire.forkcount>
|
||||
|
||||
<!-- Misc libraries versions - START -->
|
||||
<!-- Misc libraries versions - START -->
|
||||
<cron-utils.version>9.1.6</cron-utils.version>
|
||||
<jsoup.version>1.15.3</jsoup.version>
|
||||
<allure.version>2.13.6</allure.version>
|
||||
<eclipselink.version>2.7.9</eclipselink.version>
|
||||
<eclipselink.version>2.7.11</eclipselink.version>
|
||||
<eclipselink.maven.plugin.version>2.7.9.1</eclipselink.maven.plugin.version>
|
||||
<jaxb-api.version>2.3.0</jaxb-api.version>
|
||||
<gwtmockito.version>1.1.8</gwtmockito.version>
|
||||
<guava.version>30.1.1-jre</guava.version>
|
||||
<javax.el-api.version>2.2.4</javax.el-api.version>
|
||||
@@ -198,13 +209,7 @@
|
||||
${project.basedir}/../hawkbit-test-report/target/jacoco-aggregate/jacoco.xml,
|
||||
${project.basedir}/../../hawkbit-test-report/target/jacoco-aggregate/jacoco.xml
|
||||
</sonar.coverage.jacoco.xmlReportPaths>
|
||||
|
||||
<!-- Sonar - END -->
|
||||
|
||||
<!-- ************************ -->
|
||||
<!-- Maven Surefire settings -->
|
||||
<!-- ************************ -->
|
||||
<surefire.forkcount>1</surefire.forkcount>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@@ -225,6 +230,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>${maven.enforcer.plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<!-- Make sure that only non-snapshot versions are used
|
||||
@@ -404,6 +410,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven.surefire.plugin.version}</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<!-- Set output directory according to allure-framework recommendation -->
|
||||
@@ -415,9 +422,7 @@
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<reuseForks>true</reuseForks>
|
||||
<forkCount>${surefire.forkcount}</forkCount>
|
||||
<argLine>
|
||||
${jacoco.agent.ut.arg}
|
||||
</argLine>
|
||||
<argLine>${jacoco.agent.ut.arg}</argLine>
|
||||
<properties>
|
||||
<property>
|
||||
<name>listener</name>
|
||||
@@ -437,6 +442,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${maven.failsafe.plugin.version}</version>
|
||||
<configuration>
|
||||
<reuseForks>false</reuseForks>
|
||||
<forkCount>${surefire.forkcount}</forkCount>
|
||||
@@ -477,6 +483,11 @@
|
||||
<artifactId>maven-processor-plugin</artifactId>
|
||||
<version>${maven.processor.plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.ethlo.persistence.tools</groupId>
|
||||
<artifactId>eclipselink-maven-plugin</artifactId>
|
||||
<version>${eclipselink.maven.plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
@@ -653,9 +664,15 @@
|
||||
<exclusion>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>${jaxb-api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
||||
Reference in New Issue
Block a user