From 7dd92e607ad74e0beafbd0798e45b9545caaca45 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Mon, 30 Oct 2017 14:48:47 +0100 Subject: [PATCH] SONAR-10033 handle failed install and uninstall on restart --- ...tartup.java => FinalizeEditionChange.java} | 57 ++++++++----- .../platformlevel/PlatformLevelStartup.java | 4 +- ...st.java => FinalizeEditionChangeTest.java} | 80 +++++++++++++++---- 3 files changed, 105 insertions(+), 36 deletions(-) rename server/sonar-server/src/main/java/org/sonar/server/edition/{CommitPendingEditionOnStartup.java => FinalizeEditionChange.java} (61%) rename server/sonar-server/src/test/java/org/sonar/server/edition/{CommitPendingEditionOnStartupTest.java => FinalizeEditionChangeTest.java} (69%) diff --git a/server/sonar-server/src/main/java/org/sonar/server/edition/CommitPendingEditionOnStartup.java b/server/sonar-server/src/main/java/org/sonar/server/edition/FinalizeEditionChange.java similarity index 61% rename from server/sonar-server/src/main/java/org/sonar/server/edition/CommitPendingEditionOnStartup.java rename to server/sonar-server/src/main/java/org/sonar/server/edition/FinalizeEditionChange.java index 1c8c40435a8..3f73a32810e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/edition/CommitPendingEditionOnStartup.java +++ b/server/sonar-server/src/main/java/org/sonar/server/edition/FinalizeEditionChange.java @@ -19,15 +19,17 @@ */ package org.sonar.server.edition; +import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.Startable; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; +import org.sonar.server.edition.EditionManagementState.PendingStatus; import org.sonar.server.license.LicenseCommit; -public class CommitPendingEditionOnStartup implements Startable { - private static final Logger LOG = Loggers.get(CommitPendingEditionOnStartup.class); +public class FinalizeEditionChange implements Startable { + private static final Logger LOG = Loggers.get(FinalizeEditionChange.class); private final MutableEditionManagementState editionManagementState; @CheckForNull @@ -37,11 +39,11 @@ public class CommitPendingEditionOnStartup implements Startable { * Used by Pico when license-manager is not installed and therefore no implementation of {@link LicenseCommit} is * is available. */ - public CommitPendingEditionOnStartup(MutableEditionManagementState editionManagementState) { + public FinalizeEditionChange(MutableEditionManagementState editionManagementState) { this(editionManagementState, null); } - public CommitPendingEditionOnStartup(MutableEditionManagementState editionManagementState, @Nullable LicenseCommit licenseCommit) { + public FinalizeEditionChange(MutableEditionManagementState editionManagementState, @Nullable LicenseCommit licenseCommit) { this.editionManagementState = editionManagementState; this.licenseCommit = licenseCommit; } @@ -55,7 +57,7 @@ public class CommitPendingEditionOnStartup implements Startable { return; case MANUAL_IN_PROGRESS: case AUTOMATIC_READY: - finalizeInstall(status); + finalizeInstall(); break; case AUTOMATIC_IN_PROGRESS: editionManagementState.installFailed("SonarQube was restarted before asynchronous installation of edition completed"); @@ -75,27 +77,44 @@ public class CommitPendingEditionOnStartup implements Startable { } } - private void finalizeInstall(EditionManagementState.PendingStatus status) { - // license manager is not installed, can't finalize - if (licenseCommit == null) { - LOG.info("No LicenseCommit instance is not available, can not finalize installation"); - return; - } + private void finalizeInstall() { + String errorMessage = null; - String newLicense = editionManagementState.getPendingLicense() - .orElseThrow(() -> new IllegalStateException(String.format("When state is %s, a license should be available in staging", status))); try { - licenseCommit.update(newLicense); - editionManagementState.finalizeInstallation(null); - } catch (IllegalArgumentException e) { - String errorMessage = "Invalid staged license could not be commit on startup. Please input a new license."; - LOG.warn(errorMessage, e); + if (licenseCommit == null) { + errorMessage = "Edition installation didn't complete. Some plugins were not installed."; + LOG.warn(errorMessage); + return; + } + + Optional newLicense = editionManagementState.getPendingLicense(); + if (!newLicense.isPresent()) { + errorMessage = "Edition installation didn't complete. License was not found."; + LOG.warn(errorMessage); + return; + } + + try { + licenseCommit.update(newLicense.get()); + } catch (IllegalArgumentException e) { + errorMessage = "Edition installation didn't complete. License is not valid. Please set a new license."; + LOG.warn(errorMessage, e); + } + } finally { editionManagementState.finalizeInstallation(errorMessage); } } @Override public void stop() { - // nothing to do + EditionManagementState.PendingStatus status = editionManagementState.getPendingInstallationStatus(); + if (status == PendingStatus.UNINSTALL_IN_PROGRESS) { + if (licenseCommit != null) { + LOG.debug("Removing license"); + licenseCommit.delete(); + } else { + LOG.warn("License Manager plugin not found - cannot remove the license"); + } + } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java index 62c9dd6737c..9a92243526e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java @@ -20,7 +20,7 @@ package org.sonar.server.platform.platformlevel; import org.sonar.server.app.ProcessCommandWrapper; -import org.sonar.server.edition.CommitPendingEditionOnStartup; +import org.sonar.server.edition.FinalizeEditionChange; import org.sonar.server.es.IndexerStartupTask; import org.sonar.server.organization.DefaultOrganizationEnforcer; import org.sonar.server.platform.ServerLifecycleNotifier; @@ -60,7 +60,7 @@ public class PlatformLevelStartup extends PlatformLevel { RegisterMetrics.class, RegisterQualityGates.class, RegisterRules.class, - CommitPendingEditionOnStartup.class); + FinalizeEditionChange.class); add(BuiltInQProfileLoader.class); addIfStartupLeader( BuiltInQualityProfilesUpdateListener.class, diff --git a/server/sonar-server/src/test/java/org/sonar/server/edition/CommitPendingEditionOnStartupTest.java b/server/sonar-server/src/test/java/org/sonar/server/edition/FinalizeEditionChangeTest.java similarity index 69% rename from server/sonar-server/src/test/java/org/sonar/server/edition/CommitPendingEditionOnStartupTest.java rename to server/sonar-server/src/test/java/org/sonar/server/edition/FinalizeEditionChangeTest.java index e1e1e910faf..43053abd0db 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/edition/CommitPendingEditionOnStartupTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/edition/FinalizeEditionChangeTest.java @@ -39,8 +39,9 @@ import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTO import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_READY; import static org.sonar.server.edition.EditionManagementState.PendingStatus.MANUAL_IN_PROGRESS; import static org.sonar.server.edition.EditionManagementState.PendingStatus.NONE; +import static org.sonar.server.edition.EditionManagementState.PendingStatus.UNINSTALL_IN_PROGRESS; -public class CommitPendingEditionOnStartupTest { +public class FinalizeEditionChangeTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule @@ -48,8 +49,8 @@ public class CommitPendingEditionOnStartupTest { private MutableEditionManagementState editionManagementState = mock(MutableEditionManagementState.class); private LicenseCommit licenseCommit = mock(LicenseCommit.class); - private CommitPendingEditionOnStartup underTest = new CommitPendingEditionOnStartup(editionManagementState); - private CommitPendingEditionOnStartup underTestWithLicenseCommit = new CommitPendingEditionOnStartup(editionManagementState, licenseCommit); + private FinalizeEditionChange underTest = new FinalizeEditionChange(editionManagementState); + private FinalizeEditionChange underTestWithLicenseCommit = new FinalizeEditionChange(editionManagementState, licenseCommit); @Test public void start_clears_error_message_when_status_is_NONE_without_LicenseCommit() { @@ -75,17 +76,37 @@ public class CommitPendingEditionOnStartupTest { } @Test - public void start_has_no_effect_when_status_is_AUTOMATIC_READY_and_no_LicenseCommit_is_available_but_logs_at_debug_level() { + public void start_clears_status_when_status_is_AUTOMATIC_READY_and_no_LicenseCommit_is_available() { when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); underTest.start(); verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).finalizeInstallation("Edition installation didn't complete. Some plugins were not installed."); + + verifyNoMoreInteractions(editionManagementState); + verifyZeroInteractions(licenseCommit); + assertThat(logTester.logs()).hasSize(1); + assertThat(logTester.logs(LoggerLevel.WARN)) + .containsOnly("Edition installation didn't complete. Some plugins were not installed."); + } + + @Test + public void start_clears_status_when_status_is_AUTOMATIC_READY_and_license_is_not_available() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); + when(editionManagementState.getPendingLicense()).thenReturn(Optional.empty()); + + underTestWithLicenseCommit.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).finalizeInstallation("Edition installation didn't complete. License was not found."); + verify(editionManagementState).getPendingLicense(); + verifyNoMoreInteractions(editionManagementState); verifyZeroInteractions(licenseCommit); assertThat(logTester.logs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.INFO)) - .containsOnly("No LicenseCommit instance is not available, can not finalize installation"); + assertThat(logTester.logs(LoggerLevel.WARN)) + .containsOnly("Edition installation didn't complete. License was not found."); } @Test @@ -117,27 +138,28 @@ public class CommitPendingEditionOnStartupTest { verify(editionManagementState).getPendingInstallationStatus(); verify(editionManagementState).getPendingLicense(); - verify(editionManagementState).finalizeInstallation("Invalid staged license could not be commit on startup. Please input a new license."); + verify(editionManagementState).finalizeInstallation("Edition installation didn't complete. License is not valid. Please set a new license."); verifyNoMoreInteractions(editionManagementState); verify(licenseCommit).update(license); verifyNoMoreInteractions(licenseCommit); assertThat(logTester.logs()).hasSize(1); assertThat(logTester.logs(LoggerLevel.WARN)) - .containsOnly("Invalid staged license could not be commit on startup. Please input a new license."); + .containsOnly("Edition installation didn't complete. License is not valid. Please set a new license."); } @Test - public void starts_has_no_effect_when_status_is_MANUAL_IN_PROGRESS_and_no_LicenseCommit_is_available_but_logs_at_debug_level() { + public void start_clears_status_when_status_is_MANUAL_IN_PROGRESS_and_no_LicenseCommit_is_available() { when(editionManagementState.getPendingInstallationStatus()).thenReturn(MANUAL_IN_PROGRESS); underTest.start(); verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).finalizeInstallation("Edition installation didn't complete. Some plugins were not installed."); verifyNoMoreInteractions(editionManagementState); verifyZeroInteractions(licenseCommit); assertThat(logTester.logs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.INFO)) - .containsOnly("No LicenseCommit instance is not available, can not finalize installation"); + assertThat(logTester.logs(LoggerLevel.WARN)) + .containsOnly("Edition installation didn't complete. Some plugins were not installed."); } @Test @@ -169,17 +191,17 @@ public class CommitPendingEditionOnStartupTest { verify(editionManagementState).getPendingInstallationStatus(); verify(editionManagementState).getPendingLicense(); - verify(editionManagementState).finalizeInstallation("Invalid staged license could not be commit on startup. Please input a new license."); + verify(editionManagementState).finalizeInstallation("Edition installation didn't complete. License is not valid. Please set a new license."); verifyNoMoreInteractions(editionManagementState); verify(licenseCommit).update(license); verifyNoMoreInteractions(licenseCommit); assertThat(logTester.logs()).hasSize(1); assertThat(logTester.logs(LoggerLevel.WARN)) - .containsOnly("Invalid staged license could not be commit on startup. Please input a new license."); + .containsOnly("Edition installation didn't complete. License is not valid. Please set a new license."); } @Test - public void starts_put_editionManagement_set_in_automaticInstallError_when_status_is_AUTOMATIC_PROGRESS_and_no_LicenseCommit_is_available() { + public void start_put_editionManagement_set_in_automaticInstallError_when_status_is_AUTOMATIC_PROGRESS_and_no_LicenseCommit_is_available() { when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_IN_PROGRESS); underTest.start(); @@ -191,7 +213,7 @@ public class CommitPendingEditionOnStartupTest { } @Test - public void starts_put_editionManagement_set_in_automaticInstallError_when_status_is_AUTOMATIC_PROGRESS_and_LicenseCommit_is_available() { + public void start_put_editionManagement_set_in_automaticInstallError_when_status_is_AUTOMATIC_PROGRESS_and_LicenseCommit_is_available() { when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_IN_PROGRESS); underTestWithLicenseCommit.start(); @@ -202,6 +224,34 @@ public class CommitPendingEditionOnStartupTest { verifyZeroInteractions(licenseCommit); } + @Test + public void stop_should_remove_license_if_uninstalling_and_LicenseCommit_is_available() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(UNINSTALL_IN_PROGRESS); + + underTestWithLicenseCommit.stop(); + + assertThat(logTester.logs()).hasSize(1); + assertThat(logTester.logs(LoggerLevel.DEBUG)) + .containsOnly("Removing license"); + verify(licenseCommit).delete(); + verifyNoMoreInteractions(licenseCommit); + verify(editionManagementState).getPendingInstallationStatus(); + verifyNoMoreInteractions(editionManagementState); + } + + @Test + public void stop_should_log_if_uninstalling_and_LicenseCommit_is_not_available() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(UNINSTALL_IN_PROGRESS); + + underTest.stop(); + + assertThat(logTester.logs()).hasSize(1); + assertThat(logTester.logs(LoggerLevel.WARN)) + .containsOnly("License Manager plugin not found - cannot remove the license"); + verify(editionManagementState).getPendingInstallationStatus(); + verifyNoMoreInteractions(editionManagementState); + } + @Test public void should_commit_uninstall() { when(editionManagementState.getPendingInstallationStatus()).thenReturn(EditionManagementState.PendingStatus.UNINSTALL_IN_PROGRESS); -- 2.39.5