diff options
9 files changed, 88 insertions, 120 deletions
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java index fa5b7a898c4..bf712591eae 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java +++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java @@ -178,7 +178,9 @@ public class ProcessProperties { ENABLE_STOP_COMMAND("sonar.enableStopCommand"), // whether the blue/green deployment of server is enabled - BLUE_GREEN_ENABLED("sonar.blueGreenEnabled", DEFAULT_FALSE); + BLUE_GREEN_ENABLED("sonar.blueGreenEnabled", DEFAULT_FALSE), + + AUTO_DATABASE_UPGRADE("sonar.autoDatabaseUpgrade", DEFAULT_FALSE); /** * Properties that are defined for each LDAP server from the `ldap.servers` property diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java index 10755afccaa..0d4b9e27431 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/DefaultServerUpgradeStatus.java @@ -74,6 +74,10 @@ public class DefaultServerUpgradeStatus implements ServerUpgradeStatus, Startabl return configuration.getBoolean(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey()).orElse(false); } + public boolean isAutoDbUpgrade() { + return configuration.getBoolean(ProcessProperties.Property.AUTO_DATABASE_UPGRADE.getKey()).orElse(false); + } + @Override public String toString() { return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java index 140f4f297b7..9ef367e6084 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java @@ -38,6 +38,9 @@ public class AutoDbMigration implements Startable { if (serverUpgradeStatus.isFreshInstall()) { Loggers.get(getClass()).info("Automatically perform DB migration on fresh install"); migrationEngine.execute(); + } else if (serverUpgradeStatus.isUpgraded() && serverUpgradeStatus.isAutoDbUpgrade()) { + Loggers.get(getClass()).info("Automatically perform DB migration, as automatic database upgrade is enabled"); + migrationEngine.execute(); } else if (serverUpgradeStatus.isUpgraded() && serverUpgradeStatus.isBlueGreen()) { Loggers.get(getClass()).info("Automatically perform DB migration on blue/green deployment"); migrationEngine.execute(); diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/serverid/ServerIdManager.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/serverid/ServerIdManager.java index 86ecd608095..33afdd866c4 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/serverid/ServerIdManager.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/serverid/ServerIdManager.java @@ -20,9 +20,9 @@ package org.sonar.server.platform.serverid; import java.util.Optional; -import org.sonar.api.Startable; import org.sonar.api.SonarQubeSide; import org.sonar.api.SonarRuntime; +import org.sonar.api.Startable; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.platform.ServerId; @@ -36,8 +36,6 @@ import static com.google.common.base.Preconditions.checkState; import static org.apache.commons.lang.StringUtils.isEmpty; import static org.apache.commons.lang.StringUtils.isNotEmpty; import static org.sonar.api.CoreProperties.SERVER_ID; -import static org.sonar.core.platform.ServerId.Format.DEPRECATED; -import static org.sonar.core.platform.ServerId.Format.NO_DATABASE_ID; import static org.sonar.server.property.InternalProperties.SERVER_ID_CHECKSUM; public class ServerIdManager implements Startable { @@ -86,12 +84,6 @@ public class ServerIdManager implements Startable { } private boolean keepServerId(ServerId serverId, Optional<String> checksum) { - ServerId.Format format = serverId.getFormat(); - if (format == DEPRECATED || format == NO_DATABASE_ID) { - LOGGER.info("Server ID is changed to new format."); - return false; - } - if (checksum.isPresent()) { String expectedChecksum = serverIdChecksum.computeFor(serverId.toString()); if (!expectedChecksum.equals(checksum.get())) { @@ -105,9 +97,6 @@ public class ServerIdManager implements Startable { } private ServerId replaceCurrentServerId(ServerId currentServerId) { - if (currentServerId.getFormat() == DEPRECATED) { - return serverIdFactory.create(); - } return serverIdFactory.create(currentServerId); } diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java index 389b420256a..ea564a58830 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java @@ -88,4 +88,17 @@ public class DefaultServerUpgradeStatusTest { settings.setProperty("sonar.blueGreenEnabled", false); assertThat(underTest.isBlueGreen()).isFalse(); } + + + @Test + public void isAutoDbUpgrade() { + settings.clear(); + assertThat(underTest.isAutoDbUpgrade()).isFalse(); + + settings.setProperty("sonar.autoDatabaseUpgrade", true); + assertThat(underTest.isAutoDbUpgrade()).isTrue(); + + settings.setProperty("sonar.autoDatabaseUpgrade", false); + assertThat(underTest.isAutoDbUpgrade()).isFalse(); + } } diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java index 8e92b826eda..cdd29b1da43 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/db/migration/AutoDbMigrationTest.java @@ -113,6 +113,30 @@ public class AutoDbMigrationTest { } @Test + public void start_runs_MigrationEngine_if_autoDbMigration_enabled() { + mockFreshInstall(false); + when(serverUpgradeStatus.isUpgraded()).thenReturn(true); + when(serverUpgradeStatus.isAutoDbUpgrade()).thenReturn(true); + + underTest.start(); + + verify(migrationEngine).execute(); + assertThat(logTester.logs(LoggerLevel.INFO)).contains("Automatically perform DB migration, as automatic database upgrade is enabled"); + } + + @Test + public void start_does_nothing_if_autoDbMigration_but_no_upgrade() { + mockFreshInstall(false); + when(serverUpgradeStatus.isUpgraded()).thenReturn(false); + when(serverUpgradeStatus.isAutoDbUpgrade()).thenReturn(true); + + underTest.start(); + + verifyNoInteractions(migrationEngine); + assertThat(logTester.logs(LoggerLevel.INFO)).isEmpty(); + } + + @Test public void stop_has_no_effect() { underTest.stop(); } diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/serverid/ServerIdManagerTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/serverid/ServerIdManagerTest.java index a32860a6886..78b85cd5d63 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/serverid/ServerIdManagerTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/serverid/ServerIdManagerTest.java @@ -19,9 +19,7 @@ */ package org.sonar.server.platform.serverid; -import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.After; import org.junit.Rule; @@ -46,7 +44,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,19 +56,17 @@ import static org.sonar.core.platform.ServerId.UUID_DATASET_ID_LENGTH; @RunWith(DataProviderRunner.class) public class ServerIdManagerTest { - private static final ServerId OLD_FORMAT_SERVER_ID = ServerId.parse("20161123150657"); - private static final ServerId NO_DATABASE_ID_SERVER_ID = ServerId.parse(randomAlphanumeric(UUID_DATASET_ID_LENGTH)); private static final ServerId WITH_DATABASE_ID_SERVER_ID = ServerId.of(randomAlphanumeric(DATABASE_ID_LENGTH), randomAlphanumeric(NOT_UUID_DATASET_ID_LENGTH)); private static final String CHECKSUM_1 = randomAlphanumeric(12); @Rule public final DbTester dbTester = DbTester.create(System2.INSTANCE); - private ServerIdChecksum serverIdChecksum = mock(ServerIdChecksum.class); - private ServerIdFactory serverIdFactory = mock(ServerIdFactory.class); - private DbClient dbClient = dbTester.getDbClient(); - private DbSession dbSession = dbTester.getSession(); - private WebServer webServer = mock(WebServer.class); + private final ServerIdChecksum serverIdChecksum = mock(ServerIdChecksum.class); + private final ServerIdFactory serverIdFactory = mock(ServerIdFactory.class); + private final DbClient dbClient = dbTester.getDbClient(); + private final DbSession dbSession = dbTester.getSession(); + private final WebServer webServer = mock(WebServer.class); private ServerIdManager underTest; @After @@ -83,39 +78,26 @@ public class ServerIdManagerTest { @Test public void web_leader_persists_new_server_id_if_missing() { - mockCreateNewServerId(WITH_DATABASE_ID_SERVER_ID); + mockCreateNewServerId(); mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); when(webServer.isStartupLeader()).thenReturn(true); test(SERVER); - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - verifyCreateNewServerIdFromScratch(); - } - - @Test - public void web_leader_persists_new_server_id_if_format_is_old_date() { - insertServerId(OLD_FORMAT_SERVER_ID); - mockCreateNewServerId(WITH_DATABASE_ID_SERVER_ID); - mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - when(webServer.isStartupLeader()).thenReturn(true); - - test(SERVER); - - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); + verifyDb(CHECKSUM_1); verifyCreateNewServerIdFromScratch(); } @Test public void web_leader_persists_new_server_id_if_value_is_empty() { insertServerId(""); - mockCreateNewServerId(WITH_DATABASE_ID_SERVER_ID); + mockCreateNewServerId(); mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); when(webServer.isStartupLeader()).thenReturn(true); test(SERVER); - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); + verifyDb(CHECKSUM_1); verifyCreateNewServerIdFromScratch(); } @@ -128,39 +110,7 @@ public class ServerIdManagerTest { test(SERVER); - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - } - - @Test - public void web_leader_creates_server_id_from_scratch_if_checksum_fails_for_serverId_in_deprecated_format() { - ServerId currentServerId = OLD_FORMAT_SERVER_ID; - insertServerId(currentServerId); - insertChecksum("invalid"); - mockChecksumOf(currentServerId, "valid"); - mockCreateNewServerId(WITH_DATABASE_ID_SERVER_ID); - mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - when(webServer.isStartupLeader()).thenReturn(true); - - test(SERVER); - - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - verifyCreateNewServerIdFromScratch(); - } - - @Test - public void web_leader_creates_server_id_from_current_serverId_without_databaseId_if_checksum_fails() { - ServerId currentServerId = ServerId.parse(randomAlphanumeric(UUID_DATASET_ID_LENGTH)); - insertServerId(currentServerId); - insertChecksum("does_not_match_WITH_DATABASE_ID_SERVER_ID"); - mockChecksumOf(currentServerId, "matches_WITH_DATABASE_ID_SERVER_ID"); - mockCreateNewServerIdFrom(currentServerId, WITH_DATABASE_ID_SERVER_ID); - mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - when(webServer.isStartupLeader()).thenReturn(true); - - test(SERVER); - - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); - verifyCreateNewServerIdFrom(currentServerId); + verifyDb(CHECKSUM_1); } @Test @@ -169,13 +119,13 @@ public class ServerIdManagerTest { insertServerId(currentServerId); insertChecksum("does_not_match_WITH_DATABASE_ID_SERVER_ID"); mockChecksumOf(currentServerId, "matches_WITH_DATABASE_ID_SERVER_ID"); - mockCreateNewServerIdFrom(currentServerId, WITH_DATABASE_ID_SERVER_ID); + mockCreateNewServerIdFrom(currentServerId); mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); when(webServer.isStartupLeader()).thenReturn(true); test(SERVER); - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); + verifyDb(CHECKSUM_1); verifyCreateNewServerIdFrom(currentServerId); } @@ -187,21 +137,20 @@ public class ServerIdManagerTest { test(SERVER); - verifyDb(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); + verifyDb(CHECKSUM_1); } @Test - @UseDataProvider("allFormatsOfServerId") - public void web_follower_does_not_fail_if_server_id_matches_checksum(ServerId serverId) { - insertServerId(serverId); + public void web_follower_does_not_fail_if_server_id_matches_checksum() { + insertServerId(WITH_DATABASE_ID_SERVER_ID); insertChecksum(CHECKSUM_1); - mockChecksumOf(serverId, CHECKSUM_1); + mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); when(webServer.isStartupLeader()).thenReturn(false); test(SERVER); // no changes - verifyDb(serverId, CHECKSUM_1); + verifyDb(CHECKSUM_1); } @Test @@ -220,12 +169,11 @@ public class ServerIdManagerTest { } @Test - @UseDataProvider("allFormatsOfServerId") - public void web_follower_fails_if_checksum_does_not_match(ServerId serverId) { + public void web_follower_fails_if_checksum_does_not_match() { String dbChecksum = "boom"; - insertServerId(serverId); + insertServerId(WITH_DATABASE_ID_SERVER_ID); insertChecksum(dbChecksum); - mockChecksumOf(serverId, CHECKSUM_1); + mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); when(webServer.isStartupLeader()).thenReturn(false); try { @@ -234,21 +182,20 @@ public class ServerIdManagerTest { } catch (IllegalStateException e) { assertThat(e.getMessage()).isEqualTo("Server ID is invalid"); // no changes - verifyDb(serverId, dbChecksum); + verifyDb(dbChecksum); } } @Test - @UseDataProvider("allFormatsOfServerId") - public void compute_engine_does_not_fail_if_server_id_is_valid(ServerId serverId) { - insertServerId(serverId); + public void compute_engine_does_not_fail_if_server_id_is_valid() { + insertServerId(WITH_DATABASE_ID_SERVER_ID); insertChecksum(CHECKSUM_1); - mockChecksumOf(serverId, CHECKSUM_1); + mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); test(COMPUTE_ENGINE); // no changes - verifyDb(serverId, CHECKSUM_1); + verifyDb(CHECKSUM_1); } @Test @@ -264,12 +211,11 @@ public class ServerIdManagerTest { } @Test - @UseDataProvider("allFormatsOfServerId") - public void compute_engine_fails_if_server_id_is_invalid(ServerId serverId) { + public void compute_engine_fails_if_server_id_is_invalid() { String dbChecksum = "boom"; - insertServerId(serverId); + insertServerId(WITH_DATABASE_ID_SERVER_ID); insertChecksum(dbChecksum); - mockChecksumOf(serverId, CHECKSUM_1); + mockChecksumOf(WITH_DATABASE_ID_SERVER_ID, CHECKSUM_1); try { test(SERVER); @@ -277,19 +223,10 @@ public class ServerIdManagerTest { } catch (IllegalStateException e) { assertThat(e.getMessage()).isEqualTo("Server ID is invalid"); // no changes - verifyDb(serverId, dbChecksum); + verifyDb(dbChecksum); } } - @DataProvider - public static Object[][] allFormatsOfServerId() { - return new Object[][]{ - {OLD_FORMAT_SERVER_ID}, - {NO_DATABASE_ID_SERVER_ID}, - {WITH_DATABASE_ID_SERVER_ID} - }; - } - private void expectEmptyServerIdException(ThrowingCallable callback) { assertThatThrownBy(callback) .isInstanceOf(IllegalStateException.class) @@ -302,22 +239,22 @@ public class ServerIdManagerTest { .hasMessage("Property sonar.core.id is missing in database"); } - private void verifyDb(ServerId expectedServerId, String expectedChecksum) { + private void verifyDb(String expectedChecksum) { assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, CoreProperties.SERVER_ID)) .extracting(PropertyDto::getValue) - .isEqualTo(expectedServerId.toString()); + .isEqualTo(ServerIdManagerTest.WITH_DATABASE_ID_SERVER_ID.toString()); assertThat(dbClient.internalPropertiesDao().selectByKey(dbSession, InternalProperties.SERVER_ID_CHECKSUM)) .hasValue(expectedChecksum); } - private void mockCreateNewServerId(ServerId newServerId) { - when(serverIdFactory.create()).thenReturn(newServerId); + private void mockCreateNewServerId() { + when(serverIdFactory.create()).thenReturn(WITH_DATABASE_ID_SERVER_ID); when(serverIdFactory.create(any())).thenThrow(new IllegalStateException("new ServerId should not be created from current server id")); } - private void mockCreateNewServerIdFrom(ServerId currentServerId, ServerId newServerId) { + private void mockCreateNewServerIdFrom(ServerId currentServerId) { when(serverIdFactory.create()).thenThrow(new IllegalStateException("new ServerId should be created from current server id")); - when(serverIdFactory.create(eq(currentServerId))).thenReturn(newServerId); + when(serverIdFactory.create(currentServerId)).thenReturn(ServerIdManagerTest.WITH_DATABASE_ID_SERVER_ID); } private void verifyCreateNewServerIdFromScratch() { diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ServerId.java b/sonar-core/src/main/java/org/sonar/core/platform/ServerId.java index d5bc81e54c5..30861f3d600 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/ServerId.java +++ b/sonar-core/src/main/java/org/sonar/core/platform/ServerId.java @@ -28,7 +28,6 @@ import java.util.Set; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import org.sonar.api.CoreProperties; -import org.sonar.core.util.UuidFactory; import static com.google.common.base.Preconditions.checkArgument; import static org.sonar.core.platform.ServerId.Format.DEPRECATED; @@ -110,8 +109,8 @@ public final class ServerId { public static ServerId of(@Nullable String databaseId, String datasetId) { if (databaseId != null) { - int databaseIdLength = databaseId.length(); - checkArgument(databaseIdLength == DATABASE_ID_LENGTH, "Illegal databaseId length (%s)", databaseIdLength); + int databaseIdLength = databaseId.length(); + checkArgument(databaseIdLength == DATABASE_ID_LENGTH, "Illegal databaseId length (%s)", databaseIdLength); } int datasetIdLength = datasetId.length(); checkArgument(datasetIdLength == DEPRECATED_SERVER_ID_LENGTH @@ -120,9 +119,6 @@ public final class ServerId { return new ServerId(databaseId, datasetId); } - public static ServerId create(UuidFactory uuidFactory) { - return new ServerId(null, uuidFactory.create()); - } /** * Checks whether the specified value is a date according to the old format of the {@link CoreProperties#SERVER_ID}. diff --git a/sonar-core/src/test/java/org/sonar/core/platform/ServerIdTest.java b/sonar-core/src/test/java/org/sonar/core/platform/ServerIdTest.java index 57a7c2eae87..a63a3bff968 100644 --- a/sonar-core/src/test/java/org/sonar/core/platform/ServerIdTest.java +++ b/sonar-core/src/test/java/org/sonar/core/platform/ServerIdTest.java @@ -37,12 +37,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.sonar.core.platform.ServerId.DATABASE_ID_LENGTH; import static org.sonar.core.platform.ServerId.DEPRECATED_SERVER_ID_LENGTH; -import static org.sonar.core.platform.ServerId.NOT_UUID_DATASET_ID_LENGTH; -import static org.sonar.core.platform.ServerId.SPLIT_CHARACTER; -import static org.sonar.core.platform.ServerId.UUID_DATASET_ID_LENGTH; import static org.sonar.core.platform.ServerId.Format.DEPRECATED; import static org.sonar.core.platform.ServerId.Format.NO_DATABASE_ID; import static org.sonar.core.platform.ServerId.Format.WITH_DATABASE_ID; +import static org.sonar.core.platform.ServerId.NOT_UUID_DATASET_ID_LENGTH; +import static org.sonar.core.platform.ServerId.SPLIT_CHARACTER; +import static org.sonar.core.platform.ServerId.UUID_DATASET_ID_LENGTH; @RunWith(DataProviderRunner.class) public class ServerIdTest { |