Skip to content

Commit

Permalink
added triggeredBy for rollouts and autoassignment (eclipse-hawkbit#1017)
Browse files Browse the repository at this point in the history
* added triggeredBy for rollouts and autoassignment

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* use createdBy as fallback for triggeredBy in AutoAssignChecker

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* removed 'NOT NULL' from db migration scripts for JpaTargetFilterQuery

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* fixed tests

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* fixed review findings

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* inlined redundant method in JpaDeploymentManagement

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* added tests + renamed property to 'initiatedBy'

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>

* fixed review findings

Signed-off-by: Ahmed Sayed <ahmed.sayed@bosch-si.com>
  • Loading branch information
a-sayyed authored and krishna-devolo committed Sep 23, 2021
1 parent 40f5278 commit b77d41b
Show file tree
Hide file tree
Showing 27 changed files with 174 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public interface TenantAware {
*/
String getCurrentTenant();

/**
* @return the username of the currently logged-in user
*/
String getCurrentUsername();

/**
* Gives the possibility to run a certain code under a specific given
* {@code tenant}. Only the given {@link TenantRunner} is executed under the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ public interface DeploymentManagement {
*
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
List<DistributionSetAssignmentResult> assignDistributionSets(
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests);
List<DistributionSetAssignmentResult> assignDistributionSets(@Valid @NotEmpty List<DeploymentRequest> deploymentRequests);

/**
* Assigns {@link DistributionSet}s to {@link Target}s according to the
* {@link DeploymentRequest}.
*
* @param initiatedBy
* the username of the user who initiated the assignment
* @param deploymentRequests
* information about all target-ds-assignments that shall be made
* @param actionMessage
Expand All @@ -107,7 +108,7 @@ List<DistributionSetAssignmentResult> assignDistributionSets(
*
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
List<DistributionSetAssignmentResult> assignDistributionSets(
List<DistributionSetAssignmentResult> assignDistributionSets(String initiatedBy,
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests, String actionMessage);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ default boolean isCancelingOrCanceled() {
*/
String getExternalRef();

/**
* @return the username that initiated this action (directly or indirectly)
*/
String getInitiatedBy();

/**
* checks if the {@link #getForcedTime()} is hit by the given
* {@code hitTimeMillis}, by means if the given milliseconds are greater
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
*/
String getQuery();

/**
* Setter for query
* @param query {@link String}
*/
void setQuery(String query);

/**
* @return the auto assign {@link DistributionSet} if given.
*/
Expand All @@ -82,4 +76,9 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
* assignment.
*/
Optional<Integer> getAutoAssignWeight();

/**
* @return the user that triggered the auto assignment
*/
String getAutoAssignInitiatedBy();
}
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ void cancelAssignDistributionSetEvent(final Target target, final Long actionId)
new CancelTargetAssignmentEvent(target, actionId, eventPublisherHolder.getApplicationId())));
}

JpaAction createTargetAction(final TargetWithActionType targetWithActionType, final List<JpaTarget> targets,
final JpaDistributionSet set) {
JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType,
final List<JpaTarget> targets, final JpaDistributionSet set) {
final Optional<JpaTarget> optTarget = targets.stream()
.filter(t -> t.getControllerId().equals(targetWithActionType.getControllerId())).findFirst();

Expand All @@ -226,6 +226,7 @@ JpaAction createTargetAction(final TargetWithActionType targetWithActionType, fi
actionForTarget.setMaintenanceWindowSchedule(targetWithActionType.getMaintenanceSchedule());
actionForTarget.setMaintenanceWindowDuration(targetWithActionType.getMaintenanceWindowDuration());
actionForTarget.setMaintenanceWindowTimeZone(targetWithActionType.getMaintenanceWindowTimeZone());
actionForTarget.setInitiatedBy(initiatedBy);
return actionForTarget;
}).orElseGet(() -> {
LOG.warn("Cannot find target for targetWithActionType '{}'.", targetWithActionType.getControllerId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,52 +182,34 @@ public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build())
.collect(Collectors.toList());

return assignDistributionSets(deploymentRequests, null, offlineDsAssignmentStrategy);
}

@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
public DistributionSetAssignmentResult assignDistributionSet(Target target,
DeploymentRequest deploymentRequest, String actionMessage){
return assignDistributionSet(target, deploymentRequest, actionMessage, onlineDsAssignmentStrategy);
}

private DistributionSetAssignmentResult assignDistributionSet(Target target,
final DeploymentRequest deploymentRequest,
final String actionMessage, AbstractDsAssignmentStrategy strategy) {

DistributionSetAssignmentResult result = assignDistributionSetToSingleTargetWithRetry(target,
deploymentRequest.getDistributionSetId(), deploymentRequest.getTargetWithActionType(),
actionMessage, onlineDsAssignmentStrategy);

strategy.sendDeploymentEvents(result);
return result;
return assignDistributionSets(tenantAware.getCurrentUsername(), deploymentRequests, null,
offlineDsAssignmentStrategy);
}

@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
public List<DistributionSetAssignmentResult> assignDistributionSets(
final List<DeploymentRequest> deploymentRequests) {
return assignDistributionSets(deploymentRequests, null);
return assignDistributionSets(tenantAware.getCurrentUsername(), deploymentRequests, null);
}

@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
public List<DistributionSetAssignmentResult> assignDistributionSets(
public List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
.validate(deploymentRequests);
return assignDistributionSets(deploymentRequests, actionMessage, onlineDsAssignmentStrategy);
return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy);
}

