Optional support for autoclose of deprecated actions (#585)
* Introduce action autoclose into repository. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Extended test. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix typo. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Added checkbox to management ui. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix Ui allignment. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix item ID. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix sonar issues. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * readibility. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -221,7 +221,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
@PathVariable("controllerId") final String controllerId,
|
@PathVariable("controllerId") final String controllerId,
|
||||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||||
@PathVariable("fileName") final String fileName) {
|
@PathVariable("fileName") final String fileName) {
|
||||||
controllerManagement.getByControllerId(controllerId)
|
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||||
|
|
||||||
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
|
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||||
@@ -235,6 +235,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
final Artifact artifact = module.getArtifactByFilename(fileName)
|
final Artifact artifact = module.getArtifactByFilename(fileName)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Artifact.class, fileName));
|
.orElseThrow(() -> new EntityNotFoundException(Artifact.class, fileName));
|
||||||
|
|
||||||
|
checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), target, module.getId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileStreamingUtil.writeMD5FileResponse(requestResponseContextHolder.getHttpServletResponse(),
|
FileStreamingUtil.writeMD5FileResponse(requestResponseContextHolder.getHttpServletResponse(),
|
||||||
artifact.getMd5Hash(), fileName);
|
artifact.getMd5Hash(), fileName);
|
||||||
|
|||||||
@@ -208,10 +208,12 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// create ds
|
// create ds
|
||||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||||
|
|
||||||
|
assignDistributionSet(ds, target);
|
||||||
|
|
||||||
// create artifact
|
// create artifact
|
||||||
final byte random[] = RandomUtils.nextBytes(5 * 1024);
|
final byte random[] = RandomUtils.nextBytes(5 * 1024);
|
||||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
|
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "file1",
|
||||||
"file1", false);
|
false);
|
||||||
|
|
||||||
// download
|
// download
|
||||||
final MvcResult result = mvc
|
final MvcResult result = mvc
|
||||||
@@ -242,8 +244,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// create artifact
|
// create artifact
|
||||||
final byte random[] = RandomUtils.nextBytes(resultLength);
|
final byte random[] = RandomUtils.nextBytes(resultLength);
|
||||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
|
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "file1",
|
||||||
"file1", false);
|
false);
|
||||||
|
|
||||||
assertThat(random.length).isEqualTo(resultLength);
|
assertThat(random.length).isEqualTo(resultLength);
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,12 @@ public class TenantConfigurationProperties {
|
|||||||
*/
|
*/
|
||||||
public static final String ANONYMOUS_DOWNLOAD_MODE_ENABLED = "anonymous.download.enabled";
|
public static final String ANONYMOUS_DOWNLOAD_MODE_ENABLED = "anonymous.download.enabled";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository on autoclose mode instead of canceling in case of new DS
|
||||||
|
* assignment over active actions.
|
||||||
|
*/
|
||||||
|
public static final String REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED = "repository.actions.autoclose.enabled";
|
||||||
|
|
||||||
private String keyName;
|
private String keyName;
|
||||||
private String defaultValue = "";
|
private String defaultValue = "";
|
||||||
private Class<?> dataType = String.class;
|
private Class<?> dataType = String.class;
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ hawkbit.server.tenant.configuration.authentication-header-enabled.defaultValue=$
|
|||||||
hawkbit.server.tenant.configuration.authentication-header-enabled.dataType=java.lang.Boolean
|
hawkbit.server.tenant.configuration.authentication-header-enabled.dataType=java.lang.Boolean
|
||||||
hawkbit.server.tenant.configuration.authentication-header-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator
|
hawkbit.server.tenant.configuration.authentication-header-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator
|
||||||
|
|
||||||
|
hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.keyName=repository.actions.autoclose.enabled
|
||||||
|
hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.defaultValue=false
|
||||||
|
hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.dataType=java.lang.Boolean
|
||||||
|
hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator
|
||||||
|
|
||||||
hawkbit.server.tenant.configuration.authentication-header-authority.keyName=authentication.header.authority
|
hawkbit.server.tenant.configuration.authentication-header-authority.keyName=authentication.header.authority
|
||||||
hawkbit.server.tenant.configuration.authentication-header-authority.defaultValue=${hawkbit.server.ddi.security.authentication.header.authority}
|
hawkbit.server.tenant.configuration.authentication-header-authority.defaultValue=${hawkbit.server.ddi.security.authentication.header.authority}
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,19 @@ public abstract class AbstractDsAssignmentStrategy {
|
|||||||
* to cancel actions for
|
* to cancel actions for
|
||||||
* @return {@link Set} of {@link Target#getId()}s
|
* @return {@link Set} of {@link Target#getId()}s
|
||||||
*/
|
*/
|
||||||
abstract Set<Long> findTargetIdsToCancel(List<List<Long>> targetIds);
|
abstract Set<Long> cancelActiveActions(List<List<Long>> targetIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels actions that can be canceled (i.e.
|
||||||
|
* {@link DistributionSet#isRequiredMigrationStep() is <code>false</code>})
|
||||||
|
* as a result of the new assignment and returns all {@link Target}s where
|
||||||
|
* such actions existed.
|
||||||
|
*
|
||||||
|
* @param targetIds
|
||||||
|
* to cancel actions for
|
||||||
|
* @return {@link Set} of {@link Target#getId()}s
|
||||||
|
*/
|
||||||
|
abstract void closeActiveActions(List<List<Long>> targetIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles event sending related to the assignment.
|
* Handles event sending related to the assignment.
|
||||||
@@ -119,7 +131,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes {@link Action}s that are no longer necessary and sends
|
* Cancels {@link Action}s that are no longer necessary and sends
|
||||||
* cancellations to the controller.
|
* cancellations to the controller.
|
||||||
*
|
*
|
||||||
* @param targetsIds
|
* @param targetsIds
|
||||||
@@ -130,8 +142,8 @@ public abstract class AbstractDsAssignmentStrategy {
|
|||||||
// Figure out if there are potential target/action combinations that
|
// Figure out if there are potential target/action combinations that
|
||||||
// need to be considered for cancellation
|
// need to be considered for cancellation
|
||||||
final List<JpaAction> activeActions = actionRepository
|
final List<JpaAction> activeActions = actionRepository
|
||||||
.findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(targetsIds,
|
.findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetNotRequiredMigrationStep(
|
||||||
Action.Status.CANCELING);
|
targetsIds, Action.Status.CANCELING);
|
||||||
|
|
||||||
return activeActions.stream().map(action -> {
|
return activeActions.stream().map(action -> {
|
||||||
action.setStatus(Status.CANCELING);
|
action.setStatus(Status.CANCELING);
|
||||||
@@ -148,6 +160,34 @@ public abstract class AbstractDsAssignmentStrategy {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes {@link Action}s that are no longer necessary without sending a
|
||||||
|
* hint to the controller.
|
||||||
|
*
|
||||||
|
* @param targetsIds
|
||||||
|
* to override {@link Action}s
|
||||||
|
*/
|
||||||
|
protected List<Long> closeObsoleteUpdateActions(final Collection<Long> targetsIds) {
|
||||||
|
|
||||||
|
// Figure out if there are potential target/action combinations that
|
||||||
|
// need to be considered for cancellation
|
||||||
|
final List<JpaAction> activeActions = actionRepository
|
||||||
|
.findByActiveAndTargetIdInAndDistributionSetNotRequiredMigrationStep(targetsIds);
|
||||||
|
|
||||||
|
return activeActions.stream().map(action -> {
|
||||||
|
action.setStatus(Status.CANCELED);
|
||||||
|
action.setActive(false);
|
||||||
|
|
||||||
|
// document that the status has been retrieved
|
||||||
|
actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELED, System.currentTimeMillis(),
|
||||||
|
RepositoryConstants.SERVER_MESSAGE_PREFIX + "close obsolete action due to new update"));
|
||||||
|
actionRepository.save(action);
|
||||||
|
|
||||||
|
return action.getTarget().getId();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the {@link CancelTargetAssignmentEvent} for a specific target to
|
* Sends the {@link CancelTargetAssignmentEvent} for a specific target to
|
||||||
* the eventPublisher.
|
* the eventPublisher.
|
||||||
|
|||||||
@@ -219,9 +219,22 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
*/
|
*/
|
||||||
@EntityGraph(attributePaths = { "target" }, type = EntityGraphType.LOAD)
|
@EntityGraph(attributePaths = { "target" }, type = EntityGraphType.LOAD)
|
||||||
@Query("SELECT a FROM JpaAction a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1 AND a.status != ?2")
|
@Query("SELECT a FROM JpaAction a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1 AND a.status != ?2")
|
||||||
List<JpaAction> findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(
|
List<JpaAction> findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetNotRequiredMigrationStep(
|
||||||
Collection<Long> targetIds, Action.Status notStatus);
|
Collection<Long> targetIds, Action.Status notStatus);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Retrieves all {@link Action}s which are active and referring to the given
|
||||||
|
* target Ids and distribution set required migration step.
|
||||||
|
*
|
||||||
|
* @param targetIds
|
||||||
|
* the IDs of targets for the actions
|
||||||
|
* @return the found list of {@link Action}s
|
||||||
|
*/
|
||||||
|
@EntityGraph(attributePaths = { "target" }, type = EntityGraphType.LOAD)
|
||||||
|
@Query("SELECT a FROM JpaAction a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1")
|
||||||
|
List<JpaAction> findByActiveAndTargetIdInAndDistributionSetNotRequiredMigrationStep(Collection<Long> targetIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts all {@link Action}s referring to the given target.
|
* Counts all {@link Action}s referring to the given target.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.ActionFields;
|
|||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
@@ -57,6 +58,8 @@ import org.eclipse.hawkbit.repository.model.Target;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
@@ -109,13 +112,17 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
private final PlatformTransactionManager txManager;
|
private final PlatformTransactionManager txManager;
|
||||||
private final OnlineDsAssignmentStrategy onlineDsAssignmentStrategy;
|
private final OnlineDsAssignmentStrategy onlineDsAssignmentStrategy;
|
||||||
private final OfflineDsAssignmentStrategy offlineDsAssignmentStrategy;
|
private final OfflineDsAssignmentStrategy offlineDsAssignmentStrategy;
|
||||||
|
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||||
|
private final SystemSecurityContext systemSecurityContext;
|
||||||
|
|
||||||
JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
|
JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
|
||||||
final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository,
|
final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository,
|
||||||
final ActionStatusRepository actionStatusRepository, final TargetManagement targetManagement,
|
final ActionStatusRepository actionStatusRepository, final TargetManagement targetManagement,
|
||||||
final AuditorAware<String> auditorProvider, final ApplicationEventPublisher eventPublisher,
|
final AuditorAware<String> auditorProvider, final ApplicationEventPublisher eventPublisher,
|
||||||
final ApplicationContext applicationContext, final AfterTransactionCommitExecutor afterCommit,
|
final ApplicationContext applicationContext, final AfterTransactionCommitExecutor afterCommit,
|
||||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager) {
|
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||||
|
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
|
final SystemSecurityContext systemSecurityContext) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.actionRepository = actionRepository;
|
this.actionRepository = actionRepository;
|
||||||
this.distributionSetRepository = distributionSetRepository;
|
this.distributionSetRepository = distributionSetRepository;
|
||||||
@@ -132,6 +139,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
applicationContext, actionRepository, actionStatusRepository);
|
applicationContext, actionRepository, actionStatusRepository);
|
||||||
offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, eventPublisher,
|
offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, eventPublisher,
|
||||||
applicationContext, actionRepository, actionStatusRepository);
|
applicationContext, actionRepository, actionStatusRepository);
|
||||||
|
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||||
|
this.systemSecurityContext = systemSecurityContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -254,7 +263,16 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
// need to remember which one we have been switched to canceling state
|
// need to remember which one we have been switched to canceling state
|
||||||
// because for targets which we have changed to canceling we don't want
|
// because for targets which we have changed to canceling we don't want
|
||||||
// to publish the new action update event.
|
// to publish the new action update event.
|
||||||
final Set<Long> targetIdsCancellList = assignmentStrategy.findTargetIdsToCancel(targetIds);
|
final Set<Long> targetIdsCancellList;
|
||||||
|
|
||||||
|
if (systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement
|
||||||
|
.getConfigurationValue(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, Boolean.class)
|
||||||
|
.getValue())) {
|
||||||
|
targetIdsCancellList = Collections.emptySet();
|
||||||
|
assignmentStrategy.closeActiveActions(targetIds);
|
||||||
|
} else {
|
||||||
|
targetIdsCancellList = assignmentStrategy.cancelActiveActions(targetIds);
|
||||||
|
}
|
||||||
|
|
||||||
// cancel all scheduled actions which are in-active, these actions were
|
// cancel all scheduled actions which are in-active, these actions were
|
||||||
// not active before and the manual assignment which has been done
|
// not active before and the manual assignment which has been done
|
||||||
|
|||||||
@@ -85,8 +85,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
@Retryable(include = {
|
@Retryable(include = {
|
||||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void delete(final Long targetFilterQueryId) {
|
public void delete(final Long targetFilterQueryId) {
|
||||||
get(targetFilterQueryId)
|
if (!targetFilterQueryRepository.exists(targetFilterQueryId)) {
|
||||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
throw new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId);
|
||||||
|
}
|
||||||
|
|
||||||
targetFilterQueryRepository.delete(targetFilterQueryId);
|
targetFilterQueryRepository.delete(targetFilterQueryId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class JpaTenantStatsManagement implements TenantStatsManagement {
|
|||||||
|
|
||||||
result.setTargets(targetRepository.count());
|
result.setTargets(targetRepository.count());
|
||||||
result.setArtifacts(artifactRepository.countBySoftwareModuleDeleted(false));
|
result.setArtifacts(artifactRepository.countBySoftwareModuleDeleted(false));
|
||||||
artifactRepository.getSumOfUndeletedArtifactSize().map(result::setOverallArtifactVolumeInBytes);
|
artifactRepository.getSumOfUndeletedArtifactSize().ifPresent(result::setOverallArtifactVolumeInBytes);
|
||||||
result.setActions(actionRepository.count());
|
result.setActions(actionRepository.count());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -67,10 +67,15 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Long> findTargetIdsToCancel(final List<List<Long>> targetIds) {
|
public Set<Long> cancelActiveActions(final List<List<Long>> targetIds) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void closeActiveActions(final List<List<Long>> targetIds) {
|
||||||
|
// Not supported by offline case
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateTargetStatus(final JpaDistributionSet set, final List<List<Long>> targetIds, final String currentUser) {
|
void updateTargetStatus(final JpaDistributionSet set, final List<List<Long>> targetIds, final String currentUser) {
|
||||||
targetIds.forEach(tIds -> targetRepository.setAssignedAndInstalledDistributionSetAndUpdateStatus(
|
targetIds.forEach(tIds -> targetRepository.setAssignedAndInstalledDistributionSetAndUpdateStatus(
|
||||||
|
|||||||
@@ -67,11 +67,16 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Set<Long> findTargetIdsToCancel(final List<List<Long>> targetIds) {
|
Set<Long> cancelActiveActions(final List<List<Long>> targetIds) {
|
||||||
return targetIds.stream().map(this::overrideObsoleteUpdateActions).flatMap(Collection::stream)
|
return targetIds.stream().map(this::overrideObsoleteUpdateActions).flatMap(Collection::stream)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void closeActiveActions(final List<List<Long>> targetIds) {
|
||||||
|
targetIds.forEach(this::closeObsoleteUpdateActions);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateTargetStatus(final JpaDistributionSet set, final List<List<Long>> targetIds, final String currentUser) {
|
void updateTargetStatus(final JpaDistributionSet set, final List<List<Long>> targetIds, final String currentUser) {
|
||||||
targetIds.forEach(tIds -> targetRepository.setAssignedDistributionSetAndUpdateStatus(TargetUpdateStatus.PENDING,
|
targetIds.forEach(tIds -> targetRepository.setAssignedDistributionSetAndUpdateStatus(TargetUpdateStatus.PENDING,
|
||||||
|
|||||||
@@ -531,10 +531,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
final TargetManagement targetManagement, final AuditorAware<String> auditorProvider,
|
final TargetManagement targetManagement, final AuditorAware<String> auditorProvider,
|
||||||
final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext,
|
final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext,
|
||||||
final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer,
|
final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||||
final PlatformTransactionManager txManager) {
|
final PlatformTransactionManager txManager,
|
||||||
|
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
|
final SystemSecurityContext systemSecurityContext) {
|
||||||
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetRepository, targetRepository,
|
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetRepository, targetRepository,
|
||||||
actionStatusRepository, targetManagement, auditorProvider, eventPublisher, applicationContext,
|
actionStatusRepository, targetManagement, auditorProvider, eventPublisher, applicationContext,
|
||||||
afterCommit, virtualPropertyReplacer, txManager);
|
afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement, systemSecurityContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
|||||||
|
|
||||||
if (allready >= softwareModule.getType().getMaxAssignments()) {
|
if (allready >= softwareModule.getType().getMaxAssignments()) {
|
||||||
modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey()))
|
modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey()))
|
||||||
.findAny().map(modules::remove);
|
.findAny().ifPresent(modules::remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modules.add(softwareModule)) {
|
if (modules.add(softwareModule)) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
|
||||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||||
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -460,6 +461,52 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
.allMatch(target -> target.getLastModifiedAt().equals(target.getInstallationDate()));
|
.allMatch(target -> target.getLastModifiedAt().equals(target.getInstallationDate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that if an account is set to action autoclose running actions in case of a new assigned set get closed and set to CANCELED.")
|
||||||
|
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 10),
|
||||||
|
@Expect(type = TargetUpdatedEvent.class, count = 20), @Expect(type = ActionCreatedEvent.class, count = 20),
|
||||||
|
@Expect(type = ActionUpdatedEvent.class, count = 10),
|
||||||
|
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
|
||||||
|
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
|
||||||
|
@Expect(type = TargetAssignDistributionSetEvent.class, count = 20) })
|
||||||
|
public void assigneDistributionSetAndAutoCloseActiveActions() {
|
||||||
|
tenantConfigurationManagement
|
||||||
|
.addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final List<Target> targets = testdataFactory.createTargets(10);
|
||||||
|
|
||||||
|
// First assignment
|
||||||
|
final DistributionSet ds1 = testdataFactory.createDistributionSet("1");
|
||||||
|
assignDistributionSet(ds1, targets);
|
||||||
|
|
||||||
|
List<Action> assignmentOne = actionRepository.findByDistributionSetId(PAGE, ds1.getId()).getContent();
|
||||||
|
assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(Action::isActive).as("Is assigned DS")
|
||||||
|
.allMatch(action -> action.getDistributionSet().getId() == ds1.getId()).as("Is running")
|
||||||
|
.allMatch(action -> action.getStatus() == Status.RUNNING);
|
||||||
|
|
||||||
|
// Second assignment
|
||||||
|
final DistributionSet ds2 = testdataFactory.createDistributionSet("2");
|
||||||
|
assignDistributionSet(ds2, targets);
|
||||||
|
|
||||||
|
final List<Action> assignmentTwo = actionRepository.findByDistributionSetId(PAGE, ds2.getId()).getContent();
|
||||||
|
assignmentOne = actionRepository.findByDistributionSetId(PAGE, ds1.getId()).getContent();
|
||||||
|
assertThat(assignmentTwo).hasSize(10).as("Is active").allMatch(Action::isActive).as("Is assigned DS")
|
||||||
|
.allMatch(action -> action.getDistributionSet().getId() == ds2.getId()).as("Is running")
|
||||||
|
.allMatch(action -> action.getStatus() == Status.RUNNING);
|
||||||
|
assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(action -> !action.isActive())
|
||||||
|
.as("Is assigned to DS").allMatch(action -> action.getDistributionSet().getId() == ds1.getId())
|
||||||
|
.as("Is cancelled").allMatch(action -> action.getStatus() == Status.CANCELED);
|
||||||
|
|
||||||
|
assertThat(targetManagement.findByAssignedDistributionSet(PAGE, ds2.getId()).getContent()).hasSize(10)
|
||||||
|
.as("InstallationDate not set").allMatch(target -> (target.getInstallationDate() == null));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
tenantConfigurationManagement
|
||||||
|
.addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test a simple deployment by calling the
|
* test a simple deployment by calling the
|
||||||
* {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)}
|
* {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
|||||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.AnonymousDownloadAuthenticationConfigurationItem;
|
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.AnonymousDownloadAuthenticationConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.AuthenticationConfigurationItem;
|
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.CertificateAuthenticationConfigurationItem;
|
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.CertificateAuthenticationConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.GatewaySecurityTokenAuthenticationConfigurationItem;
|
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.GatewaySecurityTokenAuthenticationConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.TargetSecurityTokenAuthenticationConfigurationItem;
|
import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.TargetSecurityTokenAuthenticationConfigurationItem;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.BooleanConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
* View to configure the authentication mode.
|
* View to configure the authentication mode.
|
||||||
*/
|
*/
|
||||||
public class AuthenticationConfigurationView extends BaseConfigurationView
|
public class AuthenticationConfigurationView extends BaseConfigurationView
|
||||||
implements ConfigurationGroup, ConfigurationItem.ConfigurationItemChangeListener, ValueChangeListener {
|
implements ConfigurationItem.ConfigurationItemChangeListener, ValueChangeListener {
|
||||||
|
|
||||||
private static final String DIST_CHECKBOX_STYLE = "dist-checkbox-style";
|
private static final String DIST_CHECKBOX_STYLE = "dist-checkbox-style";
|
||||||
|
|
||||||
@@ -55,7 +55,8 @@ public class AuthenticationConfigurationView extends BaseConfigurationView
|
|||||||
|
|
||||||
private CheckBox downloadAnonymousCheckBox;
|
private CheckBox downloadAnonymousCheckBox;
|
||||||
|
|
||||||
AuthenticationConfigurationView(final VaadinMessageSource i18n, final TenantConfigurationManagement tenantConfigurationManagement,
|
AuthenticationConfigurationView(final VaadinMessageSource i18n,
|
||||||
|
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
final SecurityTokenGenerator securityTokenGenerator) {
|
final SecurityTokenGenerator securityTokenGenerator) {
|
||||||
this.i18n = i18n;
|
this.i18n = i18n;
|
||||||
this.certificateAuthenticationConfigurationItem = new CertificateAuthenticationConfigurationItem(
|
this.certificateAuthenticationConfigurationItem = new CertificateAuthenticationConfigurationItem(
|
||||||
@@ -161,7 +162,7 @@ public class AuthenticationConfigurationView extends BaseConfigurationView
|
|||||||
notifyConfigurationChanged();
|
notifyConfigurationChanged();
|
||||||
|
|
||||||
final CheckBox checkBox = (CheckBox) event.getProperty();
|
final CheckBox checkBox = (CheckBox) event.getProperty();
|
||||||
AuthenticationConfigurationItem configurationItem;
|
BooleanConfigurationItem configurationItem;
|
||||||
|
|
||||||
if (gatewaySecTokenCheckBox.equals(checkBox)) {
|
if (gatewaySecTokenCheckBox.equals(checkBox)) {
|
||||||
configurationItem = gatewaySecurityTokenAuthenticationConfigurationItem;
|
configurationItem = gatewaySecurityTokenAuthenticationConfigurationItem;
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.tenantconfiguration;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.BooleanConfigurationItem;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.repository.ActionAutocloseConfigurationItem;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
|
import com.vaadin.data.Property.ValueChangeEvent;
|
||||||
|
import com.vaadin.data.Property.ValueChangeListener;
|
||||||
|
import com.vaadin.ui.CheckBox;
|
||||||
|
import com.vaadin.ui.GridLayout;
|
||||||
|
import com.vaadin.ui.Label;
|
||||||
|
import com.vaadin.ui.Panel;
|
||||||
|
import com.vaadin.ui.VerticalLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View to configure the authentication mode.
|
||||||
|
*/
|
||||||
|
public class RepositoryConfigurationView extends BaseConfigurationView
|
||||||
|
implements ConfigurationGroup, ConfigurationItem.ConfigurationItemChangeListener, ValueChangeListener {
|
||||||
|
|
||||||
|
private static final String DIST_CHECKBOX_STYLE = "dist-checkbox-style";
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final VaadinMessageSource i18n;
|
||||||
|
|
||||||
|
private final ActionAutocloseConfigurationItem actionAutocloseConfigurationItem;
|
||||||
|
|
||||||
|
private CheckBox actionAutocloseCheckBox;
|
||||||
|
|
||||||
|
RepositoryConfigurationView(final VaadinMessageSource i18n,
|
||||||
|
final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||||
|
this.i18n = i18n;
|
||||||
|
this.actionAutocloseConfigurationItem = new ActionAutocloseConfigurationItem(tenantConfigurationManagement,
|
||||||
|
i18n);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
|
||||||
|
final Panel rootPanel = new Panel();
|
||||||
|
rootPanel.setSizeFull();
|
||||||
|
|
||||||
|
rootPanel.addStyleName("config-panel");
|
||||||
|
|
||||||
|
final VerticalLayout vLayout = new VerticalLayout();
|
||||||
|
vLayout.setMargin(true);
|
||||||
|
vLayout.setSizeFull();
|
||||||
|
|
||||||
|
final Label headerDisSetType = new Label(i18n.getMessage("configuration.repository.title"));
|
||||||
|
headerDisSetType.addStyleName("config-panel-header");
|
||||||
|
vLayout.addComponent(headerDisSetType);
|
||||||
|
|
||||||
|
final GridLayout gridLayout = new GridLayout(2, 1);
|
||||||
|
gridLayout.setSpacing(true);
|
||||||
|
gridLayout.setImmediate(true);
|
||||||
|
gridLayout.setColumnExpandRatio(1, 1.0F);
|
||||||
|
gridLayout.setSizeFull();
|
||||||
|
|
||||||
|
actionAutocloseCheckBox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, "");
|
||||||
|
actionAutocloseCheckBox.setId(UIComponentIdProvider.REPOSITORY_ACTIONS_AUTOCLOSE_CHECKBOX);
|
||||||
|
actionAutocloseCheckBox.setValue(actionAutocloseConfigurationItem.isConfigEnabled());
|
||||||
|
actionAutocloseCheckBox.addValueChangeListener(this);
|
||||||
|
actionAutocloseConfigurationItem.addChangeListener(this);
|
||||||
|
gridLayout.addComponent(actionAutocloseCheckBox, 0, 0);
|
||||||
|
gridLayout.addComponent(actionAutocloseConfigurationItem, 1, 0);
|
||||||
|
|
||||||
|
vLayout.addComponent(gridLayout);
|
||||||
|
rootPanel.setContent(vLayout);
|
||||||
|
setCompositionRoot(rootPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
actionAutocloseConfigurationItem.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo() {
|
||||||
|
actionAutocloseConfigurationItem.undo();
|
||||||
|
actionAutocloseCheckBox.setValue(actionAutocloseConfigurationItem.isConfigEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configurationHasChanged() {
|
||||||
|
notifyConfigurationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void valueChange(final ValueChangeEvent event) {
|
||||||
|
|
||||||
|
if (!(event.getProperty() instanceof CheckBox)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyConfigurationChanged();
|
||||||
|
|
||||||
|
final CheckBox checkBox = (CheckBox) event.getProperty();
|
||||||
|
BooleanConfigurationItem configurationItem;
|
||||||
|
|
||||||
|
if (actionAutocloseCheckBox.equals(checkBox)) {
|
||||||
|
configurationItem = actionAutocloseConfigurationItem;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkBox.getValue()) {
|
||||||
|
configurationItem.configEnable();
|
||||||
|
} else {
|
||||||
|
configurationItem.configDisable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,6 +56,8 @@ public class TenantConfigurationDashboardView extends CustomComponent implements
|
|||||||
|
|
||||||
private final DefaultDistributionSetTypeLayout defaultDistributionSetTypeLayout;
|
private final DefaultDistributionSetTypeLayout defaultDistributionSetTypeLayout;
|
||||||
|
|
||||||
|
private final RepositoryConfigurationView repositoryConfigurationView;
|
||||||
|
|
||||||
private final AuthenticationConfigurationView authenticationConfigurationView;
|
private final AuthenticationConfigurationView authenticationConfigurationView;
|
||||||
|
|
||||||
private final PollingConfigurationView pollingConfigurationView;
|
private final PollingConfigurationView pollingConfigurationView;
|
||||||
@@ -87,6 +89,8 @@ public class TenantConfigurationDashboardView extends CustomComponent implements
|
|||||||
securityTokenGenerator);
|
securityTokenGenerator);
|
||||||
this.pollingConfigurationView = new PollingConfigurationView(i18n, controllerPollProperties,
|
this.pollingConfigurationView = new PollingConfigurationView(i18n, controllerPollProperties,
|
||||||
tenantConfigurationManagement);
|
tenantConfigurationManagement);
|
||||||
|
this.repositoryConfigurationView = new RepositoryConfigurationView(i18n, tenantConfigurationManagement);
|
||||||
|
|
||||||
this.i18n = i18n;
|
this.i18n = i18n;
|
||||||
this.uiProperties = uiProperties;
|
this.uiProperties = uiProperties;
|
||||||
this.uINotification = uINotification;
|
this.uINotification = uINotification;
|
||||||
@@ -100,6 +104,8 @@ public class TenantConfigurationDashboardView extends CustomComponent implements
|
|||||||
if (defaultDistributionSetTypeLayout.getComponentCount() > 0) {
|
if (defaultDistributionSetTypeLayout.getComponentCount() > 0) {
|
||||||
configurationViews.add(defaultDistributionSetTypeLayout);
|
configurationViews.add(defaultDistributionSetTypeLayout);
|
||||||
}
|
}
|
||||||
|
configurationViews.add(repositoryConfigurationView);
|
||||||
|
|
||||||
configurationViews.add(authenticationConfigurationView);
|
configurationViews.add(authenticationConfigurationView);
|
||||||
configurationViews.add(pollingConfigurationView);
|
configurationViews.add(pollingConfigurationView);
|
||||||
if (customConfigurationViews != null) {
|
if (customConfigurationViews != null) {
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ package org.eclipse.hawkbit.ui.tenantconfiguration.authentication;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the UI item for the anonymous download by in the
|
* This class represents the UI item for the anonymous download by in the
|
||||||
* authentication configuration view.
|
* authentication configuration view.
|
||||||
*/
|
*/
|
||||||
public class AnonymousDownloadAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class AnonymousDownloadAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
|||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
import com.vaadin.ui.HorizontalLayout;
|
||||||
@@ -23,7 +24,7 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
* This class represents the UI item for the certificate authenticated by an
|
* This class represents the UI item for the certificate authenticated by an
|
||||||
* reverse proxy in the authentication configuration view.
|
* reverse proxy in the authentication configuration view.
|
||||||
*/
|
*/
|
||||||
public class CertificateAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class CertificateAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.T
|
|||||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
import com.vaadin.server.FontAwesome;
|
import com.vaadin.server.FontAwesome;
|
||||||
@@ -28,7 +29,7 @@ import com.vaadin.ui.themes.ValoTheme;
|
|||||||
* This class represents the UI item for the gateway security token section in
|
* This class represents the UI item for the gateway security token section in
|
||||||
* the authentication configuration view.
|
* the authentication configuration view.
|
||||||
*/
|
*/
|
||||||
public class GatewaySecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class GatewaySecurityTokenAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ package org.eclipse.hawkbit.ui.tenantconfiguration.authentication;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the UI item for the target security token section in
|
* This class represents the UI item for the target security token section in
|
||||||
* the authentication configuration view.
|
* the authentication configuration view.
|
||||||
*/
|
*/
|
||||||
public class TargetSecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem {
|
public class TargetSecurityTokenAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.tenantconfiguration.authentication;
|
package org.eclipse.hawkbit.ui.tenantconfiguration.generic;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -21,8 +21,8 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
/**
|
/**
|
||||||
* abstract authentication configuration item.
|
* abstract authentication configuration item.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractAuthenticationTenantConfigurationItem extends VerticalLayout
|
public abstract class AbstractBooleanTenantConfigurationItem extends VerticalLayout
|
||||||
implements AuthenticationConfigurationItem {
|
implements BooleanConfigurationItem {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ abstract class AbstractAuthenticationTenantConfigurationItem extends VerticalLay
|
|||||||
* the tenant configuration management to retrieve the
|
* the tenant configuration management to retrieve the
|
||||||
* configuration value
|
* configuration value
|
||||||
*/
|
*/
|
||||||
public AbstractAuthenticationTenantConfigurationItem(final String configurationKey,
|
protected AbstractBooleanTenantConfigurationItem(final String configurationKey,
|
||||||
final TenantConfigurationManagement tenantConfigurationManagement, final VaadinMessageSource i18n) {
|
final TenantConfigurationManagement tenantConfigurationManagement, final VaadinMessageSource i18n) {
|
||||||
this.configurationKey = configurationKey;
|
this.configurationKey = configurationKey;
|
||||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||||
@@ -6,21 +6,15 @@
|
|||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.tenantconfiguration.authentication;
|
package org.eclipse.hawkbit.ui.tenantconfiguration.generic;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.ui.tenantconfiguration.ConfigurationItem;
|
import org.eclipse.hawkbit.ui.tenantconfiguration.ConfigurationGroup;
|
||||||
|
|
||||||
import com.vaadin.ui.Component;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to be implemented by any tenant specific configuration to show on
|
* Interface to be implemented by any tenant specific configuration to show on
|
||||||
* the UI.
|
* the UI.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface AuthenticationConfigurationItem extends Component, ConfigurationItem {
|
public interface BooleanConfigurationItem extends ConfigurationGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@code true} if configuration is enabled, otherwise {@code false}
|
* @return {@code true} if configuration is enabled, otherwise {@code false}
|
||||||
@@ -37,14 +31,4 @@ public interface AuthenticationConfigurationItem extends Component, Configuratio
|
|||||||
*/
|
*/
|
||||||
void configDisable();
|
void configDisable();
|
||||||
|
|
||||||
/**
|
|
||||||
* called to save the configuration.
|
|
||||||
*/
|
|
||||||
void save();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* called to rollback made changes.
|
|
||||||
*/
|
|
||||||
void undo();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.tenantconfiguration.repository;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
|
import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the UI item for the target security token section in
|
||||||
|
* the authentication configuration view.
|
||||||
|
*/
|
||||||
|
public class ActionAutocloseConfigurationItem extends AbstractBooleanTenantConfigurationItem {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private boolean configurationEnabled;
|
||||||
|
private boolean configurationEnabledChange;
|
||||||
|
|
||||||
|
public ActionAutocloseConfigurationItem(final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
|
final VaadinMessageSource i18n) {
|
||||||
|
super(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, tenantConfigurationManagement, i18n);
|
||||||
|
|
||||||
|
super.init("label.configuration.repository.autoclose.action");
|
||||||
|
configurationEnabled = isConfigEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configEnable() {
|
||||||
|
if (!configurationEnabled) {
|
||||||
|
configurationEnabledChange = true;
|
||||||
|
}
|
||||||
|
configurationEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configDisable() {
|
||||||
|
if (configurationEnabled) {
|
||||||
|
configurationEnabledChange = true;
|
||||||
|
}
|
||||||
|
configurationEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
if (!configurationEnabledChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getTenantConfigurationManagement().addOrUpdateConfiguration(getConfigurationKey(), configurationEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo() {
|
||||||
|
configurationEnabledChange = false;
|
||||||
|
configurationEnabled = getTenantConfigurationManagement()
|
||||||
|
.getConfigurationValue(getConfigurationKey(), Boolean.class).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
package org.eclipse.hawkbit.ui.utils;
|
package org.eclipse.hawkbit.ui.utils;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to provide the unchanged constants.
|
* Interface to provide the unchanged constants.
|
||||||
*/
|
*/
|
||||||
@@ -1039,6 +1041,12 @@ public final class UIComponentIdProvider {
|
|||||||
*/
|
*/
|
||||||
public static final String ARTIFACT_DETAILS_HEADER_LABEL_ID = "artifact.details.header.caption";
|
public static final String ARTIFACT_DETAILS_HEADER_LABEL_ID = "artifact.details.header.caption";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration checkbox for
|
||||||
|
* {@link TenantConfigurationKey#REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED}.
|
||||||
|
*/
|
||||||
|
public static final String REPOSITORY_ACTIONS_AUTOCLOSE_CHECKBOX = "repositoryactionsautoclosecheckbox";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /* Private Constructor.
|
* /* Private Constructor.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ label.tag.name = Tag name
|
|||||||
label.configuration.auth.header = Allow targets to authenticate via a certificate authenticated by an reverse proxy
|
label.configuration.auth.header = Allow targets to authenticate via a certificate authenticated by an reverse proxy
|
||||||
label.configuration.auth.gatewaytoken = Allow a gateway to authenticate and manage multiple targets through a gateway security token
|
label.configuration.auth.gatewaytoken = Allow a gateway to authenticate and manage multiple targets through a gateway security token
|
||||||
label.configuration.auth.targettoken = Allow targets to authenticate directly with their target security token
|
label.configuration.auth.targettoken = Allow targets to authenticate directly with their target security token
|
||||||
|
label.configuration.repository.autoclose.action = Autoclose running actions with new Distribution Set assignment
|
||||||
label.configuration.anonymous.download = Allow targets to download artifacts without security credentials
|
label.configuration.anonymous.download = Allow targets to download artifacts without security credentials
|
||||||
label.unsupported.browser.ie=Sorry! current browser is not supported. Please use Internet Explorer 11 and above
|
label.unsupported.browser.ie=Sorry! current browser is not supported. Please use Internet Explorer 11 and above
|
||||||
label.auto.assign.description=When an auto assign distribution set is selected, it will be automatically assigned to all targets that match the target filter.
|
label.auto.assign.description=When an auto assign distribution set is selected, it will be automatically assigned to all targets that match the target filter.
|
||||||
@@ -450,6 +451,7 @@ configuration.defaultdistributionset.select.label=Select the default Distributio
|
|||||||
configuration.savebutton.tooltip=Save Configurations
|
configuration.savebutton.tooltip=Save Configurations
|
||||||
configuration.cancellbutton.tooltip=Cancel Configurations
|
configuration.cancellbutton.tooltip=Cancel Configurations
|
||||||
configuration.authentication.title=Authentication Configuration
|
configuration.authentication.title=Authentication Configuration
|
||||||
|
configuration.repository.title=Repository Configuration
|
||||||
configuration.polling.title=Polling Configuration
|
configuration.polling.title=Polling Configuration
|
||||||
configuration.polling.time=Polling Time
|
configuration.polling.time=Polling Time
|
||||||
configuration.polling.overduetime=Polling Overdue Time
|
configuration.polling.overduetime=Polling Overdue Time
|
||||||
|
|||||||
Reference in New Issue
Block a user