From: Duarte Meneses Date: Mon, 30 Oct 2017 13:48:47 +0000 (+0100) Subject: SONAR-10033 handle failed install and uninstall on restart X-Git-Tag: 6.7~22 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7dd92e607ad74e0beafbd0798e45b9545caaca45;p=sonarqube.git SONAR-10033 handle failed install and uninstall on restart --- 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/CommitPendingEditionOnStartup.java deleted file mode 100644 index 1c8c40435a8..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/edition/CommitPendingEditionOnStartup.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.edition; - -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.license.LicenseCommit; - -public class CommitPendingEditionOnStartup implements Startable { - private static final Logger LOG = Loggers.get(CommitPendingEditionOnStartup.class); - - private final MutableEditionManagementState editionManagementState; - @CheckForNull - private final LicenseCommit licenseCommit; - - /** - * Used by Pico when license-manager is not installed and therefore no implementation of {@link LicenseCommit} is - * is available. - */ - public CommitPendingEditionOnStartup(MutableEditionManagementState editionManagementState) { - this(editionManagementState, null); - } - - public CommitPendingEditionOnStartup(MutableEditionManagementState editionManagementState, @Nullable LicenseCommit licenseCommit) { - this.editionManagementState = editionManagementState; - this.licenseCommit = licenseCommit; - } - - @Override - public void start() { - EditionManagementState.PendingStatus status = editionManagementState.getPendingInstallationStatus(); - switch (status) { - case NONE: - editionManagementState.clearInstallErrorMessage(); - return; - case MANUAL_IN_PROGRESS: - case AUTOMATIC_READY: - finalizeInstall(status); - break; - case AUTOMATIC_IN_PROGRESS: - editionManagementState.installFailed("SonarQube was restarted before asynchronous installation of edition completed"); - break; - case UNINSTALL_IN_PROGRESS: - failIfLicenseCommitIsPresent(); - editionManagementState.finalizeInstallation(null); - break; - default: - throw new IllegalStateException("Unsupported status " + status); - } - } - - private void failIfLicenseCommitIsPresent() { - if (licenseCommit != null) { - throw new IllegalStateException("License Manager plugin is still present after uninstallation of the edition. Please remove it."); - } - } - - 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; - } - - 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); - editionManagementState.finalizeInstallation(errorMessage); - } - } - - @Override - public void stop() { - // nothing to do - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/edition/FinalizeEditionChange.java b/server/sonar-server/src/main/java/org/sonar/server/edition/FinalizeEditionChange.java new file mode 100644 index 00000000000..3f73a32810e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/edition/FinalizeEditionChange.java @@ -0,0 +1,120 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +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 FinalizeEditionChange implements Startable { + private static final Logger LOG = Loggers.get(FinalizeEditionChange.class); + + private final MutableEditionManagementState editionManagementState; + @CheckForNull + private final LicenseCommit licenseCommit; + + /** + * Used by Pico when license-manager is not installed and therefore no implementation of {@link LicenseCommit} is + * is available. + */ + public FinalizeEditionChange(MutableEditionManagementState editionManagementState) { + this(editionManagementState, null); + } + + public FinalizeEditionChange(MutableEditionManagementState editionManagementState, @Nullable LicenseCommit licenseCommit) { + this.editionManagementState = editionManagementState; + this.licenseCommit = licenseCommit; + } + + @Override + public void start() { + EditionManagementState.PendingStatus status = editionManagementState.getPendingInstallationStatus(); + switch (status) { + case NONE: + editionManagementState.clearInstallErrorMessage(); + return; + case MANUAL_IN_PROGRESS: + case AUTOMATIC_READY: + finalizeInstall(); + break; + case AUTOMATIC_IN_PROGRESS: + editionManagementState.installFailed("SonarQube was restarted before asynchronous installation of edition completed"); + break; + case UNINSTALL_IN_PROGRESS: + failIfLicenseCommitIsPresent(); + editionManagementState.finalizeInstallation(null); + break; + default: + throw new IllegalStateException("Unsupported status " + status); + } + } + + private void failIfLicenseCommitIsPresent() { + if (licenseCommit != null) { + throw new IllegalStateException("License Manager plugin is still present after uninstallation of the edition. Please remove it."); + } + } + + private void finalizeInstall() { + String errorMessage = null; + + try { + 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() { + 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/CommitPendingEditionOnStartupTest.java deleted file mode 100644 index e1e1e910faf..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/edition/CommitPendingEditionOnStartupTest.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.edition; - -import java.util.Optional; -import org.apache.commons.lang.RandomStringUtils; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.utils.log.LogTester; -import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.server.license.LicenseCommit; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; -import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_IN_PROGRESS; -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; - -public class CommitPendingEditionOnStartupTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Rule - public LogTester logTester = new LogTester(); - - 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); - - @Test - public void start_clears_error_message_when_status_is_NONE_without_LicenseCommit() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE); - - underTest.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).clearInstallErrorMessage(); - verifyNoMoreInteractions(editionManagementState); - } - - @Test - public void start_clears_error_message_when_status_is_NONE_with_LicenseCommit() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE); - - underTestWithLicenseCommit.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).clearInstallErrorMessage(); - verifyNoMoreInteractions(editionManagementState); - verifyZeroInteractions(licenseCommit); - } - - @Test - public void start_has_no_effect_when_status_is_AUTOMATIC_READY_and_no_LicenseCommit_is_available_but_logs_at_debug_level() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); - - underTest.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - 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"); - } - - @Test - public void start_commit_license_and_finalizeInstallation_in_editionManagementState_when_status_is_AUTOMATIC_READY_and_LicenseCommit_is_available() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); - String license = RandomStringUtils.randomAlphanumeric(20); - when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); - - underTestWithLicenseCommit.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).getPendingLicense(); - verify(editionManagementState).finalizeInstallation(null); - verifyNoMoreInteractions(editionManagementState); - verify(licenseCommit).update(license); - verifyNoMoreInteractions(licenseCommit); - } - - @Test - public void start_commit_license_and_finalizeInstallation_with_error_in_editionManagementState_when_status_is_AUTOMATIC_READY_and_license_is_invalid() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); - String license = RandomStringUtils.randomAlphanumeric(20); - when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); - doThrow(new IllegalArgumentException("Faking an IAE because of an invalid license")) - .when(licenseCommit) - .update(license); - - underTestWithLicenseCommit.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).getPendingLicense(); - verify(editionManagementState).finalizeInstallation("Invalid staged license could not be commit on startup. Please input 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."); - } - - @Test - public void starts_has_no_effect_when_status_is_MANUAL_IN_PROGRESS_and_no_LicenseCommit_is_available_but_logs_at_debug_level() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(MANUAL_IN_PROGRESS); - - underTest.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - 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"); - } - - @Test - public void start_commit_license_and_finalizeInstallation_in_editionManagementState_when_status_is_MANUAL_IN_PROGRESS_and_LicenseCommit_is_available() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(MANUAL_IN_PROGRESS); - String license = RandomStringUtils.randomAlphanumeric(20); - when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); - - underTestWithLicenseCommit.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).getPendingLicense(); - verify(editionManagementState).finalizeInstallation(null); - verifyNoMoreInteractions(editionManagementState); - verify(licenseCommit).update(license); - verifyNoMoreInteractions(licenseCommit); - } - - @Test - public void start_commit_license_and_finalizeInstallation_with_error_in_editionManagementState_when_status_is_MANUAL_IN_PROGRESS_and_license_is_invalid() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(MANUAL_IN_PROGRESS); - String license = RandomStringUtils.randomAlphanumeric(20); - when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); - doThrow(new IllegalArgumentException("Faking an IAE because of an invalid license")) - .when(licenseCommit) - .update(license); - - underTestWithLicenseCommit.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).getPendingLicense(); - verify(editionManagementState).finalizeInstallation("Invalid staged license could not be commit on startup. Please input 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."); - } - - @Test - public void starts_put_editionManagement_set_in_automaticInstallError_when_status_is_AUTOMATIC_PROGRESS_and_no_LicenseCommit_is_available() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_IN_PROGRESS); - - underTest.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).installFailed("SonarQube was restarted before asynchronous installation of edition completed"); - verifyNoMoreInteractions(editionManagementState); - verifyZeroInteractions(licenseCommit); - } - - @Test - public void starts_put_editionManagement_set_in_automaticInstallError_when_status_is_AUTOMATIC_PROGRESS_and_LicenseCommit_is_available() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_IN_PROGRESS); - - underTestWithLicenseCommit.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).installFailed("SonarQube was restarted before asynchronous installation of edition completed"); - verifyNoMoreInteractions(editionManagementState); - verifyZeroInteractions(licenseCommit); - } - - @Test - public void should_commit_uninstall() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(EditionManagementState.PendingStatus.UNINSTALL_IN_PROGRESS); - - underTest.start(); - - verify(editionManagementState).getPendingInstallationStatus(); - verify(editionManagementState).finalizeInstallation(null); - verifyNoMoreInteractions(editionManagementState); - } - - @Test - public void should_fail_uninstall_if_license_commit_is_present() { - when(editionManagementState.getPendingInstallationStatus()).thenReturn(EditionManagementState.PendingStatus.UNINSTALL_IN_PROGRESS); - - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("License Manager plugin is still present"); - - underTestWithLicenseCommit.start(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/edition/FinalizeEditionChangeTest.java b/server/sonar-server/src/test/java/org/sonar/server/edition/FinalizeEditionChangeTest.java new file mode 100644 index 00000000000..43053abd0db --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/edition/FinalizeEditionChangeTest.java @@ -0,0 +1,275 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.edition; + +import java.util.Optional; +import org.apache.commons.lang.RandomStringUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.log.LogTester; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.server.license.LicenseCommit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_IN_PROGRESS; +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 FinalizeEditionChangeTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public LogTester logTester = new LogTester(); + + private MutableEditionManagementState editionManagementState = mock(MutableEditionManagementState.class); + private LicenseCommit licenseCommit = mock(LicenseCommit.class); + 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() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE); + + underTest.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).clearInstallErrorMessage(); + verifyNoMoreInteractions(editionManagementState); + } + + @Test + public void start_clears_error_message_when_status_is_NONE_with_LicenseCommit() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE); + + underTestWithLicenseCommit.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).clearInstallErrorMessage(); + verifyNoMoreInteractions(editionManagementState); + verifyZeroInteractions(licenseCommit); + } + + @Test + 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.WARN)) + .containsOnly("Edition installation didn't complete. License was not found."); + } + + @Test + public void start_commit_license_and_finalizeInstallation_in_editionManagementState_when_status_is_AUTOMATIC_READY_and_LicenseCommit_is_available() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); + String license = RandomStringUtils.randomAlphanumeric(20); + when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); + + underTestWithLicenseCommit.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).getPendingLicense(); + verify(editionManagementState).finalizeInstallation(null); + verifyNoMoreInteractions(editionManagementState); + verify(licenseCommit).update(license); + verifyNoMoreInteractions(licenseCommit); + } + + @Test + public void start_commit_license_and_finalizeInstallation_with_error_in_editionManagementState_when_status_is_AUTOMATIC_READY_and_license_is_invalid() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(AUTOMATIC_READY); + String license = RandomStringUtils.randomAlphanumeric(20); + when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); + doThrow(new IllegalArgumentException("Faking an IAE because of an invalid license")) + .when(licenseCommit) + .update(license); + + underTestWithLicenseCommit.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).getPendingLicense(); + 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("Edition installation didn't complete. License is not valid. Please set a new license."); + } + + @Test + 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.WARN)) + .containsOnly("Edition installation didn't complete. Some plugins were not installed."); + } + + @Test + public void start_commit_license_and_finalizeInstallation_in_editionManagementState_when_status_is_MANUAL_IN_PROGRESS_and_LicenseCommit_is_available() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(MANUAL_IN_PROGRESS); + String license = RandomStringUtils.randomAlphanumeric(20); + when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); + + underTestWithLicenseCommit.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).getPendingLicense(); + verify(editionManagementState).finalizeInstallation(null); + verifyNoMoreInteractions(editionManagementState); + verify(licenseCommit).update(license); + verifyNoMoreInteractions(licenseCommit); + } + + @Test + public void start_commit_license_and_finalizeInstallation_with_error_in_editionManagementState_when_status_is_MANUAL_IN_PROGRESS_and_license_is_invalid() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(MANUAL_IN_PROGRESS); + String license = RandomStringUtils.randomAlphanumeric(20); + when(editionManagementState.getPendingLicense()).thenReturn(Optional.of(license)); + doThrow(new IllegalArgumentException("Faking an IAE because of an invalid license")) + .when(licenseCommit) + .update(license); + + underTestWithLicenseCommit.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).getPendingLicense(); + 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("Edition installation didn't complete. License is not valid. Please set a new license."); + } + + @Test + 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(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).installFailed("SonarQube was restarted before asynchronous installation of edition completed"); + verifyNoMoreInteractions(editionManagementState); + verifyZeroInteractions(licenseCommit); + } + + @Test + 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(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).installFailed("SonarQube was restarted before asynchronous installation of edition completed"); + verifyNoMoreInteractions(editionManagementState); + 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); + + underTest.start(); + + verify(editionManagementState).getPendingInstallationStatus(); + verify(editionManagementState).finalizeInstallation(null); + verifyNoMoreInteractions(editionManagementState); + } + + @Test + public void should_fail_uninstall_if_license_commit_is_present() { + when(editionManagementState.getPendingInstallationStatus()).thenReturn(EditionManagementState.PendingStatus.UNINSTALL_IN_PROGRESS); + + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("License Manager plugin is still present"); + + underTestWithLicenseCommit.start(); + } +}