diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index 804b456fa..9f4a34fe7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -527,4 +527,22 @@ public interface ControllerManagement { */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) void deactivateAutoConfirmation(@NotEmpty String controllerId); + + /** + * Updates distributionSet installed version (experimental) + * + * @param distributionName + * installed + * @param version + * installed + * + * @return updated {@link Target} + * + * @throws EntityNotFoundException + * if target that has to be updated could not be found + * @throws java.util.NoSuchElementException + * if DistributionSetAssignmentResult list is empty + */ + @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) + boolean updateOfflineAssignedVersion(@NotEmpty String controllerId, String distributionName, String version); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index 0ead26944..dd47da3e8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -165,6 +165,9 @@ public interface DeploymentManagement { * target and multiassignment is disabled */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) + List offlineAssignedDistributionSets(Collection> assignments, String initiatedBy); + + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) List offlineAssignedDistributionSets(Collection> assignments); /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index 6211928c2..182a8c2c8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -13,6 +13,7 @@ import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED; import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED; import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE; import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE; +import static org.eclipse.hawkbit.security.SecurityContextTenantAware.SYSTEM_USER; import java.net.URI; import java.time.Duration; @@ -44,11 +45,14 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.ListUtils; import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; +import org.eclipse.hawkbit.repository.DeploymentManagement; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.MaintenanceScheduleHelper; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryProperties; +import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.UpdateMode; @@ -85,6 +89,7 @@ import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; @@ -161,6 +166,12 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Autowired private TargetTypeManagement targetTypeManagement; + @Autowired + private DeploymentManagement deploymentManagement; + + @Autowired + private DistributionSetManagement distributionSetManagement; + public JpaControllerManagement(final ScheduledExecutorService executorService, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final RepositoryProperties repositoryProperties) { @@ -1095,6 +1106,22 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont confirmationManagement.deactivateAutoConfirmation(controllerId); } + @Override + public boolean updateOfflineAssignedVersion(@NotEmpty String controllerId, String distributionName, String version){ + List distributionSetAssignmentResults = + systemSecurityContext.runAsSystem(() -> + distributionSetManagement.getByNameAndVersion(distributionName,version).map( + distributionSet -> deploymentManagement.offlineAssignedDistributionSets( + List.of(Map.entry(controllerId, distributionSet.getId())),controllerId)) + .orElseThrow(() -> + new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version))) + .stream().toList()); + boolean notAlreadyAssigned = distributionSetAssignmentResults.stream().findFirst() + .map(result-> result.getAlreadyAssigned()==0) + .orElseThrow(); + return notAlreadyAssigned; + } + private void cancelAssignDistributionSetEvent(final Action action) { afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher() .publishEvent(new CancelTargetAssignmentEvent(action, eventPublisherHolder.getApplicationId()))); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index 7548b9f98..5b5c52e5e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -185,6 +185,12 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl @Transactional(isolation = Isolation.READ_COMMITTED) public List offlineAssignedDistributionSets( final Collection> assignments) { + return offlineAssignedDistributionSets(assignments,tenantAware.getCurrentUsername()); + } + + @Override + public List offlineAssignedDistributionSets( + Collection> assignments, String initiatedBy) { final Collection> distinctAssignments = assignments.stream().distinct().toList(); enforceMaxAssignmentsPerRequest(distinctAssignments.size()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java index d2ed12f80..d62519f05 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java @@ -1564,6 +1564,36 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(foundAction).isPresent(); assertThat(foundAction.get().getId()).isEqualTo(actionId); } + @Test + @Description("Verify that assigning version form target works") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), + @Expect(type = DistributionSetCreatedEvent.class, count = 1), + @Expect(type = TargetUpdatedEvent.class, count = 1), + @Expect(type = DistributionSetUpdatedEvent.class, count = 1), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = ActionCreatedEvent.class, count = 1), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3)} + ) + void assignVersionToTarget() { + + final DistributionSet knownDistributionSet = testdataFactory.createDistributionSet(); + + // GIVEN + testdataFactory.createTarget(DEFAULT_CONTROLLER_ID).getId(); + + // WHEN + boolean updated1 = controllerManagement.updateOfflineAssignedVersion(DEFAULT_CONTROLLER_ID, + knownDistributionSet.getName(),knownDistributionSet.getVersion()); + // if target is already assigned to a distribution then it shouldn't reassign the distribution + boolean updated2 = controllerManagement.updateOfflineAssignedVersion(DEFAULT_CONTROLLER_ID, + knownDistributionSet.getName(),knownDistributionSet.getVersion()); + + // THEN + assertAssignedDistributionSetId(DEFAULT_CONTROLLER_ID, knownDistributionSet.getId()); + assertInstalledDistributionSetId(DEFAULT_CONTROLLER_ID, knownDistributionSet.getId()); + assertThat(updated1).isTrue(); + assertThat(updated2).isFalse(); + } @Test @Description("Verify that a null externalRef cannot be assigned to an action") diff --git a/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiAssignedVersion.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiAssignedVersion.java new file mode 100644 index 000000000..086790fd7 --- /dev/null +++ b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiAssignedVersion.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.ddi.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * Allow a target to declare running distribution set version + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class DdiAssignedVersion { + + @Schema(description = "Distribution Set name", example = "linux") + private final String name; + + @Schema(description = "Distribution set version", example = "1.2.3") + private final String version; + + /** + * Constructor + * + * @param name + * Distribution set name + * @param version + * Distribution set version + */ + @JsonCreator + public DdiAssignedVersion(@JsonProperty(value = "name", required = true) String name, + @JsonProperty(value = "version", required = true) String version) { + this.name = name; + this.version = version; + } + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + + @Override + public String toString() { + return "DdiInstalledVersion{" + "name='" + name + '\'' + ", version='" + version + '\'' + '}'; + } +} diff --git a/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java index 44cb2f127..aac89226c 100644 --- a/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java +++ b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java @@ -34,6 +34,7 @@ import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationBaseAction; import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase; import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase; +import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.springframework.hateoas.MediaTypes; import org.springframework.http.HttpStatus; @@ -826,4 +827,40 @@ public interface DdiRootControllerRestApi { + DdiRestConstants.CONFIRMATION_BASE + "/" + DdiRestConstants.AUTO_CONFIRM_DEACTIVATE) ResponseEntity deactivateAutoConfirmation(@PathVariable("tenant") final String tenant, @PathVariable("controllerId") @NotEmpty final String controllerId); -} \ No newline at end of file + + + /** + * Assign an already installed distribution for a target + * + * @param tenant + * of the client + * to provide + * @param controllerId + * of the target that matches to controller id + * @param ddiAssignedVersion + * as {@link DdiAssignedVersion} + * + * @return the response + */ + @Operation(summary = "Set offline assigned version", description = """ + Allow to set current running version. + """) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successfully retrieved"), + @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), + @ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", description = "Target or Distribution not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "409", description = "E.g. in case an entity is created or modified by another user in another request at the same time. You may retry your modification request.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "410", description = "Action is not active anymore.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "415", description = "The request was attempt with a media-type which is not supported by the server for this resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) + }) + @PostMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + + DdiRestConstants.INSTALLED_BASE_ACTION, consumes = { + MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR }) + ResponseEntity setAsssignedOfflineVersion(@Valid DdiAssignedVersion ddiAssignedVersion, + @PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId); +} diff --git a/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index ad0b3a642..8cea8e857 100644 --- a/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -41,6 +41,7 @@ import org.eclipse.hawkbit.ddi.json.model.DdiDeployment; import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.DdiMaintenanceWindowStatus; import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.HandlingType; import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase; +import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion; import org.eclipse.hawkbit.ddi.json.model.DdiResult.FinalResult; import org.eclipse.hawkbit.ddi.json.model.DdiUpdateMode; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; @@ -83,7 +84,6 @@ import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; @@ -757,4 +757,14 @@ public class DdiRootController implements DdiRootControllerRestApi { confirmationManagement.deactivateAutoConfirmation(controllerId); return new ResponseEntity<>(HttpStatus.OK); } -} \ No newline at end of file + + @Override + public ResponseEntity setAsssignedOfflineVersion(@Valid @RequestBody DdiAssignedVersion ddiAssignedVersion, + @PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId){ + boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId, + ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion()); + if (updated) + return new ResponseEntity<>(HttpStatus.CREATED); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java index 6f81dca1e..560ffe934 100644 --- a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java +++ b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java @@ -26,6 +26,7 @@ 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.DdiConfirmationFeedback; +import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion; import org.eclipse.hawkbit.ddi.json.model.DdiProgress; import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiStatus; @@ -71,6 +72,8 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat protected static final String DEPLOYMENT_BASE = CONTROLLER_BASE + "/deploymentBase/{actionId}"; protected static final String CANCEL_ACTION = CONTROLLER_BASE + "/cancelAction/{actionId}"; protected static final String INSTALLED_BASE = CONTROLLER_BASE + "/installedBase/{actionId}"; + protected static final String INSTALLED_BASE_ROOT = CONTROLLER_BASE + "/installedBase"; + protected static final String DEPLOYMENT_FEEDBACK = DEPLOYMENT_BASE + "/feedback"; protected static final String CANCEL_FEEDBACK = CANCEL_ACTION + "/feedback"; @@ -134,6 +137,13 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat statusMatcher); } + protected ResultActions postInstalledBase(final String controllerId, final String content, + final ResultMatcher statusMatcher) throws Exception { + return mvc.perform(post(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId) + .content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher); + } + protected ResultActions postDeploymentFeedback(final MediaType mediaType, final String controllerId, final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception { return mvc @@ -360,6 +370,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat return objectMapper.writeValueAsString(new DdiConfirmationFeedback(confirmation, code, messages)); } + protected String getJsonInstalledBase(String name, String version) throws JsonProcessingException { + return objectMapper.writeValueAsString(new DdiAssignedVersion(name, version)); + } + protected static ObjectMapper getMapper(){ return objectMapper; } diff --git a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java index 10395839a..747a85221 100644 --- a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java +++ b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java @@ -102,6 +102,37 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { String.valueOf(softwareModuleId)); } + @Test + @Description("Ensure that assigned version is self assigned version") + public void installedVersion() throws Exception { + final Target target = createTargetAndAssertNoActiveActions(); + final DistributionSet ds = testdataFactory.createDistributionSet(""); + + + // update assigned version + postInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status() + .isCreated()); + + assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()) + .isEqualTo(ds.getId()); + + // update assigned version while version already assigned + postInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status().isOk()); + } + @Test + @Description("Ensure that installedVersion is version self assigned") + public void installedVersionNotExist() throws Exception { + final Target target = createTargetAndAssertNoActiveActions(); + final String dsName = "unknown"; + final String dsVersion = "1.0.0"; + + + // get installed base + postInstalledBase(target.getControllerId(),getJsonInstalledBase(dsName,dsVersion),status().isNotFound()); + + assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue(); + } + @Test @Description("Test several deployments to a controller. Checks that action is represented as installedBase after installation.") public void deploymentSeveralActionsInInstalledBase() throws Exception {