private List<DistributionSetAssignmentResult> assignDistributionSets(
private List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
final List<DeploymentRequest> deploymentRequests, final String actionMessage,
final AbstractDsAssignmentStrategy strategy) {
final List<DeploymentRequest> validatedRequests = validateRequestForAssignments(deploymentRequests);
final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests);

final List<DistributionSetAssignmentResult> results = assignmentsByDsIds.entrySet().stream()
.map(entry -> assignDistributionSetToTargetsWithRetry(entry.getKey(), entry.getValue(), actionMessage,
.map(entry -> assignDistributionSetToTargetsWithRetry(initiatedBy, entry.getKey(), entry.getValue(), actionMessage,
strategy))
.collect(Collectors.toList());
strategy.sendDeploymentEvents(results);
Expand Down Expand Up @@ -257,19 +239,11 @@ private static void checkIfRequiresMultiAssignment(final Collection<DeploymentRe
}
}

private DistributionSetAssignmentResult assignDistributionSetToSingleTargetWithRetry(Target target, final Long dsID,
final TargetWithActionType targetWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) {
final RetryCallback<DistributionSetAssignmentResult, ConcurrencyFailureException> retryCallback = retryContext -> assignDistributionSetToSingleTarget(
target, dsID, targetWithActionType, actionMessage, assignmentStrategy);
return retryTemplate.execute(retryCallback);
}

private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final Long dsID,
private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final String initiatedBy, final Long dsID,
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) {
final RetryCallback<DistributionSetAssignmentResult, ConcurrencyFailureException> retryCallback = retryContext -> assignDistributionSetToTargets(
dsID, targetsWithActionType, actionMessage, assignmentStrategy);
initiatedBy, dsID, targetsWithActionType, actionMessage, assignmentStrategy);
return retryTemplate.execute(retryCallback);
}

