Introduce basic functionality for invalidation of distributionsets (#1179)
* Basic DS invalidation functionality Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add checks for valid/complete DS Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Stop rollouts + auto assignments when invalidating a DS Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add methods to count AAs + rollouts for invalidation Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Small refactoring for DS management Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add invalidation functionality to REST API Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix update stopped rollouts status Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add various tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Introduce countActionsForInvalidation Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix event tests with incomplete DS Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add H2 migration script Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix action count method Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix REST documentation tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Change flyway version number Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add lock for DS invalidation + adapt tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Move concurrency test to own class Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Handle possible InterruptedException Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix concurrency test Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Use one transaction for all invalidations Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add invalidate endpoint to REST docu Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Execute invalidation in transaction when actions are cancelled Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Check that distribution set is valid when editing/creating metadata Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Remove all changes in UI Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add DB migration files for all databases Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Implement review findings Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Move DS invalidation to own class to check permissions for single steps Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Move invalidation count methods to management classes Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix failing tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com>
This commit is contained in:
committed by
GitHub
parent
b25e118e6c
commit
825cb64448
@@ -20,11 +20,11 @@ import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -34,6 +34,7 @@ import org.eclipse.hawkbit.repository.model.DeploymentRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DeploymentRequestBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
@@ -56,7 +57,7 @@ public interface DeploymentManagement {
|
||||
*
|
||||
* @param deploymentRequests
|
||||
* information about all target-ds-assignments that shall be made
|
||||
*
|
||||
*
|
||||
* @return the list of assignment results
|
||||
*
|
||||
* @throws IncompleteDistributionSetException
|
||||
@@ -66,17 +67,18 @@ public interface DeploymentManagement {
|
||||
* @throws EntityNotFoundException
|
||||
* if either provided {@link DistributionSet} or {@link Target}s
|
||||
* do not exist
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of targets the distribution set can be
|
||||
* assigned to at once is exceeded
|
||||
* @throws MultiAssignmentIsNotEnabledException
|
||||
* if the request results in multiple assignments to the same
|
||||
* target and multiassignment is disabled
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
List<DistributionSetAssignmentResult> assignDistributionSets(@Valid @NotEmpty List<DeploymentRequest> deploymentRequests);
|
||||
List<DistributionSetAssignmentResult> assignDistributionSets(
|
||||
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests);
|
||||
|
||||
/**
|
||||
* Assigns {@link DistributionSet}s to {@link Target}s according to the
|
||||
@@ -88,7 +90,7 @@ public interface DeploymentManagement {
|
||||
* information about all target-ds-assignments that shall be made
|
||||
* @param actionMessage
|
||||
* an optional message for the action status
|
||||
*
|
||||
*
|
||||
* @return the list of assignment results
|
||||
*
|
||||
* @throws IncompleteDistributionSetException
|
||||
@@ -98,23 +100,23 @@ public interface DeploymentManagement {
|
||||
* @throws EntityNotFoundException
|
||||
* if either provided {@link DistributionSet} or {@link Target}s
|
||||
* do not exist
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of targets the distribution set can be
|
||||
* assigned to at once is exceeded
|
||||
* @throws MultiAssignmentIsNotEnabledException
|
||||
* if the request results in multiple assignments to the same
|
||||
* target and multiassignment is disabled
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
List<DistributionSetAssignmentResult> assignDistributionSets(String initiatedBy,
|
||||
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests, String actionMessage);
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* build a {@link DeploymentRequest} for a target distribution set
|
||||
* assignment
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* ID of target
|
||||
* @param distributionSetId
|
||||
@@ -128,9 +130,9 @@ public interface DeploymentManagement {
|
||||
/**
|
||||
* Registers "offline" assignments. "offline" assignment means adding a
|
||||
* completed action for a {@link DistributionSet} to a {@link Target}.
|
||||
*
|
||||
*
|
||||
* The handling differs to hawkBit-managed updates by means that:<br/>
|
||||
*
|
||||
*
|
||||
* <ol type="A">
|
||||
* <li>it ignores targets completely that are in
|
||||
* {@link TargetUpdateStatus#PENDING}.</li>
|
||||
@@ -139,12 +141,12 @@ public interface DeploymentManagement {
|
||||
* status to {@link TargetUpdateStatus#IN_SYNC}.</li>
|
||||
* <li>does not send a {@link TargetAssignDistributionSetEvent}.</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* @param assignments
|
||||
* target IDs with the respective distribution set ID which they
|
||||
* are supposed to be assigned to
|
||||
* @return the assignment results
|
||||
*
|
||||
*
|
||||
* @throws IncompleteDistributionSetException
|
||||
* if mandatory {@link SoftwareModuleType} are not assigned as
|
||||
* defined by the {@link DistributionSetType}.
|
||||
@@ -152,11 +154,11 @@ public interface DeploymentManagement {
|
||||
* @throws EntityNotFoundException
|
||||
* if either provided {@link DistributionSet} or {@link Target}s
|
||||
* do not exist
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of targets the distribution set can be
|
||||
* assigned to at once is exceeded
|
||||
*
|
||||
*
|
||||
* @throws MultiAssignmentIsNotEnabledException
|
||||
* if the request results in multiple assignments to the same
|
||||
* target and multiassignment is disabled
|
||||
@@ -173,7 +175,7 @@ public interface DeploymentManagement {
|
||||
* to be canceled
|
||||
*
|
||||
* @return canceled {@link Action}
|
||||
*
|
||||
*
|
||||
* @throws CancelActionNotAllowedException
|
||||
* in case the given action is not active or is already a cancel
|
||||
* action
|
||||
@@ -221,20 +223,43 @@ public interface DeploymentManagement {
|
||||
* @param controllerId
|
||||
* the target associated to the actions to count
|
||||
* @return the count value of found actions associated to the target
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
long countActionsByTarget(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Counts all active {@link Action}s referring to the given DistributionSet.
|
||||
*
|
||||
* @param distributionSet
|
||||
* DistributionSet to count the {@link Action}s from
|
||||
* @return the count of actions referring to the given distributionSet
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
long countActionsByDistributionSetIdAndActiveIsTrue(Long distributionSet);
|
||||
|
||||
/**
|
||||
* Counts all active {@link Action}s referring to the given DistributionSet
|
||||
* that are not in a given state.
|
||||
*
|
||||
* @param distributionSet
|
||||
* DistributionSet to count the {@link Action}s from
|
||||
* @param status
|
||||
* the state the actions should not have
|
||||
* @return the count of actions referring to the given distributionSet
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
long countActionsByDistributionSetIdAndActiveIsTrueAndStatusIsNot(Long distributionSet, Status status);
|
||||
|
||||
/**
|
||||
* Get the {@link Action} entity for given actionId.
|
||||
*
|
||||
* @param actionId
|
||||
* to be id of the action
|
||||
* @return the corresponding {@link Action}
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
Optional<Action> findAction(long actionId);
|
||||
@@ -252,7 +277,7 @@ public interface DeploymentManagement {
|
||||
/**
|
||||
* Retrieves all {@link Action} which assigned to a specific
|
||||
* {@link DistributionSet}.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* the page request parameter for paging and sorting the result
|
||||
* @param distributionSetId
|
||||
@@ -260,7 +285,7 @@ public interface DeploymentManagement {
|
||||
* in the result
|
||||
* @return a list of {@link Action} which are assigned to a specific
|
||||
* {@link DistributionSet}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*/
|
||||
@@ -279,7 +304,7 @@ public interface DeploymentManagement {
|
||||
* the page request
|
||||
* @return a slice of actions assigned to the specific target and the
|
||||
* specification
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
@@ -299,7 +324,7 @@ public interface DeploymentManagement {
|
||||
* @param pageable
|
||||
* the pageable request to limit, sort the actions
|
||||
* @return a slice of actions found for a specific target
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
Slice<Action> findActionsByTarget(@NotEmpty String controllerId, @NotNull Pageable pageable);
|
||||
@@ -313,7 +338,7 @@ public interface DeploymentManagement {
|
||||
* @param actionId
|
||||
* to be filtered on
|
||||
* @return the corresponding {@link Page} of {@link ActionStatus}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if action with given ID does not exist
|
||||
*/
|
||||
@@ -346,13 +371,13 @@ public interface DeploymentManagement {
|
||||
|
||||
/**
|
||||
* Retrieves all active {@link Action}s of a specific target.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* the page request parameter for paging and sorting the result
|
||||
* @param controllerId
|
||||
* the target associated with the actions
|
||||
* @return a list of actions associated with the given target
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -367,7 +392,7 @@ public interface DeploymentManagement {
|
||||
* @param controllerId
|
||||
* the target associated with the actions
|
||||
* @return a list of actions associated with the given target
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -377,13 +402,13 @@ public interface DeploymentManagement {
|
||||
/**
|
||||
* Retrieves active {@link Action}s with highest weight that are assigned to
|
||||
* a {@link Target}.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* identifies the target to retrieve the action from
|
||||
* @param maxActionCount
|
||||
* max size of returned list
|
||||
* @return the action
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
List<Action> findActiveActionsWithHighestWeight(@NotEmpty String controllerId, int maxActionCount);
|
||||
@@ -391,7 +416,7 @@ public interface DeploymentManagement {
|
||||
/**
|
||||
* Get weight of an Action. Returns the default value if the weight is null
|
||||
* according to the properties.
|
||||
*
|
||||
*
|
||||
* @param action
|
||||
* to extract the weight from
|
||||
* @return weight of the action
|
||||
@@ -408,10 +433,10 @@ public interface DeploymentManagement {
|
||||
* to be canceled
|
||||
*
|
||||
* @return quite {@link Action}
|
||||
*
|
||||
*
|
||||
* @throws CancelActionNotAllowedException
|
||||
* in case the given action is not active
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if action with given ID does not exist
|
||||
*/
|
||||
@@ -425,7 +450,7 @@ public interface DeploymentManagement {
|
||||
* @param actionId
|
||||
* the ID of the action
|
||||
* @return the updated or the found {@link Action}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if action with given ID does not exist
|
||||
*/
|
||||
@@ -438,7 +463,7 @@ public interface DeploymentManagement {
|
||||
*
|
||||
* @param targetIds
|
||||
* ids of the {@link Target}s the actions belong to
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
||||
void cancelInactiveScheduledActionsForTargets(List<Long> targetIds);
|
||||
@@ -468,11 +493,11 @@ public interface DeploymentManagement {
|
||||
|
||||
/**
|
||||
* Returns {@link DistributionSet} that is assigned to given {@link Target}.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* of target
|
||||
* @return assigned {@link DistributionSet}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -481,11 +506,11 @@ public interface DeploymentManagement {
|
||||
/**
|
||||
* Returns {@link DistributionSet} that is installed on given
|
||||
* {@link Target}.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* of target
|
||||
* @return installed {@link DistributionSet}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if target with given ID does not exist
|
||||
*/
|
||||
@@ -494,20 +519,20 @@ public interface DeploymentManagement {
|
||||
/**
|
||||
* Deletes actions which match one of the given action status and which have
|
||||
* not been modified since the given (absolute) time-stamp.
|
||||
*
|
||||
*
|
||||
* @param status
|
||||
* Set of action status.
|
||||
* @param lastModified
|
||||
* A time-stamp in milliseconds.
|
||||
*
|
||||
*
|
||||
* @return The number of action entries that were deleted.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||
int deleteActionsByStatusAndLastModifiedBefore(@NotNull Set<Action.Status> status, long lastModified);
|
||||
|
||||
/**
|
||||
* Checks if there is an action for the device with the given controller ID that
|
||||
* is in the {@link Action.Status#CANCELING} state.
|
||||
* Checks if there is an action for the device with the given controller ID
|
||||
* that is in the {@link Action.Status#CANCELING} state.
|
||||
*
|
||||
* @param controllerId
|
||||
* of target
|
||||
@@ -516,4 +541,16 @@ public interface DeploymentManagement {
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
boolean hasPendingCancellations(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Cancels all actions that refer to a given distribution set. This method
|
||||
* is called when a distribution set is invalidated.
|
||||
*
|
||||
* @param cancelationType
|
||||
* defines if a force or soft cancel is executed
|
||||
* @param set
|
||||
* the distribution set for that the actions should be canceled
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
||||
void cancelActionsForDistributionSet(final CancelationType cancelationType, final DistributionSet set);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
|
||||
|
||||
/**
|
||||
* A DistributionSetInvalidationManagement service provides operations to
|
||||
* invalidate {@link DistributionSet}s.
|
||||
*
|
||||
*/
|
||||
public interface DistributionSetInvalidationManagement {
|
||||
|
||||
/**
|
||||
* Invalidates a given {@link DistributionSet}. The invalidation always
|
||||
* cancels all auto assignments referring this {@link DistributionSet} and
|
||||
* can not be undone. Optionally, all rollouts and actions referring this
|
||||
* {@link DistributionSet} can be canceled.
|
||||
*
|
||||
* @param distributionSetInvalidation
|
||||
* defines the {@link DistributionSet} and options what should be
|
||||
* canceled
|
||||
*/
|
||||
void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation);
|
||||
|
||||
/**
|
||||
* Counts all entities for a list of {@link DistributionSet}s that will be
|
||||
* canceled when invalidation is called for those {@link DistributionSet}s.
|
||||
*
|
||||
*
|
||||
* @param distributionSetInvalidation
|
||||
* defines the {@link DistributionSet} and options what should be
|
||||
* canceled
|
||||
* @return The {@link DistributionSetInvalidationCount} object that holds
|
||||
* information about the count of affected rollouts,
|
||||
* auto-assignments and actions
|
||||
*/
|
||||
DistributionSetInvalidationCount countEntitiesForInvalidation(
|
||||
final DistributionSetInvalidation distributionSetInvalidation);
|
||||
|
||||
}
|
||||
@@ -18,10 +18,12 @@ import javax.validation.constraints.NotNull;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
@@ -53,20 +55,20 @@ public interface DistributionSetManagement
|
||||
* to assign and update
|
||||
* @param moduleIds
|
||||
* to get assigned
|
||||
*
|
||||
*
|
||||
* @return the updated {@link DistributionSet}.
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if (at least one) given module does not exist
|
||||
*
|
||||
*
|
||||
* @throws EntityReadOnlyException
|
||||
* if use tries to change the {@link DistributionSet} s while
|
||||
* the DS is already in use.
|
||||
*
|
||||
*
|
||||
* @throws UnsupportedSoftwareModuleForThisDistributionSetException
|
||||
* if {@link SoftwareModule#getType()} is not supported by this
|
||||
* {@link DistributionSet#getType()}.
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of {@link SoftwareModule}s is exceeded
|
||||
* for the addressed {@link DistributionSet}.
|
||||
@@ -82,9 +84,9 @@ public interface DistributionSetManagement
|
||||
* to assign for
|
||||
* @param tagId
|
||||
* to assign
|
||||
*
|
||||
*
|
||||
* @return list of assigned ds
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if tag with given ID does not exist or (at least one) of the
|
||||
* distribution sets.
|
||||
@@ -101,14 +103,14 @@ public interface DistributionSetManagement
|
||||
* @param metadata
|
||||
* the meta data entries to create or update
|
||||
* @return the updated or created distribution set meta data entries
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if given set does not exist
|
||||
*
|
||||
*
|
||||
* @throws EntityAlreadyExistsException
|
||||
* in case one of the meta data entry already exists for the
|
||||
* specific key
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of {@link MetaData} entries is exceeded
|
||||
* for the addressed {@link DistributionSet}
|
||||
@@ -123,7 +125,7 @@ public interface DistributionSetManagement
|
||||
* where meta data has to be deleted
|
||||
* @param key
|
||||
* of the meta data element
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if given set does not exist
|
||||
*/
|
||||
@@ -136,7 +138,7 @@ public interface DistributionSetManagement
|
||||
* @param actionId
|
||||
* the action associated with the distribution set
|
||||
* @return the distribution set which is associated with the action
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if action with given ID does not exist
|
||||
*/
|
||||
@@ -152,7 +154,7 @@ public interface DistributionSetManagement
|
||||
*
|
||||
* @param setId
|
||||
* to look for.
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
@@ -165,15 +167,69 @@ public interface DistributionSetManagement
|
||||
* name of {@link DistributionSet}; case insensitive
|
||||
* @param version
|
||||
* version of {@link DistributionSet}
|
||||
*
|
||||
*
|
||||
* @return the page with the found {@link DistributionSet}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
Optional<DistributionSet> getByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version);
|
||||
|
||||
/**
|
||||
* Find distribution set by id and throw an exception if it is deleted,
|
||||
* incomplete or invalidated.
|
||||
*
|
||||
* @param id
|
||||
* id of {@link DistributionSet}
|
||||
*
|
||||
* @return the found valid {@link DistributionSet}
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*
|
||||
* @throws InvalidDistributionSetException
|
||||
* if distribution set with given ID is invalidated
|
||||
*
|
||||
* @throws IncompleteDistributionSetException
|
||||
* if distribution set with given ID is incomplete
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
DistributionSet getValidAndComplete(long id);
|
||||
|
||||
/**
|
||||
* Find distribution set by id and throw an exception if it is deleted or
|
||||
* invalidated.
|
||||
*
|
||||
* @param id
|
||||
* id of {@link DistributionSet}
|
||||
*
|
||||
* @return the found valid {@link DistributionSet}
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*
|
||||
* @throws InvalidDistributionSetException
|
||||
* if distribution set with given ID is invalidated
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
DistributionSet getValid(long id);
|
||||
|
||||
/**
|
||||
* Find distribution set by id and throw an exception if it is (soft)
|
||||
* deleted.
|
||||
*
|
||||
* @param id
|
||||
* id of {@link DistributionSet}
|
||||
*
|
||||
* @return the found valid {@link DistributionSet}
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
DistributionSet getOrElseThrowException(long id);
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given distribution set id.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* the page request to page the result
|
||||
* @param setId
|
||||
@@ -181,7 +237,7 @@ public interface DistributionSetManagement
|
||||
*
|
||||
* @return a paged result of all meta data entries for a given distribution
|
||||
* set id
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if distribution set with given ID does not exist
|
||||
*/
|
||||
@@ -190,7 +246,7 @@ public interface DistributionSetManagement
|
||||
|
||||
/**
|
||||
* Finds all meta data by the given distribution set id.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* the page request to page the result
|
||||
* @param setId
|
||||
@@ -200,14 +256,14 @@ public interface DistributionSetManagement
|
||||
*
|
||||
* @return a paged result of all meta data entries for a given distribution
|
||||
* set id
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterSyntaxException
|
||||
* if the RSQL syntax is wrong
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* of distribution set with given ID does not exist
|
||||
*/
|
||||
@@ -249,7 +305,7 @@ public interface DistributionSetManagement
|
||||
* has details of filters to be applied
|
||||
* @param assignedOrInstalled
|
||||
* the id of the Target to be ordered by
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet}s
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
@@ -277,14 +333,14 @@ public interface DistributionSetManagement
|
||||
* @param tagId
|
||||
* of the tag the DS are assigned to
|
||||
* @return the page of found {@link DistributionSet}
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterSyntaxException
|
||||
* if the RSQL syntax is wrong
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* of distribution set tag with given ID does not exist
|
||||
*/
|
||||
@@ -301,7 +357,7 @@ public interface DistributionSetManagement
|
||||
* @param tagId
|
||||
* of the tag the DS are assigned to
|
||||
* @return the page of found {@link DistributionSet}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* of distribution set tag with given ID does not exist
|
||||
*/
|
||||
@@ -316,7 +372,7 @@ public interface DistributionSetManagement
|
||||
* @param key
|
||||
* of the meta data element
|
||||
* @return the found DistributionSetMetadata
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* is set with given ID does not exist
|
||||
*/
|
||||
@@ -329,7 +385,7 @@ public interface DistributionSetManagement
|
||||
*
|
||||
* @param setId
|
||||
* to check
|
||||
*
|
||||
*
|
||||
* @return <code>true</code> if in use
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
@@ -338,8 +394,8 @@ public interface DistributionSetManagement
|
||||
/**
|
||||
* Toggles {@link DistributionSetTag} assignment to given
|
||||
* {@link DistributionSet}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.
|
||||
* 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.
|
||||
*
|
||||
* @param setIds
|
||||
* to toggle for
|
||||
@@ -347,7 +403,7 @@ public interface DistributionSetManagement
|
||||
* to toggle
|
||||
* @return {@link DistributionSetTagAssignmentResult} with all meta data of
|
||||
* the assignment outcome.
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if given tag does not exist or (at least one) module
|
||||
*/
|
||||
@@ -363,10 +419,10 @@ public interface DistributionSetManagement
|
||||
* @param moduleId
|
||||
* to be unassigned
|
||||
* @return the updated {@link DistributionSet}.
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if given module or DS does not exist
|
||||
*
|
||||
*
|
||||
* @throws EntityReadOnlyException
|
||||
* if use tries to change the {@link DistributionSet} s while
|
||||
* the DS is already in use.
|
||||
@@ -383,7 +439,7 @@ public interface DistributionSetManagement
|
||||
* @param tagId
|
||||
* to unassign
|
||||
* @return the unassigned ds or <null> if no ds is unassigned
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if set or tag with given ID does not exist
|
||||
*/
|
||||
@@ -398,7 +454,7 @@ public interface DistributionSetManagement
|
||||
* @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
|
||||
* updated
|
||||
@@ -409,16 +465,25 @@ public interface DistributionSetManagement
|
||||
/**
|
||||
* Count all {@link DistributionSet}s in the repository that are not marked
|
||||
* as deleted.
|
||||
*
|
||||
*
|
||||
* @param typeId
|
||||
* to look for
|
||||
*
|
||||
* @return number of {@link DistributionSet}s
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if type with given ID does not exist
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||
long countByTypeId(long typeId);
|
||||
|
||||
/**
|
||||
* Sets the specified {@link DistributionSet} as invalidated.
|
||||
*
|
||||
* @param set
|
||||
* the ID of the {@link DistributionSet} to be set to invalid
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||
void invalidate(DistributionSet set);
|
||||
|
||||
}
|
||||
|
||||
@@ -59,6 +59,12 @@ public class RepositoryProperties {
|
||||
*/
|
||||
private int actionWeightIfAbsent = 1000;
|
||||
|
||||
/**
|
||||
* Defines a timeout for the lock during invalidation of distribution sets
|
||||
* (in seconds).
|
||||
*/
|
||||
private long dsInvalidationLockTimeout = 5;
|
||||
|
||||
public boolean isEagerPollPersistence() {
|
||||
return eagerPollPersistence;
|
||||
}
|
||||
@@ -107,4 +113,12 @@ public class RepositoryProperties {
|
||||
this.actionWeightIfAbsent = actionWeightIfAbsent;
|
||||
}
|
||||
|
||||
public long getDsInvalidationLockTimeout() {
|
||||
return dsInvalidationLockTimeout;
|
||||
}
|
||||
|
||||
public void setDsInvalidationLockTimeout(final long dsInvalidationLockTimeout) {
|
||||
this.dsInvalidationLockTimeout = dsInvalidationLockTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutUpdate;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||
@@ -49,29 +49,29 @@ public interface RolloutManagement {
|
||||
|
||||
/**
|
||||
* Process rollout based on its current {@link Rollout#getStatus()}.
|
||||
*
|
||||
*
|
||||
* For {@link RolloutStatus#CREATING} that means creating the
|
||||
* {@link RolloutGroup}s with {@link Target}s and when finished switch to
|
||||
* {@link RolloutStatus#READY}.
|
||||
*
|
||||
*
|
||||
* For {@link RolloutStatus#READY} that means switching to
|
||||
* {@link RolloutStatus#STARTING} if the {@link Rollout#getStartAt()} is set
|
||||
* and time of calling this method is beyond this point in time. This auto
|
||||
* start mechanism is optional. Call {@link #start(Long)} otherwise.
|
||||
*
|
||||
*
|
||||
* For {@link RolloutStatus#STARTING} that means starting the first
|
||||
* {@link RolloutGroup}s in line and when finished switch to
|
||||
* {@link RolloutStatus#RUNNING}.
|
||||
*
|
||||
*
|
||||
* For {@link RolloutStatus#RUNNING} that means checking to activate further
|
||||
* groups based on the defined thresholds. Switched to
|
||||
* {@link RolloutStatus#FINISHED} is all groups are finished.
|
||||
*
|
||||
*
|
||||
* For {@link RolloutStatus#DELETING} that means either soft delete in case
|
||||
* rollout was already {@link RolloutStatus#RUNNING} which results in status
|
||||
* change {@link RolloutStatus#DELETED} or hard delete from the persistence
|
||||
* otherwise.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||
void handleRollouts();
|
||||
@@ -95,6 +95,17 @@ public interface RolloutManagement {
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
|
||||
long countByFilters(@NotEmpty String searchText);
|
||||
|
||||
/**
|
||||
* Counts all {@link Rollout}s for a specific {@link DistributionSet} that
|
||||
* are stoppable
|
||||
*
|
||||
* @param setId
|
||||
* the distribution set
|
||||
* @return the count
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
|
||||
long countByDistributionSetIdAndRolloutIsStoppable(long setId);
|
||||
|
||||
/**
|
||||
* Persists a new rollout entity. The filter within the
|
||||
* {@link Rollout#getTargetFilterQuery()} is used to retrieve the targets
|
||||
@@ -217,7 +228,7 @@ public interface RolloutManagement {
|
||||
|
||||
/**
|
||||
* Retrieves all rollouts found by the given specification.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* the page request to sort and limit the result
|
||||
* @param rsqlParam
|
||||
@@ -226,7 +237,7 @@ public interface RolloutManagement {
|
||||
* flag if deleted rollouts should be included
|
||||
*
|
||||
* @return a page of found rollouts
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
@@ -282,7 +293,7 @@ public interface RolloutManagement {
|
||||
* @param deleted
|
||||
* flag if deleted rollouts should be included
|
||||
* @return rollout details of targets count for different statuses
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
|
||||
@@ -293,7 +304,7 @@ public interface RolloutManagement {
|
||||
*
|
||||
* @param rolloutId
|
||||
* rollout id
|
||||
*
|
||||
*
|
||||
* @return <code>true</code> if rollout exists
|
||||
*/
|
||||
boolean exists(long rolloutId);
|
||||
@@ -318,7 +329,7 @@ public interface RolloutManagement {
|
||||
* @throws RolloutIllegalStateException
|
||||
* if given rollout is not in {@link RolloutStatus#RUNNING}.
|
||||
* Only running rollouts can be paused.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_HANDLE)
|
||||
void pauseRollout(long rolloutId);
|
||||
@@ -330,7 +341,7 @@ public interface RolloutManagement {
|
||||
*
|
||||
* @param rolloutId
|
||||
* the rollout to be resumed
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if rollout with given ID does not exist
|
||||
* @throws RolloutIllegalStateException
|
||||
@@ -368,14 +379,14 @@ public interface RolloutManagement {
|
||||
* {@link RolloutStatus#WAITING_FOR_APPROVAL}. If the rollout is approved,
|
||||
* it switches state to {@link RolloutStatus#READY}, otherwise it switches
|
||||
* to state {@link RolloutStatus#APPROVAL_DENIED}
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the rollout to be approved or denied.
|
||||
* @param decision
|
||||
* decision whether a rollout is approved or denied.
|
||||
* @param remark
|
||||
* user remark on approve / deny decision
|
||||
*
|
||||
*
|
||||
* @return approved or denied rollout
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
@@ -399,7 +410,7 @@ public interface RolloutManagement {
|
||||
* the rollout to be started
|
||||
*
|
||||
* @return started rollout
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if rollout with given ID does not exist
|
||||
* @throws RolloutIllegalStateException
|
||||
@@ -416,13 +427,13 @@ public interface RolloutManagement {
|
||||
* rollout to be updated
|
||||
*
|
||||
* @return Rollout updated rollout
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if rollout or DS with given IDs do not exist
|
||||
* @throws EntityReadOnlyException
|
||||
* if rollout is in soft deleted state, i.e. only kept as
|
||||
* reference
|
||||
*
|
||||
*
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_UPDATE)
|
||||
Rollout update(@NotNull @Valid RolloutUpdate update);
|
||||
@@ -430,12 +441,24 @@ public interface RolloutManagement {
|
||||
/**
|
||||
* Deletes a rollout. A rollout might be deleted asynchronously by
|
||||
* indicating the rollout by {@link RolloutStatus#DELETING}
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to be deleted
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_DELETE)
|
||||
void delete(long rolloutId);
|
||||
|
||||
/**
|
||||
* Cancels all rollouts that refer to the given {@link DistributionSet}.
|
||||
* This is called when a distribution set is invalidated and the cancel
|
||||
* rollouts option is activated.
|
||||
*
|
||||
* @param set
|
||||
* the {@link DistributionSet} for that the rollouts should be
|
||||
* canceled
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_UPDATE)
|
||||
void cancelRolloutsForDistributionSet(DistributionSet set);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
|
||||
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
@@ -42,13 +43,13 @@ public interface TargetFilterQueryManagement {
|
||||
*
|
||||
* @param create
|
||||
* to create
|
||||
*
|
||||
*
|
||||
* @return the new {@link TargetFilterQuery}
|
||||
*
|
||||
*
|
||||
* @throws ConstraintViolationException
|
||||
* if fields are not filled as specified. Check
|
||||
* {@link TargetFilterQueryCreate} for field constraints.
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the maximum number of targets that is addressed by the
|
||||
* given query is exceeded (auto-assignments only)
|
||||
@@ -61,7 +62,7 @@ public interface TargetFilterQueryManagement {
|
||||
*
|
||||
* @param targetFilterQueryId
|
||||
* IDs of target filter query to be deleted
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if filter with given ID does not exist
|
||||
*/
|
||||
@@ -70,16 +71,16 @@ public interface TargetFilterQueryManagement {
|
||||
|
||||
/**
|
||||
* Verifies the provided filter syntax.
|
||||
*
|
||||
*
|
||||
* @param query
|
||||
* to verify
|
||||
*
|
||||
*
|
||||
* @return <code>true</code> if syntax is valid
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterUnsupportedFieldException
|
||||
* if a field in the RSQL string is used but not provided by the
|
||||
* given {@code fieldNameProvider}
|
||||
*
|
||||
*
|
||||
* @throws RSQLParameterSyntaxException
|
||||
* if the RSQL syntax is wrong
|
||||
*/
|
||||
@@ -99,12 +100,23 @@ public interface TargetFilterQueryManagement {
|
||||
|
||||
/**
|
||||
* Counts all {@link TargetFilterQuery}s.
|
||||
*
|
||||
*
|
||||
* @return the number of all target filter queries
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
long count();
|
||||
|
||||
/**
|
||||
* Counts all target filters that have a given auto assign distribution set
|
||||
* assigned.
|
||||
*
|
||||
* @param autoAssignDistributionSetId
|
||||
* the id of the distribution set
|
||||
* @return the count
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link TargetFilterQuery}s which match the given name
|
||||
* filter.
|
||||
@@ -154,7 +166,7 @@ public interface TargetFilterQueryManagement {
|
||||
* @param rsqlParam
|
||||
* RSQL filter
|
||||
* @return the page with the found {@link TargetFilterQuery}s
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if DS with given ID does not exist
|
||||
*/
|
||||
@@ -198,17 +210,17 @@ public interface TargetFilterQueryManagement {
|
||||
*
|
||||
* @param update
|
||||
* to be updated
|
||||
*
|
||||
*
|
||||
* @return the updated {@link TargetFilterQuery}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if either {@link TargetFilterQuery} and/or autoAssignDs are
|
||||
* provided but not found
|
||||
*
|
||||
*
|
||||
* @throws ConstraintViolationException
|
||||
* if fields are not filled as specified. Check
|
||||
* {@link TargetFilterQueryUpdate} for field constraints.
|
||||
*
|
||||
*
|
||||
* @throws QuotaExceededException
|
||||
* if the update contains a new query which addresses too many
|
||||
* targets (auto-assignments only)
|
||||
@@ -218,29 +230,43 @@ public interface TargetFilterQueryManagement {
|
||||
|
||||
/**
|
||||
* Updates the auto assign settings of an {@link TargetFilterQuery}.
|
||||
*
|
||||
*
|
||||
* @param autoAssignDistributionSetUpdate
|
||||
* the new auto assignment
|
||||
*
|
||||
*
|
||||
* @return the updated {@link TargetFilterQuery}
|
||||
*
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
* if either {@link TargetFilterQuery} and/or autoAssignDs are
|
||||
* provided but not found
|
||||
*
|
||||
*
|
||||
* @throws AssignmentQuotaExceededException
|
||||
* if the query that is already associated with this filter
|
||||
* query addresses too many targets (auto-assignments only)
|
||||
*
|
||||
*
|
||||
* @throws InvalidAutoAssignActionTypeException
|
||||
* if the provided auto-assign {@link ActionType} is not valid
|
||||
* (neither FORCED, nor SOFT)
|
||||
*
|
||||
* @throws InvalidAutoAssignDistributionSetException
|
||||
* if the provided auto-assign {@link DistributionSet} is not
|
||||
* valid (incomplete or soft deleted)
|
||||
*
|
||||
* @throws IncompleteDistributionSetException
|
||||
* if the provided auto-assign {@link DistributionSet} is
|
||||
* incomplete
|
||||
*
|
||||
* @throws InvalidDistributionSetException
|
||||
* if the provided auto-assign {@link DistributionSet} is
|
||||
* invalidated
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
||||
TargetFilterQuery updateAutoAssignDS(
|
||||
@NotNull @Valid AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate);
|
||||
|
||||
/**
|
||||
* Removes the given {@link DistributionSet} from all auto assignments.
|
||||
*
|
||||
* @param setId
|
||||
* the {@link DistributionSet} to be removed from auto
|
||||
* assignments.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
|
||||
void cancelAutoAssignmentForDistributionSet(long setId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.event.remote;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* Event that is published when a rollout is stopped due to invalidation of a
|
||||
* {@link DistributionSet}.
|
||||
*/
|
||||
public class RolloutStoppedEvent extends RemoteTenantAwareEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Collection<Long> rolloutGroupIds;
|
||||
private long rolloutId;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public RolloutStoppedEvent() {
|
||||
// for serialization libs like jackson
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for json serialization.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant
|
||||
* @param entityId
|
||||
* the entity id
|
||||
* @param entityClass
|
||||
* the entity class
|
||||
* @param applicationId
|
||||
* the origin application id
|
||||
*/
|
||||
public RolloutStoppedEvent(final String tenant, final String applicationId, final long rolloutId,
|
||||
final Collection<Long> rolloutGroupIds) {
|
||||
super(rolloutId, tenant, applicationId);
|
||||
this.rolloutId = rolloutId;
|
||||
this.rolloutGroupIds = rolloutGroupIds;
|
||||
}
|
||||
|
||||
public Collection<Long> getRolloutGroupIds() {
|
||||
return rolloutGroupIds;
|
||||
}
|
||||
|
||||
public void setRolloutGroupIds(final Collection<Long> rolloutGroupIds) {
|
||||
this.rolloutGroupIds = rolloutGroupIds;
|
||||
}
|
||||
|
||||
public long getRolloutId() {
|
||||
return rolloutId;
|
||||
}
|
||||
|
||||
public void setRolloutId(final long rolloutId) {
|
||||
this.rolloutId = rolloutId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
|
||||
/**
|
||||
* Thrown if a distribution set for auto-assignment is incomplete (i.e.
|
||||
* mandatory modules are missing) or soft deleted.
|
||||
*/
|
||||
public class InvalidAutoAssignDistributionSetException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_AUTO_ASSIGN_DISTRIBUTION_SET_INVALID;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public InvalidAutoAssignDistributionSetException() {
|
||||
super(THIS_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
|
||||
public class InvalidDistributionSetException extends AbstractServerRtException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new InvalidDistributionSetException with
|
||||
* {@link SpServerError#SP_DS_INVALID} error.
|
||||
*/
|
||||
public InvalidDistributionSetException() {
|
||||
super(SpServerError.SP_DS_INVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cause
|
||||
* for the exception
|
||||
*/
|
||||
public InvalidDistributionSetException(final Throwable cause) {
|
||||
super(SpServerError.SP_DS_INVALID, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* of the error
|
||||
*/
|
||||
public InvalidDistributionSetException(final String message) {
|
||||
super(message, SpServerError.SP_DS_INVALID);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
|
||||
/**
|
||||
* {@link StopRolloutException} is thrown when an error occurs while stopping
|
||||
* the rollout (due to an invalidation of distribution set). This could be
|
||||
* caused by a long ongoing creation of a rollout.
|
||||
*/
|
||||
public class StopRolloutException extends AbstractServerRtException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new StopRolloutException with
|
||||
* {@link SpServerError#SP_STOP_ROLLOUT_FAILED} error.
|
||||
*/
|
||||
public StopRolloutException() {
|
||||
super(SpServerError.SP_STOP_ROLLOUT_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new StopRolloutException with
|
||||
* {@link SpServerError#SP_STOP_ROLLOUT_FAILED} error.
|
||||
*
|
||||
* @param cause
|
||||
* for the exception
|
||||
*/
|
||||
public StopRolloutException(final Throwable cause) {
|
||||
super(SpServerError.SP_STOP_ROLLOUT_FAILED, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new StopRolloutException with
|
||||
* {@link SpServerError#SP_STOP_ROLLOUT_FAILED} error.
|
||||
*
|
||||
* @param message
|
||||
* of the error
|
||||
*/
|
||||
public StopRolloutException(final String message) {
|
||||
super(message, SpServerError.SP_STOP_ROLLOUT_FAILED);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import java.util.Set;
|
||||
* A {@link DistributionSet} defines a meta package that combines a set of
|
||||
* {@link SoftwareModule}s which have to be or are provisioned to a
|
||||
* {@link Target}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* A {@link Target} has exactly one target {@link DistributionSet} assigned.
|
||||
* </p>
|
||||
@@ -71,4 +71,10 @@ public interface DistributionSet extends NamedVersionedEntity {
|
||||
*/
|
||||
boolean isComplete();
|
||||
|
||||
/**
|
||||
* @return <code>false</code> if this {@link DistributionSet} is
|
||||
* invalidated.
|
||||
*/
|
||||
boolean isValid();
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ public final class DistributionSetFilter {
|
||||
public static class DistributionSetFilterBuilder {
|
||||
private Boolean isDeleted;
|
||||
private Boolean isComplete;
|
||||
private Boolean isValid;
|
||||
private DistributionSetType type;
|
||||
private String searchText;
|
||||
private String filterString;
|
||||
@@ -57,6 +58,11 @@ public final class DistributionSetFilter {
|
||||
return this;
|
||||
}
|
||||
|
||||
public DistributionSetFilterBuilder setIsValid(final Boolean isValid) {
|
||||
this.isValid = isValid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DistributionSetFilterBuilder setSearchText(final String searchText) {
|
||||
this.searchText = searchText;
|
||||
return this;
|
||||
@@ -86,6 +92,7 @@ public final class DistributionSetFilter {
|
||||
|
||||
private final Boolean isDeleted;
|
||||
private final Boolean isComplete;
|
||||
private final Boolean isValid;
|
||||
private final DistributionSetType type;
|
||||
private final String searchText;
|
||||
private final String filterString;
|
||||
@@ -104,6 +111,7 @@ public final class DistributionSetFilter {
|
||||
public DistributionSetFilter(final DistributionSetFilterBuilder builder) {
|
||||
this.isDeleted = builder.isDeleted;
|
||||
this.isComplete = builder.isComplete;
|
||||
this.isValid = builder.isValid;
|
||||
this.type = builder.type;
|
||||
this.searchText = builder.searchText;
|
||||
this.filterString = builder.filterString;
|
||||
@@ -129,6 +137,10 @@ public final class DistributionSetFilter {
|
||||
return isDeleted;
|
||||
}
|
||||
|
||||
public Boolean getIsValid() {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
public String getSearchText() {
|
||||
return searchText;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.model;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Holds the information about the invalidation of a distribution set
|
||||
*/
|
||||
public class DistributionSetInvalidation {
|
||||
|
||||
private Collection<Long> distributionSetIds;
|
||||
private CancelationType cancelationType;
|
||||
private boolean cancelRollouts;
|
||||
|
||||
/**
|
||||
* Parametric constructor
|
||||
*
|
||||
* @param distributionSetIds
|
||||
* defines which distribution sets should be canceled
|
||||
* @param cancelationType
|
||||
* defines if actions should be canceled
|
||||
* @param cancelRollouts
|
||||
* defines if rollouts should be canceled
|
||||
*/
|
||||
public DistributionSetInvalidation(final Collection<Long> distributionSetIds, final CancelationType cancelationType,
|
||||
final boolean cancelRollouts) {
|
||||
this.distributionSetIds = distributionSetIds;
|
||||
this.cancelationType = cancelationType;
|
||||
this.cancelRollouts = cancelRollouts;
|
||||
}
|
||||
|
||||
public Collection<Long> getDistributionSetIds() {
|
||||
return distributionSetIds;
|
||||
}
|
||||
|
||||
public void setDistributionSetIds(final Collection<Long> distributionSetIds) {
|
||||
this.distributionSetIds = distributionSetIds;
|
||||
}
|
||||
|
||||
public CancelationType getCancelationType() {
|
||||
return cancelationType;
|
||||
}
|
||||
|
||||
public void setCancelationType(final CancelationType cancelationType) {
|
||||
this.cancelationType = cancelationType;
|
||||
}
|
||||
|
||||
public boolean isCancelRollouts() {
|
||||
return cancelRollouts;
|
||||
}
|
||||
|
||||
public void setCancelRollouts(final boolean cancelRollouts) {
|
||||
this.cancelRollouts = cancelRollouts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if and how actions should be canceled when invalidating a
|
||||
* distribution set
|
||||
*/
|
||||
public enum CancelationType {
|
||||
FORCE, SOFT, NONE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.model;
|
||||
|
||||
/**
|
||||
* object that holds information about the count of affected rollouts,
|
||||
* auto-assignments and actions, when a list of distribution sets gets
|
||||
* invalidated
|
||||
*/
|
||||
public class DistributionSetInvalidationCount {
|
||||
|
||||
private final long rolloutsCount;
|
||||
private final long autoAssignmentCount;
|
||||
private final long actionCount;
|
||||
|
||||
public DistributionSetInvalidationCount(final long rolloutsCount, final long autoAssignmentCount,
|
||||
final long actionCount) {
|
||||
this.rolloutsCount = rolloutsCount;
|
||||
this.autoAssignmentCount = autoAssignmentCount;
|
||||
this.actionCount = actionCount;
|
||||
}
|
||||
|
||||
public long getRolloutsCount() {
|
||||
return rolloutsCount;
|
||||
}
|
||||
|
||||
public long getAutoAssignmentCount() {
|
||||
return autoAssignmentCount;
|
||||
}
|
||||
|
||||
public long getActionCount() {
|
||||
return actionCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status;
|
||||
/**
|
||||
* Software update operations in large scale IoT scenarios with hundred of
|
||||
* thousands of devices require special handling.
|
||||
*
|
||||
*
|
||||
* That includes secure handling of large volumes of devices at rollout creation
|
||||
* time. Monitoring of the rollout progress. Emergency rollout shutdown in case
|
||||
* of problems on to many devices and reporting capabilities for a complete
|
||||
@@ -149,6 +149,11 @@ public interface Rollout extends NamedEntity {
|
||||
*/
|
||||
STOPPED,
|
||||
|
||||
/**
|
||||
* Rollout is going to be stopped.
|
||||
*/
|
||||
STOPPING,
|
||||
|
||||
/**
|
||||
* Rollout is running.
|
||||
*/
|
||||
@@ -174,7 +179,7 @@ public interface Rollout extends NamedEntity {
|
||||
/**
|
||||
* Rollout could not be created due to errors, might be a database
|
||||
* problem during asynchronous creating.
|
||||
*
|
||||
*
|
||||
* @deprecated legacy status is not used anymore
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -183,7 +188,7 @@ public interface Rollout extends NamedEntity {
|
||||
/**
|
||||
* Rollout could not be started due to errors, might be database problem
|
||||
* during asynchronous starting.
|
||||
*
|
||||
*
|
||||
* @deprecated legacy status is not used anymore
|
||||
*/
|
||||
@Deprecated
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleTypeDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
@@ -60,7 +61,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationUpd
|
||||
* The {@link EventType} class declares the event-type and it's corresponding
|
||||
* encoding value in the payload of an remote header. The event-type is encoded
|
||||
* into the payload of the message which is distributed.
|
||||
*
|
||||
*
|
||||
* To encode and decode the event class type we need some conversation mapping
|
||||
* between the actual class and the corresponding integer value which is the
|
||||
* encoded value in the byte-payload.
|
||||
@@ -146,6 +147,9 @@ public class EventType {
|
||||
TYPES.put(40, TenantConfigurationCreatedEvent.class);
|
||||
TYPES.put(41, TenantConfigurationUpdatedEvent.class);
|
||||
TYPES.put(42, TenantConfigurationDeletedEvent.class);
|
||||
|
||||
// rollout stopped due to invalidated distribution set
|
||||
TYPES.put(43, RolloutStoppedEvent.class);
|
||||
}
|
||||
|
||||
private int value;
|
||||
@@ -159,7 +163,7 @@ public class EventType {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
* the value to initialize
|
||||
*/
|
||||
@@ -177,7 +181,7 @@ public class EventType {
|
||||
|
||||
/**
|
||||
* Returns a {@link EventType} based on the given class type.
|
||||
*
|
||||
*
|
||||
* @param clazz
|
||||
* the clazz type to retrieve the corresponding {@link EventType}
|
||||
* .
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.AbstractActionEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
@@ -67,7 +68,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Retrieves cached list of {@link TotalTargetCountActionStatus} of
|
||||
* {@link Rollout}s.
|
||||
*
|
||||
*
|
||||
* @param rollouts
|
||||
* rolloutIds to retrieve cache entries for
|
||||
* @return map of cached entries
|
||||
@@ -81,7 +82,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Retrieves cached list of {@link TotalTargetCountActionStatus} of
|
||||
* {@link Rollout}s.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* to retrieve cache entries for
|
||||
* @return map of cached entries
|
||||
@@ -95,7 +96,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Retrieves cached list of {@link TotalTargetCountActionStatus} of
|
||||
* {@link RolloutGroup}s.
|
||||
*
|
||||
*
|
||||
* @param rolloutGroups
|
||||
* rolloutGroupsIds to retrieve cache entries for
|
||||
* @return map of cached entries
|
||||
@@ -109,7 +110,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Retrieves cached list of {@link TotalTargetCountActionStatus} of
|
||||
* {@link RolloutGroup}.
|
||||
*
|
||||
*
|
||||
* @param groupId
|
||||
* to retrieve cache entries for
|
||||
* @return map of cached entries
|
||||
@@ -123,7 +124,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Put map of {@link TotalTargetCountActionStatus} for multiple
|
||||
* {@link Rollout}s into cache.
|
||||
*
|
||||
*
|
||||
* @param put
|
||||
* map of cached entries
|
||||
*/
|
||||
@@ -135,12 +136,12 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Put {@link TotalTargetCountActionStatus} for one {@link Rollout}s into
|
||||
* cache.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the cache entries belong to
|
||||
* @param status
|
||||
* list to cache
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void putRolloutStatus(final Long rolloutId, final List<TotalTargetCountActionStatus> status) {
|
||||
final Cache cache = cacheManager.getCache(CACHE_RO_NAME);
|
||||
@@ -150,7 +151,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Put {@link TotalTargetCountActionStatus} for multiple
|
||||
* {@link RolloutGroup}s into cache.
|
||||
*
|
||||
*
|
||||
* @param put
|
||||
* map of cached entries
|
||||
*/
|
||||
@@ -162,7 +163,7 @@ public class RolloutStatusCache {
|
||||
/**
|
||||
* Put {@link TotalTargetCountActionStatus} for multiple
|
||||
* {@link RolloutGroup}s into cache.
|
||||
*
|
||||
*
|
||||
* @param groupId
|
||||
* the cache entries belong to
|
||||
* @param status
|
||||
@@ -223,6 +224,18 @@ public class RolloutStatusCache {
|
||||
cache.evict(event.getEntityId());
|
||||
}
|
||||
|
||||
@EventListener(classes = RolloutStoppedEvent.class)
|
||||
void invalidateCachedTotalTargetCountOnRolloutStopped(final RolloutStoppedEvent event) {
|
||||
final Cache cache = tenantAware.runAsTenant(event.getTenant(), () -> cacheManager.getCache(CACHE_RO_NAME));
|
||||
cache.evict(event.getRolloutId());
|
||||
|
||||
for (final long groupId : event.getRolloutGroupIds()) {
|
||||
final Cache groupCache = tenantAware.runAsTenant(event.getTenant(),
|
||||
() -> cacheManager.getCache(CACHE_GR_NAME));
|
||||
groupCache.evict(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all caches for a given tenant. All caches under a certain tenant
|
||||
* gets evicted.
|
||||
|
||||
@@ -64,6 +64,28 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
*/
|
||||
Page<Action> findByDistributionSetId(Pageable pageable, Long dsId);
|
||||
|
||||
/**
|
||||
* Retrieves all active {@link Action}s which are referring the given
|
||||
* {@link DistributionSet}.
|
||||
*
|
||||
* @param set
|
||||
* the {@link DistributionSet} on which will be filtered
|
||||
* @return the found {@link Action}s
|
||||
*/
|
||||
List<Action> findByDistributionSetAndActiveIsTrue(DistributionSet set);
|
||||
|
||||
/**
|
||||
* Retrieves all active {@link Action}s which are referring the given
|
||||
* {@link DistributionSet} and are not in the given state
|
||||
*
|
||||
* @param set
|
||||
* the {@link DistributionSet} on which will be filtered
|
||||
* @param status
|
||||
* the state the actions should not have
|
||||
* @return the found {@link Action}s
|
||||
*/
|
||||
List<Action> findByDistributionSetAndActiveIsTrueAndStatusIsNot(DistributionSet set, Status status);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Action}s which are referring the given
|
||||
* {@link Target}.
|
||||
@@ -103,7 +125,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
* Retrieves the active {@link Action}s with the highest weights that refer
|
||||
* to the given {@link Target}. If {@link Action}s have the same weight they
|
||||
* are ordered ascending by ID (oldest ones first).
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* pageable
|
||||
* @param controllerId
|
||||
@@ -117,7 +139,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Retrieves the active {@link Action}s with the lowest IDs (the oldest one)
|
||||
* whose weight is null and that that refers to the given {@link Target}.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* pageable
|
||||
* @param controllerId
|
||||
@@ -131,7 +153,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Checks if an active action exists for given
|
||||
* {@link Target#getControllerId()}.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* of target to check
|
||||
* @return <code>true</code> if an active action for the target exists.
|
||||
@@ -264,10 +286,9 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
List<Action> findByExternalRefInAndActive(@Param("externalRefs") List<String> externalRefs,
|
||||
@Param("active") boolean active);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves an {@link Action} that matches the queried externalRef.
|
||||
*
|
||||
*
|
||||
* @param externalRef
|
||||
* of the action. See {@link Action#getExternalRef()}
|
||||
* @return the found {@link Action}
|
||||
@@ -351,6 +372,27 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
*/
|
||||
Long countByDistributionSetId(Long distributionSet);
|
||||
|
||||
/**
|
||||
* Counts all active {@link Action}s referring to the given DistributionSet.
|
||||
*
|
||||
* @param distributionSet
|
||||
* DistributionSet to count the {@link Action}s from
|
||||
* @return the count of actions referring to the given distributionSet
|
||||
*/
|
||||
Long countByDistributionSetIdAndActiveIsTrue(Long distributionSet);
|
||||
|
||||
/**
|
||||
* Counts all active {@link Action}s referring to the given DistributionSet
|
||||
* that are not in a given state.
|
||||
*
|
||||
* @param distributionSet
|
||||
* DistributionSet to count the {@link Action}s from
|
||||
* @param status
|
||||
* the state the actions should not have
|
||||
* @return the count of actions referring to the given distributionSet
|
||||
*/
|
||||
Long countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(Long distributionSet, Status status);
|
||||
|
||||
/**
|
||||
* Counts all actions referring to a given rollout and rolloutgroup which
|
||||
* are currently not in the given status. An in-clause statement does not
|
||||
@@ -396,7 +438,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
|
||||
/**
|
||||
* Counts all actions referring to a given rollout and status.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the actions belong to
|
||||
* @param status
|
||||
@@ -409,7 +451,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Returns {@code true} if actions for the given rollout exists, otherwise
|
||||
* {@code false}
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the actions belong to
|
||||
* @return {@code true} if actions for the given rollout exists, otherwise
|
||||
@@ -421,7 +463,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Returns {@code true} if actions for the given rollout exists, otherwise
|
||||
* {@code false}
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the actions belong to
|
||||
* @param status
|
||||
@@ -471,7 +513,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
|
||||
/**
|
||||
* Retrieves all actions for a specific rollout and in a specific status.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* page parameters
|
||||
* @param rolloutId
|
||||
@@ -528,7 +570,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
|
||||
/**
|
||||
* Deletes all actions with the given IDs.
|
||||
*
|
||||
*
|
||||
* @param actionIDs
|
||||
* the IDs of the actions to be deleted.
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ import javax.persistence.criteria.Root;
|
||||
|
||||
import org.eclipse.hawkbit.repository.ActionFields;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
@@ -43,7 +44,6 @@ import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEv
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
@@ -67,6 +67,7 @@ import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DeploymentRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
@@ -130,6 +131,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
private final EntityManager entityManager;
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final DistributionSetRepository distributionSetRepository;
|
||||
private final TargetRepository targetRepository;
|
||||
private final ActionStatusRepository actionStatusRepository;
|
||||
@@ -146,6 +148,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
private final RetryTemplate retryTemplate;
|
||||
|
||||
protected JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
|
||||
final DistributionSetManagement distributionSetManagement,
|
||||
final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository,
|
||||
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
|
||||
final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit,
|
||||
@@ -156,6 +159,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
super(actionRepository, repositoryProperties);
|
||||
this.entityManager = entityManager;
|
||||
this.distributionSetRepository = distributionSetRepository;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.targetRepository = targetRepository;
|
||||
this.actionStatusRepository = actionStatusRepository;
|
||||
this.auditorProvider = auditorProvider;
|
||||
@@ -254,8 +258,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
/**
|
||||
* method assigns the {@link DistributionSet} to all {@link Target}s by
|
||||
* their IDs with a specific {@link ActionType} and {@code forcetime}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* In case the update was executed offline (i.e. not managed by hawkBit) the
|
||||
* handling differs my means that:<br/>
|
||||
* A. it ignores targets completely that are in
|
||||
@@ -285,7 +289,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
||||
final AbstractDsAssignmentStrategy assignmentStrategy) {
|
||||
|
||||
final JpaDistributionSet distributionSetEntity = getAndValidateDsById(dsID);
|
||||
final JpaDistributionSet distributionSetEntity = (JpaDistributionSet) distributionSetManagement
|
||||
.getValidAndComplete(dsID);
|
||||
final List<String> providedTargetIds = targetsWithActionType.stream().map(TargetWithActionType::getControllerId)
|
||||
.distinct().collect(Collectors.toList());
|
||||
|
||||
@@ -363,18 +368,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions);
|
||||
}
|
||||
|
||||
private JpaDistributionSet getAndValidateDsById(final Long dsID) {
|
||||
final JpaDistributionSet distributionSet = distributionSetRepository.findById(dsID)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, dsID));
|
||||
|
||||
if (!distributionSet.isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Distribution set of type "
|
||||
+ distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId());
|
||||
}
|
||||
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
private void checkQuotaForAssignment(final Collection<DeploymentRequest> deploymentRequests) {
|
||||
if (!deploymentRequests.isEmpty()) {
|
||||
enforceMaxAssignmentsPerRequest(deploymentRequests.size());
|
||||
@@ -656,8 +649,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
private Specification<JpaAction> createSpecificationFor(final String controllerId, final String rsqlParam) {
|
||||
final Specification<JpaAction> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer,
|
||||
database);
|
||||
final Specification<JpaAction> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class,
|
||||
virtualPropertyReplacer, database);
|
||||
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
|
||||
cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId));
|
||||
}
|
||||
@@ -779,6 +772,17 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
return actionRepository.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countActionsByDistributionSetIdAndActiveIsTrue(final Long distributionSet) {
|
||||
return actionRepository.countByDistributionSetIdAndActiveIsTrue(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countActionsByDistributionSetIdAndActiveIsTrueAndStatusIsNot(final Long distributionSet,
|
||||
final Status status) {
|
||||
return actionRepository.countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(distributionSet, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Action> findActionsByDistributionSet(final Pageable pageable, final long dsId) {
|
||||
throwExceptionIfDistributionSetDoesNotExist(dsId);
|
||||
@@ -832,7 +836,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPendingCancellations(String controllerId) {
|
||||
public boolean hasPendingCancellations(final String controllerId) {
|
||||
return actionRepository.existsByTargetControllerIdAndStatusAndActiveIsTrue(controllerId,
|
||||
Action.Status.CANCELING);
|
||||
}
|
||||
@@ -881,4 +885,21 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelActionsForDistributionSet(final CancelationType cancelationType, final DistributionSet set) {
|
||||
actionRepository.findByDistributionSetAndActiveIsTrueAndStatusIsNot(set, Status.CANCELING).forEach(action -> {
|
||||
final JpaAction jpaAction = (JpaAction) action;
|
||||
cancelAction(jpaAction.getId());
|
||||
LOG.debug("Action {} canceled", jpaAction.getId());
|
||||
});
|
||||
if (cancelationType == CancelationType.FORCE) {
|
||||
actionRepository.findByDistributionSetAndActiveIsTrue(set).forEach(action -> {
|
||||
final JpaAction jpaAction = (JpaAction) action;
|
||||
forceQuitAction(jpaAction.getId());
|
||||
LOG.debug("Action {} force canceled", jpaAction.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.StopRolloutException;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Jpa implementation for {@link DistributionSetInvalidationManagement}
|
||||
*
|
||||
*/
|
||||
public class JpaDistributionSetInvalidationManagement implements DistributionSetInvalidationManagement {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JpaDistributionSetInvalidationManagement.class);
|
||||
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final RolloutManagement rolloutManagement;
|
||||
private final DeploymentManagement deploymentManagement;
|
||||
private final TargetFilterQueryManagement targetFilterQueryManagement;
|
||||
private final PlatformTransactionManager txManager;
|
||||
private final RepositoryProperties repositoryProperties;
|
||||
private final TenantAware tenantAware;
|
||||
private final LockRegistry lockRegistry;
|
||||
|
||||
protected JpaDistributionSetInvalidationManagement(final DistributionSetManagement distributionSetManagement,
|
||||
final RolloutManagement rolloutManagement, final DeploymentManagement deploymentManagement,
|
||||
final TargetFilterQueryManagement targetFilterQueryManagement, final PlatformTransactionManager txManager,
|
||||
final RepositoryProperties repositoryProperties, final TenantAware tenantAware,
|
||||
final LockRegistry lockRegistry) {
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.rolloutManagement = rolloutManagement;
|
||||
this.deploymentManagement = deploymentManagement;
|
||||
this.targetFilterQueryManagement = targetFilterQueryManagement;
|
||||
this.txManager = txManager;
|
||||
this.repositoryProperties = repositoryProperties;
|
||||
this.tenantAware = tenantAware;
|
||||
this.lockRegistry = lockRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation) {
|
||||
LOG.debug("Invalidate distribution sets {}", distributionSetInvalidation.getDistributionSetIds());
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
|
||||
if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
|
||||
distributionSetInvalidation.isCancelRollouts())) {
|
||||
final String handlerId = JpaRolloutManagement.createRolloutLockKey(tenant);
|
||||
final Lock lock = lockRegistry.obtain(handlerId);
|
||||
try {
|
||||
if (!lock.tryLock(repositoryProperties.getDsInvalidationLockTimeout(), TimeUnit.SECONDS)) {
|
||||
throw new StopRolloutException("Timeout while trying to invalidate distribution sets");
|
||||
}
|
||||
try {
|
||||
invalidateDistributionSetsInTransaction(distributionSetInvalidation, tenant);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
} catch (final InterruptedException e) {
|
||||
LOG.error("InterruptedException while invalidating distribution sets {}!",
|
||||
distributionSetInvalidation.getDistributionSetIds(), e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
} else {
|
||||
// no lock is needed as no rollout will be stopped
|
||||
invalidateDistributionSetsInTransaction(distributionSetInvalidation, tenant);
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation,
|
||||
final String tenant) {
|
||||
DeploymentHelper.runInNewTransaction(txManager, tenant + "-invalidateDS", status -> {
|
||||
distributionSetInvalidation.getDistributionSetIds().forEach(setId -> invalidateDistributionSet(setId,
|
||||
distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts()));
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
private void invalidateDistributionSet(final long setId, final CancelationType cancelationType,
|
||||
final boolean cancelRollouts) {
|
||||
final DistributionSet set = distributionSetManagement.getValidAndComplete(setId);
|
||||
distributionSetManagement.invalidate(set);
|
||||
LOG.debug("Distribution set {} set to invalid", setId);
|
||||
|
||||
if (shouldRolloutsBeCanceled(cancelationType, cancelRollouts)) {
|
||||
rolloutManagement.cancelRolloutsForDistributionSet(set);
|
||||
}
|
||||
|
||||
if (cancelationType != CancelationType.NONE) {
|
||||
deploymentManagement.cancelActionsForDistributionSet(cancelationType, set);
|
||||
}
|
||||
|
||||
targetFilterQueryManagement.cancelAutoAssignmentForDistributionSet(setId);
|
||||
}
|
||||
|
||||
private static boolean shouldRolloutsBeCanceled(final CancelationType cancelationType,
|
||||
final boolean cancelRollouts) {
|
||||
return cancelationType != CancelationType.NONE || cancelRollouts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSetInvalidationCount countEntitiesForInvalidation(
|
||||
final DistributionSetInvalidation distributionSetInvalidation) {
|
||||
final Collection<Long> setIds = distributionSetInvalidation.getDistributionSetIds();
|
||||
final long rolloutsCount = shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
|
||||
distributionSetInvalidation.isCancelRollouts()) ? countRolloutsForInvalidation(setIds) : 0;
|
||||
final long autoAssignmentsCount = countAutoAssignmentsForInvalidation(setIds);
|
||||
final long actionsCount = countActionsForInvalidation(setIds, distributionSetInvalidation.getCancelationType());
|
||||
|
||||
return new DistributionSetInvalidationCount(rolloutsCount, autoAssignmentsCount, actionsCount);
|
||||
}
|
||||
|
||||
private long countRolloutsForInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(rolloutManagement::countByDistributionSetIdAndRolloutIsStoppable).sum();
|
||||
}
|
||||
|
||||
private long countAutoAssignmentsForInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(targetFilterQueryManagement::countByAutoAssignDistributionSetId).sum();
|
||||
}
|
||||
|
||||
private long countActionsForInvalidation(final Collection<Long> setIds, final CancelationType cancelationType) {
|
||||
long affectedActionsByDSInvalidation = 0;
|
||||
if (cancelationType == CancelationType.FORCE) {
|
||||
affectedActionsByDSInvalidation = countActionsForForcedInvalidation(setIds);
|
||||
} else if (cancelationType == CancelationType.SOFT) {
|
||||
affectedActionsByDSInvalidation = countActionsForSoftInvalidation(setIds);
|
||||
}
|
||||
return affectedActionsByDSInvalidation;
|
||||
}
|
||||
|
||||
private long countActionsForForcedInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(deploymentManagement::countActionsByDistributionSetIdAndActiveIsTrue).sum();
|
||||
}
|
||||
|
||||
private long countActionsForSoftInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(distributionSet -> deploymentManagement
|
||||
.countActionsByDistributionSetIdAndActiveIsTrueAndStatusIsNot(distributionSet, Status.CANCELING)).sum();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,8 @@ import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
@@ -213,7 +215,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
public DistributionSet update(final DistributionSetUpdate u) {
|
||||
final GenericDistributionSetUpdate update = (GenericDistributionSetUpdate) u;
|
||||
|
||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(update.getId());
|
||||
final JpaDistributionSet set = (JpaDistributionSet) getValid(update.getId());
|
||||
|
||||
update.getName().ifPresent(set::setName);
|
||||
update.getDescription().ifPresent(set::setDescription);
|
||||
@@ -228,11 +230,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return distributionSetRepository.save(set);
|
||||
}
|
||||
|
||||
private JpaDistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return (JpaDistributionSet) get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
|
||||
private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long moduleId) {
|
||||
return softwareModuleRepository.findById(moduleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId));
|
||||
@@ -315,7 +312,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
assertDistributionSetIsNotAssignedToTargets(setId);
|
||||
|
||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||
final JpaDistributionSet set = (JpaDistributionSet) getValid(setId);
|
||||
|
||||
assertSoftwareModuleQuota(setId, modules.size());
|
||||
|
||||
@@ -329,7 +326,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Retryable(include = {
|
||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public DistributionSet unassignSoftwareModule(final long setId, final long moduleId) {
|
||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||
final JpaDistributionSet set = (JpaDistributionSet) getValid(setId);
|
||||
final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId);
|
||||
|
||||
assertDistributionSetIsNotAssignedToTargets(setId);
|
||||
@@ -531,7 +528,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
* of the DS to touch
|
||||
*/
|
||||
private JpaDistributionSet touch(final Long distId) {
|
||||
return touch(get(distId).orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distId)));
|
||||
return touch(getValid(distId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -595,7 +592,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
private static List<Specification<JpaDistributionSet>> buildDistributionSetSpecifications(
|
||||
final DistributionSetFilter distributionSetFilter) {
|
||||
final List<Specification<JpaDistributionSet>> specList = Lists.newArrayListWithExpectedSize(8);
|
||||
final List<Specification<JpaDistributionSet>> specList = Lists.newArrayListWithExpectedSize(9);
|
||||
|
||||
Specification<JpaDistributionSet> spec;
|
||||
|
||||
@@ -609,6 +606,11 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
specList.add(spec);
|
||||
}
|
||||
|
||||
if (distributionSetFilter.getIsValid() != null) {
|
||||
spec = DistributionSetSpecification.isValid(distributionSetFilter.getIsValid());
|
||||
specList.add(spec);
|
||||
}
|
||||
|
||||
if (distributionSetFilter.getType() != null) {
|
||||
spec = DistributionSetSpecification.byType(distributionSetFilter.getType());
|
||||
specList.add(spec);
|
||||
@@ -781,8 +783,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
public Page<DistributionSet> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
|
||||
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
|
||||
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class,
|
||||
virtualPropertyReplacer, database);
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
|
||||
DistributionSetFields.class, virtualPropertyReplacer, database);
|
||||
|
||||
return convertDsPage(findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.hasTag(tagId),
|
||||
DistributionSetSpecification.isDeleted(false))), pageable);
|
||||
@@ -797,8 +799,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
@Override
|
||||
public Page<DistributionSet> findByRsql(final Pageable pageable, final String rsqlParam) {
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class,
|
||||
virtualPropertyReplacer, database);
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
|
||||
DistributionSetFields.class, virtualPropertyReplacer, database);
|
||||
|
||||
return convertDsPage(
|
||||
findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.isDeleted(false))),
|
||||
@@ -815,4 +817,41 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return distributionSetRepository.existsById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSet getOrElseThrowException(final long id) {
|
||||
return get(id).orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSet getValidAndComplete(final long id) {
|
||||
final DistributionSet distributionSet = getValid(id);
|
||||
|
||||
if (!distributionSet.isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Distribution set of type "
|
||||
+ distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId());
|
||||
}
|
||||
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSet getValid(final long id) {
|
||||
final DistributionSet distributionSet = getOrElseThrowException(id);
|
||||
|
||||
if (!distributionSet.isValid()) {
|
||||
throw new InvalidDistributionSetException("Distribution set of type " + distributionSet.getType().getKey()
|
||||
+ " is invalid: " + distributionSet.getId());
|
||||
}
|
||||
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void invalidate(final DistributionSet set) {
|
||||
final JpaDistributionSet jpaSet = (JpaDistributionSet) set;
|
||||
jpaSet.invalidate();
|
||||
distributionSetRepository.save(jpaSet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.RolloutHelper;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||
@@ -155,6 +156,9 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
case RUNNING:
|
||||
handleRunningRollout((JpaRollout) rollout);
|
||||
break;
|
||||
case STOPPING:
|
||||
handleStopRollout((JpaRollout) rollout);
|
||||
break;
|
||||
default:
|
||||
LOGGER.error("Rollout in status {} not supposed to be handled!", rollout.getStatus());
|
||||
break;
|
||||
@@ -244,6 +248,39 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
sendRolloutGroupDeletedEvents(rollout);
|
||||
}
|
||||
|
||||
private void handleStopRollout(final JpaRollout rollout) {
|
||||
LOGGER.debug("handleStopRollout called for {}", rollout.getId());
|
||||
// clean up all scheduled actions
|
||||
final Slice<JpaAction> scheduledActions = findScheduledActionsByRollout(rollout);
|
||||
deleteScheduledActions(rollout, scheduledActions);
|
||||
|
||||
// avoid another scheduler round and re-check if all scheduled actions
|
||||
// has been cleaned up. we flush first to ensure that the we include the
|
||||
// deletion above
|
||||
entityManager.flush();
|
||||
final boolean hasScheduledActionsLeft = actionRepository.countByRolloutIdAndStatus(rollout.getId(),
|
||||
Status.SCHEDULED) > 0;
|
||||
|
||||
if (hasScheduledActionsLeft) {
|
||||
return;
|
||||
}
|
||||
|
||||
rolloutGroupRepository.findByRolloutAndStatusNotIn(rollout,
|
||||
Arrays.asList(RolloutGroupStatus.FINISHED, RolloutGroupStatus.ERROR)).forEach(rolloutGroup -> {
|
||||
rolloutGroup.setStatus(RolloutGroupStatus.FINISHED);
|
||||
rolloutGroupRepository.save(rolloutGroup);
|
||||
});
|
||||
|
||||
rollout.setStatus(RolloutStatus.FINISHED);
|
||||
rolloutRepository.save(rollout);
|
||||
|
||||
final List<Long> groupIds = rollout.getRolloutGroups().stream().map(RolloutGroup::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent(new RolloutStoppedEvent(
|
||||
tenantAware.getCurrentTenant(), eventPublisherHolder.getApplicationId(), rollout.getId(), groupIds)));
|
||||
}
|
||||
|
||||
private void handleReadyRollout(final Rollout rollout) {
|
||||
if (rollout.getStartAt() != null && rollout.getStartAt() <= System.currentTimeMillis()) {
|
||||
LOGGER.debug(
|
||||
|
||||
@@ -100,7 +100,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaRolloutManagement.class);
|
||||
|
||||
private static final List<RolloutStatus> ACTIVE_ROLLOUTS = Arrays.asList(RolloutStatus.CREATING,
|
||||
RolloutStatus.DELETING, RolloutStatus.STARTING, RolloutStatus.READY, RolloutStatus.RUNNING);
|
||||
RolloutStatus.DELETING, RolloutStatus.STARTING, RolloutStatus.READY, RolloutStatus.RUNNING,
|
||||
RolloutStatus.STOPPING);
|
||||
|
||||
private static final List<RolloutStatus> ROLLOUT_STATUS_STOPPABLE = Arrays.asList(RolloutStatus.RUNNING,
|
||||
RolloutStatus.CREATING, RolloutStatus.PAUSED, RolloutStatus.READY, RolloutStatus.STARTING,
|
||||
RolloutStatus.WAITING_FOR_APPROVAL, RolloutStatus.APPROVAL_DENIED);
|
||||
|
||||
@Autowired
|
||||
private RolloutRepository rolloutRepository;
|
||||
@@ -126,8 +131,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
|
||||
private final Database database;
|
||||
|
||||
public JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
|
||||
final RolloutGroupManagement rolloutGroupManagement,
|
||||
public JpaRolloutManagement(final TargetManagement targetManagement,
|
||||
final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement,
|
||||
final DistributionSetManagement distributionSetManagement, final ApplicationContext context,
|
||||
final EventPublisherHolder eventPublisherHolder, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final PlatformTransactionManager txManager, final TenantAware tenantAware, final LockRegistry lockRegistry,
|
||||
@@ -151,7 +156,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
@Override
|
||||
public Page<Rollout> findByRsql(final Pageable pageable, final String rsqlParam, final boolean deleted) {
|
||||
final List<Specification<JpaRollout>> specList = Lists.newArrayListWithExpectedSize(2);
|
||||
specList.add(RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted));
|
||||
|
||||
return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable);
|
||||
@@ -400,7 +406,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
|
||||
final String handlerId = tenant + "-rollout";
|
||||
final String handlerId = createRolloutLockKey(tenant);
|
||||
final Lock lock = lockRegistry.obtain(handlerId);
|
||||
if (!lock.tryLock()) {
|
||||
return;
|
||||
@@ -414,6 +420,10 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
}
|
||||
|
||||
public static String createRolloutLockKey(final String tenant) {
|
||||
return tenant + "-rollout";
|
||||
}
|
||||
|
||||
private long handleRollout(final long rolloutId) {
|
||||
final JpaRollout rollout = rolloutRepository.findById(rolloutId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||
@@ -451,6 +461,11 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
return rolloutRepository.count(JpaRolloutHelper.likeNameOrDescription(searchText, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByDistributionSetIdAndRolloutIsStoppable(final long setId) {
|
||||
return rolloutRepository.countByDistributionSetIdAndStatusIn(setId, ROLLOUT_STATUS_STOPPABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Rollout> findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText,
|
||||
final boolean deleted) {
|
||||
@@ -483,8 +498,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
// null
|
||||
rollout.setStartAt(update.getStartAt().orElse(null));
|
||||
update.getSet().ifPresent(setId -> {
|
||||
final DistributionSet set = distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
final DistributionSet set = distributionSetManagement.getValidAndComplete(setId);
|
||||
|
||||
rollout.setDistributionSet(set);
|
||||
});
|
||||
@@ -596,7 +610,20 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
|
||||
private void runInUserContext(final BaseEntity rollout, final Runnable handler) {
|
||||
DeploymentHelper.runInNonSystemContext(handler, () -> Objects.requireNonNull(rollout.getCreatedBy()), tenantAware);
|
||||
DeploymentHelper.runInNonSystemContext(handler, () -> Objects.requireNonNull(rollout.getCreatedBy()),
|
||||
tenantAware);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelRolloutsForDistributionSet(final DistributionSet set) {
|
||||
// stop all rollouts for this distribution set
|
||||
rolloutRepository.findByDistributionSetAndStatusIn(set, ROLLOUT_STATUS_STOPPABLE).forEach(rollout -> {
|
||||
final JpaRollout jpaRollout = (JpaRollout) rollout;
|
||||
jpaRollout.setStatus(RolloutStatus.STOPPING);
|
||||
rolloutRepository.save(jpaRollout);
|
||||
LOGGER.debug("Rollout {} stopped", jpaRollout.getId());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
@@ -72,7 +71,7 @@ import cz.jirutka.rsql.parser.RSQLParserException;
|
||||
public class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaTargetFilterQueryManagement.class);
|
||||
|
||||
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final TargetManagement targetManagement;
|
||||
|
||||
@@ -147,6 +146,11 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
return targetFilterQueryRepository.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByAutoAssignDistributionSetId(final long autoAssignDistributionSetId) {
|
||||
return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
|
||||
}
|
||||
|
||||
private static Page<TargetFilterQuery> convertPage(final Page<JpaTargetFilterQuery> findAll,
|
||||
final Pageable pageable) {
|
||||
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
|
||||
@@ -165,8 +169,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
public Page<TargetFilterQuery> findByRsql(final Pageable pageable, final String rsqlFilter) {
|
||||
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList();
|
||||
if (!StringUtils.isEmpty(rsqlFilter)) {
|
||||
specList = Collections.singletonList(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database));
|
||||
specList = Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter,
|
||||
TargetFilterQueryFields.class, virtualPropertyReplacer, database));
|
||||
}
|
||||
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
|
||||
}
|
||||
@@ -185,13 +189,13 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
final String rsqlFilter) {
|
||||
final List<Specification<JpaTargetFilterQuery>> specList = Lists.newArrayListWithExpectedSize(2);
|
||||
|
||||
final DistributionSet distributionSet = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
|
||||
|
||||
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
|
||||
|
||||
if (!StringUtils.isEmpty(rsqlFilter)) {
|
||||
specList.add(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class,
|
||||
virtualPropertyReplacer, database));
|
||||
}
|
||||
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
|
||||
}
|
||||
@@ -264,8 +268,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
// specify an
|
||||
// auto-assign distribution set when creating a target filter query
|
||||
assertMaxTargetsQuota(targetFilterQuery.getQuery());
|
||||
final JpaDistributionSet ds = findDistributionSetAndThrowExceptionIfNotFound(update.getDsId());
|
||||
verifyDistributionSetAndThrowExceptionIfNotValid(ds);
|
||||
final JpaDistributionSet ds = (JpaDistributionSet) distributionSetManagement
|
||||
.getValidAndComplete(update.getDsId());
|
||||
verifyDistributionSetAndThrowExceptionIfDeleted(ds);
|
||||
targetFilterQuery.setAutoAssignDistributionSet(ds);
|
||||
targetFilterQuery.setAutoAssignInitiatedBy(tenantAware.getCurrentUsername());
|
||||
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType()));
|
||||
@@ -274,9 +279,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
return targetFilterQueryRepository.save(targetFilterQuery);
|
||||
}
|
||||
|
||||
private static void verifyDistributionSetAndThrowExceptionIfNotValid(final DistributionSet distributionSet) {
|
||||
if (!distributionSet.isComplete() || distributionSet.isDeleted()) {
|
||||
throw new InvalidAutoAssignDistributionSetException();
|
||||
private static void verifyDistributionSetAndThrowExceptionIfDeleted(final DistributionSet distributionSet) {
|
||||
if (distributionSet.isDeleted()) {
|
||||
throw new EntityNotFoundException(DistributionSet.class, distributionSet.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,11 +297,6 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
return actionType;
|
||||
}
|
||||
|
||||
private JpaDistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return (JpaDistributionSet) distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
|
||||
private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) {
|
||||
return targetFilterQueryRepository.findById(queryId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
|
||||
@@ -317,4 +317,11 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
QuotaHelper.assertAssignmentQuota(targetManagement.countByRsql(query),
|
||||
quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelAutoAssignmentForDistributionSet(final long setId) {
|
||||
targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionType(setId);
|
||||
LOGGER.debug("Auto assignments for distribution sets {} deactivated", setId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAct
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParserValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.DefaultRsqlVisitorFactory;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParserValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -238,13 +238,14 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
TargetBuilder targetBuilder(final TargetTypeManagement targetTypeManagement){
|
||||
TargetBuilder targetBuilder(final TargetTypeManagement targetTypeManagement) {
|
||||
return new JpaTargetBuilder(targetTypeManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dsTypeManagement
|
||||
* for loading {@link TargetType#getCompatibleDistributionSetTypes()}
|
||||
* for loading
|
||||
* {@link TargetType#getCompatibleDistributionSetTypes()}
|
||||
* @return TargetTypeBuilder bean
|
||||
*/
|
||||
@Bean
|
||||
@@ -434,7 +435,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
@Override
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager(
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
final ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
return new MultiTenantJpaTransactionManager();
|
||||
}
|
||||
|
||||
@@ -485,12 +486,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
DistributionSetTypeManagement distributionSetTypeManagement(
|
||||
final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final TargetTypeRepository targetTypeRepository,
|
||||
final DistributionSetRepository distributionSetRepository, final TargetTypeRepository targetTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties,
|
||||
final QuotaManagement quotaManagement) {
|
||||
return new JpaDistributionSetTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository,
|
||||
distributionSetRepository, targetTypeRepository, virtualPropertyReplacer, properties.getDatabase(), quotaManagement);
|
||||
distributionSetRepository, targetTypeRepository, virtualPropertyReplacer, properties.getDatabase(),
|
||||
quotaManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,13 +542,15 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
final TargetRepository targetRepository, final TargetMetadataRepository targetMetadataRepository,
|
||||
final RolloutGroupRepository rolloutGroupRepository,
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final TargetTypeRepository targetTypeRepository,
|
||||
final TargetTagRepository targetTagRepository, final EventPublisherHolder eventPublisherHolder,
|
||||
final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties) {
|
||||
return new JpaTargetManagement(entityManager, quotaManagement, targetRepository, targetTypeRepository, targetMetadataRepository,
|
||||
rolloutGroupRepository, distributionSetRepository, targetFilterQueryRepository, targetTagRepository,
|
||||
eventPublisherHolder, tenantAware, afterCommit, virtualPropertyReplacer, properties.getDatabase());
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository,
|
||||
final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware,
|
||||
final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final JpaProperties properties) {
|
||||
return new JpaTargetManagement(entityManager, quotaManagement, targetRepository, targetTypeRepository,
|
||||
targetMetadataRepository, rolloutGroupRepository, distributionSetRepository,
|
||||
targetFilterQueryRepository, targetTagRepository, eventPublisherHolder, tenantAware, afterCommit,
|
||||
virtualPropertyReplacer, properties.getDatabase());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -718,17 +721,17 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
DeploymentManagement deploymentManagement(final EntityManager entityManager,
|
||||
final ActionRepository actionRepository, final DistributionSetRepository distributionSetRepository,
|
||||
final TargetRepository targetRepository, final ActionStatusRepository actionStatusRepository,
|
||||
final AuditorAware<String> auditorProvider, final EventPublisherHolder eventPublisherHolder,
|
||||
final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final PlatformTransactionManager txManager,
|
||||
final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository,
|
||||
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
|
||||
final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware,
|
||||
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetRepository, targetRepository,
|
||||
actionStatusRepository, auditorProvider, eventPublisherHolder, afterCommit, virtualPropertyReplacer,
|
||||
txManager, tenantConfigurationManagement, quotaManagement, systemSecurityContext, tenantAware,
|
||||
properties.getDatabase(), repositoryProperties);
|
||||
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetManagement,
|
||||
distributionSetRepository, targetRepository, actionStatusRepository, auditorProvider,
|
||||
eventPublisherHolder, afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement,
|
||||
quotaManagement, systemSecurityContext, tenantAware, properties.getDatabase(), repositoryProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -813,7 +816,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link AutoAssignScheduler} bean.
|
||||
*
|
||||
*
|
||||
* Note: does not activate in test profile, otherwise it is hard to test the
|
||||
* auto assign functionality.
|
||||
*
|
||||
@@ -843,12 +846,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link AutoActionCleanup} bean.
|
||||
*
|
||||
*
|
||||
* @param deploymentManagement
|
||||
* Deployment management service
|
||||
* @param configManagement
|
||||
* Tenant configuration service
|
||||
*
|
||||
*
|
||||
* @return a new {@link AutoActionCleanup} bean
|
||||
*/
|
||||
@Bean
|
||||
@@ -859,7 +862,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link AutoCleanupScheduler} bean.
|
||||
*
|
||||
*
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param systemSecurityContext
|
||||
@@ -868,7 +871,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
* to lock the tenant for auto assignment
|
||||
* @param cleanupTasks
|
||||
* a list of cleanup tasks
|
||||
*
|
||||
*
|
||||
* @return a new {@link AutoCleanupScheduler} bean
|
||||
*/
|
||||
@Bean
|
||||
@@ -883,10 +886,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link RolloutScheduler} bean.
|
||||
*
|
||||
*
|
||||
* Note: does not activate in test profile, otherwise it is hard to test the
|
||||
* rollout handling functionality.
|
||||
*
|
||||
*
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param rolloutManagement
|
||||
@@ -906,7 +909,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* Creates the {@link RsqlVisitorFactory} bean.
|
||||
*
|
||||
*
|
||||
* @return A new {@link RsqlVisitorFactory} bean.
|
||||
*/
|
||||
@Bean
|
||||
@@ -917,7 +920,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* Obtains the {@link RsqlVisitorFactoryHolder} bean.
|
||||
*
|
||||
*
|
||||
* @return The {@link RsqlVisitorFactoryHolder} singleton.
|
||||
*/
|
||||
@Bean
|
||||
@@ -925,4 +928,22 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return RsqlVisitorFactoryHolder.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link JpaDistributionSetInvalidationManagement} bean.
|
||||
*
|
||||
* @return a new {@link JpaDistributionSetInvalidationManagement}
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
JpaDistributionSetInvalidationManagement distributionSetInvalidationManagement(
|
||||
final DistributionSetManagement distributionSetManagement, final RolloutManagement rolloutManagement,
|
||||
final DeploymentManagement deploymentManagement,
|
||||
final TargetFilterQueryManagement targetFilterQueryManagement, final PlatformTransactionManager txManager,
|
||||
final RepositoryProperties repositoryProperties, final TenantAware tenantAware,
|
||||
final LockRegistry lockRegistry) {
|
||||
return new JpaDistributionSetInvalidationManagement(distributionSetManagement, rolloutManagement,
|
||||
deploymentManagement, targetFilterQueryManagement, txManager, repositoryProperties, tenantAware,
|
||||
lockRegistry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
@@ -33,7 +34,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} referring a specific rollout in the
|
||||
* order of creating them. ID ASC.
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroups belong to
|
||||
* @return the rollout groups belonging to a rollout ordered by ID ASC.
|
||||
@@ -43,7 +44,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} referring a specific rollout in a
|
||||
* specific {@link RolloutGroupStatus}.
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroup belong to
|
||||
* @param status
|
||||
@@ -58,7 +59,7 @@ public interface RolloutGroupRepository
|
||||
* the spring-data, so this is specific usecase regarding to the
|
||||
* rollout-management to find out rolloutgroups which are in specific
|
||||
* states.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the rolloutgroup belong to
|
||||
* @param rolloutGroupStatus1
|
||||
@@ -74,10 +75,10 @@ public interface RolloutGroupRepository
|
||||
@Param("status2") RolloutGroupStatus rolloutGroupStatus2);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Counts all rollout-groups refering to a given {@link Rollout} by its ID
|
||||
* and groups which not having the given status.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout refering the groups
|
||||
* @param status1
|
||||
@@ -97,7 +98,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} for a specific parent in a specific
|
||||
* status. Retrieves the child rolloutgroup for a specific status.
|
||||
*
|
||||
*
|
||||
* @param rolloutGroupId
|
||||
* the rolloutgroupId to find the parents
|
||||
* @param status
|
||||
@@ -111,7 +112,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Updates all {@link RolloutGroup#getStatus()} of children for given
|
||||
* parent.
|
||||
*
|
||||
*
|
||||
* @param parent
|
||||
* the parent rolloutgroup
|
||||
* @param status
|
||||
@@ -125,7 +126,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} for a specific rollout and status not
|
||||
* having ordered by ID DESC, latest top.
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroup belong to
|
||||
* @param notStatus
|
||||
@@ -135,9 +136,22 @@ public interface RolloutGroupRepository
|
||||
*/
|
||||
List<JpaRolloutGroup> findByRolloutAndStatusNotOrderByIdDesc(JpaRollout rollout, RolloutGroupStatus notStatus);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup}s for a specific rollout and status not
|
||||
* having.
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroup belong to
|
||||
* @param status
|
||||
* the status which the rolloutgroup should not have
|
||||
* @return rolloutgroup referring to a rollout and not having a specific
|
||||
* status.
|
||||
*/
|
||||
List<JpaRolloutGroup> findByRolloutAndStatusNotIn(JpaRollout rollout, Collection<RolloutGroupStatus> status);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} for a specific rollout.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to find the rollout groups
|
||||
* @param page
|
||||
@@ -148,10 +162,10 @@ public interface RolloutGroupRepository
|
||||
|
||||
/**
|
||||
* Counts all {@link RolloutGroup} for a specific rollout.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to find the rollout groups
|
||||
*
|
||||
*
|
||||
* @return the amount of found {@link RolloutGroup}s.
|
||||
*/
|
||||
long countByRolloutId(Long rolloutId);
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.Optional;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
@@ -33,7 +34,7 @@ public interface RolloutRepository
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Rollout} for given status.
|
||||
*
|
||||
*
|
||||
* @param status
|
||||
* the status of the rollouts to find
|
||||
* @return the list of {@link Rollout} for specific status
|
||||
@@ -44,7 +45,7 @@ public interface RolloutRepository
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Rollout} for a specific {@code name}
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* the rollout name
|
||||
* @return {@link Rollout} for specific name
|
||||
@@ -64,4 +65,28 @@ public interface RolloutRepository
|
||||
@Transactional
|
||||
@Query("DELETE FROM JpaRollout t WHERE t.tenant = :tenant")
|
||||
void deleteByTenant(@Param("tenant") String tenant);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Rollout}s for a specific {@link DistributionSet} in
|
||||
* a given {@link RolloutStatus}.
|
||||
*
|
||||
* @param set
|
||||
* the distribution set
|
||||
* @param status
|
||||
* the status of the rollout
|
||||
* @return {@link Rollout} for specific distribution set
|
||||
*/
|
||||
List<Rollout> findByDistributionSetAndStatusIn(DistributionSet set, Collection<RolloutStatus> status);
|
||||
|
||||
/**
|
||||
* Counts all {@link Rollout}s for a specific {@link DistributionSet} in a
|
||||
* given {@link RolloutStatus}.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the distribution set
|
||||
* @param status
|
||||
* the status of the rollout
|
||||
* @return the count
|
||||
*/
|
||||
long countByDistributionSetIdAndStatusIn(long distributionSetId, Collection<RolloutStatus> status);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface TargetFilterQueryRepository
|
||||
|
||||
/**
|
||||
* Find customer target filter by name
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @return custom target filter
|
||||
*/
|
||||
@@ -56,6 +56,16 @@ public interface TargetFilterQueryRepository
|
||||
@Query("update JpaTargetFilterQuery d set d.autoAssignDistributionSet = NULL, d.autoAssignActionType = NULL where d.autoAssignDistributionSet in :ids")
|
||||
void unsetAutoAssignDistributionSetAndActionType(@Param("ids") Long... dsIds);
|
||||
|
||||
/**
|
||||
* Counts all target filters that have a given auto assign distribution set
|
||||
* assigned.
|
||||
*
|
||||
* @param autoAssignDistributionSetId
|
||||
* the id of the distribution set
|
||||
* @return the count
|
||||
*/
|
||||
long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId);
|
||||
|
||||
/**
|
||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||
|
||||
@@ -11,9 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.builder;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.builder.AbstractRolloutUpdateCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
public class JpaRolloutCreate extends AbstractRolloutUpdateCreate<RolloutCreate> implements RolloutCreate {
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
@@ -28,7 +26,7 @@ public class JpaRolloutCreate extends AbstractRolloutUpdateCreate<RolloutCreate>
|
||||
|
||||
rollout.setName(name);
|
||||
rollout.setDescription(description);
|
||||
rollout.setDistributionSet(findDistributionSetAndThrowExceptionIfNotFound(set));
|
||||
rollout.setDistributionSet(distributionSetManagement.getValidAndComplete(set));
|
||||
rollout.setTargetFilterQuery(targetFilterQuery);
|
||||
rollout.setStartAt(startAt);
|
||||
rollout.setWeight(weight);
|
||||
@@ -43,9 +41,4 @@ public class JpaRolloutCreate extends AbstractRolloutUpdateCreate<RolloutCreate>
|
||||
|
||||
return rollout;
|
||||
}
|
||||
|
||||
private DistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.builder;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.builder.AbstractTargetFilterQueryUpdateCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
|
||||
/**
|
||||
@@ -35,16 +33,11 @@ public class JpaTargetFilterQueryCreate extends AbstractTargetFilterQueryUpdateC
|
||||
public JpaTargetFilterQuery build() {
|
||||
|
||||
return new JpaTargetFilterQuery(name, query,
|
||||
getAutoAssignDistributionSetId().map(this::findDistributionSetAndThrowExceptionIfNotFound).orElse(null),
|
||||
getAutoAssignDistributionSetId().map(distributionSetManagement::getValidAndComplete).orElse(null),
|
||||
getAutoAssignActionType().filter(JpaTargetFilterQueryCreate::isAutoAssignActionTypeValid).orElse(null),
|
||||
weight);
|
||||
}
|
||||
|
||||
private DistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
|
||||
private static boolean isAutoAssignActionTypeValid(final ActionType actionType) {
|
||||
if (!TargetFilterQuery.ALLOWED_AUTO_ASSIGN_ACTION_TYPES.contains(actionType)) {
|
||||
throw new InvalidAutoAssignActionTypeException();
|
||||
|
||||
@@ -116,6 +116,9 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
@Column(name = "complete")
|
||||
private boolean complete;
|
||||
|
||||
@Column(name = "valid")
|
||||
private boolean valid;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@@ -145,6 +148,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
super(name, version, description);
|
||||
|
||||
this.requiredMigrationStep = requiredMigrationStep;
|
||||
this.valid = true;
|
||||
this.type = type;
|
||||
if (moduleList != null) {
|
||||
moduleList.forEach(this::addModule);
|
||||
@@ -327,6 +331,15 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
return complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
this.valid = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
publishEventWithEventPublisher(
|
||||
|
||||
@@ -93,7 +93,8 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
|
||||
@ConversionValue(objectValue = "DELETING", dataValue = "9"),
|
||||
@ConversionValue(objectValue = "DELETED", dataValue = "10"),
|
||||
@ConversionValue(objectValue = "WAITING_FOR_APPROVAL", dataValue = "11"),
|
||||
@ConversionValue(objectValue = "APPROVAL_DENIED", dataValue = "12") })
|
||||
@ConversionValue(objectValue = "APPROVAL_DENIED", dataValue = "12"),
|
||||
@ConversionValue(objectValue = "STOPPING", dataValue = "13") })
|
||||
@Convert("rolloutstatus")
|
||||
@NotNull
|
||||
private RolloutStatus status = RolloutStatus.CREATING;
|
||||
|
||||
@@ -45,7 +45,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* DELETED attribute.
|
||||
*
|
||||
*
|
||||
* @param isDeleted
|
||||
* TRUE/FALSE are compared to the attribute DELETED. If NULL the
|
||||
* attribute is ignored
|
||||
@@ -59,7 +59,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* COMPLETED attribute.
|
||||
*
|
||||
*
|
||||
* @param isCompleted
|
||||
* TRUE/FALSE are compared to the attribute COMPLETED. If NULL
|
||||
* the attribute is ignored
|
||||
@@ -70,6 +70,20 @@ public final class DistributionSetSpecification {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* VALID attribute.
|
||||
*
|
||||
* @param isValid
|
||||
* TRUE/FALSE are compared to the attribute VALID. If NULL the
|
||||
* attribute is ignored
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSet> isValid(final Boolean isValid) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.valid), isValid);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet} with given
|
||||
* {@link DistributionSet#getId()}.
|
||||
@@ -111,7 +125,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by "like
|
||||
* name or like description or like version".
|
||||
*
|
||||
*
|
||||
* @param subString
|
||||
* to be filtered on
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
@@ -126,7 +140,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by "like
|
||||
* name and like version".
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* to be filtered on
|
||||
* @param version
|
||||
@@ -142,7 +156,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by "has at
|
||||
* least one of the given tag names".
|
||||
*
|
||||
*
|
||||
* @param tagNames
|
||||
* to be filtered on
|
||||
* @param selectDSWithNoTag
|
||||
@@ -187,7 +201,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* returns query criteria {@link Specification} comparing case insensitive
|
||||
* "NAME == AND VERSION ==".
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* to be filtered on
|
||||
* @param version
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -8,10 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.event.remote.entity;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
@@ -34,8 +37,11 @@ public class RolloutEventTest extends AbstractRemoteEntityEventTest<Rollout> {
|
||||
@Override
|
||||
protected Rollout createEntity() {
|
||||
testdataFactory.createTarget("12345");
|
||||
final DistributionSet ds = distributionSetManagement.create(entityFactory.distributionSet()
|
||||
.create().name("incomplete").version("2").description("incomplete").type("os"));
|
||||
final SoftwareModule module = softwareModuleManagement.create(
|
||||
entityFactory.softwareModule().create().name("swm").version("2").description("desc").type("os"));
|
||||
final DistributionSet ds = distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("complete").version("2").description("complete")
|
||||
.type("os").modules(Collections.singletonList(module.getId())));
|
||||
|
||||
return rolloutManagement.create(
|
||||
entityFactory.rollout().create().name("exampleRollout").targetFilterQuery("controllerId==*").set(ds),
|
||||
|
||||
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.event.remote.entity;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -17,6 +18,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
@@ -75,9 +77,11 @@ public class RolloutGroupEventTest extends AbstractRemoteEntityEventTest<Rollout
|
||||
@Override
|
||||
protected RolloutGroup createEntity() {
|
||||
testdataFactory.createTarget(UUID.randomUUID().toString());
|
||||
|
||||
final DistributionSet ds = distributionSetManagement.create(entityFactory.distributionSet().create()
|
||||
.name("incomplete").version("2").description("incomplete").type("os"));
|
||||
final SoftwareModule module = softwareModuleManagement.create(
|
||||
entityFactory.softwareModule().create().name("swm").version("2").description("desc").type("os"));
|
||||
final DistributionSet ds = distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("complete").version("2").description("complete")
|
||||
.type("os").modules(Collections.singletonList(module.getId())));
|
||||
|
||||
final Rollout entity = rolloutManagement.create(
|
||||
entityFactory.rollout().create().name("exampleRollout").targetFilterQuery("controllerId==*").set(ds),
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.eclipse.hawkbit.repository.exception.StopRolloutException;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
/**
|
||||
* Test class testing the invalidation of a {@link DistributionSet} while the
|
||||
* handle rollouts is ongoing.
|
||||
*
|
||||
*/
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Concurrent Distribution Set invalidation")
|
||||
@TestPropertySource(properties = "hawkbit.server.repository.dsInvalidationLockTimeout=1")
|
||||
public class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify that a large rollout causes a timeout when trying to invalidate a distribution set")
|
||||
public void verifyInvalidateDistributionSetWithLargeRolloutThrowsException() throws Exception {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
testdataFactory.createTargets(10000, "verifyInvalidateDistributionSetWithLargeRolloutThrowsException");
|
||||
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "50")
|
||||
.errorCondition(RolloutGroupErrorCondition.THRESHOLD, "80")
|
||||
.errorAction(RolloutGroupErrorAction.PAUSE, null).build();
|
||||
final Rollout rollout = rolloutManagement.create(entityFactory.rollout().create()
|
||||
.name("verifyInvalidateDistributionSetWithLargeRolloutThrowsException").description("desc")
|
||||
.targetFilterQuery("name==*").set(distributionSet).actionType(ActionType.FORCED), 20, conditions);
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
|
||||
// run in new Thread so that the invalidation can be executed in
|
||||
// parallel
|
||||
final Thread handleRolloutsThread = new Thread(() -> {
|
||||
tenantAware.runAsTenant(tenant, () -> systemSecurityContext.runAsSystem(() -> {
|
||||
rolloutManagement.handleRollouts();
|
||||
return 0;
|
||||
}));
|
||||
});
|
||||
handleRolloutsThread.start();
|
||||
// wait until at least one RolloutGroup is created, as this means that
|
||||
// the thread has started and has acquired the lock
|
||||
Awaitility.await().until(() -> tenantAware.runAsTenant(tenant, () -> systemSecurityContext
|
||||
.runAsSystem(() -> rolloutGroupManagement.findByRollout(PAGE, rollout.getId()).getSize() > 0)));
|
||||
|
||||
assertThatExceptionOfType(StopRolloutException.class)
|
||||
.as("Invalidation of distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()),
|
||||
CancelationType.SOFT, true)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
@@ -844,8 +845,8 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
/**
|
||||
* test a simple deployment by calling the
|
||||
* {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)} and
|
||||
* checking the active action and the action history of the targets.
|
||||
* {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)}
|
||||
* and checking the active action and the action history of the targets.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
@@ -1088,9 +1089,10 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* test the deletion of {@link DistributionSet}s including exception in case of
|
||||
* {@link Target}s are assigned by {@link Target#getAssignedDistributionSet()}
|
||||
* or {@link Target#getInstalledDistributionSet()}
|
||||
* test the deletion of {@link DistributionSet}s including exception in case
|
||||
* of {@link Target}s are assigned by
|
||||
* {@link Target#getAssignedDistributionSet()} or
|
||||
* {@link Target#getInstalledDistributionSet()}
|
||||
*/
|
||||
@Test
|
||||
@Description("Deletes distribution set. Expected behaviour is that a soft delete is performed "
|
||||
@@ -1357,12 +1359,36 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(distributionSetRepository.findAll()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests that an exception is thrown when a target is assigned to an incomplete distribution set")
|
||||
public void verifyAssignTargetsToIncompleteDistribution() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
final Target target = testdataFactory.createTarget();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> assignDistributionSet(distributionSet, target));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests that an exception is thrown when a target is assigned to an invalidated distribution set")
|
||||
public void verifyAssignTargetsToInvalidDistribution() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
final Target target = testdataFactory.createTarget();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> assignDistributionSet(distributionSet, target));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper methods that creates 2 lists of targets and a list of distribution
|
||||
* sets.
|
||||
* <p>
|
||||
* <b>All created distribution sets are assigned to all targets of the target
|
||||
* list deployedTargets.</b>
|
||||
* <b>All created distribution sets are assigned to all targets of the
|
||||
* target list deployedTargets.</b>
|
||||
*
|
||||
* @param undeployedTargetPrefix
|
||||
* prefix to be used as target controller prefix
|
||||
@@ -1371,7 +1397,8 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
* @param deployedTargetPrefix
|
||||
* prefix to be used as target controller prefix
|
||||
* @param noOfDeployedTargets
|
||||
* number of targets to which the created distribution sets assigned
|
||||
* number of targets to which the created distribution sets
|
||||
* assigned
|
||||
* @param noOfDistributionSets
|
||||
* number of distribution sets
|
||||
* @param distributionSetPrefix
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
/**
|
||||
* Test class testing the functionality of invalidating a
|
||||
* {@link DistributionSet}
|
||||
*
|
||||
*/
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Distribution set invalidation management")
|
||||
class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verify invalidation of distribution sets that only removes distribution sets from auto assignments")
|
||||
void verifyInvalidateDistributionSetStopAutoAssignment() {
|
||||
final InvalidationTestData invalidationTestData = createInvalidationTestData(
|
||||
"verifyInvalidateDistributionSetStopAutoAssignment");
|
||||
|
||||
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.NONE,
|
||||
false);
|
||||
final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement
|
||||
.countEntitiesForInvalidation(distributionSetInvalidation);
|
||||
assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 0, 0);
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(distributionSetInvalidation);
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
assertThat(targetFilterQueryManagement.get(invalidationTestData.getTargetFilterQuery().getId()).get()
|
||||
.getAutoAssignDistributionSet()).isNull();
|
||||
assertThat(rolloutRepository.findById(invalidationTestData.getRollout().getId()).get().getStatus())
|
||||
.isNotIn(RolloutStatus.STOPPING, RolloutStatus.FINISHED);
|
||||
for (final Target target : invalidationTestData.getTargets()) {
|
||||
// if status is pending, the assignment has not been canceled
|
||||
assertThat(targetRepository.findById(target.getId()).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(actionRepository.findByTarget(target).size()).isEqualTo(1);
|
||||
assertThat(actionRepository.findByTarget(target).get(0).getStatus()).isEqualTo(Status.RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify invalidation of distribution sets that removes distribution sets from auto assignments and stops rollouts")
|
||||
void verifyInvalidateDistributionSetStopRollouts() {
|
||||
final InvalidationTestData invalidationTestData = createInvalidationTestData(
|
||||
"verifyInvalidateDistributionSetStopRollouts");
|
||||
|
||||
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.NONE,
|
||||
true);
|
||||
final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement
|
||||
.countEntitiesForInvalidation(distributionSetInvalidation);
|
||||
assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 0, 1);
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(distributionSetInvalidation);
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
assertThat(targetFilterQueryManagement.get(invalidationTestData.getTargetFilterQuery().getId()).get()
|
||||
.getAutoAssignDistributionSet()).isNull();
|
||||
assertThat(rolloutRepository.findById(invalidationTestData.getRollout().getId()).get().getStatus())
|
||||
.isEqualTo(RolloutStatus.FINISHED);
|
||||
assertNoScheduledActionsExist(invalidationTestData.getRollout());
|
||||
assertRolloutGroupsAreFinished(invalidationTestData.getRollout());
|
||||
for (final Target target : invalidationTestData.getTargets()) {
|
||||
// if status is pending, the assignment has not been canceled
|
||||
assertThat(
|
||||
targetRepository.findById(invalidationTestData.getTargets().get(0).getId()).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(actionRepository.findByTarget(target).size()).isEqualTo(1);
|
||||
assertThat(actionRepository.findByTarget(target).get(0).getStatus()).isEqualTo(Status.RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify invalidation of distribution sets that removes distribution sets from auto assignments, stops rollouts and force cancels assignments")
|
||||
void verifyInvalidateDistributionSetStopAllAndForceCancel() {
|
||||
final InvalidationTestData invalidationTestData = createInvalidationTestData(
|
||||
"verifyInvalidateDistributionSetStopAllAndForceCancel");
|
||||
|
||||
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.FORCE,
|
||||
true);
|
||||
final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement
|
||||
.countEntitiesForInvalidation(distributionSetInvalidation);
|
||||
assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 5, 1);
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(distributionSetInvalidation);
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
assertThat(targetFilterQueryManagement.get(invalidationTestData.getTargetFilterQuery().getId()).get()
|
||||
.getAutoAssignDistributionSet()).isNull();
|
||||
assertThat(rolloutRepository.findById(invalidationTestData.getRollout().getId()).get().getStatus())
|
||||
.isEqualTo(RolloutStatus.FINISHED);
|
||||
assertNoScheduledActionsExist(invalidationTestData.getRollout());
|
||||
assertRolloutGroupsAreFinished(invalidationTestData.getRollout());
|
||||
for (final Target target : invalidationTestData.getTargets()) {
|
||||
assertThat(targetRepository.findById(target.getId()).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
assertThat(actionRepository.findByTarget(target).size()).isEqualTo(1);
|
||||
assertThat(actionRepository.findByTarget(target).get(0).getStatus()).isEqualTo(Status.CANCELED);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertNoScheduledActionsExist(final Rollout rollout) {
|
||||
assertThat(
|
||||
actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Status.SCHEDULED).getTotalElements())
|
||||
.isZero();
|
||||
}
|
||||
|
||||
private void assertRolloutGroupsAreFinished(final Rollout rollout) {
|
||||
assertThat(rolloutGroupRepository.findByRolloutId(rollout.getId(), PAGE))
|
||||
.allMatch(rolloutGroup -> rolloutGroup.getStatus().equals(RolloutGroupStatus.FINISHED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify invalidation of distribution sets that removes distribution sets from auto assignments, stops rollouts and cancels assignments")
|
||||
void verifyInvalidateDistributionSetStopAll() {
|
||||
final InvalidationTestData invalidationTestData = createInvalidationTestData(
|
||||
"verifyInvalidateDistributionSetStopAll");
|
||||
|
||||
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.SOFT,
|
||||
true);
|
||||
final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement
|
||||
.countEntitiesForInvalidation(distributionSetInvalidation);
|
||||
assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 5, 1);
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(distributionSetInvalidation);
|
||||
|
||||
assertThat(targetFilterQueryManagement.get(invalidationTestData.getTargetFilterQuery().getId()).get()
|
||||
.getAutoAssignDistributionSet()).isNull();
|
||||
assertThat(rolloutRepository.findById(invalidationTestData.getRollout().getId()).get().getStatus())
|
||||
.isIn(RolloutStatus.STOPPING, RolloutStatus.FINISHED);
|
||||
for (final Target target : invalidationTestData.getTargets()) {
|
||||
assertThat(targetRepository.findById(target.getId()).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(actionRepository.findByTarget(target).size()).isEqualTo(1);
|
||||
assertThat(actionRepository.findByTarget(target).get(0).getStatus()).isEqualTo(Status.CANCELING);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that invalidating an incomplete distribution set throws an exception")
|
||||
void verifyInvalidateIncompleteDistributionSetThrowsException() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()),
|
||||
CancelationType.SOFT, true)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that invalidating an invalidated distribution set throws an exception")
|
||||
void verifyInvalidateInvalidatedDistributionSetThrowsException() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(Collections.singletonList(distributionSet.getId()),
|
||||
CancelationType.SOFT, true)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a user that has authority READ_REPOSITORY and UPDATE_REPOSITORY is not allowed to invalidate a distribution set")
|
||||
@WithUser(authorities = { "READ_REPOSITORY", "UPDATE_REPOSITORY" })
|
||||
void verifyInvalidateWithReadAndUpdateRepoAuthority() {
|
||||
final InvalidationTestData invalidationTestData = systemSecurityContext
|
||||
.runAsSystem(() -> createInvalidationTestData("verifyInvalidateWithUpdateRepoAuthority"));
|
||||
|
||||
assertThatExceptionOfType(InsufficientPermissionException.class)
|
||||
.as("Insufficient permission exception expected")
|
||||
.isThrownBy(() -> distributionSetInvalidationManagement
|
||||
.invalidateDistributionSet(new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()),
|
||||
CancelationType.NONE, false)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a user that has authority READ_REPOSITORY, UPDATE_REPOSITORY and UPDATE_TARGET is allowed to invalidate a distribution set only without canceling rollouts")
|
||||
@WithUser(authorities = { "READ_REPOSITORY", "UPDATE_REPOSITORY", "UPDATE_TARGET" })
|
||||
void verifyInvalidateWithReadAndUpdateRepoAndUpdateTargetAuthority() {
|
||||
final InvalidationTestData invalidationTestData = systemSecurityContext.runAsSystem(
|
||||
() -> createInvalidationTestData("verifyInvalidateWithUpdateRepoAndUpdateTargetAuthority"));
|
||||
|
||||
assertThatExceptionOfType(InsufficientPermissionException.class)
|
||||
.as("Insufficient permission exception expected")
|
||||
.isThrownBy(() -> distributionSetInvalidationManagement
|
||||
.invalidateDistributionSet(new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()),
|
||||
CancelationType.SOFT, true)));
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.NONE,
|
||||
false));
|
||||
assertThat(
|
||||
distributionSetRepository.findById(invalidationTestData.getDistributionSet().getId()).get().isValid())
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a user that has authority READ_REPOSITORY, UPDATE_REPOSITORY, UPDATE_ROLLOUT and UPDATE_TARGET is allowed to invalidate a distribution")
|
||||
@WithUser(authorities = { "READ_REPOSITORY", "UPDATE_REPOSITORY", "UPDATE_TARGET", "UPDATE_ROLLOUT" })
|
||||
void verifyInvalidateWithReadAndUpdateRepoAndUpdateTargetAndUpdateRolloutAuthority() {
|
||||
final InvalidationTestData invalidationTestData = systemSecurityContext.runAsSystem(
|
||||
() -> createInvalidationTestData("verifyInvalidateWithUpdateRepoAndUpdateTargetAuthority"));
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation(
|
||||
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.SOFT,
|
||||
true));
|
||||
assertThat(
|
||||
distributionSetRepository.findById(invalidationTestData.getDistributionSet().getId()).get().isValid())
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
private InvalidationTestData createInvalidationTestData(final String testName) {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
final List<Target> targets = testdataFactory.createTargets(5, testName);
|
||||
assignDistributionSet(distributionSet, targets);
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery()
|
||||
.create().name(testName).query("name==*").autoAssignDistributionSet(distributionSet));
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(testName, "desc", 2, "name==*",
|
||||
distributionSet, "50", "80");
|
||||
|
||||
return new InvalidationTestData(distributionSet, targets, targetFilterQuery, rollout);
|
||||
}
|
||||
|
||||
private static class InvalidationTestData {
|
||||
private final DistributionSet distributionSet;
|
||||
private final List<Target> targets;
|
||||
private final TargetFilterQuery targetFilterQuery;
|
||||
private final Rollout rollout;
|
||||
|
||||
public InvalidationTestData(final DistributionSet distributionSet, final List<Target> targets,
|
||||
final TargetFilterQuery targetFilterQuery, final Rollout rollout) {
|
||||
super();
|
||||
this.distributionSet = distributionSet;
|
||||
this.targets = targets;
|
||||
this.targetFilterQuery = targetFilterQuery;
|
||||
this.rollout = rollout;
|
||||
}
|
||||
|
||||
public DistributionSet getDistributionSet() {
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
public List<Target> getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
public TargetFilterQuery getTargetFilterQuery() {
|
||||
return targetFilterQuery;
|
||||
}
|
||||
|
||||
public Rollout getRollout() {
|
||||
return rollout;
|
||||
}
|
||||
}
|
||||
|
||||
private void assertDistributionSetInvalidationCount(
|
||||
final DistributionSetInvalidationCount distributionSetInvalidationCount,
|
||||
final long expectedAutoAssignmentCount, final long expectedActionCount, final long expectedRolloutCount) {
|
||||
assertThat(distributionSetInvalidationCount.getAutoAssignmentCount()).isEqualTo(expectedAutoAssignmentCount);
|
||||
assertThat(distributionSetInvalidationCount.getActionCount()).isEqualTo(expectedActionCount);
|
||||
assertThat(distributionSetInvalidationCount.getRolloutsCount()).isEqualTo(expectedRolloutCount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,16 +31,20 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreated
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
@@ -174,6 +178,13 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(set.getId(),
|
||||
entityFactory.generateDsMetadata(NOT_EXIST_ID, "xxx")), "DistributionSetMetadata");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL),
|
||||
"DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getValidAndComplete(NOT_EXIST_IDL), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getValid(NOT_EXIST_IDL), "DistributionSet");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -493,6 +504,16 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(ds.isRequiredMigrationStep()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update an invalid distribution set")
|
||||
public void updateInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement
|
||||
.update(entityFactory.distributionSet().update(distributionSet.getId()).name("new_name")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies the enforcement of the software module quota per distribution set.")
|
||||
public void assignSoftwareModulesUntilQuotaIsExceeded() {
|
||||
@@ -533,6 +554,33 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to assign software modules to an invalidated distribution set.")
|
||||
public void verifyAssignSoftwareModulesToInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSet.getId(),
|
||||
Collections.singletonList(softwareModule.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to unassign a software module from an invalidated distribution set.")
|
||||
public void verifyUnassignSoftwareModulesToInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleOs();
|
||||
distributionSetManagement.assignSoftwareModules(distributionSet.getId(),
|
||||
Collections.singletonList(softwareModule.getId()));
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation(
|
||||
Collections.singletonList(distributionSet.getId()), CancelationType.NONE, false));
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement
|
||||
.unassignSoftwareModule(distributionSet.getId(), softwareModule.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that metadata for a distribution set can be updated.")
|
||||
@@ -937,6 +985,24 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(distributionSetManagement.findByCompleted(PAGE, true).getTotalElements()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Deletes an invalid distribution set")
|
||||
public void deleteInvalidDistributionSet() {
|
||||
final DistributionSet set = testdataFactory.createAndInvalidateDistributionSet();
|
||||
assertThat(distributionSetRepository.findById(set.getId())).isNotEmpty();
|
||||
distributionSetManagement.delete(set.getId());
|
||||
assertThat(distributionSetRepository.findById(set.getId())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Deletes an incomplete distribution set")
|
||||
public void deleteIncompleteDistributionSet() {
|
||||
final DistributionSet set = testdataFactory.createIncompleteDistributionSet();
|
||||
assertThat(distributionSetRepository.findById(set.getId())).isNotEmpty();
|
||||
distributionSetManagement.delete(set.getId());
|
||||
assertThat(distributionSetRepository.findById(set.getId())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Queries and loads the metadata related to a given software module.")
|
||||
public void findAllDistributionSetMetadataByDsId() {
|
||||
@@ -1013,4 +1079,54 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(collect).containsAll(searchIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that an exception is thrown when trying to get an invalid distribution set")
|
||||
public void verifyGetValid() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.getValid(distributionSet.getId()));
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.getValidAndComplete(distributionSet.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that an exception is thrown when trying to get an incomplete distribution set")
|
||||
public void verifyGetValidAndComplete() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.getValidAndComplete(distributionSet.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that an exception is thrown when trying to create or update metadata for an invalid distribution set.")
|
||||
public void createMetadataForInvalidDistributionSet() {
|
||||
final String knownKey1 = "myKnownKey1";
|
||||
final String knownKey2 = "myKnownKey2";
|
||||
final String knownValue = "myKnownValue";
|
||||
final String knownUpdateValue = "knownUpdateValue";
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.createMetaData(ds.getId(),
|
||||
Collections.singletonList(entityFactory.generateDsMetadata(knownKey1, knownValue)));
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(Arrays.asList(ds.getId()), CancelationType.NONE, false));
|
||||
|
||||
// assert that no new metadata can be created
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.createMetaData(ds.getId(),
|
||||
Collections.singletonList(entityFactory.generateDsMetadata(knownKey2, knownValue))));
|
||||
|
||||
// assert that an existing metadata can not be updated
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement
|
||||
.updateMetaData(ds.getId(), entityFactory.generateDsMetadata(knownKey1, knownUpdateValue)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
|
||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
@@ -72,7 +74,6 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -243,8 +244,9 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(firstGroup.getStatus()).isEqualTo(RolloutGroupStatus.RUNNING);
|
||||
|
||||
// verify other groups are scheduled
|
||||
final List<RolloutGroup> scheduledGroups = rolloutGroupManagement.findByRollout(
|
||||
new OffsetBasedPageRequest(1, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId()).getContent();
|
||||
final List<RolloutGroup> scheduledGroups = rolloutGroupManagement
|
||||
.findByRollout(new OffsetBasedPageRequest(1, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId())
|
||||
.getContent();
|
||||
scheduledGroups.forEach(group -> assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.SCHEDULED)
|
||||
.as("group which should be in scheduled state is in " + group.getStatus() + " state"));
|
||||
// verify that the first group actions has been started and are in state
|
||||
@@ -436,8 +438,9 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(errorGroup.get(0).getStatus()).isEqualTo(RolloutGroupStatus.ERROR);
|
||||
|
||||
// all other groups should still be in scheduled state
|
||||
final List<RolloutGroup> scheduleGroups = rolloutGroupManagement.findByRollout(
|
||||
new OffsetBasedPageRequest(1, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId()).getContent();
|
||||
final List<RolloutGroup> scheduleGroups = rolloutGroupManagement
|
||||
.findByRollout(new OffsetBasedPageRequest(1, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId())
|
||||
.getContent();
|
||||
scheduleGroups.forEach(group -> assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.SCHEDULED));
|
||||
}
|
||||
|
||||
@@ -470,8 +473,9 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(rollout.getStatus()).isEqualTo(RolloutStatus.PAUSED);
|
||||
|
||||
// all other groups should still be in scheduled state
|
||||
final List<RolloutGroup> scheduleGroups = rolloutGroupManagement.findByRollout(
|
||||
new OffsetBasedPageRequest(1, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId()).getContent();
|
||||
final List<RolloutGroup> scheduleGroups = rolloutGroupManagement
|
||||
.findByRollout(new OffsetBasedPageRequest(1, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId())
|
||||
.getContent();
|
||||
scheduleGroups.forEach(group -> assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.SCHEDULED));
|
||||
|
||||
// resume the rollout again after it gets paused by error action
|
||||
@@ -521,8 +525,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// verify all groups are in finished state
|
||||
rolloutGroupManagement
|
||||
.findByRollout(new OffsetBasedPageRequest(0, 100, Sort.by(Direction.ASC, "id")),
|
||||
createdRollout.getId())
|
||||
.findByRollout(new OffsetBasedPageRequest(0, 100, Sort.by(Direction.ASC, "id")), createdRollout.getId())
|
||||
.forEach(group -> assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.FINISHED));
|
||||
|
||||
// verify that rollout itself is in finished state
|
||||
@@ -1823,6 +1826,56 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(actions).allMatch(action -> !action.getWeight().isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to create a rollout with an invalidated distribution set.")
|
||||
public void createRolloutWithInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithInvalidDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to create a rollout with an incomplete distribution set.")
|
||||
public void createRolloutWithIncompleteDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> testdataFactory.createRolloutByVariables("createRolloutWithIncompleteDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update a rollout with an invalidated distribution set.")
|
||||
public void updateRolloutWithInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
testdataFactory.createTarget();
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("updateRolloutWithInvalidDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80");
|
||||
final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception").isThrownBy(() -> rolloutManagement
|
||||
.update(entityFactory.rollout().update(rollout.getId()).set(invalidDistributionSet.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update a rollout with an incomplete distribution set.")
|
||||
public void updateRolloutWithIncompleteDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
testdataFactory.createTarget();
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("updateRolloutWithIncompleteDistributionSet",
|
||||
"desc", 2, "name==*", distributionSet, "50", "80");
|
||||
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception").isThrownBy(() -> rolloutManagement.update(
|
||||
entityFactory.rollout().update(rollout.getId()).set(incompleteDistributionSet.getId())));
|
||||
}
|
||||
|
||||
private RolloutGroupCreate generateRolloutGroup(final int index, final Integer percentage,
|
||||
final String targetFilter) {
|
||||
return entityFactory.rolloutGroup().create().name("Group" + index).description("Group" + index + "desc")
|
||||
|
||||
@@ -23,14 +23,17 @@ import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -51,7 +54,7 @@ import io.qameta.allure.Story;
|
||||
|
||||
/**
|
||||
* Test class for {@link TargetFilterQueryManagement}.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Target Filter Query Management")
|
||||
@@ -252,7 +255,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
|
||||
.create(entityFactory.distributionSet().create().name("incomplete").version("1")
|
||||
.type(testdataFactory.findOrCreateDefaultTestDsType()));
|
||||
|
||||
assertThatExceptionOfType(InvalidAutoAssignDistributionSetException.class)
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
|
||||
.updateAutoAssign(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId())));
|
||||
}
|
||||
@@ -263,7 +266,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
|
||||
assignDistributionSet(softDeletedDs, testdataFactory.createTarget("forSoftDeletedDs"));
|
||||
distributionSetManagement.delete(softDeletedDs.getId());
|
||||
|
||||
assertThatExceptionOfType(InvalidAutoAssignDistributionSetException.class)
|
||||
assertThatExceptionOfType(EntityNotFoundException.class)
|
||||
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
|
||||
.updateAutoAssign(targetFilterQuery.getId()).ds(softDeletedDs.getId())));
|
||||
}
|
||||
@@ -502,4 +505,60 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
|
||||
assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight().get())
|
||||
.isEqualTo(Action.WEIGHT_MIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to create a target filter with an invalidated distribution set.")
|
||||
public void createTargetFilterWithInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> targetFilterQueryManagement.create(
|
||||
entityFactory.targetFilterQuery().create().name("createTargetFilterWithInvalidDistributionSet")
|
||||
.query("name==*").autoAssignDistributionSet(distributionSet)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to create a target filter with an incomplete distribution set.")
|
||||
public void createTargetFilterWithIncompleteDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create()
|
||||
.name("createTargetFilterWithIncompleteDistributionSet").query("name==*")
|
||||
.autoAssignDistributionSet(distributionSet)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update a target filter with an invalidated distribution set.")
|
||||
public void updateAutoAssignDsWithInvalidDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name("updateAutoAssignDsWithInvalidDistributionSet")
|
||||
.query("name==*").autoAssignDistributionSet(distributionSet));
|
||||
final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> targetFilterQueryManagement
|
||||
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
|
||||
.ds(invalidDistributionSet.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that an exception is thrown when trying to update a target filter with an incomplete distribution set.")
|
||||
public void updateAutoAssignDsWithIncompleteDistributionSet() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
|
||||
entityFactory.targetFilterQuery().create().name("updateAutoAssignDsWithIncompleteDistributionSet")
|
||||
.query("name==*").autoAssignDistributionSet(distributionSet));
|
||||
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
.as("Incomplete distributionSet should throw an exception")
|
||||
.isThrownBy(() -> targetFilterQueryManagement
|
||||
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
|
||||
.ds(incompleteDistributionSet.getId())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -105,11 +105,11 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet setB = testdataFactory.createDistributionSet("dsB");
|
||||
|
||||
// target filter query that matches all targets
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(
|
||||
entityFactory.targetFilterQuery()
|
||||
.updateAutoAssign(targetFilterQueryManagement.create(
|
||||
entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
|
||||
.ds(setA.getId()));
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(entityFactory
|
||||
.targetFilterQuery()
|
||||
.updateAutoAssign(targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
|
||||
.ds(setA.getId()));
|
||||
|
||||
final String targetDsAIdPref = "targ";
|
||||
final List<Target> targets = testdataFactory.createTargets(100, targetDsAIdPref,
|
||||
@@ -159,7 +159,7 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
// target filter query that matches first bunch of targets, that should
|
||||
// fail
|
||||
assertThatExceptionOfType(InvalidAutoAssignDistributionSetException.class).isThrownBy(() -> {
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class).isThrownBy(() -> {
|
||||
final Long filterId = targetFilterQueryManagement.create(
|
||||
entityFactory.targetFilterQuery().create().name("filterA").query("id==" + targetDsFIdPref + "*"))
|
||||
.getId();
|
||||
@@ -221,10 +221,10 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
||||
final DistributionSet distributionSet, final List<Target> targets) {
|
||||
final Set<String> targetIds = targets.stream().map(Target::getControllerId).collect(Collectors.toSet());
|
||||
|
||||
actionRepository.findByDistributionSetId(Pageable.unpaged(), distributionSet.getId())
|
||||
.stream().filter(a -> targetIds.contains(a.getTarget().getControllerId()))
|
||||
.forEach(a -> assertThat(a.getInitiatedBy()).as(
|
||||
"Action should be initiated by the user who initiated the auto assignment")
|
||||
actionRepository.findByDistributionSetId(Pageable.unpaged(), distributionSet.getId()).stream()
|
||||
.filter(a -> targetIds.contains(a.getTarget().getControllerId()))
|
||||
.forEach(a -> assertThat(a.getInitiatedBy())
|
||||
.as("Action should be initiated by the user who initiated the auto assignment")
|
||||
.isEqualTo(targetFilterQuery.getAutoAssignInitiatedBy()));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
|
||||
@@ -159,6 +160,9 @@ public abstract class AbstractIntegrationTest {
|
||||
@Autowired
|
||||
protected DeploymentManagement deploymentManagement;
|
||||
|
||||
@Autowired
|
||||
protected DistributionSetInvalidationManagement distributionSetInvalidationManagement;
|
||||
|
||||
@Autowired
|
||||
protected ArtifactManagement artifactManagement;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.Constants;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
|
||||
@@ -48,6 +49,8 @@ import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.ArtifactUpload;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
@@ -140,6 +143,9 @@ public class TestdataFactory {
|
||||
@Autowired
|
||||
private DistributionSetManagement distributionSetManagement;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetInvalidationManagement distributionSetInvalidationManagement;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetTypeManagement distributionSetTypeManagement;
|
||||
|
||||
@@ -172,11 +178,11 @@ public class TestdataFactory {
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} and
|
||||
* {@link DistributionSet#isRequiredMigrationStep()} <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String prefix) {
|
||||
@@ -188,7 +194,7 @@ public class TestdataFactory {
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} and
|
||||
* {@link DistributionSet#isRequiredMigrationStep()} <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet() {
|
||||
@@ -200,10 +206,10 @@ public class TestdataFactory {
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} and
|
||||
* {@link DistributionSet#isRequiredMigrationStep()} <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param modules
|
||||
* of {@link DistributionSet#getModules()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final Collection<SoftwareModule> modules) {
|
||||
@@ -215,13 +221,13 @@ public class TestdataFactory {
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} and
|
||||
* {@link DistributionSet#isRequiredMigrationStep()} <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param modules
|
||||
* of {@link DistributionSet#getModules()}
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final Collection<SoftwareModule> modules, final String prefix) {
|
||||
@@ -232,13 +238,13 @@ public class TestdataFactory {
|
||||
* Creates {@link DistributionSet} in repository including three
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION}.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
* @param isRequiredMigrationStep
|
||||
* for {@link DistributionSet#isRequiredMigrationStep()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String prefix, final boolean isRequiredMigrationStep) {
|
||||
@@ -250,13 +256,13 @@ public class TestdataFactory {
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} and
|
||||
* {@link DistributionSet#isRequiredMigrationStep()} <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
* @param tags
|
||||
* {@link DistributionSet#getTags()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String prefix, final Collection<DistributionSetTag> tags) {
|
||||
@@ -267,7 +273,7 @@ public class TestdataFactory {
|
||||
* Creates {@link DistributionSet} in repository including three
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP}.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
@@ -277,7 +283,7 @@ public class TestdataFactory {
|
||||
* number.
|
||||
* @param isRequiredMigrationStep
|
||||
* for {@link DistributionSet#isRequiredMigrationStep()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String prefix, final String version,
|
||||
@@ -306,12 +312,12 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Adds {@link SoftwareModuleMetadata} to every module of given
|
||||
* {@link DistributionSet}.
|
||||
*
|
||||
*
|
||||
* {@link #VISIBLE_SM_MD_VALUE}, {@link #VISIBLE_SM_MD_KEY} with
|
||||
* {@link SoftwareModuleMetadata#isTargetVisible()} and
|
||||
* {@link #INVISIBLE_SM_MD_KEY}, {@link #INVISIBLE_SM_MD_VALUE} without
|
||||
* {@link SoftwareModuleMetadata#isTargetVisible()}
|
||||
*
|
||||
*
|
||||
* @param set
|
||||
* to add metadata to
|
||||
*/
|
||||
@@ -329,7 +335,7 @@ public class TestdataFactory {
|
||||
|
||||
/**
|
||||
* Creates {@link DistributionSet} in repository.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
@@ -341,7 +347,7 @@ public class TestdataFactory {
|
||||
* for {@link DistributionSet#isRequiredMigrationStep()}
|
||||
* @param modules
|
||||
* for {@link DistributionSet#getModules()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String prefix, final String version,
|
||||
@@ -358,7 +364,7 @@ public class TestdataFactory {
|
||||
* Creates {@link DistributionSet} in repository including three
|
||||
* {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT}
|
||||
* , {@link #SM_TYPE_APP}.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
@@ -368,7 +374,7 @@ public class TestdataFactory {
|
||||
* number.updat
|
||||
* @param tags
|
||||
* {@link DistributionSet#getTags()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity.
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String prefix, final String version,
|
||||
@@ -388,10 +394,10 @@ public class TestdataFactory {
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} followed by an
|
||||
* iterative number and {@link DistributionSet#isRequiredMigrationStep()}
|
||||
* <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param number
|
||||
* of {@link DistributionSet}s to create
|
||||
*
|
||||
*
|
||||
* @return {@link List} of {@link DistributionSet} entities
|
||||
*/
|
||||
public List<DistributionSet> createDistributionSets(final int number) {
|
||||
@@ -402,7 +408,7 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Create a list of {@link DistributionSet}s without modules, i.e.
|
||||
* incomplete.
|
||||
*
|
||||
*
|
||||
* @param number
|
||||
* of {@link DistributionSet}s to create
|
||||
* @return {@link List} of {@link DistributionSet} entities
|
||||
@@ -425,13 +431,13 @@ public class TestdataFactory {
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} followed by an
|
||||
* iterative number and {@link DistributionSet#isRequiredMigrationStep()}
|
||||
* <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for {@link SoftwareModule}s and {@link DistributionSet}s name,
|
||||
* vendor and description.
|
||||
* @param number
|
||||
* of {@link DistributionSet}s to create
|
||||
*
|
||||
*
|
||||
* @return {@link List} of {@link DistributionSet} entities
|
||||
*/
|
||||
public List<DistributionSet> createDistributionSets(final String prefix, final int number) {
|
||||
@@ -448,12 +454,12 @@ public class TestdataFactory {
|
||||
* Creates {@link DistributionSet}s in repository with
|
||||
* {@link #DEFAULT_DESCRIPTION} and
|
||||
* {@link DistributionSet#isRequiredMigrationStep()} <code>false</code>.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* {@link DistributionSet#getName()}
|
||||
* @param version
|
||||
* {@link DistributionSet#getVersion()}
|
||||
*
|
||||
*
|
||||
* @return {@link DistributionSet} entity
|
||||
*/
|
||||
public DistributionSet createDistributionSetWithNoSoftwareModules(final String name, final String version) {
|
||||
@@ -465,10 +471,10 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Creates {@link Artifact}s for given {@link SoftwareModule} with a small
|
||||
* text payload.
|
||||
*
|
||||
*
|
||||
* @param moduleId
|
||||
* the {@link Artifact}s belong to.
|
||||
*
|
||||
*
|
||||
* @return {@link Artifact} entity.
|
||||
*/
|
||||
public List<Artifact> createArtifacts(final Long moduleId) {
|
||||
@@ -484,16 +490,16 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Create an {@link Artifact} for given {@link SoftwareModule} with a small
|
||||
* text payload.
|
||||
*
|
||||
*
|
||||
* @param artifactData
|
||||
* the {@link Artifact} Inputstream
|
||||
*
|
||||
*
|
||||
* @param moduleId
|
||||
* the {@link Artifact} belongs to
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* that was provided during upload.
|
||||
*
|
||||
*
|
||||
* @return {@link Artifact} entity.
|
||||
*/
|
||||
public Artifact createArtifact(final String artifactData, final Long moduleId, final String filename) {
|
||||
@@ -530,10 +536,10 @@ public class TestdataFactory {
|
||||
* Creates {@link SoftwareModule} with {@link #DEFAULT_VENDOR} and
|
||||
* {@link #DEFAULT_VERSION} and random generated
|
||||
* {@link Target#getDescription()} in the repository.
|
||||
*
|
||||
*
|
||||
* @param typeKey
|
||||
* of the {@link SoftwareModuleType}
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModule}.
|
||||
*/
|
||||
public SoftwareModule createSoftwareModule(final String typeKey) {
|
||||
@@ -545,8 +551,8 @@ public class TestdataFactory {
|
||||
* {@value Constants#SMT_DEFAULT_APP_KEY} with {@link #DEFAULT_VENDOR} and
|
||||
* {@link #DEFAULT_VERSION} and random generated
|
||||
* {@link Target#getDescription()} in the repository.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModule}.
|
||||
*/
|
||||
public SoftwareModule createSoftwareModuleApp() {
|
||||
@@ -558,11 +564,11 @@ public class TestdataFactory {
|
||||
* {@value Constants#SMT_DEFAULT_APP_KEY} with {@link #DEFAULT_VENDOR} and
|
||||
* {@link #DEFAULT_VERSION} and random generated
|
||||
* {@link Target#getDescription()} in the repository.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* added to name and version
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModule}.
|
||||
*/
|
||||
public SoftwareModule createSoftwareModuleApp(final String prefix) {
|
||||
@@ -574,8 +580,8 @@ public class TestdataFactory {
|
||||
* {@value Constants#SMT_DEFAULT_OS_KEY} with {@link #DEFAULT_VENDOR} and
|
||||
* {@link #DEFAULT_VERSION} and random generated
|
||||
* {@link Target#getDescription()} in the repository.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModule}.
|
||||
*/
|
||||
public SoftwareModule createSoftwareModuleOs() {
|
||||
@@ -587,11 +593,11 @@ public class TestdataFactory {
|
||||
* {@value Constants#SMT_DEFAULT_OS_KEY} with {@link #DEFAULT_VENDOR} and
|
||||
* {@link #DEFAULT_VERSION} and random generated
|
||||
* {@link Target#getDescription()} in the repository.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* added to name and version
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModule}.
|
||||
*/
|
||||
public SoftwareModule createSoftwareModuleOs(final String prefix) {
|
||||
@@ -602,12 +608,12 @@ public class TestdataFactory {
|
||||
* Creates {@link SoftwareModule} with {@link #DEFAULT_VENDOR} and
|
||||
* {@link #DEFAULT_VERSION} and random generated
|
||||
* {@link Target#getDescription()} in the repository.
|
||||
*
|
||||
*
|
||||
* @param typeKey
|
||||
* of the {@link SoftwareModuleType}
|
||||
* @param prefix
|
||||
* added to name and version
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModule}.
|
||||
*/
|
||||
public SoftwareModule createSoftwareModule(final String typeKey, final String prefix) {
|
||||
@@ -652,12 +658,12 @@ public class TestdataFactory {
|
||||
* @param targetName
|
||||
* name of the target
|
||||
* @param targetTypeId
|
||||
* target type id
|
||||
* target type id
|
||||
* @return persisted {@link Target}
|
||||
*/
|
||||
public Target createTarget(final String controllerId, final String targetName, final Long targetTypeId) {
|
||||
final Target target = targetManagement
|
||||
.create(entityFactory.target().create().controllerId(controllerId).name(targetName).targetType(targetTypeId));
|
||||
final Target target = targetManagement.create(
|
||||
entityFactory.target().create().controllerId(controllerId).name(targetName).targetType(targetTypeId));
|
||||
assertTargetProperlyCreated(target);
|
||||
return target;
|
||||
}
|
||||
@@ -677,12 +683,12 @@ public class TestdataFactory {
|
||||
* , {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} followed by an
|
||||
* iterative number and {@link DistributionSet#isRequiredMigrationStep()}
|
||||
* <code>false</code>.
|
||||
*
|
||||
*
|
||||
* In addition it updates the created {@link DistributionSet}s and
|
||||
* {@link SoftwareModule}s to ensure that
|
||||
* {@link BaseEntity#getLastModifiedAt()} and
|
||||
* {@link BaseEntity#getLastModifiedBy()} is filled.
|
||||
*
|
||||
*
|
||||
* @return persisted {@link DistributionSet}.
|
||||
*/
|
||||
public DistributionSet createUpdatedDistributionSet() {
|
||||
@@ -716,12 +722,12 @@ public class TestdataFactory {
|
||||
|
||||
/**
|
||||
* Creates {@link DistributionSetType} in repository.
|
||||
*
|
||||
*
|
||||
* @param dsTypeKey
|
||||
* {@link DistributionSetType#getKey()}
|
||||
* @param dsTypeName
|
||||
* {@link DistributionSetType#getName()}
|
||||
*
|
||||
*
|
||||
* @return persisted {@link DistributionSetType}
|
||||
*/
|
||||
public DistributionSetType findOrCreateDistributionSetType(final String dsTypeKey, final String dsTypeName) {
|
||||
@@ -733,7 +739,7 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Finds {@link DistributionSetType} in repository with given
|
||||
* {@link DistributionSetType#getKey()} or creates if it does not exist yet.
|
||||
*
|
||||
*
|
||||
* @param dsTypeKey
|
||||
* {@link DistributionSetType#getKey()}
|
||||
* @param dsTypeName
|
||||
@@ -742,7 +748,7 @@ public class TestdataFactory {
|
||||
* {@link DistributionSetType#getMandatoryModuleTypes()}
|
||||
* @param optional
|
||||
* {@link DistributionSetType#getOptionalModuleTypes()}
|
||||
*
|
||||
*
|
||||
* @return persisted {@link DistributionSetType}
|
||||
*/
|
||||
public DistributionSetType findOrCreateDistributionSetType(final String dsTypeKey, final String dsTypeName,
|
||||
@@ -758,10 +764,10 @@ public class TestdataFactory {
|
||||
* Finds {@link SoftwareModuleType} in repository with given
|
||||
* {@link SoftwareModuleType#getKey()} or creates if it does not exist yet
|
||||
* with {@link SoftwareModuleType#getMaxAssignments()} = 1.
|
||||
*
|
||||
*
|
||||
* @param key
|
||||
* {@link SoftwareModuleType#getKey()}
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModuleType}
|
||||
*/
|
||||
public SoftwareModuleType findOrCreateSoftwareModuleType(final String key) {
|
||||
@@ -771,18 +777,18 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Finds {@link SoftwareModuleType} in repository with given
|
||||
* {@link SoftwareModuleType#getKey()} or creates if it does not exist yet.
|
||||
*
|
||||
*
|
||||
* @param key
|
||||
* {@link SoftwareModuleType#getKey()}
|
||||
* @param maxAssignments
|
||||
* {@link SoftwareModuleType#getMaxAssignments()}
|
||||
*
|
||||
*
|
||||
* @return persisted {@link SoftwareModuleType}
|
||||
*/
|
||||
public SoftwareModuleType findOrCreateSoftwareModuleType(final String key, final int maxAssignments) {
|
||||
return softwareModuleTypeManagement.getByKey(key)
|
||||
.orElseGet(() -> softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create()
|
||||
.key(key).name(key).description(LOREM.words(10)).colour("#ffffff").maxAssignments(maxAssignments)));
|
||||
return softwareModuleTypeManagement.getByKey(key).orElseGet(
|
||||
() -> softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create().key(key).name(key)
|
||||
.description(LOREM.words(10)).colour("#ffffff").maxAssignments(maxAssignments)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -796,7 +802,7 @@ public class TestdataFactory {
|
||||
* {@link DistributionSet#getType()}
|
||||
* @param modules
|
||||
* {@link DistributionSet#getModules()}
|
||||
*
|
||||
*
|
||||
* @return the created {@link DistributionSet}
|
||||
*/
|
||||
public DistributionSet createDistributionSet(final String name, final String version,
|
||||
@@ -819,7 +825,7 @@ public class TestdataFactory {
|
||||
* {@link DistributionSet#getModules()}
|
||||
* @param requiredMigrationStep
|
||||
* {@link DistributionSet#isRequiredMigrationStep()}
|
||||
*
|
||||
*
|
||||
* @return the created {@link DistributionSet}
|
||||
*/
|
||||
public DistributionSet generateDistributionSet(final String name, final String version,
|
||||
@@ -841,7 +847,7 @@ public class TestdataFactory {
|
||||
* {@link DistributionSet#getType()}
|
||||
* @param modules
|
||||
* {@link DistributionSet#getModules()}
|
||||
*
|
||||
*
|
||||
* @return the created {@link DistributionSet}
|
||||
*/
|
||||
public DistributionSet generateDistributionSet(final String name, final String version,
|
||||
@@ -854,7 +860,7 @@ public class TestdataFactory {
|
||||
*
|
||||
* @param name
|
||||
* {@link DistributionSet#getName()}
|
||||
*
|
||||
*
|
||||
* @return the generated {@link DistributionSet}
|
||||
*/
|
||||
public DistributionSet generateDistributionSet(final String name) {
|
||||
@@ -866,10 +872,10 @@ public class TestdataFactory {
|
||||
* Creates {@link Target}s in repository and with
|
||||
* {@link #DEFAULT_CONTROLLER_ID} as prefix for
|
||||
* {@link Target#getControllerId()}.
|
||||
*
|
||||
*
|
||||
* @param number
|
||||
* of {@link Target}s to create
|
||||
*
|
||||
*
|
||||
* @return {@link List} of {@link Target} entities
|
||||
*/
|
||||
public List<Target> createTargets(final int number) {
|
||||
@@ -884,10 +890,10 @@ public class TestdataFactory {
|
||||
|
||||
/**
|
||||
* Creates {@link Target}s in repository and with given targetIds.
|
||||
*
|
||||
*
|
||||
* @param targetIds
|
||||
* specifies the IDs of the targets
|
||||
*
|
||||
*
|
||||
* @return {@link List} of {@link Target} entities
|
||||
*/
|
||||
public List<Target> createTargets(final String... targetIds) {
|
||||
@@ -903,7 +909,7 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Builds {@link Target} objects with given prefix for
|
||||
* {@link Target#getControllerId()} followed by a number suffix.
|
||||
*
|
||||
*
|
||||
* @param start
|
||||
* value for the controllerId suffix
|
||||
* @param numberOfTargets
|
||||
@@ -925,7 +931,7 @@ public class TestdataFactory {
|
||||
* Builds {@link Target} objects with given prefix for
|
||||
* {@link Target#getControllerId()} followed by a number suffix starting
|
||||
* with 0.
|
||||
*
|
||||
*
|
||||
* @param numberOfTargets
|
||||
* of {@link Target}s to generate
|
||||
* @param controllerIdPrefix
|
||||
@@ -1015,10 +1021,10 @@ public class TestdataFactory {
|
||||
|
||||
/**
|
||||
* Creates {@link DistributionSetTag}s in repository.
|
||||
*
|
||||
*
|
||||
* @param number
|
||||
* of {@link DistributionSetTag}s
|
||||
*
|
||||
*
|
||||
* @return the persisted {@link DistributionSetTag}s
|
||||
*/
|
||||
public List<DistributionSetTag> createDistributionSetTags(final int number) {
|
||||
@@ -1042,14 +1048,14 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Append {@link ActionStatus} to all {@link Action}s of given
|
||||
* {@link Target}s.
|
||||
*
|
||||
*
|
||||
* @param targets
|
||||
* to add {@link ActionStatus}
|
||||
* @param status
|
||||
* to add
|
||||
* @param message
|
||||
* to add
|
||||
*
|
||||
*
|
||||
* @return updated {@link Action}.
|
||||
*/
|
||||
public List<Action> sendUpdateActionStatusToTargets(final Collection<Target> targets, final Status status,
|
||||
@@ -1060,14 +1066,14 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Append {@link ActionStatus} to all {@link Action}s of given
|
||||
* {@link Target}s.
|
||||
*
|
||||
*
|
||||
* @param targets
|
||||
* to add {@link ActionStatus}
|
||||
* @param status
|
||||
* to add
|
||||
* @param msgs
|
||||
* to add
|
||||
*
|
||||
*
|
||||
* @return updated {@link Action}.
|
||||
*/
|
||||
public List<Action> sendUpdateActionStatusToTargets(final Collection<Target> targets, final Status status,
|
||||
@@ -1085,7 +1091,7 @@ public class TestdataFactory {
|
||||
|
||||
/**
|
||||
* Creates rollout based on given parameters.
|
||||
*
|
||||
*
|
||||
* @param rolloutName
|
||||
* of the {@link Rollout}
|
||||
* @param rolloutDescription
|
||||
@@ -1155,7 +1161,7 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Create {@link Rollout} with a new {@link DistributionSet} and
|
||||
* {@link Target}s.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for rollouts name, description,
|
||||
* {@link Target#getControllerId()} filter
|
||||
@@ -1170,7 +1176,7 @@ public class TestdataFactory {
|
||||
/**
|
||||
* Create the soft deleted {@link Rollout} with a new
|
||||
* {@link DistributionSet} and {@link Target}s.
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* for rollouts name, description,
|
||||
* {@link Target#getControllerId()} filter
|
||||
@@ -1187,8 +1193,8 @@ public class TestdataFactory {
|
||||
|
||||
/**
|
||||
* Finds {@link TargetType} in repository with given
|
||||
* {@link TargetType#getName()} or creates if it does not exist yet.
|
||||
* No ds types are assigned on creation.
|
||||
* {@link TargetType#getName()} or creates if it does not exist yet. No ds
|
||||
* types are assigned on creation.
|
||||
*
|
||||
* @param targetTypeName
|
||||
* {@link TargetType#getName()}
|
||||
@@ -1197,25 +1203,26 @@ public class TestdataFactory {
|
||||
*/
|
||||
public TargetType findOrCreateTargetType(final String targetTypeName) {
|
||||
return targetTypeManagement.getByName(targetTypeName)
|
||||
.orElseGet(() -> targetTypeManagement.create(entityFactory.targetType().create()
|
||||
.name(targetTypeName).description(targetTypeName + " description").colour(DEFAULT_COLOUR)));
|
||||
.orElseGet(() -> targetTypeManagement.create(entityFactory.targetType().create().name(targetTypeName)
|
||||
.description(targetTypeName + " description").colour(DEFAULT_COLOUR)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates {@link TargetType} in repository with given
|
||||
* {@link TargetType#getName()}. Compatible distribution set types are assigned on creation
|
||||
* {@link TargetType#getName()}. Compatible distribution set types are
|
||||
* assigned on creation
|
||||
*
|
||||
* @param targetTypeName
|
||||
* {@link TargetType#getName()}
|
||||
*
|
||||
* @return persisted {@link TargetType}
|
||||
*/
|
||||
public TargetType createTargetType(final String targetTypeName, List<DistributionSetType> compatibleDsTypes) {
|
||||
return targetTypeManagement.create(entityFactory.targetType().create()
|
||||
.name(targetTypeName).description(targetTypeName + " description").colour(DEFAULT_COLOUR)
|
||||
.compatible(compatibleDsTypes.stream().map(DistributionSetType::getId).collect(Collectors.toList())));
|
||||
public TargetType createTargetType(final String targetTypeName, final List<DistributionSetType> compatibleDsTypes) {
|
||||
return targetTypeManagement.create(entityFactory.targetType().create().name(targetTypeName)
|
||||
.description(targetTypeName + " description").colour(DEFAULT_COLOUR)
|
||||
.compatible(compatibleDsTypes.stream().map(DistributionSetType::getId).collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates {@link TargetType} in repository with given
|
||||
* {@link TargetType#getName()}. No ds types are assigned on creation.
|
||||
@@ -1225,13 +1232,37 @@ public class TestdataFactory {
|
||||
*
|
||||
* @return persisted {@link TargetType}
|
||||
*/
|
||||
public List<TargetType> createTargetTypes(final String targetTypePrefix, int count) {
|
||||
public List<TargetType> createTargetTypes(final String targetTypePrefix, final int count) {
|
||||
final List<TargetTypeCreate> result = Lists.newArrayListWithExpectedSize(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
result.add(entityFactory.targetType().create().name(targetTypePrefix + i).description(targetTypePrefix + " description")
|
||||
.colour(DEFAULT_COLOUR));
|
||||
result.add(entityFactory.targetType().create().name(targetTypePrefix + i)
|
||||
.description(targetTypePrefix + " description").colour(DEFAULT_COLOUR));
|
||||
}
|
||||
return targetTypeManagement.create(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a distribution set and directly invalidates it. No actions will
|
||||
* be canceled and no rollouts will be stopped with this invalidation.
|
||||
*
|
||||
* @return created invalidated {@link DistributionSet}
|
||||
*/
|
||||
public DistributionSet createAndInvalidateDistributionSet() {
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(Arrays.asList(distributionSet.getId()), CancelationType.NONE, false));
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a distribution set that has no software modules assigned, so it
|
||||
* is incomplete.
|
||||
*
|
||||
* @return created incomplete {@link DistributionSet}
|
||||
*/
|
||||
public DistributionSet createIncompleteDistributionSet() {
|
||||
return distributionSetManagement.create(entityFactory.distributionSet().create()
|
||||
.name(UUID.randomUUID().toString()).version(DEFAULT_VERSION).description(LOREM.words(10))
|
||||
.type(findOrCreateDefaultTestDsType()).requiredMigrationStep(false));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user