Feature download only (#810)
* Added initial version of DOWNLOAD_ONLY * Added DOWNLOAD_ONLY option to ActionTypeOptionGroupLayout * Removed DOWNLOAD_ONLY checkbox, added Download Only UI option * Mark actions that finished with DOWNLOADED as finished * initial changes to realize downoadOnly in UI * Changed method of disabling maintenanceWindow into smarter solution * Added new icon for download only option * Set DistributionSet as unassigned when DOWNLOAD_ONLY * Enabled update action status for DOWNLOAD_ONLY after download * Current state of abstraction task * Assign DistributionSet to target if target installs it after downloading * Abstracted class redundant methods * Added tests * Fixed Rollout finish status for DWONLOAD_ONLY Rollouts * Added Rollout type json property in test documentation * Added DOWNLOAD_ONLY test for target assignment * Added event listener also to DistributionTable * Fixed event listener problem * Change column name to "Type" and added also DownloadOnly icon to that column. * Cleanup * Center aligned the icons in type column * Fixed DistributionSet already assigned but not installed * Rename download_only to downloadonly * Further changes regarding center aligned the icons * Fixed target assign status in Rollout view when download_only * Fixed SonarQube issues * Fixed SonarQube issues + code formatting * Fixed Tests * Marked squid:S128 as suppressed - irrelevant * Adapting rollouts view by additional column (not finished by now) * Putted type column on proper position * Trying to display icons in new type column in rollouts view * Added icon also for soft, icon might change -> just change * createOptionGroup method in ActionTypeOptionGroupLayout class * added first draft of type column in rollouts view * increase visibility of sendUpdateMessageToTarget method * Ground functionality of new type column in deployment view is now implemented * Type column implementation in rollouts view is finished for now * Rebased on master * Fixed DurationControl change on ScheduleControl change. * (Re)Added Soft deployment Icon * Fixed SonarQube issues * Fixed SonarQube issues * Fixed failing test * Fixes + added missing header * Added message to the fail() instruction * Fixed copyright header * Apply suggestions from code review * Fixed TotalTargetCountStatus.java * Removed unused method from TotalTargetCountStatus.java * add id to rollout create and update UI popup * Added download_only tests for MgmtTargetResourceTest.java * added missing header in TotalTargetCountStatusTest.java * Rename because of newest changes * added Download_Only dmf integration tests * Renamed MgmtAction.forcedType to actionType * renamed actionType to forceType for Mgmt API * added missing javadocs for public methods * Added Download Only support for AutoAssignment Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com> Signed-off-by: Ammar Bikic <ammar.bikic@bosch-si.com>
This commit is contained in:
@@ -313,17 +313,13 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
* the rollout the actions are belong to
|
||||
* @param rolloutGroup
|
||||
* the rolloutgroup the actions are belong to
|
||||
* @param notStatus1
|
||||
* the status the action should not have
|
||||
* @param notStatus2
|
||||
* the status the action should not have
|
||||
* @param notStatus3
|
||||
* the status the action should not have
|
||||
* @param statuses
|
||||
* the list of statuses the action should not have
|
||||
* @return the count of actions referring the rollout and rolloutgroup and
|
||||
* are not in given states
|
||||
*/
|
||||
Long countByRolloutAndRolloutGroupAndStatusNotAndStatusNotAndStatusNot(JpaRollout rollout,
|
||||
JpaRolloutGroup rolloutGroup, Status notStatus1, Status notStatus2, Status notStatus3);
|
||||
Long countByRolloutAndRolloutGroupAndStatusNotIn(JpaRollout rollout, JpaRolloutGroup rolloutGroup,
|
||||
List<Status> statuses);
|
||||
|
||||
/**
|
||||
* Counts all actions referring to a given rollout and rolloutgroup.
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY;
|
||||
import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED;
|
||||
import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED;
|
||||
import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_KEY_SIZE;
|
||||
import static org.eclipse.hawkbit.repository.model.Target.CONTROLLER_ATTRIBUTE_VALUE_SIZE;
|
||||
|
||||
@@ -452,7 +455,7 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
"UPDATE sp_target SET last_target_query = #last_target_query WHERE controller_id IN ("
|
||||
+ formatQueryInStatementParams(paramMapping.keySet()) + ") AND tenant = #tenant");
|
||||
|
||||
paramMapping.entrySet().forEach(entry -> updateQuery.setParameter(entry.getKey(), entry.getValue()));
|
||||
paramMapping.forEach(updateQuery::setParameter);
|
||||
updateQuery.setParameter("last_target_query", currentTimeMillis);
|
||||
updateQuery.setParameter("tenant", tenant);
|
||||
|
||||
@@ -561,23 +564,37 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
||||
final JpaActionStatus actionStatus = create.build();
|
||||
|
||||
// if action is already closed we accept further status updates if
|
||||
// permitted so by configuration. This is especially useful if the
|
||||
// action status feedback channel order from the device cannot be
|
||||
// guaranteed. However, if an action is closed we do not accept further
|
||||
// close messages.
|
||||
if (actionIsNotActiveButIntermediateFeedbackStillAllowed(actionStatus, action.isActive())) {
|
||||
LOG.debug("Update of actionStatus {} for action {} not possible since action not active anymore.",
|
||||
actionStatus.getStatus(), action.getId());
|
||||
return action;
|
||||
if (isUpdatingActionStatusAllowed(action, actionStatus)) {
|
||||
return handleAddUpdateActionStatus(actionStatus, action);
|
||||
}
|
||||
return handleAddUpdateActionStatus(actionStatus, action);
|
||||
|
||||
LOG.debug("Update of actionStatus {} for action {} not possible since action not active anymore.",
|
||||
actionStatus.getStatus(), action.getId());
|
||||
return action;
|
||||
}
|
||||
|
||||
private boolean actionIsNotActiveButIntermediateFeedbackStillAllowed(final ActionStatus actionStatus,
|
||||
final boolean actionActive) {
|
||||
return !actionActive && (repositoryProperties.isRejectActionStatusForClosedAction()
|
||||
|| Status.ERROR.equals(actionStatus.getStatus()) || Status.FINISHED.equals(actionStatus.getStatus()));
|
||||
/**
|
||||
* ActionStatus updates are allowed mainly if the action is active. If the
|
||||
* action is not active we accept further status updates if permitted so
|
||||
* by repository configuration. In this case, only the values: Status.ERROR
|
||||
* and Status.FINISHED are allowed. In the case of a DOWNLOAD_ONLY action,
|
||||
* we accept status updates only once.
|
||||
*/
|
||||
private boolean isUpdatingActionStatusAllowed(final JpaAction action, final JpaActionStatus actionStatus) {
|
||||
|
||||
final boolean isIntermediateFeedback = !FINISHED.equals(actionStatus.getStatus())
|
||||
&& !Status.ERROR.equals(actionStatus.getStatus());
|
||||
|
||||
final boolean isAllowedByRepositoryConfiguration = !repositoryProperties.isRejectActionStatusForClosedAction()
|
||||
&& isIntermediateFeedback;
|
||||
|
||||
final boolean isAllowedForDownloadOnlyActions = isDownloadOnly(action) && !isIntermediateFeedback;
|
||||
|
||||
return action.isActive() || isAllowedByRepositoryConfiguration || isAllowedForDownloadOnlyActions;
|
||||
}
|
||||
|
||||
private static boolean isDownloadOnly(final JpaAction action) {
|
||||
return DOWNLOAD_ONLY.equals(action.getActionType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -588,6 +605,10 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
String controllerId = null;
|
||||
LOG.debug("handleAddUpdateActionStatus for action {}", action.getId());
|
||||
|
||||
// information status entry - check for a potential DOS attack
|
||||
assertActionStatusQuota(action);
|
||||
assertActionStatusMessageQuota(actionStatus);
|
||||
|
||||
switch (actionStatus.getStatus()) {
|
||||
case ERROR:
|
||||
final JpaTarget target = (JpaTarget) action.getTarget();
|
||||
@@ -597,10 +618,10 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
case FINISHED:
|
||||
controllerId = handleFinishedAndStoreInTargetStatus(action);
|
||||
break;
|
||||
case DOWNLOADED:
|
||||
controllerId = handleDownloadedActionStatus(action);
|
||||
break;
|
||||
default:
|
||||
// information status entry - check for a potential DOS attack
|
||||
assertActionStatusQuota(action);
|
||||
assertActionStatusMessageQuota(actionStatus);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -615,6 +636,20 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
return savedAction;
|
||||
}
|
||||
|
||||
private String handleDownloadedActionStatus(final JpaAction action) {
|
||||
if(!isDownloadOnly(action)){
|
||||
return null;
|
||||
}
|
||||
|
||||
JpaTarget target = (JpaTarget) action.getTarget();
|
||||
action.setActive(false);
|
||||
action.setStatus(DOWNLOADED);
|
||||
target.setUpdateStatus(TargetUpdateStatus.IN_SYNC);
|
||||
targetRepository.save(target);
|
||||
|
||||
return target.getControllerId();
|
||||
}
|
||||
|
||||
private void requestControllerAttributes(final String controllerId) {
|
||||
final JpaTarget target = (JpaTarget) getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
@@ -648,6 +683,12 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
target.setInstalledDistributionSet(ds);
|
||||
target.setInstallationDate(System.currentTimeMillis());
|
||||
|
||||
// Target reported an installation of a DOWNLOAD_ONLY assignment, the assigned DS has to be adapted
|
||||
// because the currently assigned DS can be unequal to the currently installed DS (the downloadOnly DS)
|
||||
if(isDownloadOnly(action)){
|
||||
target.setAssignedDistributionSet(action.getDistributionSet());
|
||||
}
|
||||
|
||||
// check if the assigned set is equal to the installed set (not
|
||||
// necessarily the case as another update might be pending already).
|
||||
if (target.getAssignedDistributionSet() != null
|
||||
|
||||
@@ -151,7 +151,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
|
||||
for (final JpaRolloutGroup rolloutGroup : rolloutGroups) {
|
||||
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(
|
||||
allStatesForRollout.get(rolloutGroup.getId()), Long.valueOf(rolloutGroup.getTotalTargets()));
|
||||
allStatesForRollout.get(rolloutGroup.getId()), Long.valueOf(rolloutGroup.getTotalTargets()),
|
||||
rolloutGroup.getRollout().getActionType());
|
||||
rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus);
|
||||
}
|
||||
|
||||
@@ -177,7 +178,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
}
|
||||
|
||||
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems,
|
||||
Long.valueOf(jpaRolloutGroup.getTotalTargets()));
|
||||
Long.valueOf(jpaRolloutGroup.getTotalTargets()), jpaRolloutGroup.getRollout().getActionType());
|
||||
jpaRolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus);
|
||||
return rolloutGroup;
|
||||
|
||||
|
||||
@@ -105,6 +105,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions;
|
||||
|
||||
/**
|
||||
* JPA implementation of {@link RolloutManagement}.
|
||||
*/
|
||||
@@ -126,6 +128,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
private static final List<RolloutStatus> ACTIVE_ROLLOUTS = Arrays.asList(RolloutStatus.CREATING,
|
||||
RolloutStatus.DELETING, RolloutStatus.STARTING, RolloutStatus.READY, RolloutStatus.RUNNING);
|
||||
|
||||
// In case of DOWNLOAD_ONLY, actions can be finished with DOWNLOADED status.
|
||||
private static final List<Status> DOWNLOAD_ONLY_ACTION_TERMINATION_STATUSES = Arrays.asList(Status.ERROR,
|
||||
Status.FINISHED, Status.CANCELED, Status.DOWNLOADED);
|
||||
private static final List<Status> DEFAULT_ACTION_TERMINATION_STATUSES = Arrays.asList(Status.ERROR, Status.FINISHED,
|
||||
Status.CANCELED);
|
||||
|
||||
@Autowired
|
||||
private RolloutRepository rolloutRepository;
|
||||
|
||||
@@ -251,17 +259,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
group.setParent(lastSavedGroup);
|
||||
group.setStatus(RolloutGroupStatus.CREATING);
|
||||
|
||||
group.setSuccessCondition(conditions.getSuccessCondition());
|
||||
group.setSuccessConditionExp(conditions.getSuccessConditionExp());
|
||||
|
||||
group.setSuccessAction(conditions.getSuccessAction());
|
||||
group.setSuccessActionExp(conditions.getSuccessActionExp());
|
||||
|
||||
group.setErrorCondition(conditions.getErrorCondition());
|
||||
group.setErrorConditionExp(conditions.getErrorConditionExp());
|
||||
|
||||
group.setErrorAction(conditions.getErrorAction());
|
||||
group.setErrorActionExp(conditions.getErrorActionExp());
|
||||
addSuccessAndErrorConditionsAndActions(group, conditions);
|
||||
|
||||
group.setTargetPercentage(1.0F / (amountOfGroups - i) * 100);
|
||||
|
||||
@@ -310,17 +308,10 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
group.setTargetFilterQuery("");
|
||||
}
|
||||
|
||||
group.setSuccessCondition(srcGroup.getSuccessCondition());
|
||||
group.setSuccessConditionExp(srcGroup.getSuccessConditionExp());
|
||||
|
||||
group.setSuccessAction(srcGroup.getSuccessAction());
|
||||
group.setSuccessActionExp(srcGroup.getSuccessActionExp());
|
||||
|
||||
group.setErrorCondition(srcGroup.getErrorCondition());
|
||||
group.setErrorConditionExp(srcGroup.getErrorConditionExp());
|
||||
|
||||
group.setErrorAction(srcGroup.getErrorAction());
|
||||
group.setErrorActionExp(srcGroup.getErrorActionExp());
|
||||
addSuccessAndErrorConditionsAndActions(group, srcGroup.getSuccessCondition(),
|
||||
srcGroup.getSuccessConditionExp(), srcGroup.getSuccessAction(), srcGroup.getSuccessActionExp(),
|
||||
srcGroup.getErrorCondition(), srcGroup.getErrorConditionExp(), srcGroup.getErrorAction(),
|
||||
srcGroup.getErrorActionExp());
|
||||
|
||||
lastSavedGroup = rolloutGroupRepository.save(group);
|
||||
publishRolloutGroupCreatedEventAfterCommit(lastSavedGroup, rollout);
|
||||
@@ -760,9 +751,11 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
|
||||
private boolean isRolloutGroupComplete(final JpaRollout rollout, final JpaRolloutGroup rolloutGroup) {
|
||||
final Long actionsLeftForRollout = actionRepository
|
||||
.countByRolloutAndRolloutGroupAndStatusNotAndStatusNotAndStatusNot(rollout, rolloutGroup,
|
||||
Action.Status.ERROR, Action.Status.FINISHED, Action.Status.CANCELED);
|
||||
final Long actionsLeftForRollout = ActionType.DOWNLOAD_ONLY.equals(rollout.getActionType())
|
||||
? actionRepository.countByRolloutAndRolloutGroupAndStatusNotIn(rollout, rolloutGroup,
|
||||
DOWNLOAD_ONLY_ACTION_TERMINATION_STATUSES)
|
||||
: actionRepository.countByRolloutAndRolloutGroupAndStatusNotIn(rollout, rolloutGroup,
|
||||
DEFAULT_ACTION_TERMINATION_STATUSES);
|
||||
return actionsLeftForRollout == 0;
|
||||
}
|
||||
|
||||
@@ -1070,7 +1063,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
|
||||
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(rolloutStatusCountItems,
|
||||
rollout.get().getTotalTargets());
|
||||
rollout.get().getTotalTargets(), rollout.get().getActionType());
|
||||
((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus);
|
||||
return rollout;
|
||||
}
|
||||
@@ -1112,7 +1105,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
if (allStatesForRollout != null) {
|
||||
rollouts.forEach(rollout -> {
|
||||
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(
|
||||
allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets());
|
||||
allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType());
|
||||
rollout.setTotalTargetCountStatus(totalTargetCountStatus);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.jpa.builder;
|
||||
import org.eclipse.hawkbit.repository.builder.AbstractRolloutGroupCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
|
||||
|
||||
public class JpaRolloutGroupCreate extends AbstractRolloutGroupCreate<RolloutGroupCreate>
|
||||
implements RolloutGroupCreate {
|
||||
@@ -30,20 +32,66 @@ public class JpaRolloutGroupCreate extends AbstractRolloutGroupCreate<RolloutGro
|
||||
group.setTargetPercentage(targetPercentage);
|
||||
|
||||
if (conditions != null) {
|
||||
group.setSuccessCondition(conditions.getSuccessCondition());
|
||||
group.setSuccessConditionExp(conditions.getSuccessConditionExp());
|
||||
|
||||
group.setSuccessAction(conditions.getSuccessAction());
|
||||
group.setSuccessActionExp(conditions.getSuccessActionExp());
|
||||
|
||||
group.setErrorCondition(conditions.getErrorCondition());
|
||||
group.setErrorConditionExp(conditions.getErrorConditionExp());
|
||||
|
||||
group.setErrorAction(conditions.getErrorAction());
|
||||
group.setErrorActionExp(conditions.getErrorActionExp());
|
||||
addSuccessAndErrorConditionsAndActions(group, conditions);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Success And Error conditions for the rollout group
|
||||
*
|
||||
* @param group
|
||||
* The Rollout group
|
||||
* @param conditions
|
||||
* The Rollout Success and Error Conditions
|
||||
*/
|
||||
public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group,
|
||||
final RolloutGroupConditions conditions) {
|
||||
addSuccessAndErrorConditionsAndActions(group, conditions.getSuccessCondition(),
|
||||
conditions.getSuccessConditionExp(), conditions.getSuccessAction(), conditions.getSuccessActionExp(),
|
||||
conditions.getErrorCondition(), conditions.getErrorConditionExp(), conditions.getErrorAction(),
|
||||
conditions.getErrorActionExp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Success And Error conditions for the rollout group
|
||||
*
|
||||
* @param group
|
||||
* The Rollout group
|
||||
* @param successCondition
|
||||
* The Rollout group success condition
|
||||
* @param successConditionExp
|
||||
* The Rollout group success expression
|
||||
* @param successAction
|
||||
* The Rollout group success action
|
||||
* @param successActionExp
|
||||
* The Rollout group success action expression
|
||||
* @param errorCondition
|
||||
* The Rollout group error condition
|
||||
* @param errorConditionExp
|
||||
* The Rollout group error expression
|
||||
* @param errorAction
|
||||
* The Rollout group error action
|
||||
* @param errorActionExp
|
||||
* The Rollout group error action expression
|
||||
*/
|
||||
public static void addSuccessAndErrorConditionsAndActions(final JpaRolloutGroup group,
|
||||
final RolloutGroup.RolloutGroupSuccessCondition successCondition, final String successConditionExp,
|
||||
final RolloutGroup.RolloutGroupSuccessAction successAction, final String successActionExp,
|
||||
final RolloutGroup.RolloutGroupErrorCondition errorCondition, final String errorConditionExp,
|
||||
final RolloutGroup.RolloutGroupErrorAction errorAction, final String errorActionExp) {
|
||||
group.setSuccessCondition(successCondition);
|
||||
group.setSuccessConditionExp(successConditionExp);
|
||||
|
||||
group.setSuccessAction(successAction);
|
||||
group.setSuccessActionExp(successActionExp);
|
||||
|
||||
group.setErrorCondition(errorCondition);
|
||||
group.setErrorConditionExp(errorConditionExp);
|
||||
|
||||
group.setErrorAction(errorAction);
|
||||
group.setErrorActionExp(errorActionExp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -80,7 +80,8 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
||||
@ObjectTypeConverter(name = "actionType", objectType = Action.ActionType.class, dataType = Integer.class, conversionValues = {
|
||||
@ConversionValue(objectValue = "FORCED", dataValue = "0"),
|
||||
@ConversionValue(objectValue = "SOFT", dataValue = "1"),
|
||||
@ConversionValue(objectValue = "TIMEFORCED", dataValue = "2") })
|
||||
@ConversionValue(objectValue = "TIMEFORCED", dataValue = "2"),
|
||||
@ConversionValue(objectValue = "DOWNLOAD_ONLY", dataValue = "3") })
|
||||
@Convert("actionType")
|
||||
@NotNull
|
||||
private ActionType actionType;
|
||||
|
||||
@@ -102,7 +102,8 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
|
||||
@ObjectTypeConverter(name = "actionType", objectType = Action.ActionType.class, dataType = Integer.class, conversionValues = {
|
||||
@ConversionValue(objectValue = "FORCED", dataValue = "0"),
|
||||
@ConversionValue(objectValue = "SOFT", dataValue = "1"),
|
||||
@ConversionValue(objectValue = "TIMEFORCED", dataValue = "2") })
|
||||
@ConversionValue(objectValue = "TIMEFORCED", dataValue = "2"),
|
||||
@ConversionValue(objectValue = "DOWNLOAD_ONLY", dataValue = "3") })
|
||||
@Convert("actionType")
|
||||
@NotNull
|
||||
private ActionType actionType = ActionType.FORCED;
|
||||
@@ -224,7 +225,7 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
|
||||
@Override
|
||||
public TotalTargetCountStatus getTotalTargetCountStatus() {
|
||||
if (totalTargetCountStatus == null) {
|
||||
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets);
|
||||
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets, actionType);
|
||||
}
|
||||
return totalTargetCountStatus;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
|
||||
@Override
|
||||
public TotalTargetCountStatus getTotalTargetCountStatus() {
|
||||
if (totalTargetCountStatus == null) {
|
||||
totalTargetCountStatus = new TotalTargetCountStatus(Long.valueOf(totalTargets));
|
||||
totalTargetCountStatus = new TotalTargetCountStatus(Long.valueOf(totalTargets), rollout.getActionType());
|
||||
}
|
||||
return totalTargetCountStatus;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,9 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity
|
||||
@Column(name = "auto_assign_action_type", nullable = true)
|
||||
@ObjectTypeConverter(name = "autoAssignActionType", objectType = Action.ActionType.class, dataType = Integer.class, conversionValues = {
|
||||
@ConversionValue(objectValue = "FORCED", dataValue = "0"),
|
||||
@ConversionValue(objectValue = "SOFT", dataValue = "1") })
|
||||
@ConversionValue(objectValue = "SOFT", dataValue = "1"),
|
||||
// Conversion for 'TIMEFORCED' is disabled because it is not permitted in autoAssignment
|
||||
@ConversionValue(objectValue = "DOWNLOAD_ONLY", dataValue = "3")})
|
||||
@Convert("autoAssignActionType")
|
||||
private ActionType autoAssignActionType;
|
||||
|
||||
|
||||
@@ -38,8 +38,10 @@ public class ThresholdRolloutGroupSuccessCondition implements RolloutGroupCondit
|
||||
return true;
|
||||
}
|
||||
|
||||
Action.Status completeActionStatus = Action.ActionType.DOWNLOAD_ONLY.equals(rollout.getActionType()) ?
|
||||
Action.Status.DOWNLOADED : Action.Status.FINISHED;
|
||||
final long finished = this.actionRepository.countByRolloutIdAndRolloutGroupIdAndStatus(rollout.getId(),
|
||||
rolloutGroup.getId(), Action.Status.FINISHED);
|
||||
rolloutGroup.getId(), completeActionStatus);
|
||||
try {
|
||||
final Integer threshold = Integer.valueOf(expression);
|
||||
// calculate threshold
|
||||
|
||||
@@ -10,14 +10,13 @@ package org.eclipse.hawkbit.repository.event.remote;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionProperties;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.junit.Test;
|
||||
@@ -69,10 +68,10 @@ public class RemoteTenantAwareEventTest extends AbstractRemoteEventTest {
|
||||
private void assertTargetAssignDistributionSetEvent(final Action action,
|
||||
final TargetAssignDistributionSetEvent underTest) {
|
||||
|
||||
final Entry<String, Long> entry = new SimpleImmutableEntry(action.getTarget().getControllerId(),
|
||||
action.getId());
|
||||
|
||||
assertThat(underTest.getActions()).containsExactly(entry);
|
||||
assertThat(underTest.getActions().size()).isEqualTo(1);
|
||||
ActionProperties actionProperties = underTest.getActions().get(action.getTarget().getControllerId());
|
||||
assertThat(actionProperties).isNotNull();
|
||||
assertThat(actionProperties).isEqualToComparingFieldByField(new ActionProperties(action));
|
||||
assertThat(underTest.getDistributionSetId()).isEqualTo(action.getDistributionSet().getId());
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.jpa;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS;
|
||||
import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY;
|
||||
import static org.eclipse.hawkbit.repository.test.util.TestdataFactory.DEFAULT_CONTROLLER_ID;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -20,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -42,19 +45,20 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.ArtifactUpload;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -148,7 +152,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.FINISHED, Action.Status.FINISHED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(7);
|
||||
@@ -199,7 +203,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.FINISHED, Action.Status.FINISHED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(3);
|
||||
@@ -224,7 +228,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
// expected
|
||||
}
|
||||
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.RUNNING, true);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(1);
|
||||
@@ -245,14 +249,14 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.CANCELING, true);
|
||||
|
||||
simulateIntermediateStatusOnCancellation(actionId);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.CANCELED, Action.Status.FINISHED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(8);
|
||||
@@ -272,14 +276,14 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.CANCELING, true);
|
||||
|
||||
simulateIntermediateStatusOnCancellation(actionId);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.CANCELED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.CANCELED, Action.Status.CANCELED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(8);
|
||||
@@ -300,14 +304,14 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.CANCELING, true);
|
||||
|
||||
simulateIntermediateStatusOnCancellation(actionId);
|
||||
|
||||
controllerManagement.addCancelActionStatus(
|
||||
entityFactory.actionStatus().create(actionId).status(Action.Status.CANCEL_REJECTED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.CANCEL_REJECTED, true);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(8);
|
||||
@@ -328,14 +332,14 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
|
||||
deploymentManagement.cancelAction(actionId);
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.CANCELING, true);
|
||||
|
||||
simulateIntermediateStatusOnCancellation(actionId);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.ERROR));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.ERROR, true);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(8);
|
||||
@@ -346,39 +350,64 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
private Long createTargetAndAssignDs() {
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
testdataFactory.createTarget();
|
||||
assignDistributionSet(dsId, TestdataFactory.DEFAULT_CONTROLLER_ID);
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
assignDistributionSet(dsId, DEFAULT_CONTROLLER_ID);
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
|
||||
return deploymentManagement.findActiveActionsByTarget(PAGE, TestdataFactory.DEFAULT_CONTROLLER_ID).getContent()
|
||||
return deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent()
|
||||
.get(0).getId();
|
||||
}
|
||||
|
||||
@Step
|
||||
private Long createAndAssignDsAsDownloadOnly(final String dsName, final String defaultControllerId) {
|
||||
final Long dsId = testdataFactory.createDistributionSet(dsName).getId();
|
||||
assignDistributionSet(dsId, defaultControllerId, DOWNLOAD_ONLY);
|
||||
assertThat(targetManagement.getByControllerID(defaultControllerId).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
|
||||
final Long id = deploymentManagement.findActiveActionsByTarget(PAGE, defaultControllerId).getContent()
|
||||
.get(0).getId();
|
||||
assertThat(id).isNotNull();
|
||||
return id;
|
||||
}
|
||||
|
||||
@Step
|
||||
private Long assignDs(final Long dsId, final String defaultControllerId, final Action.ActionType actionType) {
|
||||
assignDistributionSet(dsId, defaultControllerId, actionType);
|
||||
assertThat(targetManagement.getByControllerID(defaultControllerId).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.PENDING);
|
||||
|
||||
final Long id = deploymentManagement.findActiveActionsByTarget(PAGE, defaultControllerId).getContent()
|
||||
.get(0).getId();
|
||||
assertThat(id).isNotNull();
|
||||
return id;
|
||||
}
|
||||
|
||||
@Step
|
||||
private void simulateIntermediateStatusOnCancellation(final Long actionId) {
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.RUNNING, true);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.DOWNLOAD, true);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOADED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.DOWNLOADED, true);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.RETRIEVED, true);
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.CANCELING, Action.Status.WARNING, true);
|
||||
}
|
||||
|
||||
@@ -386,26 +415,26 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
private void simulateIntermediateStatusOnUpdate(final Long actionId) {
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.RUNNING, true);
|
||||
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.DOWNLOAD, true);
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOADED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.DOWNLOADED, true);
|
||||
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.RETRIEVED, true);
|
||||
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.WARNING, true);
|
||||
}
|
||||
|
||||
@@ -509,7 +538,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller trys to finish an update process after it has been finished by an error action status.")
|
||||
@Description("Controller tries to finish an update process after it has been finished by an error action status.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@@ -522,12 +551,12 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
// test and verify
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.RUNNING, true);
|
||||
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.ERROR));
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
|
||||
Action.Status.ERROR, Action.Status.ERROR, false);
|
||||
|
||||
// try with disabled late feedback
|
||||
@@ -536,7 +565,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
|
||||
// test
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
|
||||
Action.Status.ERROR, Action.Status.ERROR, false);
|
||||
|
||||
// try with enabled late feedback - should not make a difference as it
|
||||
@@ -546,7 +575,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
|
||||
// test
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
|
||||
Action.Status.ERROR, Action.Status.ERROR, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(3);
|
||||
@@ -572,7 +601,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
|
||||
// test
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.FINISHED, Action.Status.FINISHED, false);
|
||||
|
||||
// try with enabled late feedback - should not make a difference as it
|
||||
@@ -582,7 +611,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
|
||||
|
||||
// test
|
||||
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.FINISHED, Action.Status.FINISHED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(3);
|
||||
@@ -609,7 +638,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
entityFactory.actionStatus().create(action.getId()).status(Action.Status.RUNNING));
|
||||
|
||||
// nothing changed as "feedback after close" is disabled
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(3);
|
||||
@@ -635,7 +664,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
entityFactory.actionStatus().create(action.getId()).status(Action.Status.RUNNING));
|
||||
|
||||
// nothing changed as "feedback after close" is disabled
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
|
||||
// however, additional action status has been stored
|
||||
@@ -989,4 +1018,312 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a DOWNLOAD_ONLY action is not marked complete when the controller reports DOWNLOAD")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsDownloadForDownloadOnlyAction() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOAD));
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
|
||||
Action.Status.RUNNING, Action.Status.DOWNLOAD, true);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(2);
|
||||
assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(2);
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID))
|
||||
.isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a DOWNLOAD_ONLY action is marked complete once the controller reports DOWNLOADED")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsDownloadedForDownloadOnlyAction() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED));
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.DOWNLOADED, Action.Status.DOWNLOADED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(2);
|
||||
assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(2);
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID))
|
||||
.isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a controller can report a FINISHED event for a DOWNLOAD_ONLY non-active action.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 2),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsActionFinishedForDownloadOnlyActionThatIsNotActive() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
finishDownloadOnlyUpdateAndSendUpdateActionStatus(actionId, Status.FINISHED);
|
||||
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Action.Status.FINISHED, Action.Status.FINISHED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(3);
|
||||
assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(3);
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID))
|
||||
.isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that multiple DOWNLOADED events for a DOWNLOAD_ONLY action are handled.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 3),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void controllerReportsMultipleDownloadedForDownloadOnlyAction() {
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
IntStream.range(0, 3).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)));
|
||||
|
||||
assertActionStatus(actionId, DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
|
||||
Status.DOWNLOADED, Status.DOWNLOADED, false);
|
||||
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(4);
|
||||
assertThat(controllerManagement.findActionStatusByAction(PAGE, actionId).getNumberOfElements()).isEqualTo(4);
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID))
|
||||
.isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test(expected = QuotaExceededException.class)
|
||||
@Description("Verifies that quota is asserted when a controller reports too many DOWNLOADED events for a " +
|
||||
"DOWNLOAD_ONLY action.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 9),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void quotaExceptionWhencontrollerReportsTooManyDownloadedMessagesForDownloadOnlyAction() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that quota is enforced for UpdateActionStatus events for DOWNLOAD_ONLY assignments.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 9),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void quotaEceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForDownloadOnlyAction() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
testdataFactory.createTarget();
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)));
|
||||
fail("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates");
|
||||
} catch (QuotaExceededException e) { }
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)));
|
||||
fail("No QuotaExceededException thrown for too many ERROR updateActionStatus updates");
|
||||
} catch (QuotaExceededException e) { }
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)));
|
||||
fail("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates");
|
||||
} catch (QuotaExceededException e) { }
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that quota is enforced for UpdateActionStatus events for FORCED assignments.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void quotaEceededExceptionWhenControllerReportsTooManyUpdateActionStatusMessagesForForced() {
|
||||
final int maxMessages = quotaManagement.getMaxMessagesPerActionStatus();
|
||||
final Long actionId = createTargetAndAssignDs();
|
||||
assertThat(actionId).isNotNull();
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)));
|
||||
fail("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates");
|
||||
} catch (QuotaExceededException e) { }
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)));
|
||||
fail("No QuotaExceededException thrown for too many ERROR updateActionStatus updates");
|
||||
} catch (QuotaExceededException e) { }
|
||||
|
||||
try {
|
||||
IntStream.range(0, maxMessages).forEach(i -> controllerManagement
|
||||
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)));
|
||||
fail("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates");
|
||||
} catch (QuotaExceededException e) { }
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a target can report FINISHED/ERROR updates for DOWNLOAD_ONLY assignments regardless of " +
|
||||
"repositoryProperties.rejectActionStatusForClosedAction value.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 4),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 4),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 12),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 4),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 6),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 8),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 12) })
|
||||
public void targetCanAlwaysReportFinishedOrErrorAfterActionIsClosedForDownloadOnlyAssignments() {
|
||||
|
||||
testdataFactory.createTarget();
|
||||
|
||||
// allow actionStatusUpdates for closed actions
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(false);
|
||||
|
||||
final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs1", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
finishDownloadOnlyUpdateAndSendUpdateActionStatus(actionId, Status.FINISHED);
|
||||
|
||||
final Long actionId2 = createAndAssignDsAsDownloadOnly("downloadOnlyDs2", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
finishDownloadOnlyUpdateAndSendUpdateActionStatus(actionId2, Status.ERROR);
|
||||
|
||||
// disallow actionStatusUpdates for closed actions
|
||||
repositoryProperties.setRejectActionStatusForClosedAction(true);
|
||||
|
||||
final Long actionId3 = createAndAssignDsAsDownloadOnly("downloadOnlyDs3", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
finishDownloadOnlyUpdateAndSendUpdateActionStatus(actionId3, Status.FINISHED);
|
||||
|
||||
|
||||
final Long actionId4 = createAndAssignDsAsDownloadOnly("downloadOnlyDs4", DEFAULT_CONTROLLER_ID);
|
||||
assertThat(actionId).isNotNull();
|
||||
finishDownloadOnlyUpdateAndSendUpdateActionStatus(actionId4, Status.ERROR);
|
||||
|
||||
// actionStatusRepository should have 12 ActionStatusUpdates, 3 from each action
|
||||
assertThat(actionStatusRepository.count()).isEqualTo(12L);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void finishDownloadOnlyUpdateAndSendUpdateActionStatus(final Long actionId, final Status status) {
|
||||
// finishing action
|
||||
controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId)
|
||||
.status(Status.DOWNLOADED));
|
||||
|
||||
controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId)
|
||||
.status(status));
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID))
|
||||
.isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that a controller can report a FINISHED event for a DOWNLOAD_ONLY action after having" +
|
||||
" installed an intermediate update.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 5),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 3),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6) })
|
||||
public void controllerReportsFinishedForOldDownloadOnlyActionAfterSuccessfulForcedAssignment() {
|
||||
|
||||
testdataFactory.createTarget();
|
||||
final DistributionSet downloadOnlyDs = testdataFactory.createDistributionSet("downloadOnlyDs1");
|
||||
|
||||
// assign DOWNLOAD_ONLY Distribution set
|
||||
final Long downloadOnlyActionId = assignDs(downloadOnlyDs.getId(), DEFAULT_CONTROLLER_ID, DOWNLOAD_ONLY);
|
||||
addUpdateActionStatus(downloadOnlyActionId, DEFAULT_CONTROLLER_ID, Status.DOWNLOADED);
|
||||
assertAssignedDistributionSetId(DEFAULT_CONTROLLER_ID, downloadOnlyDs.getId());
|
||||
assertInstalledDistributionSetId(DEFAULT_CONTROLLER_ID, null);
|
||||
assertNoActiveActionsExistsForControllerId(DEFAULT_CONTROLLER_ID);
|
||||
|
||||
// assign distributionSet as FORCED assignment
|
||||
final Long forcedDistributionSetId = testdataFactory.createDistributionSet("forcedDs1").getId();
|
||||
final DistributionSetAssignmentResult assignmentResult =
|
||||
assignDistributionSet(forcedDistributionSetId, DEFAULT_CONTROLLER_ID, Action.ActionType.SOFT);
|
||||
addUpdateActionStatus(assignmentResult.getActions().get(0), DEFAULT_CONTROLLER_ID, Status.FINISHED);
|
||||
assertAssignedDistributionSetId(DEFAULT_CONTROLLER_ID, forcedDistributionSetId);
|
||||
assertInstalledDistributionSetId(DEFAULT_CONTROLLER_ID, forcedDistributionSetId);
|
||||
assertNoActiveActionsExistsForControllerId(DEFAULT_CONTROLLER_ID);
|
||||
|
||||
// report FINISHED for the DOWNLOAD_ONLY action
|
||||
addUpdateActionStatus(downloadOnlyActionId, DEFAULT_CONTROLLER_ID, Status.FINISHED);
|
||||
assertAssignedDistributionSetId(DEFAULT_CONTROLLER_ID, downloadOnlyDs.getId());
|
||||
assertInstalledDistributionSetId(DEFAULT_CONTROLLER_ID, downloadOnlyDs.getId());
|
||||
assertNoActiveActionsExistsForControllerId(DEFAULT_CONTROLLER_ID);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void addUpdateActionStatus(final Long actionId, final String controllerId, final Status actionStatus) {
|
||||
controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(actionStatus));
|
||||
assertActionStatus(actionId, controllerId, TargetUpdateStatus.IN_SYNC, actionStatus, actionStatus, false);
|
||||
}
|
||||
|
||||
private void assertAssignedDistributionSetId(final String controllerId, final Long dsId) {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(controllerId);
|
||||
assertThat(target).isPresent();
|
||||
final DistributionSet assignedDistributionSet = ((JpaTarget) target.get()).getAssignedDistributionSet();
|
||||
assertThat(assignedDistributionSet.getId()).isEqualTo(dsId);
|
||||
}
|
||||
|
||||
private void assertInstalledDistributionSetId(final String controllerId, final Long dsId) {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(controllerId);
|
||||
assertThat(target).isPresent();
|
||||
final DistributionSet installedDistributionSet = ((JpaTarget) target.get()).getInstalledDistributionSet();
|
||||
if(dsId == null){
|
||||
assertThat(installedDistributionSet).isNull();
|
||||
} else {
|
||||
assertThat(installedDistributionSet.getId()).isEqualTo(dsId);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertNoActiveActionsExistsForControllerId(final String controllerId) {
|
||||
assertThat(actionRepository.activeActionExistsForControllerId(controllerId)).isEqualTo(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionProperties;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
@@ -1086,11 +1087,15 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributionSetId()).isEqualTo(ds.getId());
|
||||
|
||||
assertThat(event.getActions()).isEqualTo(targets.stream()
|
||||
.map(target -> deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent())
|
||||
List<Long> eventActionIds = event.getActions().values().stream().map(ActionProperties::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Long> targetActiveActionIds = targets.stream()
|
||||
.map(t -> deploymentManagement.findActiveActionsByTarget(PAGE, t.getControllerId()).getContent())
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.toMap(action -> action.getTarget().getControllerId(), Action::getId)));
|
||||
.map(Action::getId)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(eventActionIds).containsOnlyElementsOf(targetActiveActionIds);
|
||||
}
|
||||
|
||||
private class DeploymentResult {
|
||||
|
||||
@@ -590,6 +590,69 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the targets have the right status during a download_only rollout.")
|
||||
public void countCorrectStatusForEachTargetDuringDownloadOnlyRollout() {
|
||||
|
||||
final int amountTargetsForRollout = 8;
|
||||
final int amountOtherTargets = 15;
|
||||
final int amountGroups = 4;
|
||||
final String successCondition = "50";
|
||||
final String errorCondition = "80";
|
||||
final Rollout createdRollout = createSimpleTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout,
|
||||
amountOtherTargets, amountGroups, successCondition, errorCondition, ActionType.DOWNLOAD_ONLY);
|
||||
|
||||
// targets have not started
|
||||
Map<TotalTargetCountStatus.Status, Long> validationMap = createInitStatusMap();
|
||||
validationMap.put(TotalTargetCountStatus.Status.NOTSTARTED, 8L);
|
||||
validateRolloutActionStatus(createdRollout.getId(), validationMap);
|
||||
|
||||
rolloutManagement.start(createdRollout.getId());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
// 6 targets are ready and 2 are running
|
||||
validationMap = createInitStatusMap();
|
||||
validationMap.put(TotalTargetCountStatus.Status.SCHEDULED, 6L);
|
||||
validationMap.put(TotalTargetCountStatus.Status.RUNNING, 2L);
|
||||
validateRolloutActionStatus(createdRollout.getId(), validationMap);
|
||||
|
||||
changeStatusForAllRunningActions(createdRollout, Status.DOWNLOADED);
|
||||
rolloutManagement.handleRollouts();
|
||||
// 4 targets are ready, 2 are finished(with DOWNLOADED action status) and 2 are running
|
||||
validationMap = createInitStatusMap();
|
||||
validationMap.put(TotalTargetCountStatus.Status.SCHEDULED, 4L);
|
||||
validationMap.put(TotalTargetCountStatus.Status.FINISHED, 2L);
|
||||
validationMap.put(TotalTargetCountStatus.Status.RUNNING, 2L);
|
||||
validateRolloutActionStatus(createdRollout.getId(), validationMap);
|
||||
|
||||
changeStatusForAllRunningActions(createdRollout, Status.DOWNLOADED);
|
||||
rolloutManagement.handleRollouts();
|
||||
// 2 targets are ready, 4 are finished(with DOWNLOADED action status) and 2 are running
|
||||
validationMap = createInitStatusMap();
|
||||
validationMap.put(TotalTargetCountStatus.Status.SCHEDULED, 2L);
|
||||
validationMap.put(TotalTargetCountStatus.Status.FINISHED, 4L);
|
||||
validationMap.put(TotalTargetCountStatus.Status.RUNNING, 2L);
|
||||
validateRolloutActionStatus(createdRollout.getId(), validationMap);
|
||||
|
||||
changeStatusForAllRunningActions(createdRollout, Status.DOWNLOADED);
|
||||
rolloutManagement.handleRollouts();
|
||||
// 0 targets are ready, 6 are finished(with DOWNLOADED action status) and 2 are running
|
||||
validationMap = createInitStatusMap();
|
||||
validationMap.put(TotalTargetCountStatus.Status.FINISHED, 6L);
|
||||
validationMap.put(TotalTargetCountStatus.Status.RUNNING, 2L);
|
||||
validateRolloutActionStatus(createdRollout.getId(), validationMap);
|
||||
|
||||
changeStatusForAllRunningActions(createdRollout, Status.FINISHED);
|
||||
rolloutManagement.handleRollouts();
|
||||
// 0 targets are ready, 6 are finished(with DOWNLOADED action status), 2 are finished and 0 are running
|
||||
validationMap = createInitStatusMap();
|
||||
validationMap.put(TotalTargetCountStatus.Status.FINISHED, 8L);
|
||||
validateRolloutActionStatus(createdRollout.getId(), validationMap);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the targets have the right status during the rollout when an error emerges.")
|
||||
public void countCorrectStatusForEachTargetDuringRolloutWithError() {
|
||||
@@ -1727,12 +1790,19 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
private Rollout createSimpleTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout,
|
||||
final int amountOtherTargets, final int groupSize, final String successCondition,
|
||||
final String errorCondition) {
|
||||
return createSimpleTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout, amountOtherTargets,
|
||||
groupSize, successCondition, errorCondition, ActionType.FORCED);
|
||||
}
|
||||
|
||||
private Rollout createSimpleTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout,
|
||||
final int amountOtherTargets, final int groupSize, final String successCondition,
|
||||
final String errorCondition, final ActionType actionType) {
|
||||
final DistributionSet rolloutDS = testdataFactory.createDistributionSet("rolloutDS");
|
||||
testdataFactory.createTargets(amountTargetsForRollout, "rollout-", "rollout");
|
||||
testdataFactory.createTargets(amountOtherTargets, "others-", "rollout");
|
||||
final String filterQuery = "controllerId==rollout-*";
|
||||
return testdataFactory.createRolloutByVariables("test-rollout-name-1", "test-rollout-description-1", groupSize,
|
||||
filterQuery, rolloutDS, successCondition, errorCondition);
|
||||
filterQuery, rolloutDS, successCondition, errorCondition, actionType);
|
||||
}
|
||||
|
||||
private Rollout createTestRolloutWithTargetsAndDistributionSet(final int amountTargetsForRollout,
|
||||
|
||||
@@ -196,6 +196,8 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
|
||||
|
||||
verifyAutoAssignmentWithSoftActionType(filterName, targetFilterQuery, distributionSet);
|
||||
|
||||
verifyAutoAssignmentWithDownloadOnlyActionType(filterName, targetFilterQuery, distributionSet);
|
||||
|
||||
verifyAutoAssignmentWithInvalidActionType(targetFilterQuery, distributionSet);
|
||||
|
||||
verifyAutoAssignmentWithIncompleteDs(targetFilterQuery);
|
||||
@@ -218,6 +220,14 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
|
||||
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.SOFT);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void verifyAutoAssignmentWithDownloadOnlyActionType(final String filterName,
|
||||
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
|
||||
targetFilterQueryManagement.updateAutoAssignDSWithActionType(targetFilterQuery.getId(), distributionSet.getId(),
|
||||
ActionType.DOWNLOAD_ONLY);
|
||||
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.DOWNLOAD_ONLY);
|
||||
}
|
||||
|
||||
@Step
|
||||
private void verifyAutoAssignmentWithInvalidActionType(final TargetFilterQuery targetFilterQuery,
|
||||
final DistributionSet distributionSet) {
|
||||
|
||||
@@ -211,36 +211,46 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test auto assignment of a distribution set with FORCED and SOFT action types")
|
||||
@Description("Test auto assignment of a distribution set with FORCED, SOFT and DOWNLOAD_ONLY action types")
|
||||
public void checkAutoAssignWithDifferentActionTypes() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
final String targetDsAIdPref = "targA";
|
||||
final String targetDsBIdPref = "targB";
|
||||
final String targetDsAIdPref = "A";
|
||||
final String targetDsBIdPref = "B";
|
||||
final String targetDsCIdPref = "C";
|
||||
|
||||
final List<Target> targetsA = testdataFactory.createTargets(5, targetDsAIdPref,
|
||||
targetDsAIdPref.concat(" description"));
|
||||
final List<Target> targetsB = testdataFactory.createTargets(10, targetDsBIdPref,
|
||||
targetDsBIdPref.concat(" description"));
|
||||
final int targetsCount = targetsA.size() + targetsB.size();
|
||||
List<Target> targetsA = createTargetsAndAutoAssignDistSet(targetDsAIdPref, 5, distributionSet,
|
||||
ActionType.FORCED);
|
||||
List<Target> targetsB = createTargetsAndAutoAssignDistSet(targetDsBIdPref, 10, distributionSet,
|
||||
ActionType.SOFT);
|
||||
List<Target> targetsC = createTargetsAndAutoAssignDistSet(targetDsCIdPref, 10, distributionSet,
|
||||
ActionType.DOWNLOAD_ONLY);
|
||||
|
||||
targetFilterQueryManagement
|
||||
.updateAutoAssignDSWithActionType(
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("filterA")
|
||||
.query("id==" + targetDsAIdPref + "*")).getId(),
|
||||
distributionSet.getId(), ActionType.FORCED);
|
||||
targetFilterQueryManagement
|
||||
.updateAutoAssignDSWithActionType(
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("filterB")
|
||||
.query("id==" + targetDsBIdPref + "*")).getId(),
|
||||
distributionSet.getId(), ActionType.SOFT);
|
||||
final int targetsCount = targetsA.size() + targetsB.size() + targetsC.size();
|
||||
|
||||
autoAssignChecker.check();
|
||||
|
||||
verifyThatTargetsHaveDistributionSetAssignment(distributionSet, targetsA, targetsCount);
|
||||
verifyThatTargetsHaveDistributionSetAssignment(distributionSet, targetsB, targetsCount);
|
||||
verifyThatTargetsHaveDistributionSetAssignment(distributionSet, targetsC, targetsCount);
|
||||
|
||||
verifyThatTargetsHaveAssignmentActionType(ActionType.FORCED, targetsA);
|
||||
verifyThatTargetsHaveAssignmentActionType(ActionType.SOFT, targetsB);
|
||||
verifyThatTargetsHaveAssignmentActionType(ActionType.DOWNLOAD_ONLY, targetsC);
|
||||
}
|
||||
|
||||
@Step
|
||||
private List<Target> createTargetsAndAutoAssignDistSet(final String prefix, final int targetCount,
|
||||
final DistributionSet distributionSet, final ActionType actionType) {
|
||||
|
||||
final List<Target> targets = testdataFactory.createTargets(targetCount, "target" + prefix,
|
||||
prefix.concat(" description"));
|
||||
|
||||
targetFilterQueryManagement
|
||||
.updateAutoAssignDSWithActionType(
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create()
|
||||
.name("filter" + prefix).query("id==target" + prefix + "*")).getId(),
|
||||
distributionSet.getId(), actionType);
|
||||
return targets;
|
||||
}
|
||||
|
||||
@Step
|
||||
|
||||
Reference in New Issue
Block a user