diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java index 5a3825ccb..cb6a1a44f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java @@ -115,7 +115,6 @@ public class JpaRolloutExecutor implements RolloutExecutor { private final RolloutApprovalStrategy rolloutApprovalStrategy; private final RolloutGroupEvaluationManager evaluationManager; private final RolloutManagement rolloutManagement; - private final RepositoryProperties repositoryProperties; /** * Constructor @@ -128,8 +127,7 @@ public JpaRolloutExecutor(final RolloutTargetGroupRepository rolloutTargetGroupR final DeploymentManagement deploymentManagement, final TargetManagement targetManagement, final EventPublisherHolder eventPublisherHolder, final PlatformTransactionManager txManager, final RolloutApprovalStrategy rolloutApprovalStrategy, - final RolloutGroupEvaluationManager evaluationManager, final RolloutManagement rolloutManagement, - final RepositoryProperties repositoryProperties) { + final RolloutGroupEvaluationManager evaluationManager, final RolloutManagement rolloutManagement) { this.rolloutTargetGroupRepository = rolloutTargetGroupRepository; this.entityManager = entityManager; this.rolloutRepository = rolloutRepository; @@ -146,7 +144,6 @@ public JpaRolloutExecutor(final RolloutTargetGroupRepository rolloutTargetGroupR this.rolloutApprovalStrategy = rolloutApprovalStrategy; this.evaluationManager = evaluationManager; this.rolloutManagement = rolloutManagement; - this.repositoryProperties = repositoryProperties; } @Override @@ -341,7 +338,7 @@ private void handleRunningRollout(final JpaRollout rollout) { executeLatestRolloutGroup(rollout); } else { LOGGER.debug("Rollout {} has {} running groups", rollout.getId(), rolloutGroupsRunning.size()); - executeRolloutGroups(rollout, rolloutGroupsRunning); + executeRolloutGroups(rollout, rolloutGroupsRunning, rollout.getRolloutGroups().get(rollout.getRolloutGroups().size() - 1)); } if (isRolloutComplete(rollout)) { @@ -446,7 +443,7 @@ private RolloutGroup evalProxy(final RolloutGroup group, final List rolloutGroups) { + private void executeRolloutGroups(final JpaRollout rollout, final List rolloutGroups, final RolloutGroup lastRolloutGroup) { for (final JpaRolloutGroup rolloutGroup : rolloutGroups) { final long targetCount = countTargetsFrom(rolloutGroup); if (rolloutGroup.getTotalTargets() != targetCount) { @@ -465,7 +462,7 @@ private void executeRolloutGroups(final JpaRollout rollout, final List targets = targetManagement.findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable( pageRequest, - rollout.getId(), rollout.getWeight().orElse(repositoryProperties.getActionWeightIfAbsent()), + rollout.getId(), rollout.getWeight().orElse(1000), // Dynamic rollouts shall always have weight! rolloutGroupRepository.findByRolloutOrderByIdAsc(rollout).get(0).getId(), targetFilter, rollout.getDistributionSet().getType()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java index 905c69afb..6bc1dedb9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java @@ -655,10 +655,11 @@ TargetFilterQueryManagement targetFilterQueryManagement( final VirtualPropertyReplacer virtualPropertyReplacer, final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement, final JpaProperties properties, final TenantConfigurationManagement tenantConfigurationManagement, + final RepositoryProperties repositoryProperties, final SystemSecurityContext systemSecurityContext, final ContextAware contextAware) { return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, targetManagement, virtualPropertyReplacer, distributionSetManagement, quotaManagement, properties.getDatabase(), - tenantConfigurationManagement, systemSecurityContext, contextAware); + tenantConfigurationManagement, repositoryProperties, systemSecurityContext, contextAware); } @@ -749,12 +750,11 @@ RolloutExecutor rolloutExecutor(final RolloutTargetGroupRepository rolloutTarget final DeploymentManagement deploymentManagement, final TargetManagement targetManagement, final EventPublisherHolder eventPublisherHolder, final PlatformTransactionManager txManager, final RolloutApprovalStrategy rolloutApprovalStrategy, - final RolloutGroupEvaluationManager evaluationManager, final RolloutManagement rolloutManagement, - final RepositoryProperties repositoryProperties) { + final RolloutGroupEvaluationManager evaluationManager, final RolloutManagement rolloutManagement) { return new JpaRolloutExecutor(rolloutTargetGroupRepository, entityManager, rolloutRepository, actionRepository, rolloutGroupRepository, afterCommit, tenantAware, rolloutGroupManagement, quotaManagement, deploymentManagement, targetManagement, eventPublisherHolder, txManager, rolloutApprovalStrategy, - evaluationManager, rolloutManagement, repositoryProperties); + evaluationManager, rolloutManagement); } @Bean diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java index 7370810d0..70b5b563f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractDsAssignmentStrategy.java @@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; @@ -67,12 +68,13 @@ public abstract class AbstractDsAssignmentStrategy { private final QuotaManagement quotaManagement; private final BooleanSupplier multiAssignmentsConfig; private final BooleanSupplier confirmationFlowConfig; + private final RepositoryProperties repositoryProperties; AbstractDsAssignmentStrategy(final TargetRepository targetRepository, final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, - final BooleanSupplier confirmationFlowConfig) { + final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { this.targetRepository = targetRepository; this.afterCommit = afterCommit; this.eventPublisherHolder = eventPublisherHolder; @@ -81,6 +83,7 @@ public abstract class AbstractDsAssignmentStrategy { this.quotaManagement = quotaManagement; this.multiAssignmentsConfig = multiAssignmentsConfig; this.confirmationFlowConfig = confirmationFlowConfig; + this.repositoryProperties = repositoryProperties; } /** @@ -252,7 +255,9 @@ public JpaAction createTargetAction(final String initiatedBy, final TargetWithAc final JpaAction actionForTarget = new JpaAction(); actionForTarget.setActionType(targetWithActionType.getActionType()); actionForTarget.setForcedTime(targetWithActionType.getForceTime()); - actionForTarget.setWeight(targetWithActionType.getWeight()); + actionForTarget.setWeight( + targetWithActionType.getWeight() == null ? + repositoryProperties.getActionWeightIfAbsent() : targetWithActionType.getWeight()); actionForTarget.setActive(true); actionForTarget.setTarget(target); actionForTarget.setDistributionSet(set); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index eca4eb209..7e5c17554 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -176,10 +176,10 @@ public JpaDeploymentManagement(final EntityManager entityManager, final ActionRe this.txManager = txManager; onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, eventPublisherHolder, actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled, - this::isConfirmationFlowEnabled); + this::isConfirmationFlowEnabled, repositoryProperties); offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, eventPublisherHolder, actionRepository, actionStatusRepository, quotaManagement, - this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled); + this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties); this.tenantConfigurationManagement = tenantConfigurationManagement; this.systemSecurityContext = systemSecurityContext; this.tenantAware = tenantAware; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index d61398923..c1a6ef97a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -27,6 +27,7 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.QuotaManagement; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RolloutApprovalStrategy; import org.eclipse.hawkbit.repository.RolloutFields; import org.eclipse.hawkbit.repository.RolloutHelper; @@ -110,6 +111,9 @@ public class JpaRolloutManagement implements RolloutManagement { RolloutStatus.CREATING, RolloutStatus.PAUSED, RolloutStatus.READY, RolloutStatus.STARTING, RolloutStatus.WAITING_FOR_APPROVAL, RolloutStatus.APPROVAL_DENIED); + @Autowired + private RepositoryProperties repositoryProperties; + @Autowired private RolloutRepository rolloutRepository; @@ -220,6 +224,9 @@ private JpaRollout createRollout(final JpaRollout rollout) { throw new ValidationException(errMsg); } rollout.setTotalTargets(totalTargets); + if (rollout.getWeight().isEmpty()) { + rollout.setWeight(repositoryProperties.getActionWeightIfAbsent()); + } contextAware.getCurrentContext().ifPresent(rollout::setAccessControlContext); return rolloutRepository.save(rollout); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java index e99395e32..f4ce0d726 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java @@ -17,6 +17,7 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.QuotaManagement; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.TargetFilterQueryFields; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; @@ -84,6 +85,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme private final DistributionSetManagement distributionSetManagement; private final QuotaManagement quotaManagement; private final TenantConfigurationManagement tenantConfigurationManagement; + private final RepositoryProperties repositoryProperties; private final SystemSecurityContext systemSecurityContext; private final ContextAware contextAware; @@ -93,6 +95,7 @@ public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFi final TargetManagement targetManagement, final VirtualPropertyReplacer virtualPropertyReplacer, final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement, final Database database, final TenantConfigurationManagement tenantConfigurationManagement, + final RepositoryProperties repositoryProperties, final SystemSecurityContext systemSecurityContext, final ContextAware contextAware) { this.targetFilterQueryRepository = targetFilterQueryRepository; this.targetManagement = targetManagement; @@ -101,6 +104,7 @@ public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFi this.quotaManagement = quotaManagement; this.database = database; this.tenantConfigurationManagement = tenantConfigurationManagement; + this.repositoryProperties = repositoryProperties; this.systemSecurityContext = systemSecurityContext; this.contextAware = contextAware; } @@ -270,7 +274,7 @@ public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdat targetFilterQuery.setAccessControlContext(null); targetFilterQuery.setAutoAssignDistributionSet(null); targetFilterQuery.setAutoAssignActionType(null); - targetFilterQuery.setAutoAssignWeight(null); + targetFilterQuery.setAutoAssignWeight(0); targetFilterQuery.setAutoAssignInitiatedBy(null); targetFilterQuery.setConfirmationRequired(false); } else { @@ -284,9 +288,11 @@ public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdat contextAware.getCurrentContext().ifPresent(targetFilterQuery::setAccessControlContext); targetFilterQuery.setAutoAssignInitiatedBy(contextAware.getCurrentUsername()); targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType())); - targetFilterQuery.setAutoAssignWeight(update.getWeight()); - final boolean confirmationRequired = update.isConfirmationRequired() == null ? isConfirmationFlowEnabled() - : update.isConfirmationRequired(); + targetFilterQuery.setAutoAssignWeight( + update.getWeight() == null ? repositoryProperties.getActionWeightIfAbsent() : update.getWeight()); + final boolean confirmationRequired = + update.isConfirmationRequired() == null ? + isConfirmationFlowEnabled() : update.isConfirmationRequired(); targetFilterQuery.setConfirmationRequired(confirmationRequired); } return targetFilterQueryRepository.save(targetFilterQuery); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java index 6df9497f0..f7fc19e63 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java @@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; @@ -52,9 +53,9 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, - final BooleanSupplier confirmationFlowConfig) { + final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { super(targetRepository, afterCommit, eventPublisherHolder, actionRepository, actionStatusRepository, - quotaManagement, multiAssignmentsConfig, confirmationFlowConfig); + quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java index aef827234..56cb4a561 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java @@ -19,6 +19,7 @@ import java.util.stream.Stream; import org.eclipse.hawkbit.repository.QuotaManagement; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; @@ -55,9 +56,9 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { final AfterTransactionCommitExecutor afterCommit, final EventPublisherHolder eventPublisherHolder, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig, - final BooleanSupplier confirmationFlowConfig) { + final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties) { super(targetRepository, afterCommit, eventPublisherHolder, actionRepository, actionStatusRepository, - quotaManagement, multiAssignmentsConfig, confirmationFlowConfig); + quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java index 5e456afcf..b97a29600 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java @@ -140,7 +140,7 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event @Max(Action.WEIGHT_MAX) private Integer weight; - @Column(name = "dynamic") + @Column(name = "is_dynamic") // dynamic is reserved keyword in some databases private Boolean dynamic; @Column(name = "access_control_context", nullable = true) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java index 36c1e3fa0..ad6011e10 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java @@ -78,7 +78,7 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr @JoinColumn(name = "parent_id") private JpaRolloutGroup parent; - @Column(name = "dynamic") + @Column(name = "is_dynamic") // dynamic is reserved keyword in some databases private boolean dynamic; @Column(name = "success_condition", nullable = false) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java index 01bb072dc..81d95ca23 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetFilterQuery.java @@ -113,7 +113,7 @@ public JpaTargetFilterQuery(final String name, final String query, final Distrib this.query = query; this.autoAssignDistributionSet = (JpaDistributionSet) autoAssignDistributionSet; this.autoAssignActionType = autoAssignActionType; - this.autoAssignWeight = autoAssignWeight; + this.autoAssignWeight = autoAssignWeight == null ? 0 : autoAssignWeight; this.confirmationRequired = confirmationRequired; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index 18b478c3c..c231d3db8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -634,12 +634,23 @@ public static Specification hasNoActiveActionWithGEWeightOrInRollout( final ListJoin actionsJoin = targetRoot.join(JpaTarget_.actions, JoinType.LEFT); actionsJoin.on( cb.or( - // in rollout - cb.equal(actionsJoin.get(JpaAction_.ROLLOUT).get(JpaRollout_.ID), rolloutId), - // or, active action with ge status + cb.gt(actionsJoin.get(JpaAction_.weight), weight), cb.and( - cb.not(actionsJoin.get(JpaAction_.STATUS).in(Action.Status.FINISHED, Action.Status.ERROR, Action.Status.CANCELED)), - cb.ge(actionsJoin.get(JpaAction_.weight), weight)))); + cb.equal(actionsJoin.get(JpaAction_.weight), weight), + cb.ge(actionsJoin.get(JpaAction_.ROLLOUT).get(JpaRollout_.ID), rolloutId)))); + // another, but probably heavier variant +// actionsJoin.on( +// cb.or( +// // in rollout +// cb.equal(actionsJoin.get(JpaAction_.ROLLOUT).get(JpaRollout_.ID), rolloutId), +// // or, in newer rollout with greater or equal weight +// cb.and( +// cb.gt(actionsJoin.get(JpaAction_.ROLLOUT).get(JpaRollout_.ID), rolloutId), +// cb.ge(actionsJoin.get(JpaAction_.weight), weight)), +// // or, in older with greater status +// cb.and( +// cb.lt(actionsJoin.get(JpaAction_.ROLLOUT).get(JpaRollout_.ID), rolloutId), +// cb.gt(actionsJoin.get(JpaAction_.weight), weight)))); return cb.isNull(actionsJoin.get(JpaAction_.id)); }; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql index a18185bb0..cff85ae84 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_28__add_dynamic_rollout___DB2.sql @@ -1,2 +1,9 @@ -ALTER TABLE sp_rollout ADD COLUMN dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN dynamic BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file +ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; + +UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_action ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight SET NOT NULL; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql index a18185bb0..f392ccd87 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_28__add_dynamic_rollout___H2.sql @@ -1,2 +1,9 @@ -ALTER TABLE sp_rollout ADD COLUMN dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN dynamic BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file +ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; + +UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout ALTER COLUMN weight INT NOT NULL; +ALTER TABLE sp_action ALTER COLUMN weight INT NOT NULL; +ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight INT NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql index a18185bb0..030727a57 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_28__add_dynamic_rollout___MYSQL.sql @@ -1,2 +1,9 @@ -ALTER TABLE sp_rollout ADD COLUMN dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN dynamic BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file +ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; + +UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout MODIFY COLUMN weight INT NOT NULL; +ALTER TABLE sp_action MODIFY COLUMN weight INT NOT NULL; +ALTER TABLE sp_target_filter_query MODIFY COLUMN auto_assign_weight INT NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql index a18185bb0..de6a6f14f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_28__add_dynamic_rollout___POSTGRESQL.sql @@ -1,2 +1,9 @@ -ALTER TABLE sp_rollout ADD COLUMN dynamic BOOLEAN; -ALTER TABLE sp_rolloutgroup ADD COLUMN dynamic BOOLEAN NOT NULL DEFAULT false; \ No newline at end of file +ALTER TABLE sp_rollout ADD COLUMN is_dynamic BOOLEAN; +ALTER TABLE sp_rolloutgroup ADD COLUMN is_dynamic BOOLEAN NOT NULL DEFAULT false; + +UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_action ALTER COLUMN weight SET NOT NULL; +ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight SET NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql index 5ed11f013..a22a7f997 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_28__add_dynamic_rollout___SQL_SERVER.sql @@ -1,2 +1,9 @@ -ALTER TABLE sp_rollout ADD dynamic BIT; -ALTER TABLE sp_rolloutgroup ADD dynamic BIT NOT NULL DEFAULT 0; \ No newline at end of file +ALTER TABLE sp_rollout ADD is_dynamic BIT; +ALTER TABLE sp_rolloutgroup ADD is_dynamic BIT NOT NULL DEFAULT 0; + +UPDATE sp_rollout SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_action SET weight = 1000 WHERE weight IS NULL; +UPDATE sp_target_filter_query SET auto_assign_weight = 1000 WHERE auto_assign_weight IS NULL; +ALTER TABLE sp_rollout ALTER COLUMN weight INT NOT NULL; +ALTER TABLE sp_action ALTER COLUMN weight INT NOT NULL; +ALTER TABLE sp_target_filter_query ALTER COLUMN auto_assign_weight INT NOT NULL; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java index ad88c0f42..eaa3a7494 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/RemoteTenantAwareEventTest.java @@ -106,6 +106,7 @@ public void testTargetAssignDistributionSetEvent() { generateAction.setDistributionSet(dsA); generateAction.setStatus(Status.RUNNING); generateAction.setInitiatedBy(tenantAware.getCurrentUsername()); + generateAction.setWeight(1000); final Action action = actionRepository.save(generateAction); @@ -132,6 +133,7 @@ public void testCancelTargetAssignmentEvent() { generateAction.setDistributionSet(dsA); generateAction.setStatus(Status.RUNNING); generateAction.setInitiatedBy(tenantAware.getCurrentUsername()); + generateAction.setWeight(1000); final Action action = actionRepository.save(generateAction); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java index fd871ca6c..1522cdea9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/ActionEventTest.java @@ -11,6 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import net.bytebuddy.agent.builder.AgentBuilder; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; @@ -86,6 +87,7 @@ protected Action createEntity() { generateAction.setDistributionSet(distributionSet); generateAction.setStatus(Status.RUNNING); generateAction.setInitiatedBy(tenantAware.getCurrentUsername()); + generateAction.setWeight(1000); return actionRepository.save(generateAction); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index 83e862e7d..6784023fa 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -19,6 +19,9 @@ import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.jpa.model.JpaAction; +import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; +import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; @@ -40,6 +43,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.Rollout; +import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; @@ -52,6 +56,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration; +import org.springframework.data.domain.Page; import org.springframework.orm.jpa.vendor.Database; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; @@ -59,6 +64,8 @@ import com.google.common.collect.Lists; +import static org.assertj.core.api.Assertions.assertThat; + @ContextConfiguration(classes = { RepositoryApplicationConfiguration.class, TestConfiguration.class, TestSupportBinderAutoConfiguration.class }) @@ -159,4 +166,42 @@ protected TargetTypeAssignmentResult initiateTypeAssignment(final Collection assertAndGetRunning(final Rollout rollout, final int count) { + final Page running = actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Action.Status.RUNNING); + assertThat(running.getTotalElements()).isEqualTo(count); + return running; + } + + protected void assertScheduled(final Rollout rollout, final int count) { + final Page running = actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Action.Status.SCHEDULED); + assertThat(running.getTotalElements()).isEqualTo(count); + } + + protected void finishAction(final Action action) { + controllerManagement + .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Action.Status.FINISHED)); + } + + private JpaRollout refresh(final Rollout rollout) { + return rolloutRepository.findById(rollout.getId()).get(); + } + + protected JpaRolloutGroup refresh(final RolloutGroup group) { + return rolloutGroupRepository.findById(group.getId()).get(); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java index 322c2bcb6..72fe63161 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java @@ -440,7 +440,7 @@ void filterWithoutWeightWorksInMultiAssignmentMode() throws Exception { final List actions = deploymentManagement.findActionsAll(PAGE).getContent(); assertThat(actions).hasSize(amountOfTargets); - assertThat(actions).allMatch(action -> !action.getWeight().isPresent()); + assertThat(actions).allMatch(action -> action.getWeight().isPresent()); } @Test diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java index b92bdba88..fde6fe3ed 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autocleanup/AutoActionCleanupTest.java @@ -115,15 +115,7 @@ public void canceledAndFailedActionsAreCleanedUp() { assertThat(actionRepository.count()).isEqualTo(3); - final long createTime = System.currentTimeMillis(); - // ensure that autoActionCleanup.run() will be run AFTER action create - while (System.currentTimeMillis() == createTime) { - try { - Thread.sleep(1); - } catch (final InterruptedException e) { - Thread.currentThread().interrupt(); - } - } + waitNextMillis(); autoActionCleanup.run(); assertThat(actionRepository.count()).isEqualTo(1); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java index 35125f7d9..b1e7531f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java @@ -1101,6 +1101,9 @@ public void findMessagesByActionStatusId() { controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) .messages(Lists.newArrayList("proceeding message 1"))); + + final long createTime = System.currentTimeMillis(); + waitNextMillis(); controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId) .status(Action.Status.RUNNING).occurredAt(System.currentTimeMillis()) .messages(Lists.newArrayList("proceeding message 2"))); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java index 8bc891308..22b937624 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementFlowTest.java @@ -14,10 +14,6 @@ import io.qameta.allure.Story; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; -import org.eclipse.hawkbit.repository.jpa.model.JpaAction; -import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; -import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; -import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; @@ -25,7 +21,6 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -207,43 +202,4 @@ void dynamicRolloutFlow() { assertAndGetRunning(rollout, 3); assertGroup(dynamic2, true, RolloutGroupStatus.RUNNING, 2); // assign the target created when paused } - - private void assertRollout(final Rollout rollout, final boolean dynamic, final RolloutStatus status, final int groupCreated, final long totalTargets) { - final Rollout refreshed = refresh(rollout); - assertThat(refreshed.isDynamic()).isEqualTo(dynamic); - assertThat(refreshed.getStatus()).isEqualTo(status); - assertThat(refreshed.getRolloutGroupsCreated()).isEqualTo(groupCreated); - assertThat(refreshed.getTotalTargets()).isEqualTo(totalTargets); - } - - private void assertGroup(final RolloutGroup group, final boolean dynamic, final RolloutGroupStatus status, final long totalTargets) { - final RolloutGroup refreshed = refresh(group); - assertThat(refreshed.isDynamic()).isEqualTo(dynamic); - assertThat(refreshed.getStatus()).isEqualTo(status); - assertThat(refreshed.getTotalTargets()).isEqualTo(totalTargets); - } - - private Page assertAndGetRunning(final Rollout rollout, final int count) { - final Page running = actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Action.Status.RUNNING); - assertThat(running.getTotalElements()).isEqualTo(count); - return running; - } - - private void assertScheduled(final Rollout rollout, final int count) { - final Page running = actionRepository.findByRolloutIdAndStatus(PAGE, rollout.getId(), Action.Status.SCHEDULED); - assertThat(running.getTotalElements()).isEqualTo(count); - } - - private void finishAction(final Action action) { - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Action.Status.FINISHED)); - } - - private JpaRollout refresh(final Rollout rollout) { - return rolloutRepository.findById(rollout.getId()).get(); - } - - private JpaRolloutGroup refresh(final RolloutGroup group) { - return rolloutGroupRepository.findById(group.getId()).get(); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java index 1be1bf65d..b6874b1ab 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java @@ -440,11 +440,6 @@ private void verifyRolloutAndAllGroupsAreFinished(final Rollout createdRollout) } - private void finishAction(final Action action) { - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Status.FINISHED)); - } - @Test @Description("Verifying that the error handling action of a group is executed to pause the current rollout") void checkErrorHitOfGroupCallsErrorActionToPauseTheRollout() { @@ -2027,7 +2022,7 @@ void actionsWithWeightAreCreated() { @Test @Description("Rollout can be created without weight in single assignment and be started in multi assignment") - void createInSingleStartInMultiassigMode() { + void createInSingleStartInMultiassignMode() { final int amountOfTargets = 5; final Long rolloutId = testdataFactory.createSimpleTestRolloutWithTargetsAndDistributionSet(amountOfTargets, 2, amountOfTargets, @@ -2037,7 +2032,8 @@ void createInSingleStartInMultiassigMode() { rolloutManagement.start(rolloutId); rolloutHandler.handleAll(); final List actions = deploymentManagement.findActionsAll(PAGE).getContent(); - assertThat(actions).hasSize(amountOfTargets).allMatch(action -> !action.getWeight().isPresent()); + // wight replaced with default + assertThat(actions).hasSize(5).allMatch(action -> action.getWeight().isPresent()); } @Test @@ -2318,4 +2314,66 @@ void triggeringNextGroupRolloutWrongState() { .isThrownBy(() -> rolloutManagement.triggerNextGroup(createdRollout.getId())) .withMessageContaining(errorMessage); } + + /** + * Tests static assignment aspects of the dynamic group assignment filters. + */ + @Test + @Description("Dynamic group doesn't override newer static group assignments") + public void dynamicGroupDoesntOverrideItsOrNewerStaticGroups() { + final int amountGroups = 1; // static only + final String targetPrefix = "controller-dynamic-rollout-"; + final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds"); + + testdataFactory.createTargets(targetPrefix, 0, amountGroups * 2); + final Rollout dynamicRollout = testdataFactory.createRolloutByVariables("dynamic", "static rollout", amountGroups, + "controllerid==" + targetPrefix + "*", distributionSet, "0", "30", ActionType.FORCED, 1000, false, true); + rolloutManagement.start(dynamicRollout.getId()); + rolloutHandler.handleAll(); + assertRollout(dynamicRollout, true, RolloutStatus.RUNNING, amountGroups + 1, amountGroups * 2); + final List dynamicGroups = rolloutGroupManagement.findByRollout( + new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id")), + dynamicRollout.getId()).getContent(); + for (int i = 0; i < dynamicGroups.size(); i++) { + final RolloutGroup group = dynamicGroups.get(i); + if (i + 1 == dynamicGroups.size()) { + assertGroup(group, true, RolloutGroupStatus.SCHEDULED, 0); + } else { + assertGroup(group, false, RolloutGroupStatus.RUNNING, 2); + } + } + assertAndGetRunning(dynamicRollout, 2).forEach(this::finishAction); + rolloutHandler.handleAll(); + for (int i = 0; i < dynamicGroups.size(); i++) { + final RolloutGroup group = dynamicGroups.get(i); + if (i + 1 == dynamicGroups.size()) { + assertGroup(group, true, RolloutGroupStatus.RUNNING, 0); + } else { + assertGroup(group, false, RolloutGroupStatus.FINISHED, 2); + } + } + assertAndGetRunning(dynamicRollout, 0); + rolloutHandler.handleAll(); + // NB: asserts that dynamic group doesn't get from its static groups (already finished action targets) + assertGroup(dynamicGroups.get(dynamicGroups.size() - 1), true, RolloutGroupStatus.RUNNING, 0); + assertAndGetRunning(dynamicRollout, 0); + rolloutManagement.pauseRollout(dynamicRollout.getId()); + rolloutHandler.handleAll(); + + testdataFactory.createTargets(targetPrefix, amountGroups * 2, amountGroups); + final Rollout staticRollout = testdataFactory.createRolloutByVariables("static", "static rollout", amountGroups, + "controllerid==" + targetPrefix + "*", distributionSet, "0", "30", ActionType.FORCED, 0, false, false); + rolloutManagement.start(staticRollout.getId()); + rolloutHandler.handleAll(); + assertRollout(staticRollout, false, RolloutStatus.RUNNING, amountGroups, amountGroups * 3); + final List staticGroups = rolloutGroupManagement.findByRollout( + new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id")), + staticRollout.getId()).getContent(); + staticGroups.forEach(group -> assertGroup(group, false, RolloutGroupStatus.RUNNING, 3)); + + rolloutManagement.resumeRollout(dynamicRollout.getId()); + rolloutHandler.handleAll(); // resume, do not get last devices (they are assigned to a newer group, nevertheless newer is with bigger weight + assertGroup(dynamicGroups.get(dynamicGroups.size() - 1), true, RolloutGroupStatus.RUNNING, 0); + assertAndGetRunning(dynamicRollout, 0); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java index e774d2c9a..fc5097775 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java @@ -54,6 +54,7 @@ import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; +import org.eclipse.hawkbit.repository.jpa.model.JpaAction_; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata; import org.eclipse.hawkbit.repository.model.Action; @@ -1331,77 +1332,37 @@ void matchesFilterTargetNotExists() { "name==*")).isFalse(); } + /** + * Tests action based aspects of the dynamic group assignment filters. + */ @Test @Description("Target matches filter no active action with ge weight.") void findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable() { final String targetPrefix = "dyn_action_filter_"; final DistributionSet distributionSet = testdataFactory.createDistributionSet(); - final List targets = testdataFactory.createTargets(targetPrefix, 10); + final List targets = testdataFactory.createTargets(targetPrefix, 9); + final Rollout rolloutOlder = testdataFactory.createRollout(); final Rollout rollout = testdataFactory.createRollout(); - for (int i = 0; i < targets.size(); i++) { - final Target target = targets.get(i); - JpaAction action = new JpaAction(); - action.setActionType(Action.ActionType.FORCED); - action.setTarget(target); - action.setInitiatedBy("test"); - action.setDistributionSet(distributionSet); - switch (i % 3) { - case 0: { - action.setStatus(Status.FINISHED); - action.setWeight(100); - if (i == 6) { // for 6th device that otherwise match action condition - add it already in rollout - action.setRollout(rollout); - } - break; - } - case 1: { - action.setStatus(Status.ERROR); - action.setWeight(100); - break; - } - default: { - action.setStatus(Status.CANCELED); - action.setWeight(100); - break; - } - } - actionRepository.save(action); - - action = new JpaAction(); - action.setActionType(Action.ActionType.FORCED); - action.setTarget(target); - action.setInitiatedBy("test"); - action.setDistributionSet(distributionSet); - action.setStatus(Status.RUNNING); - - switch (i % 5) { - case 0: { - action.setStatus(Status.DOWNLOADED); - action.setWeight(1); - break; - } - case 1: { - action.setStatus(Status.WAIT_FOR_CONFIRMATION); - break; - } - case 2: { - action.setStatus(Status.SCHEDULED); - action.setWeight(10); - break; - } - case 3: { - action.setStatus(Status.RUNNING); - action.setWeight(100); - break; - } - default: { - action.setStatus(Status.RUNNING); - action.setWeight(3); - break; - } - } - actionRepository.save(action); - } + final Rollout rolloutNewer = testdataFactory.createRollout(); + + // old ro with less weight - match + createAction(targets.get(0), rolloutOlder, 0, Status.RUNNING, distributionSet); + // old ro with less weight - match + createAction(targets.get(1), rolloutOlder, 5, Status.SCHEDULED, distributionSet); + // old ro with equal weight - match + createAction(targets.get(2), rolloutOlder, 10, Status.RUNNING, distributionSet); + // old ro with BIGGER weight - doesn't match + createAction(targets.get(3), rolloutOlder, 20, Status.WAIT_FOR_CONFIRMATION, distributionSet); + // same ro - doesn't match + createAction(targets.get(4), rollout, 10, Status.RUNNING, distributionSet); + // new ro with less weight - match + createAction(targets.get(5), rolloutNewer, 0, Status.RUNNING, distributionSet); + // new ro with less weight - match + createAction(targets.get(6), rolloutNewer, 5, Status.WARNING, distributionSet); + // NEW ro with EQUAL weight - doesn't match + createAction(targets.get(7), rolloutNewer, 10, Status.RUNNING, distributionSet); + // new ro with BIGGER weight - doesn't match + createAction(targets.get(8), rolloutNewer, 20, Status.DOWNLOADED, distributionSet); final Slice matching = targetManagement.findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable( PAGE, rollout.getId(), 10, Long.MAX_VALUE,"controllerid==dyn_action_filter_*", distributionSet.getType()); @@ -1412,7 +1373,22 @@ void findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQue .map(s -> s.substring(targetPrefix.length())) .map(Integer::parseInt) .sorted() - .toList()).isEqualTo(List.of(0, 1, 4, 5, 9)); + .toList()).isEqualTo(List.of(0, 1, 2, 5, 6)); + } + private void createAction(final Target target, final Rollout rollout, final Integer weight, final Action.Status status, final DistributionSet distributionSet) { + final JpaAction action = new JpaAction(); + action.setActionType(Action.ActionType.FORCED); + action.setTarget(target); + action.setInitiatedBy("test"); + if (rollout != null) { + action.setRollout(rollout); + } + if (weight != null) { + action.setWeight(weight); + } + action.setStatus(status); + action.setDistributionSet(distributionSet); + actionRepository.save(action); } @Test diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 84ca4d9bf..1b79887ce 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -513,4 +513,15 @@ protected boolean isConfirmationFlowEnabled() { .getConfigurationValue(TenantConfigurationKey.USER_CONFIRMATION_ENABLED, Boolean.class).getValue(); } + // ensure that next action will get current time millis AFTER got from the previous + protected void waitNextMillis() { + final long createTime = System.currentTimeMillis(); + while (System.currentTimeMillis() == createTime) { + try { + Thread.sleep(1); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java index 7ed3d683d..47555db64 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java @@ -79,6 +79,7 @@ static MgmtRolloutResponseBody toResponseRollout(final Rollout rollout, final bo body.setLastModifiedBy(rollout.getLastModifiedBy()); body.setName(rollout.getName()); body.setRolloutId(rollout.getId()); + body.setDynamic(rollout.isDynamic()); body.setTargetFilterQuery(rollout.getTargetFilterQuery()); body.setDistributionSetId(rollout.getDistributionSet().getId()); body.setStatus(rollout.getStatus().toString().toLowerCase()); @@ -126,6 +127,7 @@ static RolloutCreate fromRequest(final EntityFactory entityFactory, final MgmtRo final DistributionSet distributionSet) { return entityFactory.rollout().create().name(restRequest.getName()).description(restRequest.getDescription()) + .dynamic(restRequest.isDynamic()) .set(distributionSet).targetFilterQuery(restRequest.getTargetFilterQuery()) .actionType(MgmtRestModelMapper.convertActionType(restRequest.getType())) .forcedTime(restRequest.getForcetime()).startAt(restRequest.getStartAt()) diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java index 8f21237bc..29ef464f4 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java @@ -2196,28 +2196,17 @@ void getActionWeight() throws Exception { final Long dsId = testdataFactory.createDistributionSet().getId(); final int customWeightHigh = 800; final int customWeightLow = 300; - assignDistributionSet(dsId, targetId); + assignDistributionSet(dsId, targetId); // default weight 1000 enableMultiAssignments(); assignDistributionSet(dsId, targetId, customWeightHigh); assignDistributionSet(dsId, targetId, customWeightLow); - // POSTGRESQL sets null values at the end, not the beginning - if (Database.POSTGRESQL.equals(jpaProperties.getDatabase())) { - mvc.perform(get("/rest/v1/targets/{targetId}/actions", targetId) - .param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "WEIGHT:ASC")) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(jsonPath("content.[0].weight", equalTo(customWeightLow))) - .andExpect(jsonPath("content.[1].weight", equalTo(customWeightHigh))) - .andExpect(jsonPath("content.[2].weight").doesNotExist()); - } else { - mvc.perform(get("/rest/v1/targets/{targetId}/actions", targetId) - .param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "WEIGHT:ASC")) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(jsonPath("content.[0].weight").doesNotExist()) - .andExpect(jsonPath("content.[1].weight", equalTo(customWeightLow))) - .andExpect(jsonPath("content.[2].weight", equalTo(customWeightHigh))); - } - + mvc.perform(get("/rest/v1/targets/{targetId}/actions", targetId) + .param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "WEIGHT:ASC")) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(jsonPath("content.[0].weight", equalTo(customWeightLow))) + .andExpect(jsonPath("content.[1].weight", equalTo(customWeightHigh))) + .andExpect(jsonPath("content.[2].weight", equalTo(1000))); } @Test diff --git a/hawkbit-sdk/spring-shell.log b/hawkbit-sdk/spring-shell.log new file mode 100644 index 000000000..a2871c187 --- /dev/null +++ b/hawkbit-sdk/spring-shell.log @@ -0,0 +1,18 @@ +1705138557487:start -prefix test_ -off 1 -count 10 +1705138578110:start prefix test_ off 1 count 10 +1705138661865:exit +1705138735828:start --prefix test_ --off 1 --count 10 +1705138745752:start -prefix test_ --off 1 --count 10 +1705138749380:start prefix test_ --off 1 --count 10 +1705139324442:start +1705139394677:start --count 10 +1705139500993:startOne +1705139527630:startMany --prefix test_ --offset 1 --count 10 +1705139644181:start-many --predix test_ --off 1 --count 10 +1705139652849:start-many --prefix test_ --off 1 --count 10 +1705141055480:start-many --prefix test_ --off 11 --count 10 +1705141191878:start-many --prefix test_ --off 21 --count 10 +1705158272217:start-many --prefix test_ --off 0 --count 1 +1705160009780:start-many --prefix test_ --off 1 --count 40 +1705160159903:start-many --prefix test_ --off 1 --count 10 +1705160175922:start-many --prefix test- --off 1 --count 10