added triggeredBy for rollouts and autoassignment (#1017)
* 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>
This commit is contained in:
@@ -21,6 +21,11 @@ public interface TenantAware {
|
|||||||
*/
|
*/
|
||||||
String getCurrentTenant();
|
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
|
* Gives the possibility to run a certain code under a specific given
|
||||||
* {@code tenant}. Only the given {@link TenantRunner} is executed under the
|
* {@code tenant}. Only the given {@link TenantRunner} is executed under the
|
||||||
|
|||||||
@@ -76,13 +76,14 @@ public interface DeploymentManagement {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||||
List<DistributionSetAssignmentResult> assignDistributionSets(
|
List<DistributionSetAssignmentResult> assignDistributionSets(@Valid @NotEmpty List<DeploymentRequest> deploymentRequests);
|
||||||
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns {@link DistributionSet}s to {@link Target}s according to the
|
* Assigns {@link DistributionSet}s to {@link Target}s according to the
|
||||||
* {@link DeploymentRequest}.
|
* {@link DeploymentRequest}.
|
||||||
*
|
*
|
||||||
|
* @param initiatedBy
|
||||||
|
* the username of the user who initiated the assignment
|
||||||
* @param deploymentRequests
|
* @param deploymentRequests
|
||||||
* information about all target-ds-assignments that shall be made
|
* information about all target-ds-assignments that shall be made
|
||||||
* @param actionMessage
|
* @param actionMessage
|
||||||
@@ -107,7 +108,7 @@ public interface DeploymentManagement {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||||
List<DistributionSetAssignmentResult> assignDistributionSets(
|
List<DistributionSetAssignmentResult> assignDistributionSets(String initiatedBy,
|
||||||
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests, String actionMessage);
|
@Valid @NotEmpty List<DeploymentRequest> deploymentRequests, String actionMessage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ public interface Action extends TenantAwareBaseEntity {
|
|||||||
*/
|
*/
|
||||||
String getExternalRef();
|
String getExternalRef();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the username that initiated this action (directly or indirectly)
|
||||||
|
*/
|
||||||
|
String getInitiatedBy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checks if the {@link #getForcedTime()} is hit by the given
|
* checks if the {@link #getForcedTime()} is hit by the given
|
||||||
* {@code hitTimeMillis}, by means if the given milliseconds are greater
|
* {@code hitTimeMillis}, by means if the given milliseconds are greater
|
||||||
|
|||||||
@@ -77,4 +77,8 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
|
|||||||
*/
|
*/
|
||||||
Optional<Integer> getAutoAssignWeight();
|
Optional<Integer> getAutoAssignWeight();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the user that triggered the auto assignment
|
||||||
|
*/
|
||||||
|
String getAutoAssignInitiatedBy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,8 +201,8 @@ public abstract class AbstractDsAssignmentStrategy {
|
|||||||
new CancelTargetAssignmentEvent(target, actionId, eventPublisherHolder.getApplicationId())));
|
new CancelTargetAssignmentEvent(target, actionId, eventPublisherHolder.getApplicationId())));
|
||||||
}
|
}
|
||||||
|
|
||||||
JpaAction createTargetAction(final TargetWithActionType targetWithActionType, final List<JpaTarget> targets,
|
JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType,
|
||||||
final JpaDistributionSet set) {
|
final List<JpaTarget> targets, final JpaDistributionSet set) {
|
||||||
final Optional<JpaTarget> optTarget = targets.stream()
|
final Optional<JpaTarget> optTarget = targets.stream()
|
||||||
.filter(t -> t.getControllerId().equals(targetWithActionType.getControllerId())).findFirst();
|
.filter(t -> t.getControllerId().equals(targetWithActionType.getControllerId())).findFirst();
|
||||||
|
|
||||||
@@ -219,6 +219,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
|||||||
actionForTarget.setMaintenanceWindowSchedule(targetWithActionType.getMaintenanceSchedule());
|
actionForTarget.setMaintenanceWindowSchedule(targetWithActionType.getMaintenanceSchedule());
|
||||||
actionForTarget.setMaintenanceWindowDuration(targetWithActionType.getMaintenanceWindowDuration());
|
actionForTarget.setMaintenanceWindowDuration(targetWithActionType.getMaintenanceWindowDuration());
|
||||||
actionForTarget.setMaintenanceWindowTimeZone(targetWithActionType.getMaintenanceWindowTimeZone());
|
actionForTarget.setMaintenanceWindowTimeZone(targetWithActionType.getMaintenanceWindowTimeZone());
|
||||||
|
actionForTarget.setInitiatedBy(initiatedBy);
|
||||||
return actionForTarget;
|
return actionForTarget;
|
||||||
}).orElseGet(() -> {
|
}).orElseGet(() -> {
|
||||||
LOG.warn("Cannot find target for targetWithActionType '{}'.", targetWithActionType.getControllerId());
|
LOG.warn("Cannot find target for targetWithActionType '{}'.", targetWithActionType.getControllerId());
|
||||||
|
|||||||
@@ -182,33 +182,34 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build())
|
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
return assignDistributionSets(deploymentRequests, null, offlineDsAssignmentStrategy);
|
return assignDistributionSets(tenantAware.getCurrentUsername(), deploymentRequests, null,
|
||||||
|
offlineDsAssignmentStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
public List<DistributionSetAssignmentResult> assignDistributionSets(
|
public List<DistributionSetAssignmentResult> assignDistributionSets(
|
||||||
final List<DeploymentRequest> deploymentRequests) {
|
final List<DeploymentRequest> deploymentRequests) {
|
||||||
return assignDistributionSets(deploymentRequests, null);
|
return assignDistributionSets(tenantAware.getCurrentUsername(), deploymentRequests, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
public List<DistributionSetAssignmentResult> assignDistributionSets(
|
public List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
|
||||||
final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
|
final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
|
||||||
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
|
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
|
||||||
.validate(deploymentRequests);
|
.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 List<DeploymentRequest> deploymentRequests, final String actionMessage,
|
||||||
final AbstractDsAssignmentStrategy strategy) {
|
final AbstractDsAssignmentStrategy strategy) {
|
||||||
final List<DeploymentRequest> validatedRequests = validateRequestForAssignments(deploymentRequests);
|
final List<DeploymentRequest> validatedRequests = validateRequestForAssignments(deploymentRequests);
|
||||||
final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests);
|
final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests);
|
||||||
|
|
||||||
final List<DistributionSetAssignmentResult> results = assignmentsByDsIds.entrySet().stream()
|
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))
|
strategy))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
strategy.sendDeploymentEvents(results);
|
strategy.sendDeploymentEvents(results);
|
||||||
@@ -238,11 +239,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final Long dsID,
|
private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final String initiatedBy, final Long dsID,
|
||||||
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
||||||
final AbstractDsAssignmentStrategy assignmentStrategy) {
|
final AbstractDsAssignmentStrategy assignmentStrategy) {
|
||||||
final RetryCallback<DistributionSetAssignmentResult, ConcurrencyFailureException> retryCallback = retryContext -> assignDistributionSetToTargets(
|
final RetryCallback<DistributionSetAssignmentResult, ConcurrencyFailureException> retryCallback = retryContext -> assignDistributionSetToTargets(
|
||||||
dsID, targetsWithActionType, actionMessage, assignmentStrategy);
|
initiatedBy, dsID, targetsWithActionType, actionMessage, assignmentStrategy);
|
||||||
return retryTemplate.execute(retryCallback);
|
return retryTemplate.execute(retryCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +261,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
* status to {@link TargetUpdateStatus#IN_SYNC} <br/>
|
* status to {@link TargetUpdateStatus#IN_SYNC} <br/>
|
||||||
* D. does not send a {@link TargetAssignDistributionSetEvent}.<br/>
|
* D. does not send a {@link TargetAssignDistributionSetEvent}.<br/>
|
||||||
*
|
*
|
||||||
|
* @param initiatedBy
|
||||||
|
* the username of the user who initiated the assignment
|
||||||
* @param dsID
|
* @param dsID
|
||||||
* the ID of the distribution set to assign
|
* the ID of the distribution set to assign
|
||||||
* @param targetsWithActionType
|
* @param targetsWithActionType
|
||||||
@@ -274,7 +277,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
* {@link SoftwareModuleType} are not assigned as define by the
|
* {@link SoftwareModuleType} are not assigned as define by the
|
||||||
* {@link DistributionSetType}.
|
* {@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 Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
||||||
final AbstractDsAssignmentStrategy assignmentStrategy) {
|
final AbstractDsAssignmentStrategy assignmentStrategy) {
|
||||||
|
|
||||||
@@ -296,8 +299,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
final List<TargetWithActionType> existingTargetsWithActionType = targetsWithActionType.stream()
|
final List<TargetWithActionType> existingTargetsWithActionType = targetsWithActionType.stream()
|
||||||
.filter(target -> existingTargetIds.contains(target.getControllerId())).collect(Collectors.toList());
|
.filter(target -> existingTargetIds.contains(target.getControllerId())).collect(Collectors.toList());
|
||||||
|
|
||||||
final List<JpaAction> assignedActions = doAssignDistributionSetToTargets(existingTargetsWithActionType,
|
final List<JpaAction> assignedActions = doAssignDistributionSetToTargets(initiatedBy,
|
||||||
actionMessage, assignmentStrategy, distributionSetEntity, targetEntities);
|
existingTargetsWithActionType, actionMessage, assignmentStrategy, distributionSetEntity,
|
||||||
|
targetEntities);
|
||||||
return buildAssignmentResult(distributionSetEntity, assignedActions, existingTargetsWithActionType.size());
|
return buildAssignmentResult(distributionSetEntity, assignedActions, existingTargetsWithActionType.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +314,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
Collections.emptyList());
|
Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<JpaAction> doAssignDistributionSetToTargets(
|
private List<JpaAction> doAssignDistributionSetToTargets(final String initiatedBy,
|
||||||
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
||||||
final AbstractDsAssignmentStrategy assignmentStrategy, final JpaDistributionSet distributionSetEntity,
|
final AbstractDsAssignmentStrategy assignmentStrategy, final JpaDistributionSet distributionSetEntity,
|
||||||
final List<JpaTarget> targetEntities) {
|
final List<JpaTarget> targetEntities) {
|
||||||
@@ -325,8 +329,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets);
|
targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets);
|
||||||
setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity,
|
setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity,
|
||||||
targetEntitiesIdsChunks);
|
targetEntitiesIdsChunks);
|
||||||
final List<JpaAction> assignedActions = createActions(targetsWithActionType, targetEntities, assignmentStrategy,
|
final List<JpaAction> assignedActions = createActions(initiatedBy, targetsWithActionType, targetEntities,
|
||||||
distributionSetEntity);
|
assignmentStrategy, distributionSetEntity);
|
||||||
// create initial action status when action is created so we remember
|
// create initial action status when action is created so we remember
|
||||||
// the initial running status because we will change the status
|
// the initial running status because we will change the status
|
||||||
// of the action itself and with this action status we have a nicer
|
// of the action itself and with this action status we have a nicer
|
||||||
@@ -417,12 +421,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetIdsChunks, currentUser);
|
assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetIdsChunks, currentUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<JpaAction> createActions(final Collection<TargetWithActionType> targetsWithActionType,
|
private List<JpaAction> createActions(final String initiatedBy,
|
||||||
final List<JpaTarget> targets, final AbstractDsAssignmentStrategy assignmentStrategy,
|
final Collection<TargetWithActionType> targetsWithActionType, final List<JpaTarget> targets,
|
||||||
final JpaDistributionSet set) {
|
final AbstractDsAssignmentStrategy assignmentStrategy, final JpaDistributionSet set) {
|
||||||
|
|
||||||
return targetsWithActionType.stream().map(twt -> assignmentStrategy.createTargetAction(twt, targets, set))
|
return targetsWithActionType.stream()
|
||||||
.filter(Objects::nonNull).map(actionRepository::save).collect(Collectors.toList());
|
.map(twt -> assignmentStrategy.createTargetAction(initiatedBy, twt, targets, set))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(actionRepository::save)
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createActionsStatus(final Collection<JpaAction> actions,
|
private void createActionsStatus(final Collection<JpaAction> actions,
|
||||||
|
|||||||
@@ -624,6 +624,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
action.setStatus(Status.SCHEDULED);
|
action.setStatus(Status.SCHEDULED);
|
||||||
action.setRollout(rollout);
|
action.setRollout(rollout);
|
||||||
action.setRolloutGroup(rolloutGroup);
|
action.setRolloutGroup(rolloutGroup);
|
||||||
|
action.setInitiatedBy(rollout.getCreatedBy());
|
||||||
rollout.getWeight().ifPresent(action::setWeight);
|
rollout.getWeight().ifPresent(action::setWeight);
|
||||||
actionRepository.save(action);
|
actionRepository.save(action);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
|
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
|
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.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
@@ -74,6 +74,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
private final QuotaManagement quotaManagement;
|
private final QuotaManagement quotaManagement;
|
||||||
private final TenantConfigurationManagement tenantConfigurationManagement;
|
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||||
private final SystemSecurityContext systemSecurityContext;
|
private final SystemSecurityContext systemSecurityContext;
|
||||||
|
private final TenantAware tenantAware;
|
||||||
|
|
||||||
private final Database database;
|
private final Database database;
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
final TargetRepository targetRepository, final VirtualPropertyReplacer virtualPropertyReplacer,
|
final TargetRepository targetRepository, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||||
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||||
final Database database, final TenantConfigurationManagement tenantConfigurationManagement,
|
final Database database, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
final SystemSecurityContext systemSecurityContext) {
|
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware) {
|
||||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||||
this.targetRepository = targetRepository;
|
this.targetRepository = targetRepository;
|
||||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||||
@@ -90,6 +91,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
this.database = database;
|
this.database = database;
|
||||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||||
this.systemSecurityContext = systemSecurityContext;
|
this.systemSecurityContext = systemSecurityContext;
|
||||||
|
this.tenantAware = tenantAware;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -240,6 +242,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
targetFilterQuery.setAutoAssignDistributionSet(null);
|
targetFilterQuery.setAutoAssignDistributionSet(null);
|
||||||
targetFilterQuery.setAutoAssignActionType(null);
|
targetFilterQuery.setAutoAssignActionType(null);
|
||||||
targetFilterQuery.setAutoAssignWeight(null);
|
targetFilterQuery.setAutoAssignWeight(null);
|
||||||
|
targetFilterQuery.setAutoAssignInitiatedBy(null);
|
||||||
} else {
|
} else {
|
||||||
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update);
|
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update);
|
||||||
// we cannot be sure that the quota was enforced at creation time
|
// we cannot be sure that the quota was enforced at creation time
|
||||||
@@ -250,6 +253,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
final JpaDistributionSet ds = findDistributionSetAndThrowExceptionIfNotFound(update.getDsId());
|
final JpaDistributionSet ds = findDistributionSetAndThrowExceptionIfNotFound(update.getDsId());
|
||||||
verifyDistributionSetAndThrowExceptionIfNotValid(ds);
|
verifyDistributionSetAndThrowExceptionIfNotValid(ds);
|
||||||
targetFilterQuery.setAutoAssignDistributionSet(ds);
|
targetFilterQuery.setAutoAssignDistributionSet(ds);
|
||||||
|
targetFilterQuery.setAutoAssignInitiatedBy(tenantAware.getCurrentUsername());
|
||||||
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType()));
|
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType()));
|
||||||
targetFilterQuery.setAutoAssignWeight(update.getWeight());
|
targetFilterQuery.setAutoAssignWeight(update.getWeight());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected JpaAction createTargetAction(final TargetWithActionType targetWithActionType,
|
protected JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType,
|
||||||
final List<JpaTarget> targets, final JpaDistributionSet set) {
|
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) {
|
if (result != null) {
|
||||||
result.setStatus(Status.FINISHED);
|
result.setStatus(Status.FINISHED);
|
||||||
result.setActive(Boolean.FALSE);
|
result.setActive(Boolean.FALSE);
|
||||||
|
|||||||
@@ -127,9 +127,9 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
JpaAction createTargetAction(final TargetWithActionType targetWithActionType, final List<JpaTarget> targets,
|
JpaAction createTargetAction(final String initiatedBy, final TargetWithActionType targetWithActionType,
|
||||||
final JpaDistributionSet set) {
|
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) {
|
if (result != null) {
|
||||||
result.setStatus(Status.RUNNING);
|
result.setStatus(Status.RUNNING);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -533,6 +533,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
* to access quotas
|
* to access quotas
|
||||||
* @param properties
|
* @param properties
|
||||||
* JPA properties
|
* JPA properties
|
||||||
|
* @param tenantAware
|
||||||
|
* the {@link TenantAware} bean holding the tenant information
|
||||||
*
|
*
|
||||||
* @return a new {@link TargetFilterQueryManagement}
|
* @return a new {@link TargetFilterQueryManagement}
|
||||||
*/
|
*/
|
||||||
@@ -543,10 +545,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||||
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||||
final JpaProperties properties, final TenantConfigurationManagement tenantConfigurationManagement,
|
final JpaProperties properties, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
final SystemSecurityContext systemSecurityContext) {
|
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware) {
|
||||||
return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, targetRepository,
|
return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, targetRepository,
|
||||||
virtualPropertyReplacer, distributionSetManagement, quotaManagement, properties.getDatabase(),
|
virtualPropertyReplacer, distributionSetManagement, quotaManagement, properties.getDatabase(),
|
||||||
tenantConfigurationManagement, systemSecurityContext);
|
tenantConfigurationManagement, systemSecurityContext, tenantAware);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.springframework.transaction.PlatformTransactionManager;
|
|||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
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
|
* Checks if targets need a new distribution set (DS) based on the target filter
|
||||||
@@ -146,12 +147,19 @@ public class AutoAssignChecker implements AutoAssignExecutor {
|
|||||||
targetFilterQuery.getAutoAssignWeight().orElse(null), PAGE_SIZE);
|
targetFilterQuery.getAutoAssignWeight().orElse(null), PAGE_SIZE);
|
||||||
final int count = deploymentRequests.size();
|
final int count = deploymentRequests.size();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
deploymentManagement.assignDistributionSets(deploymentRequests, actionMessage);
|
deploymentManagement.assignDistributionSets(getAutoAssignmentInitiatedBy(targetFilterQuery),
|
||||||
|
deploymentRequests, actionMessage);
|
||||||
}
|
}
|
||||||
return count;
|
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
|
* Gets all matching targets with the designated action from the target
|
||||||
* management
|
* management
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
@EntityListeners({ AuditingEntityListener.class, EntityPropertyChangeListener.class, EntityInterceptorListener.class })
|
@EntityListeners({ AuditingEntityListener.class, EntityPropertyChangeListener.class, EntityInterceptorListener.class })
|
||||||
public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
protected static final int USERNAME_FIELD_LENGTH = 64;
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@@ -67,7 +68,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Access(AccessType.PROPERTY)
|
@Access(AccessType.PROPERTY)
|
||||||
@Column(name = "created_by", insertable = true, updatable = false, nullable = false, length = 64)
|
@Column(name = "created_by", insertable = true, updatable = false, nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||||
public String getCreatedBy() {
|
public String getCreatedBy() {
|
||||||
return createdBy;
|
return createdBy;
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Access(AccessType.PROPERTY)
|
@Access(AccessType.PROPERTY)
|
||||||
@Column(name = "last_modified_by", insertable = true, updatable = true, nullable = false, length = 64)
|
@Column(name = "last_modified_by", insertable = true, updatable = true, nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||||
public String getLastModifiedBy() {
|
public String getLastModifiedBy() {
|
||||||
return lastModifiedBy;
|
return lastModifiedBy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,9 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
|||||||
@Column(name = "external_ref", length = Action.EXTERNAL_REF_MAX_LENGTH)
|
@Column(name = "external_ref", length = Action.EXTERNAL_REF_MAX_LENGTH)
|
||||||
private String externalRef;
|
private String externalRef;
|
||||||
|
|
||||||
|
@Column(name = "initiated_by", updatable = false, nullable = false, length = USERNAME_FIELD_LENGTH)
|
||||||
|
private String initiatedBy;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DistributionSet getDistributionSet() {
|
public DistributionSet getDistributionSet() {
|
||||||
return distributionSet;
|
return distributionSet;
|
||||||
@@ -363,4 +366,13 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
|||||||
public String getExternalRef() {
|
public String getExternalRef() {
|
||||||
return externalRef;
|
return externalRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInitiatedBy(final String initiatedBy) {
|
||||||
|
this.initiatedBy = initiatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInitiatedBy() {
|
||||||
|
return initiatedBy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity
|
|||||||
@Column(name = "auto_assign_weight", nullable = true)
|
@Column(name = "auto_assign_weight", nullable = true)
|
||||||
private Integer autoAssignWeight;
|
private Integer autoAssignWeight;
|
||||||
|
|
||||||
|
@Column(name = "auto_assign_initiated_by", nullable = true, length = USERNAME_FIELD_LENGTH)
|
||||||
|
private String autoAssignInitiatedBy;
|
||||||
|
|
||||||
public JpaTargetFilterQuery() {
|
public JpaTargetFilterQuery() {
|
||||||
// Default constructor for JPA.
|
// Default constructor for JPA.
|
||||||
}
|
}
|
||||||
@@ -149,6 +152,14 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity
|
|||||||
this.autoAssignWeight = weight;
|
this.autoAssignWeight = weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAutoAssignInitiatedBy() {
|
||||||
|
return autoAssignInitiatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoAssignInitiatedBy(final String autoAssignInitiatedBy) {
|
||||||
|
this.autoAssignInitiatedBy = autoAssignInitiatedBy;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(
|
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE sp_action ADD COLUMN initiated_by VARCHAR(64) NOT NULL;
|
||||||
|
ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_initiated_by VARCHAR(64);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE sp_action ADD COLUMN initiated_by VARCHAR(64) NOT NULL;
|
||||||
|
ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_initiated_by VARCHAR(64);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE sp_action ADD COLUMN initiated_by VARCHAR(64) NOT NULL;
|
||||||
|
ALTER TABLE sp_target_filter_query ADD COLUMN auto_assign_initiated_by VARCHAR(64);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE sp_action
|
||||||
|
ADD COLUMN initiated_by VARCHAR (64) NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE sp_target_filter_query
|
||||||
|
ADD COLUMN auto_assign_initiated_by VARCHAR (64);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE sp_action ADD initiated_by VARCHAR(64) NOT NULL;
|
||||||
|
ALTER TABLE sp_target_filter_query ADD auto_assign_initiated_by VARCHAR(64);
|
||||||
@@ -104,6 +104,7 @@ public class RemoteTenantAwareEventTest extends AbstractRemoteEventTest {
|
|||||||
generateAction.setTarget(testdataFactory.createTarget("Test"));
|
generateAction.setTarget(testdataFactory.createTarget("Test"));
|
||||||
generateAction.setDistributionSet(dsA);
|
generateAction.setDistributionSet(dsA);
|
||||||
generateAction.setStatus(Status.RUNNING);
|
generateAction.setStatus(Status.RUNNING);
|
||||||
|
generateAction.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||||
|
|
||||||
final Action action = actionRepository.save(generateAction);
|
final Action action = actionRepository.save(generateAction);
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public class ActionEventTest extends AbstractRemoteEntityEventTest<Action> {
|
|||||||
generateAction.setTarget(target);
|
generateAction.setTarget(target);
|
||||||
generateAction.setDistributionSet(distributionSet);
|
generateAction.setDistributionSet(distributionSet);
|
||||||
generateAction.setStatus(Status.RUNNING);
|
generateAction.setStatus(Status.RUNNING);
|
||||||
|
generateAction.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||||
return actionRepository.save(generateAction);
|
return actionRepository.save(generateAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -480,7 +480,9 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
assertThat(actionRepository.count()).isEqualTo(20);
|
assertThat(actionRepository.count()).isEqualTo(20);
|
||||||
assertThat(actionRepository.findByDistributionSetId(PAGE, ds.getId())).as("Offline actions are not active")
|
assertThat(actionRepository.findByDistributionSetId(PAGE, ds.getId())).as("Offline actions are not active")
|
||||||
.allMatch(action -> !action.isActive());
|
.allMatch(action -> !action.isActive())
|
||||||
|
.as("Actions should be initiated by current user")
|
||||||
|
.allMatch(a -> a.getInitiatedBy().equals(tenantAware.getCurrentUsername()));
|
||||||
|
|
||||||
assertThat(targetManagement.findByInstalledDistributionSet(PAGE, ds.getId()).getContent())
|
assertThat(targetManagement.findByInstalledDistributionSet(PAGE, ds.getId()).getContent())
|
||||||
.usingElementComparator(controllerIdComparator()).containsAll(targets).hasSize(10)
|
.usingElementComparator(controllerIdComparator()).containsAll(targets).hasSize(10)
|
||||||
@@ -514,6 +516,8 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(getResultingActionCount(assignmentResults)).isEqualTo(4);
|
assertThat(getResultingActionCount(assignmentResults)).isEqualTo(4);
|
||||||
targetIds.forEach(controllerId -> {
|
targetIds.forEach(controllerId -> {
|
||||||
final List<Long> assignedDsIds = actionRepository.findByTargetControllerId(PAGE, controllerId).stream()
|
final List<Long> assignedDsIds = actionRepository.findByTargetControllerId(PAGE, controllerId).stream()
|
||||||
|
.peek(a -> assertThat(a.getInitiatedBy()).as("Actions should be initiated by current user")
|
||||||
|
.isEqualTo(tenantAware.getCurrentUsername()))
|
||||||
.map(action -> action.getDistributionSet().getId()).collect(Collectors.toList());
|
.map(action -> action.getDistributionSet().getId()).collect(Collectors.toList());
|
||||||
assertThat(assignedDsIds).containsExactlyInAnyOrderElementsOf(dsIds);
|
assertThat(assignedDsIds).containsExactlyInAnyOrderElementsOf(dsIds);
|
||||||
});
|
});
|
||||||
@@ -587,10 +591,12 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
private void assertDsExclusivelyAssignedToTargets(final List<Target> targets, final long dsId, final boolean active,
|
private void assertDsExclusivelyAssignedToTargets(final List<Target> targets, final long dsId, final boolean active,
|
||||||
final Status status) {
|
final Status status) {
|
||||||
final List<Action> assignment = actionRepository.findByDistributionSetId(PAGE, dsId).getContent();
|
final List<Action> assignment = actionRepository.findByDistributionSetId(PAGE, dsId).getContent();
|
||||||
|
final String currentUsername = tenantAware.getCurrentUsername();
|
||||||
|
|
||||||
assertThat(assignment).hasSize(10).allMatch(action -> action.isActive() == active)
|
assertThat(assignment).hasSize(10).allMatch(action -> action.isActive() == active)
|
||||||
.as("Is assigned to DS " + dsId).allMatch(action -> action.getDistributionSet().getId().equals(dsId))
|
.as("Is assigned to DS " + dsId).allMatch(action -> action.getDistributionSet().getId().equals(dsId))
|
||||||
.as("State is " + status).allMatch(action -> action.getStatus() == status);
|
.as("State is " + status).allMatch(action -> action.getStatus() == status)
|
||||||
|
.as("Initiated by " + currentUsername).allMatch(a -> a.getInitiatedBy().equals(currentUsername));
|
||||||
final long[] targetIds = targets.stream().mapToLong(Target::getId).toArray();
|
final long[] targetIds = targets.stream().mapToLong(Target::getId).toArray();
|
||||||
assertThat(targetIds).as("All targets represented in assignment").containsExactlyInAnyOrder(
|
assertThat(targetIds).as("All targets represented in assignment").containsExactlyInAnyOrder(
|
||||||
assignment.stream().mapToLong(action -> action.getTarget().getId()).toArray());
|
assignment.stream().mapToLong(action -> action.getTarget().getId()).toArray());
|
||||||
@@ -617,7 +623,10 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
final List<Long> dsIds = distributionSets.stream().map(DistributionSet::getId).collect(Collectors.toList());
|
final List<Long> dsIds = distributionSets.stream().map(DistributionSet::getId).collect(Collectors.toList());
|
||||||
targets.forEach(target -> {
|
targets.forEach(target -> {
|
||||||
final List<Long> assignedDsIds = actionRepository.findByTargetControllerId(PAGE, target.getControllerId())
|
final List<Long> assignedDsIds = actionRepository.findByTargetControllerId(PAGE, target.getControllerId())
|
||||||
.stream().map(action -> action.getDistributionSet().getId()).collect(Collectors.toList());
|
.stream()
|
||||||
|
.peek(a -> assertThat(a.getInitiatedBy()).as("Initiated by current user")
|
||||||
|
.isEqualTo(tenantAware.getCurrentUsername()))
|
||||||
|
.map(action -> action.getDistributionSet().getId()).collect(Collectors.toList());
|
||||||
assertThat(assignedDsIds).containsExactlyInAnyOrderElementsOf(dsIds);
|
assertThat(assignedDsIds).containsExactlyInAnyOrderElementsOf(dsIds);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -647,6 +656,8 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
targets.forEach(target -> {
|
targets.forEach(target -> {
|
||||||
actionRepository.findByTargetControllerId(PAGE, target.getControllerId()).forEach(action -> {
|
actionRepository.findByTargetControllerId(PAGE, target.getControllerId()).forEach(action -> {
|
||||||
assertThat(action.getDistributionSet().getId()).isIn(dsIds);
|
assertThat(action.getDistributionSet().getId()).isIn(dsIds);
|
||||||
|
assertThat(action.getInitiatedBy()).as("Should be Initiated by current user")
|
||||||
|
.isEqualTo(tenantAware.getCurrentUsername());
|
||||||
deploymentManagement.cancelAction(action.getId());
|
deploymentManagement.cancelAction(action.getId());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -851,7 +862,10 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assignDistributionSet(ds, savedDeployedTargets);
|
assignDistributionSet(ds, savedDeployedTargets);
|
||||||
|
|
||||||
// verify that one Action for each assignDistributionSet
|
// verify that one Action for each assignDistributionSet
|
||||||
assertThat(actionRepository.findAll(PAGE).getNumberOfElements()).as("wrong size of actions").isEqualTo(20);
|
final Page<JpaAction> actions = actionRepository.findAll(PAGE);
|
||||||
|
assertThat(actions.getNumberOfElements()).as("wrong size of actions").isEqualTo(20);
|
||||||
|
assertThat(actions).as("Actions should be initiated by current user")
|
||||||
|
.allMatch(a -> a.getInitiatedBy().equals(tenantAware.getCurrentUsername()));
|
||||||
|
|
||||||
final Iterable<Target> allFoundTargets = targetManagement.findAll(PAGE).getContent();
|
final Iterable<Target> allFoundTargets = targetManagement.findAll(PAGE).getContent();
|
||||||
|
|
||||||
@@ -945,6 +959,8 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
// retrieving all Actions created by the assignDistributionSet call
|
// retrieving all Actions created by the assignDistributionSet call
|
||||||
final Page<JpaAction> page = actionRepository.findAll(PAGE);
|
final Page<JpaAction> page = actionRepository.findAll(PAGE);
|
||||||
|
assertThat(page).as("Actions should be initiated by current user")
|
||||||
|
.allMatch(a -> a.getInitiatedBy().equals(tenantAware.getCurrentUsername()));
|
||||||
// and verify the number
|
// and verify the number
|
||||||
assertThat(page.getTotalElements()).as("wrong size of actions")
|
assertThat(page.getTotalElements()).as("wrong size of actions")
|
||||||
.isEqualTo(noOfDeployedTargets * noOfDistributionSets);
|
.isEqualTo(noOfDeployedTargets * noOfDistributionSets);
|
||||||
|
|||||||
@@ -252,6 +252,8 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
// running
|
// running
|
||||||
final List<Action> runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING);
|
final List<Action> runningActions = findActionsByRolloutAndStatus(createdRollout, Status.RUNNING);
|
||||||
assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups);
|
assertThat(runningActions).hasSize(amountTargetsForRollout / amountGroups);
|
||||||
|
assertThat(runningActions).as("Created actions are initiated by rollout creator")
|
||||||
|
.allMatch(a -> a.getInitiatedBy().equals(createdRollout.getCreatedBy()));
|
||||||
// the rest targets are only scheduled
|
// the rest targets are only scheduled
|
||||||
assertThat(findActionsByRolloutAndStatus(createdRollout, Status.SCHEDULED))
|
assertThat(findActionsByRolloutAndStatus(createdRollout, Status.SCHEDULED))
|
||||||
.hasSize(amountTargetsForRollout - (amountTargetsForRollout / amountGroups));
|
.hasSize(amountTargetsForRollout - (amountTargetsForRollout / amountGroups));
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.ActionRepository;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
@@ -26,6 +28,7 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
|||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
import io.qameta.allure.Description;
|
||||||
@@ -44,6 +47,9 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AutoAssignChecker autoAssignChecker;
|
private AutoAssignChecker autoAssignChecker;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ActionRepository actionRepository;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies that a running action is auto canceled by a AutoAssignment which assigns another distribution-set.")
|
@Description("Verifies that a running action is auto canceled by a AutoAssignment which assigns another distribution-set.")
|
||||||
public void autoAssignDistributionSetAndAutoCloseOldActions() {
|
public void autoAssignDistributionSetAndAutoCloseOldActions() {
|
||||||
@@ -99,10 +105,11 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
|||||||
final DistributionSet setB = testdataFactory.createDistributionSet("dsB");
|
final DistributionSet setB = testdataFactory.createDistributionSet("dsB");
|
||||||
|
|
||||||
// target filter query that matches all targets
|
// target filter query that matches all targets
|
||||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
|
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(
|
||||||
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*"));
|
entityFactory.targetFilterQuery()
|
||||||
targetFilterQueryManagement.updateAutoAssignDS(
|
.updateAutoAssign(targetFilterQueryManagement.create(
|
||||||
entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(setA.getId()));
|
entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
|
||||||
|
.ds(setA.getId()));
|
||||||
|
|
||||||
final String targetDsAIdPref = "targ";
|
final String targetDsAIdPref = "targ";
|
||||||
final List<Target> targets = testdataFactory.createTargets(100, targetDsAIdPref,
|
final List<Target> targets = testdataFactory.createTargets(100, targetDsAIdPref,
|
||||||
@@ -134,6 +141,7 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
|||||||
// first 5 should keep their dsB, because they already had the dsA once
|
// first 5 should keep their dsB, because they already had the dsA once
|
||||||
verifyThatTargetsHaveDistributionSetAssignment(setB, targets.subList(0, 5), targetsCount);
|
verifyThatTargetsHaveDistributionSetAssignment(setB, targets.subList(0, 5), targetsCount);
|
||||||
|
|
||||||
|
verifyThatCreatedActionsAreInitiatedByCurrentUser(targetFilterQuery, setA, targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -208,6 +216,18 @@ public class AutoAssignCheckerTest extends AbstractJpaIntegrationTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void verifyThatCreatedActionsAreInitiatedByCurrentUser(final TargetFilterQuery targetFilterQuery,
|
||||||
|
final DistributionSet distributionSet, final List<Target> targets) {
|
||||||
|
final Set<String> targetIds = targets.stream().map(Target::getControllerId).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
actionRepository.findByDistributionSetId(Pageable.unpaged(), distributionSet.getId())
|
||||||
|
.stream().filter(a -> targetIds.contains(a.getTarget().getControllerId()))
|
||||||
|
.forEach(a -> assertThat(a.getInitiatedBy()).as(
|
||||||
|
"Action should be initiated by the user who initiated the auto assignment")
|
||||||
|
.isEqualTo(targetFilterQuery.getAutoAssignInitiatedBy()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test auto assignment of a distribution set with FORCED, SOFT and DOWNLOAD_ONLY action types")
|
@Description("Test auto assignment of a distribution set with FORCED, SOFT and DOWNLOAD_ONLY action types")
|
||||||
public void checkAutoAssignWithDifferentActionTypes() {
|
public void checkAutoAssignWithDifferentActionTypes() {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest {
|
|||||||
action.setTarget(target);
|
action.setTarget(target);
|
||||||
action.setStatus(Status.RUNNING);
|
action.setStatus(Status.RUNNING);
|
||||||
action.setWeight(45);
|
action.setWeight(45);
|
||||||
|
action.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||||
target.addAction(action);
|
target.addAction(action);
|
||||||
|
|
||||||
actionRepository.save(action);
|
actionRepository.save(action);
|
||||||
@@ -58,6 +59,7 @@ public class RSQLActionFieldsTest extends AbstractJpaIntegrationTest {
|
|||||||
newAction.setStatus(Status.RUNNING);
|
newAction.setStatus(Status.RUNNING);
|
||||||
newAction.setTarget(target);
|
newAction.setTarget(target);
|
||||||
newAction.setWeight(45);
|
newAction.setWeight(45);
|
||||||
|
newAction.setInitiatedBy(tenantAware.getCurrentUsername());
|
||||||
actionRepository.save(newAction);
|
actionRepository.save(newAction);
|
||||||
target.addAction(newAction);
|
target.addAction(newAction);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,18 @@ public class SecurityContextTenantAware implements TenantAware {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrentUsername() {
|
||||||
|
final SecurityContext context = SecurityContextHolder.getContext();
|
||||||
|
if (context.getAuthentication() != null) {
|
||||||
|
final Object principal = context.getAuthentication().getPrincipal();
|
||||||
|
if (principal instanceof UserPrincipal) {
|
||||||
|
return ((UserPrincipal) principal).getUsername();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T runAsTenant(final String tenant, final TenantRunner<T> callable) {
|
public <T> T runAsTenant(final String tenant, final TenantRunner<T> callable) {
|
||||||
final SecurityContext originalContext = SecurityContextHolder.getContext();
|
final SecurityContext originalContext = SecurityContextHolder.getContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user