Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added triggeredBy for rollouts and autoassignment #1017

Merged
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 @@ -77,4 +77,8 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
*/
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 @@ -201,8 +201,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 @@ -219,6 +219,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,33 +182,34 @@ public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build())
.collect(Collectors.toList());

return assignDistributionSets(deploymentRequests, null, offlineDsAssignmentStrategy);
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 @@ -238,11 +239,11 @@ private static void checkIfRequiresMultiAssignment(final Collection<DeploymentRe
}
}

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 @@ -260,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 @@ -274,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 @@ -296,8 +299,9 @@ 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());
}

Expand All @@ -310,7 +314,7 @@ private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult(
Collections.emptyList());
}

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 @@ -325,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 @@ -417,12 +421,15 @@ private void setAssignedDistributionSetAndTargetUpdateStatus(final AbstractDsAss
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
import org.eclipse.hawkbit.repository.jpa.utils.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -74,14 +74,15 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
private final QuotaManagement quotaManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final SystemSecurityContext systemSecurityContext;
private final TenantAware tenantAware;

private final Database database;

JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFilterQueryRepository,
final TargetRepository targetRepository, final VirtualPropertyReplacer virtualPropertyReplacer,
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
final Database database, final TenantConfigurationManagement tenantConfigurationManagement,
final SystemSecurityContext systemSecurityContext) {
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware) {
this.targetFilterQueryRepository = targetFilterQueryRepository;
this.targetRepository = targetRepository;
this.virtualPropertyReplacer = virtualPropertyReplacer;
Expand All @@ -90,6 +91,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
this.database = database;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.systemSecurityContext = systemSecurityContext;
this.tenantAware = tenantAware;
}

@Override
Expand Down Expand Up @@ -240,6 +242,7 @@ public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdat
targetFilterQuery.setAutoAssignDistributionSet(null);
targetFilterQuery.setAutoAssignActionType(null);
targetFilterQuery.setAutoAssignWeight(null);
targetFilterQuery.setAutoAssignInitiatedBy(null);
} else {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update);
// we cannot be sure that the quota was enforced at creation time
Expand All @@ -250,6 +253,7 @@ public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdat
final JpaDistributionSet ds = findDistributionSetAndThrowExceptionIfNotFound(update.getDsId());
verifyDistributionSetAndThrowExceptionIfNotValid(ds);
targetFilterQuery.setAutoAssignDistributionSet(ds);
targetFilterQuery.setAutoAssignInitiatedBy(tenantAware.getCurrentUsername());
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType()));
targetFilterQuery.setAutoAssignWeight(update.getWeight());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet set, fin
}

@Override
protected JpaAction createTargetAction(final TargetWithActionType targetWithActionType,
protected JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType,
final List<JpaTarget> targets, final JpaDistributionSet set) {
final JpaAction result = super.createTargetAction(targetWithActionType, targets, set);
final JpaAction result = super.createTargetAction(initiatedBy, targetWithActionType, targets, set);
if (result != null) {
result.setStatus(Status.FINISHED);
result.setActive(Boolean.FALSE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet set, fin
}

@Override
JpaAction createTargetAction(final TargetWithActionType targetWithActionType, final List<JpaTarget> targets,
final JpaDistributionSet set) {
final JpaAction result = super.createTargetAction(targetWithActionType, targets, set);
JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType,
final List<JpaTarget> targets, final JpaDistributionSet set) {
final JpaAction result = super.createTargetAction(initiatedBy, targetWithActionType, targets, set);
if (result != null) {
result.setStatus(Status.RUNNING);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ TargetManagement targetManagement(final EntityManager entityManager, final Quota
* to access quotas
* @param properties
* JPA properties
* @param tenantAware
* the {@link TenantAware} bean holding the tenant information
*
* @return a new {@link TargetFilterQueryManagement}
*/
Expand All @@ -543,10 +545,10 @@ TargetFilterQueryManagement targetFilterQueryManagement(
final VirtualPropertyReplacer virtualPropertyReplacer,
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
final JpaProperties properties, final TenantConfigurationManagement tenantConfigurationManagement,
final SystemSecurityContext systemSecurityContext) {
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware) {
return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, targetRepository,
virtualPropertyReplacer, distributionSetManagement, quotaManagement, properties.getDatabase(),
tenantConfigurationManagement, systemSecurityContext);
tenantConfigurationManagement, systemSecurityContext, tenantAware);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
* Checks if targets need a new distribution set (DS) based on the target filter
Expand Down Expand Up @@ -146,12 +147,19 @@ private int runTransactionalAssignment(final TargetFilterQuery targetFilterQuery
targetFilterQuery.getAutoAssignWeight().orElse(null), PAGE_SIZE);
final int count = deploymentRequests.size();
if (count > 0) {
deploymentManagement.assignDistributionSets(deploymentRequests, actionMessage);
deploymentManagement.assignDistributionSets(getAutoAssignmentInitiatedBy(targetFilterQuery),
deploymentRequests, actionMessage);
}
return count;
});
}

private static String getAutoAssignmentInitiatedBy(final TargetFilterQuery targetFilterQuery) {
return StringUtils.isEmpty(targetFilterQuery.getAutoAssignInitiatedBy()) ?
targetFilterQuery.getCreatedBy() :
targetFilterQuery.getAutoAssignInitiatedBy();
}

/**
* Gets all matching targets with the designated action from the target
* management
Expand Down
Loading