public interface DatabaseMigrationState {
+ String UNSUPPORTED_DATABASE_MIGRATION_STATUS = "Unsupported DatabaseMigration status";
+ String NO_CONNECTION_TO_DB = "Cannot connect to Database.";
+
enum Status {
- NONE, RUNNING, FAILED, SUCCEEDED
+ NONE("NO_MIGRATION", "Database is up-to-date, no migration needed."),
+ RUNNING("MIGRATION_RUNNING", "Database migration is running."),
+ FAILED("MIGRATION_FAILED", "Migration failed: %s.<br/> Please check logs."),
+ SUCCEEDED("MIGRATION_SUCCEEDED", "Migration succeeded."),
+ STATUS_NOT_SUPPORTED("NOT_SUPPORTED", "Upgrade is not supported on embedded database."),
+ MIGRATION_REQUIRED("MIGRATION_REQUIRED", "Database migration is required. DB migration can be started using WS /api/system/migrate_db.");
+
+ private final String stringRepresentation;
+ private final String message;
+
+ Status(String stringRepresentation, String message) {
+ this.stringRepresentation = stringRepresentation;
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return stringRepresentation;
+ }
+
}
/**
private static final String SYSTEM_ENDPOINTS = "/system";
public static final String LIVENESS_ENDPOINT = SYSTEM_ENDPOINTS + "/liveness";
public static final String HEALTH_ENDPOINT = SYSTEM_ENDPOINTS + "/health";
+ public static final String DATABASE_MIGRATIONS_ENDPOINT = SYSTEM_ENDPOINTS + "/migrations-status";
public static final String USERS_MANAGEMENT_DOMAIN = "/users-management";
public static final String USER_ENDPOINT = USERS_MANAGEMENT_DOMAIN + "/users";
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.v2.api.system.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.DatabaseMigrationState;
+import org.sonar.server.platform.db.migration.version.DatabaseVersion;
+import org.sonar.server.v2.common.DateString;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.NO_CONNECTION_TO_DB;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.UNSUPPORTED_DATABASE_MIGRATION_STATUS;
+import static org.sonar.server.v2.WebApiEndpoints.DATABASE_MIGRATIONS_ENDPOINT;
+
+@RestController
+@RequestMapping(DATABASE_MIGRATIONS_ENDPOINT)
+public class DatabaseMigrationsController {
+
+ private final DatabaseVersion databaseVersion;
+ private final DatabaseMigrationState databaseMigrationState;
+ private final Database database;
+
+ public DatabaseMigrationsController(DatabaseVersion databaseVersion, DatabaseMigrationState databaseMigrationState, Database database) {
+ this.databaseVersion = databaseVersion;
+ this.databaseMigrationState = databaseMigrationState;
+ this.database = database;
+ }
+
+ @Operation(summary = "Gets the status of ongoing database migrations, if any", description = "Return the detailed status of ongoing database migrations" +
+ " including starting date. If no migration is ongoing or needed it is still possible to call this endpoint and receive appropriate information.")
+ @GetMapping
+ public DatabaseMigrationsResponse getStatus() {
+ Optional<Long> currentVersion = databaseVersion.getVersion();
+ checkState(currentVersion.isPresent(), NO_CONNECTION_TO_DB);
+ DatabaseVersion.Status status = databaseVersion.getStatus();
+ if (status == DatabaseVersion.Status.UP_TO_DATE || status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
+ return new DatabaseMigrationsResponse(databaseMigrationState);
+ } else if (!database.getDialect().supportsMigration()) {
+ return new DatabaseMigrationsResponse(DatabaseMigrationState.Status.STATUS_NOT_SUPPORTED);
+ } else {
+ return switch (databaseMigrationState.getStatus()) {
+ case RUNNING, FAILED, SUCCEEDED -> new DatabaseMigrationsResponse(databaseMigrationState);
+ case NONE -> new DatabaseMigrationsResponse(DatabaseMigrationState.Status.MIGRATION_REQUIRED);
+ default -> throw new IllegalArgumentException(UNSUPPORTED_DATABASE_MIGRATION_STATUS);
+ };
+ }
+
+ }
+
+ public record DatabaseMigrationsResponse(String status, @Nullable String startedAt, @Nullable String message) {
+
+ public DatabaseMigrationsResponse(DatabaseMigrationState state) {
+ this(state.getStatus().toString(),
+ DateString.from(state.getStartedAt()),
+ state.getError() != null ? state.getError().getMessage() : state.getStatus().getMessage());
+ }
+
+ public DatabaseMigrationsResponse(DatabaseMigrationState.Status status) {
+ this(status.toString(), null, status.getMessage());
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.v2.common;
+
+import java.util.Date;
+import javax.annotation.Nullable;
+
+public class DateString {
+
+ private DateString() {
+ // intentionally empty
+ }
+
+ public static String from(@Nullable Date date) {
+ if (date == null) {
+ return null;
+ }
+ return date.toString();
+ }
+}
import javax.annotation.Nullable;
import org.sonar.api.platform.Server;
import org.sonar.api.resources.Languages;
+import org.sonar.db.Database;
import org.sonar.db.DbClient;
import org.sonar.server.common.gitlab.config.GitlabConfigurationService;
import org.sonar.server.common.group.service.GroupMembershipService;
import org.sonar.server.health.HealthChecker;
import org.sonar.server.platform.NodeInformation;
import org.sonar.server.platform.ServerFileSystem;
+import org.sonar.server.platform.db.migration.DatabaseMigrationState;
+import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import org.sonar.server.rule.RuleDescriptionFormatter;
import org.sonar.server.user.SystemPasscode;
import org.sonar.server.user.UserSession;
import org.sonar.server.v2.api.rule.controller.DefaultRuleController;
import org.sonar.server.v2.api.rule.controller.RuleController;
import org.sonar.server.v2.api.rule.converter.RuleRestResponseGenerator;
+import org.sonar.server.v2.api.system.controller.DatabaseMigrationsController;
import org.sonar.server.v2.api.system.controller.DefaultLivenessController;
import org.sonar.server.v2.api.system.controller.HealthController;
import org.sonar.server.v2.api.system.controller.LivenessController;
return new HealthController(healthChecker, systemPasscode, nodeInformation, userSession);
}
+ @Bean
+ public DatabaseMigrationsController databaseMigrationsController(DatabaseVersion databaseVersion, DatabaseMigrationState databaseMigrationState,
+ Database database) {
+ return new DatabaseMigrationsController(databaseVersion, databaseMigrationState, database);
+ }
+
@Bean
public UsersSearchRestResponseGenerator usersSearchResponseGenerator(UserSession userSession) {
return new UsersSearchRestResponseGenerator(userSession);
*/
package org.sonar.server.v2.config;
+import org.sonar.db.Database;
import org.sonar.server.common.health.DbConnectionNodeCheck;
import org.sonar.server.common.platform.LivenessChecker;
import org.sonar.server.common.platform.SafeModeLivenessCheckerImpl;
import org.sonar.server.health.HealthChecker;
+import org.sonar.server.platform.db.migration.DatabaseMigrationState;
+import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import org.sonar.server.user.SystemPasscode;
+import org.sonar.server.v2.api.system.controller.DatabaseMigrationsController;
import org.sonar.server.v2.api.system.controller.DefaultLivenessController;
import org.sonar.server.v2.api.system.controller.HealthController;
import org.sonar.server.v2.api.system.controller.LivenessController;
public HealthController healthController(HealthChecker healthChecker, SystemPasscode systemPasscode) {
return new HealthController(healthChecker, systemPasscode);
}
+
+ @Bean
+ public DatabaseMigrationsController databaseMigrationsController(DatabaseVersion databaseVersion, DatabaseMigrationState databaseMigrationState,
+ Database database) {
+ return new DatabaseMigrationsController(databaseVersion, databaseMigrationState, database);
+ }
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.v2.api.system.controller;
+
+import java.util.Date;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.server.platform.db.migration.DatabaseMigrationState;
+import org.sonar.server.platform.db.migration.version.DatabaseVersion;
+import org.sonar.server.v2.api.ControllerTester;
+import org.springframework.test.web.servlet.MockMvc;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.FAILED;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.NONE;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.RUNNING;
+import static org.sonar.server.v2.WebApiEndpoints.DATABASE_MIGRATIONS_ENDPOINT;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+class DatabaseMigrationsControllerTest {
+
+ private static final Date SOME_DATE = new Date();
+ private final DatabaseVersion databaseVersion = mock();
+ private final DatabaseMigrationState migrationState = mock();
+ private final Dialect dialect = mock(Dialect.class);
+ private final Database database = mock();
+ private final MockMvc mockMvc = ControllerTester.getMockMvc(new DatabaseMigrationsController(databaseVersion, migrationState, database));
+
+ @BeforeEach
+ public void before() {
+ when(database.getDialect()).thenReturn(dialect);
+ when(databaseVersion.getVersion()).thenReturn(Optional.of(1L));
+ }
+
+ @Test
+ void getStatus_whenDatabaseHasNoVersion_return500() throws Exception {
+ Mockito.reset(databaseVersion);
+ when(databaseVersion.getVersion()).thenReturn(Optional.empty());
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().is5xxServerError(),
+ content().json("{\"message\":\"Cannot connect to Database.\"}"));
+ }
+
+ @Test
+ void getStatus_migrationNotNeeded_returnUpToDateStatus() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE);
+ when(migrationState.getStatus()).thenReturn(NONE);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"NO_MIGRATION\",\"message\":\"Database is up-to-date, no migration needed.\"}"));
+ }
+
+ @Test
+ void getStatus_whenDowngradeRequired_returnNone() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE);
+ when(migrationState.getStatus()).thenReturn(NONE);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"NO_MIGRATION\",\"message\":\"Database is up-to-date, no migration needed.\"}"));
+ }
+
+ @Test
+ void getStatus_whenDbRequiresUpgradeButDialectIsNotSupported_returnNotSupported() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.FRESH_INSTALL);
+ when(dialect.supportsMigration()).thenReturn(false);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"NOT_SUPPORTED\",\"message\":\"Upgrade is not supported on embedded database.\"}"));
+ }
+
+ @Test
+ void getStatus_whenDbMigrationsRunning_returnRunning() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+ when(dialect.supportsMigration()).thenReturn(true);
+ when(migrationState.getStatus()).thenReturn(RUNNING);
+ when(migrationState.getStartedAt()).thenReturn(SOME_DATE);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"MIGRATION_RUNNING\",\"message\":\"Database migration is running.\"}"));
+ }
+
+ @Test
+ void getStatus_whenDbMigrationsFailed_returnFailed() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+ when(dialect.supportsMigration()).thenReturn(true);
+ when(migrationState.getStatus()).thenReturn(DatabaseMigrationState.Status.FAILED);
+ when(migrationState.getStartedAt()).thenReturn(SOME_DATE);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"MIGRATION_FAILED\",\"message\":\"Migration failed: %s.<br/> Please check logs.\"}"));
+ }
+
+ @Test
+ void getStatus_whenDbMigrationsSucceeded_returnSucceeded() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+ when(dialect.supportsMigration()).thenReturn(true);
+ when(migrationState.getStatus()).thenReturn(DatabaseMigrationState.Status.SUCCEEDED);
+ when(migrationState.getStartedAt()).thenReturn(SOME_DATE);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"MIGRATION_SUCCEEDED\",\"message\":\"Migration succeeded.\"}"));
+ }
+
+
+ @Test
+ void getStatus_whenMigrationRequired_returnMigrationRequired() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+ when(dialect.supportsMigration()).thenReturn(true);
+ when(migrationState.getStatus()).thenReturn(NONE);
+ when(migrationState.getStartedAt()).thenReturn(SOME_DATE);
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"MIGRATION_REQUIRED\",\"message\":\"Database migration is required. DB migration " +
+ "can be started using WS /api/system/migrate_db.\"}"));
+ }
+
+ @Test
+ void getStatus_whenMigrationFailedWithError_IncludeErrorInResponse() throws Exception {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.FRESH_INSTALL);
+ when(dialect.supportsMigration()).thenReturn(true);
+ when(migrationState.getStatus()).thenReturn(FAILED);
+ when(migrationState.getStartedAt()).thenReturn(SOME_DATE);
+ when(migrationState.getError()).thenReturn(new UnsupportedOperationException("error message"));
+
+ mockMvc.perform(get(DATABASE_MIGRATIONS_ENDPOINT)).andExpectAll(status().isOk(),
+ content().json("{\"status\":\"MIGRATION_FAILED\",\"message\":\"error message\"}"));
+ }
+}
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.server.platform.db.migration.DatabaseMigrationState;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.FAILED;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.MIGRATION_REQUIRED;
import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.RUNNING;
public class DbMigrationJsonWriter {
static final String FIELD_MESSAGE = "message";
static final String FIELD_STARTED_AT = "startedAt";
- static final String STATUS_NO_MIGRATION = "NO_MIGRATION";
- static final String STATUS_NOT_SUPPORTED = "NOT_SUPPORTED";
- static final String STATUS_MIGRATION_RUNNING = "MIGRATION_RUNNING";
- static final String STATUS_MIGRATION_FAILED = "MIGRATION_FAILED";
- static final String STATUS_MIGRATION_SUCCEEDED = "MIGRATION_SUCCEEDED";
- static final String STATUS_MIGRATION_REQUIRED = "MIGRATION_REQUIRED";
-
- static final String NO_CONNECTION_TO_DB = "Cannot connect to Database.";
- static final String UNSUPPORTED_DATABASE_MIGRATION_STATUS = "Unsupported DatabaseMigration status";
- static final String MESSAGE_NO_MIGRATION_ON_EMBEDDED_DATABASE = "Upgrade is not supported on embedded database.";
- static final String MESSAGE_MIGRATION_REQUIRED = "Database migration is required. DB migration can be started using WS /api/system/migrate_db.";
- static final String MESSAGE_STATUS_NONE = "Database is up-to-date, no migration needed.";
- static final String MESSAGE_STATUS_RUNNING = "Database migration is running.";
- static final String MESSAGE_STATUS_SUCCEEDED = "Migration succeeded.";
- static final String MESSAGE_STATUS_FAILED = "Migration failed: %s.<br/> Please check logs.";
private DbMigrationJsonWriter() {
// static methods only
static void write(JsonWriter json, DatabaseMigrationState databaseMigrationState) {
json.beginObject()
- .prop(FIELD_STATE, statusToJson(databaseMigrationState.getStatus()))
- .prop(FIELD_MESSAGE, buildMessage(databaseMigrationState))
+ .prop(FIELD_STATE, databaseMigrationState.getStatus().toString())
+ .prop(FIELD_MESSAGE, writeMessageIncludingError(databaseMigrationState))
.propDateTime(FIELD_STARTED_AT, databaseMigrationState.getStartedAt())
.endObject();
}
+ private static String writeMessageIncludingError(DatabaseMigrationState state) {
+ if (state.getStatus() == FAILED) {
+ Throwable error = state.getError();
+ return String.format(state.getStatus().getMessage(), error != null ? error.getMessage() : "No failure error");
+ } else {
+ return state.getStatus().getMessage();
+ }
+ }
+
static void writeNotSupportedResponse(JsonWriter json) {
json.beginObject()
- .prop(FIELD_STATE, STATUS_NOT_SUPPORTED)
- .prop(FIELD_MESSAGE, MESSAGE_NO_MIGRATION_ON_EMBEDDED_DATABASE)
+ .prop(FIELD_STATE, DatabaseMigrationState.Status.STATUS_NOT_SUPPORTED.toString())
+ .prop(FIELD_MESSAGE, DatabaseMigrationState.Status.STATUS_NOT_SUPPORTED.getMessage())
.endObject();
}
static void writeJustStartedResponse(JsonWriter json, DatabaseMigrationState databaseMigrationState) {
json.beginObject()
- .prop(FIELD_STATE, statusToJson(RUNNING))
- .prop(FIELD_MESSAGE, MESSAGE_STATUS_RUNNING)
+ .prop(FIELD_STATE, RUNNING.toString())
+ .prop(FIELD_MESSAGE, RUNNING.getMessage())
.propDateTime(FIELD_STARTED_AT, databaseMigrationState.getStartedAt())
.endObject();
}
static void writeMigrationRequiredResponse(JsonWriter json) {
json.beginObject()
- .prop(FIELD_STATE, STATUS_MIGRATION_REQUIRED)
- .prop(FIELD_MESSAGE, MESSAGE_MIGRATION_REQUIRED)
+ .prop(FIELD_STATE, MIGRATION_REQUIRED.toString())
+ .prop(FIELD_MESSAGE, MIGRATION_REQUIRED.getMessage())
.endObject();
}
- private static String statusToJson(DatabaseMigrationState.Status status) {
- switch (status) {
- case NONE:
- return STATUS_NO_MIGRATION;
- case RUNNING:
- return STATUS_MIGRATION_RUNNING;
- case FAILED:
- return STATUS_MIGRATION_FAILED;
- case SUCCEEDED:
- return STATUS_MIGRATION_SUCCEEDED;
- default:
- throw new IllegalArgumentException(
- "Unsupported DatabaseMigration.Status " + status + " can not be converted to JSON value");
- }
- }
-
- private static String buildMessage(DatabaseMigrationState databaseMigrationState) {
- switch (databaseMigrationState.getStatus()) {
- case NONE:
- return MESSAGE_STATUS_NONE;
- case RUNNING:
- return MESSAGE_STATUS_RUNNING;
- case SUCCEEDED:
- return MESSAGE_STATUS_SUCCEEDED;
- case FAILED:
- return String.format(MESSAGE_STATUS_FAILED, failureMessage(databaseMigrationState));
- default:
- return UNSUPPORTED_DATABASE_MIGRATION_STATUS;
- }
- }
-
- private static String failureMessage(DatabaseMigrationState databaseMigrationState) {
- Throwable failureError = databaseMigrationState.getError();
- if (failureError == null) {
- return "No failure error";
- }
- return failureError.getMessage();
- }
-
static String statusDescription() {
return "State values are:" +
"<ul>" +
import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import static com.google.common.base.Preconditions.checkState;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.NO_CONNECTION_TO_DB;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.UNSUPPORTED_DATABASE_MIGRATION_STATUS;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.NO_CONNECTION_TO_DB;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.UNSUPPORTED_DATABASE_MIGRATION_STATUS;
import static org.sonar.server.platform.ws.DbMigrationJsonWriter.statusDescription;
import static org.sonar.server.platform.ws.DbMigrationJsonWriter.write;
import static org.sonar.server.platform.ws.DbMigrationJsonWriter.writeMigrationRequiredResponse;
import org.sonar.server.platform.db.migration.DatabaseMigrationState;
import static com.google.common.base.Preconditions.checkState;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.NO_CONNECTION_TO_DB;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.UNSUPPORTED_DATABASE_MIGRATION_STATUS;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.NO_CONNECTION_TO_DB;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.UNSUPPORTED_DATABASE_MIGRATION_STATUS;
import static org.sonar.server.platform.ws.DbMigrationJsonWriter.statusDescription;
import static org.sonar.server.platform.ws.DbMigrationJsonWriter.write;
import static org.sonar.server.platform.ws.DbMigrationJsonWriter.writeJustStartedResponse;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.FAILED;
+import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.MIGRATION_REQUIRED;
import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.NONE;
import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.RUNNING;
import static org.sonar.server.platform.db.migration.DatabaseMigrationState.Status.SUCCEEDED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.MESSAGE_MIGRATION_REQUIRED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.MESSAGE_NO_MIGRATION_ON_EMBEDDED_DATABASE;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.MESSAGE_STATUS_NONE;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.MESSAGE_STATUS_RUNNING;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.MESSAGE_STATUS_SUCCEEDED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_MIGRATION_FAILED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_MIGRATION_REQUIRED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_MIGRATION_RUNNING;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_MIGRATION_SUCCEEDED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_NOT_SUPPORTED;
-import static org.sonar.server.platform.ws.DbMigrationJsonWriter.STATUS_NO_MIGRATION;
import static org.sonar.test.JsonAssert.assertJson;
@RunWith(DataProviderRunner.class)
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_NO_MIGRATION, MESSAGE_STATUS_NONE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(NONE.toString(), NONE.getMessage()));
}
// this test will raise a IllegalArgumentException when an unsupported value is added to the Status enum
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_NO_MIGRATION, MESSAGE_STATUS_NONE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(NONE.toString(), NONE.getMessage()));
}
@Test
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_NOT_SUPPORTED, MESSAGE_NO_MIGRATION_ON_EMBEDDED_DATABASE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(Status.STATUS_NOT_SUPPORTED.toString(), Status.STATUS_NOT_SUPPORTED.getMessage()));
}
@Test
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_MIGRATION_RUNNING, MESSAGE_STATUS_RUNNING, SOME_DATE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(RUNNING.toString(), RUNNING.getMessage(), SOME_DATE));
}
@Test
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_MIGRATION_FAILED, failedMsg(SOME_THROWABLE_MSG), SOME_DATE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(FAILED.toString(), failedMsg(SOME_THROWABLE_MSG), SOME_DATE));
}
@Test
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_MIGRATION_FAILED, failedMsg(DEFAULT_ERROR_MSG), SOME_DATE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(FAILED.toString(), failedMsg(DEFAULT_ERROR_MSG), SOME_DATE));
}
@Test
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_MIGRATION_SUCCEEDED, MESSAGE_STATUS_SUCCEEDED, SOME_DATE));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(SUCCEEDED.toString(), SUCCEEDED.getMessage(), SOME_DATE));
}
@Test
TestResponse response = tester.newRequest().execute();
- assertJson(response.getInput()).isSimilarTo(expectedResponse(STATUS_MIGRATION_REQUIRED, MESSAGE_MIGRATION_REQUIRED));
+ assertJson(response.getInput()).isSimilarTo(expectedResponse(MIGRATION_REQUIRED.toString(), MIGRATION_REQUIRED.getMessage()));
}
@DataProvider
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
-import static com.google.common.collect.ImmutableSet.of;
import static com.google.common.collect.Iterables.filter;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
private static final String STATUS_MIGRATION_NEEDED = "DB_MIGRATION_NEEDED";
private static final String STATUS_MIGRATION_RUNNING = "DB_MIGRATION_RUNNING";
private static final String STATUS_RESTARTING = "RESTARTING";
- private static final Set<DatabaseMigrationState.Status> SUPPORTED_DATABASE_MIGRATION_STATUSES = of(DatabaseMigrationState.Status.FAILED, DatabaseMigrationState.Status.NONE,
- DatabaseMigrationState.Status.SUCCEEDED, DatabaseMigrationState.Status.RUNNING);
- private static final Set<Platform.Status> SUPPORTED_PLATFORM_STATUSES = of(Platform.Status.BOOTING, Platform.Status.SAFEMODE, Platform.Status.STARTING, Platform.Status.UP);
+ private static final Set<DatabaseMigrationState.Status> SUPPORTED_DATABASE_MIGRATION_STATUSES = Set.of(DatabaseMigrationState.Status.FAILED, DatabaseMigrationState.Status.NONE,
+ DatabaseMigrationState.Status.SUCCEEDED, DatabaseMigrationState.Status.RUNNING, DatabaseMigrationState.Status.STATUS_NOT_SUPPORTED, DatabaseMigrationState.Status.MIGRATION_REQUIRED);
+ private static final Set<Platform.Status> SUPPORTED_PLATFORM_STATUSES = Set.of(Platform.Status.BOOTING, Platform.Status.SAFEMODE, Platform.Status.STARTING, Platform.Status.UP);
private static Server server = new Dummy51Server();
private DatabaseMigrationState migrationState = mock(DatabaseMigrationState.class);