Expand All @@ -287,6 +261,8 @@ private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(
* status to {@link TargetUpdateStatus#IN_SYNC} <br/>
* D. does not send a {@link TargetAssignDistributionSetEvent}.<br/>
*
* @param initiatedBy
* the username of the user who initiated the assignment
* @param dsID
* the ID of the distribution set to assign
* @param targetsWithActionType
Expand All @@ -301,7 +277,7 @@ private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(
* {@link SoftwareModuleType} are not assigned as define by the
* {@link DistributionSetType}.
*/
private DistributionSetAssignmentResult assignDistributionSetToTargets(final Long dsID,
private DistributionSetAssignmentResult assignDistributionSetToTargets(final String initiatedBy, final Long dsID,
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) {

Expand All @@ -323,26 +299,12 @@ private DistributionSetAssignmentResult assignDistributionSetToTargets(final Lon
final List<TargetWithActionType> existingTargetsWithActionType = targetsWithActionType.stream()
.filter(target -> existingTargetIds.contains(target.getControllerId())).collect(Collectors.toList());

final List<JpaAction> assignedActions = doAssignDistributionSetToTargets(existingTargetsWithActionType,
actionMessage, assignmentStrategy, distributionSetEntity, targetEntities);
final List<JpaAction> assignedActions = doAssignDistributionSetToTargets(initiatedBy,
existingTargetsWithActionType, actionMessage, assignmentStrategy, distributionSetEntity,
targetEntities);
return buildAssignmentResult(distributionSetEntity, assignedActions, existingTargetsWithActionType.size());
}

private DistributionSetAssignmentResult assignDistributionSetToSingleTarget(Target target, final Long dsID,
final TargetWithActionType targetWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) {

final JpaDistributionSet distributionSet = getAndValidateDsById(dsID);

if(assignmentStrategy.actionHistoryContainsAssignment(target, distributionSet))
return allTargetsAlreadyAssignedResult(distributionSet, 1);

final List<JpaAction> assignedActions = doAssignDistributionSetToSingleTarget(targetWithActionType,
actionMessage, assignmentStrategy, distributionSet, target);

return buildAssignmentResult(distributionSet, assignedActions, 1);
}

private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult(
final JpaDistributionSet distributionSetEntity, final int alreadyAssignedCount) {
// detaching as it is not necessary to persist the set itself
Expand All @@ -352,29 +314,7 @@ private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult(
Collections.emptyList());
}

private List<JpaAction> doAssignDistributionSetToSingleTarget(TargetWithActionType targetWithActionType,
String actionMessage, AbstractDsAssignmentStrategy strategy, JpaDistributionSet distributionSet, Target target){

// skip this check for performance, since multiAssignment is never used
// if (!isMultiAssignmentsEnabled())
closeOrCancelActiveActions(strategy, target.getId());

cancelInactiveScheduledActionsForTargets(Collections.singletonList(target.getId()));

setAssignedDistributionSetAndTargetUpdateStatus(strategy, distributionSet, target.getId());

final List<JpaAction> assignedActions = createActions(
Collections.singletonList(targetWithActionType),
Collections.singletonList((JpaTarget)target),
strategy, distributionSet);

createActionsStatus(assignedActions, strategy, actionMessage);

detachEntitiesAndSendTargetUpdatedEvents(distributionSet, Collections.singletonList((JpaTarget) target), strategy);
return assignedActions;
}

private List<JpaAction> doAssignDistributionSetToTargets(
private List<JpaAction> doAssignDistributionSetToTargets(final String initiatedBy,
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy, final JpaDistributionSet distributionSetEntity,
final List<JpaTarget> targetEntities) {
Expand All @@ -389,8 +329,8 @@ private List<JpaAction> doAssignDistributionSetToTargets(
targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets);
setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity,
targetEntitiesIdsChunks);
final List<JpaAction> assignedActions = createActions(targetsWithActionType, targetEntities, assignmentStrategy,
distributionSetEntity);
final List<JpaAction> assignedActions = createActions(initiatedBy, targetsWithActionType, targetEntities,
assignmentStrategy, distributionSetEntity);
// create initial action status when action is created so we remember
// the initial running status because we will change the status
// of the action itself and with this action status we have a nicer
Expand Down Expand Up @@ -454,15 +394,6 @@ private void enforceMaxActionsPerTarget(final Collection<DeploymentRequest> depl
quota, Action.class, Target.class, actionRepository::countByTargetControllerId));
}

private void closeOrCancelActiveActions(final AbstractDsAssignmentStrategy assignmentStrategy,
final Long targetId) {
if (isActionsAutocloseEnabled()) {
assignmentStrategy.closeActiveActions(targetId);
} else {
assignmentStrategy.cancelActiveActions(targetId);
}
}

private void closeOrCancelActiveActions(final AbstractDsAssignmentStrategy assignmentStrategy,
final List<List<Long>> targetIdsChunks) {
if (isActionsAutocloseEnabled()) {
Expand All @@ -484,24 +415,21 @@ public void cancelInactiveScheduledActionsForTargets(final List<Long> targetIds)
}
}

private void setAssignedDistributionSetAndTargetUpdateStatus(final AbstractDsAssignmentStrategy assignmentStrategy,
final DistributionSet set, final Long targetId) {
final String currentUser = auditorProvider.getCurrentAuditor().orElse(null);
assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetId, currentUser);
}

private void setAssignedDistributionSetAndTargetUpdateStatus(final AbstractDsAssignmentStrategy assignmentStrategy,
final JpaDistributionSet set, final List<List<Long>> targetIdsChunks) {
final String currentUser = auditorProvider.getCurrentAuditor().orElse(null);
assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetIdsChunks, currentUser);
}

private List<JpaAction> createActions(final Collection<TargetWithActionType> targetsWithActionType,
final List<JpaTarget> targets, final AbstractDsAssignmentStrategy assignmentStrategy,
final JpaDistributionSet set) {
private List<JpaAction> createActions(final String initiatedBy,
final Collection<TargetWithActionType> targetsWithActionType, final List<JpaTarget> targets,
final AbstractDsAssignmentStrategy assignmentStrategy, final JpaDistributionSet set) {

return targetsWithActionType.stream().map(twt -> assignmentStrategy.createTargetAction(twt, targets, set))
.filter(Objects::nonNull).map(actionRepository::save).collect(Collectors.toList());
return targetsWithActionType.stream()
.map(twt -> assignmentStrategy.createTargetAction(initiatedBy, twt, targets, set))
.filter(Objects::nonNull)
.map(actionRepository::save)
.collect(Collectors.toList());
}

private void createActionsStatus(final Collection<JpaAction> actions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ private void createScheduledAction(final Collection<Target> targets, final Distr
action.setStatus(Status.SCHEDULED);
action.setRollout(rollout);
action.setRolloutGroup(rolloutGroup);
action.setInitiatedBy(rollout.getCreatedBy());
rollout.getWeight().ifPresent(action::setWeight);
actionRepository.save(action);
});
Expand Down
Loading

0 comments on commit b77d41b

Please sign in to comment.