Feature action cleanup (#704)
* Initial commit * Tenant configuration enhancements * Update REST documentation * Enhance System Configuration view in UI * Add unit tests * Fix delete query for H2 * Improve test coverage * Fix Sonar findings * Fix Hawkbit bot findings * Fix PR review findings * Fix peer review findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com>
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
/**
|
||||
* Copyright (c) 2018 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.repository.jpa.autocleanup;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.ACTION_CLEANUP_ACTION_EXPIRY;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.ACTION_CLEANUP_ACTION_STATUS;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.ACTION_CLEANUP_ENABLED;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test class for {@link AutoActionCleanup}.
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Action cleanup handler")
|
||||
public class AutoActionCleanupTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private AutoActionCleanup autoActionCleanup;
|
||||
|
||||
@Test
|
||||
@Description("Verifies that running actions are not cleaned up.")
|
||||
public void runningActionsAreNotCleanedUp() {
|
||||
|
||||
// cleanup config for this test case
|
||||
setupCleanupConfiguration(true, 0, Action.Status.CANCELED, Action.Status.ERROR);
|
||||
|
||||
final Target trg1 = testdataFactory.createTarget("trg1");
|
||||
final Target trg2 = testdataFactory.createTarget("trg2");
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
|
||||
deploymentManagement.assignDistributionSet(ds1.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg1.getControllerId()));
|
||||
deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg2.getControllerId()));
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(2);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that nothing is cleaned up if the cleanup is disabled.")
|
||||
public void cleanupDisabled() {
|
||||
|
||||
// cleanup config for this test case
|
||||
setupCleanupConfiguration(false, 0, Action.Status.CANCELED);
|
||||
|
||||
final Target trg1 = testdataFactory.createTarget("trg1");
|
||||
final Target trg2 = testdataFactory.createTarget("trg2");
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
|
||||
final Long action1 = deploymentManagement.assignDistributionSet(ds1.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg1.getControllerId())).getActions().get(0);
|
||||
deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg2.getControllerId()));
|
||||
|
||||
setActionToCanceled(action1);
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(2);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that canceled and failed actions are cleaned up.")
|
||||
public void canceledAndFailedActionsAreCleanedUp() {
|
||||
|
||||
// cleanup config for this test case
|
||||
setupCleanupConfiguration(true, 0, Action.Status.CANCELED, Action.Status.ERROR);
|
||||
|
||||
final Target trg1 = testdataFactory.createTarget("trg1");
|
||||
final Target trg2 = testdataFactory.createTarget("trg2");
|
||||
final Target trg3 = testdataFactory.createTarget("trg3");
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
|
||||
final Long action1 = deploymentManagement.assignDistributionSet(ds1.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg1.getControllerId())).getActions().get(0);
|
||||
final Long action2 = deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg2.getControllerId())).getActions().get(0);
|
||||
final Long action3 = deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg3.getControllerId())).getActions().get(0);
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
setActionToCanceled(action1);
|
||||
setActionToFailed(action2);
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(1);
|
||||
assertThat(actionRepository.getById(action3)).isPresent();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that canceled actions are cleaned up.")
|
||||
public void canceledActionsAreCleanedUp() {
|
||||
|
||||
// cleanup config for this test case
|
||||
setupCleanupConfiguration(true, 0, Action.Status.CANCELED);
|
||||
|
||||
final Target trg1 = testdataFactory.createTarget("trg1");
|
||||
final Target trg2 = testdataFactory.createTarget("trg2");
|
||||
final Target trg3 = testdataFactory.createTarget("trg3");
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
|
||||
final Long action1 = deploymentManagement.assignDistributionSet(ds1.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg1.getControllerId())).getActions().get(0);
|
||||
final Long action2 = deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg2.getControllerId())).getActions().get(0);
|
||||
final Long action3 = deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg3.getControllerId())).getActions().get(0);
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
setActionToCanceled(action1);
|
||||
setActionToFailed(action2);
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(2);
|
||||
assertThat(actionRepository.getById(action2)).isPresent();
|
||||
assertThat(actionRepository.getById(action3)).isPresent();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that canceled and failed actions are cleaned up once they expired.")
|
||||
@SuppressWarnings("squid:S2925")
|
||||
public void canceledAndFailedActionsAreCleanedUpWhenExpired() throws InterruptedException {
|
||||
|
||||
// cleanup config for this test case
|
||||
setupCleanupConfiguration(true, 500, Action.Status.CANCELED, Action.Status.ERROR);
|
||||
|
||||
final Target trg1 = testdataFactory.createTarget("trg1");
|
||||
final Target trg2 = testdataFactory.createTarget("trg2");
|
||||
final Target trg3 = testdataFactory.createTarget("trg3");
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
|
||||
final Long action1 = deploymentManagement.assignDistributionSet(ds1.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg1.getControllerId())).getActions().get(0);
|
||||
final Long action2 = deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg2.getControllerId())).getActions().get(0);
|
||||
final Long action3 = deploymentManagement.assignDistributionSet(ds2.getId(), ActionType.FORCED, 0,
|
||||
Collections.singletonList(trg3.getControllerId())).getActions().get(0);
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
setActionToCanceled(action1);
|
||||
setActionToFailed(action2);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
// actions have not expired yet
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
// wait for expiry to elapse
|
||||
Thread.sleep(800);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
assertThat(actionRepository.count()).isEqualTo(1);
|
||||
assertThat(actionRepository.getById(action3)).isPresent();
|
||||
|
||||
}
|
||||
|
||||
private void setActionToCanceled(final Long id) {
|
||||
deploymentManagement.cancelAction(id);
|
||||
deploymentManagement.forceQuitAction(id);
|
||||
}
|
||||
|
||||
private void setActionToFailed(final Long id) {
|
||||
controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(id).status(Status.ERROR));
|
||||
}
|
||||
|
||||
private void setupCleanupConfiguration(final boolean cleanupEnabled, final long expiry, final Status... status) {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(ACTION_CLEANUP_ENABLED, cleanupEnabled);
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(ACTION_CLEANUP_ACTION_EXPIRY, expiry);
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(ACTION_CLEANUP_ACTION_STATUS,
|
||||
Arrays.stream(status).map(Status::toString).collect(Collectors.joining(",")));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) 2018 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.repository.jpa.autocleanup;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test class for {@link AutoCleanupScheduler}.
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Auto cleanup scheduler")
|
||||
public class AutoCleanupSchedulerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
@Autowired
|
||||
private LockRegistry lockRegistry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
counter.set(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that all cleanup handlers are executed regardless if one of them throws an error")
|
||||
public void executeHandlerChain() {
|
||||
|
||||
new AutoCleanupScheduler(systemManagement, systemSecurityContext, lockRegistry, Arrays.asList(
|
||||
new SuccessfulCleanup(), new SuccessfulCleanup(), new FailingCleanup(), new SuccessfulCleanup())).run();
|
||||
|
||||
assertThat(counter.get()).isEqualTo(4);
|
||||
|
||||
}
|
||||
|
||||
private class SuccessfulCleanup implements CleanupTask {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
counter.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class FailingCleanup implements CleanupTask {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
counter.incrementAndGet();
|
||||
throw new RuntimeException("cleanup failed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user