import com.sonar.orchestrator.Orchestrator;
import com.sonar.orchestrator.locator.FileLocation;
import java.io.File;
+import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.wsclient.services.Server;
-import org.sonar.wsclient.services.ServerQuery;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsResponse;
import util.ItUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
+import static util.ItUtils.newWsClient;
/**
* This class start a new orchestrator on each test case
.build();
orchestrator.start();
- Server.Status status = orchestrator.getServer().getAdminWsClient().find(new ServerQuery()).getStatus();
- assertThat(status).isEqualTo(Server.Status.UP);
+ WsResponse statusResponse = newWsClient(orchestrator).wsConnector().call(new GetRequest("api/system/status"));
+ Map<String, Object> json = ItUtils.jsonToMap(statusResponse.content());
+ assertThat(json.get("status")).isEqualTo("UP");
}
// SONAR-4748
import okhttp3.Response;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
import org.json.simple.JSONValue;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
-import org.sonar.wsclient.services.Server;
-import org.sonar.wsclient.services.ServerQuery;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.ServerId.ShowWsResponse;
import org.sonarqube.ws.client.GetRequest;
import pageobjects.ServerIdPage;
import util.ItUtils;
+import static org.apache.commons.lang.StringUtils.startsWithAny;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static util.ItUtils.call;
import static util.ItUtils.newAdminWsClient;
+import static util.ItUtils.newWsClient;
import static util.selenium.Selenese.runSelenese;
public class ServerSystemTest {
@Test
public void get_sonarqube_version() {
- String version = orchestrator.getServer().getWsClient().find(new ServerQuery()).getVersion();
- if (!StringUtils.startsWithAny(version, new String[] {"5.", "6."})) {
+ Map<String, Object> json = callStatus();
+
+ String version = (String)json.get("version");
+ if (!startsWithAny(version, new String[] {"6."})) {
fail("Bad version: " + version);
}
}
@Test
public void get_server_status() {
- assertThat(orchestrator.getServer().getWsClient().find(new ServerQuery()).getStatus()).isEqualTo(Server.Status.UP);
+ Map<String, Object> json = callStatus();
+ assertThat(json.get("status")).isEqualTo("UP");
}
@Test
assertThat(serverId).isNotEmpty();
}
+ private Map<String, Object> callStatus() {
+ WsResponse statusResponse = newWsClient(orchestrator).wsConnector().call(new GetRequest("api/system/status"));
+ return ItUtils.jsonToMap(statusResponse.content());
+ }
+
@Test
public void display_system_info() {
runSelenese(orchestrator, "/serverSystem/ServerSystemTest/system_info.html");
"/api/issues/bulk_change",
"/api/projects/create",
"/api/properties/create",
- "/api/server",
"/api/user_properties");
public String generateState(HttpServletRequest request, HttpServletResponse response, int timeoutInSeconds) {
"/setup/*",
"/sessions/*",
"/api/system/db_migration_status", "/api/system/status", "/api/system/migrate_db",
- "/api/server/index", "/api/server/setup", "/api/server/version",
+ "/api/server/version",
"/api/users/identity_providers", "/api/l10n/index",
LOGIN_URL, LOGOUT_URL, VALIDATE_URL);
package org.sonar.server.platform.ws;
import com.google.common.io.Resources;
-import org.sonar.api.server.ws.RailsHandler;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.platform.Server;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
+import org.sonarqube.ws.MediaTypes;
-public class ServerWs implements WebService {
+public class ServerWs implements WebService, RequestHandler {
- @Override
- public void define(Context context) {
- NewController controller = context.createController("api/server")
- .setDescription("Get system properties and upgrade db")
- .setSince("2.10");
-
- defineIndexAction(controller);
- defineSetupAction(controller);
+ private final Server server;
- controller.done();
+ public ServerWs(Server server) {
+ this.server = server;
}
- private void defineIndexAction(NewController controller) {
- NewAction action = controller.createAction("index")
- .setDescription("Get the server status:" +
- "<ul>" +
- "<li>UP</li>" +
- "<li>DOWN (generally for database connection failures)</li>" +
- "<li>SETUP (if the server must be upgraded)</li>" +
- "<li>MIGRATION_RUNNING (the upgrade process is currently running)</li>" +
- "</ul>")
- .setSince("2.10")
- .setHandler(RailsHandler.INSTANCE)
- .setInternal(true)
- .setResponseExample(Resources.getResource(this.getClass(), "example-index.json"));
-
- RailsHandler.addFormatParam(action);
- }
+ @Override
+ public void define(Context context) {
+ NewController controller = context.createController("api/server");
- private void defineSetupAction(NewController controller) {
- NewAction action = controller.createAction("setup")
- .setDescription("Upgrade the SonarQube database")
+ controller.createAction("version")
+ .setDescription("Version of SonarQube in plain text")
.setSince("2.10")
- .setPost(true)
- .setInternal(true)
- .setHandler(RailsHandler.INSTANCE)
- .setResponseExample(Resources.getResource(this.getClass(), "example-setup.json"));
+ .setResponseExample(Resources.getResource(this.getClass(), "example-server-version.txt"))
+ .setHandler(this);
- action.createParam("format")
- .setDescription("Response format")
- .setPossibleValues("json", "csv", "text");
+ controller.done();
}
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ response.stream().setMediaType(MediaTypes.TXT);
+ IOUtils.write(server.getVersion(), response.stream().output());
+ }
}
+++ /dev/null
-{
- "id": "20140507170538",
- "version": "4.3",
- "status": "UP"
-}
--- /dev/null
+6.3.0.1234
+++ /dev/null
-{
- "status": "ok",
- "migration_status": "NO_MIGRATION",
- "message": "Database is up-to-date, no migration needed."
-}
executeVerifyStateDoesNotFailOnRequest("/api/issues/bulk_change?key=ABCD", "POST");
executeVerifyStateDoesNotFailOnRequest("/api/projects/create?key=ABCD", "POST");
executeVerifyStateDoesNotFailOnRequest("/api/properties/create?key=ABCD", "POST");
- executeVerifyStateDoesNotFailOnRequest("/api/server", "POST");
executeVerifyStateDoesNotFailOnRequest("/api/user_properties", "POST");
}
assertPathIsIgnored("/api/system/db_migration_status");
assertPathIsIgnored("/api/system/status");
assertPathIsIgnored("/api/system/migrate_db");
- assertPathIsIgnored("/api/server/index");
- assertPathIsIgnored("/api/server/setup");
assertPathIsIgnored("/api/server/version");
assertPathIsIgnored("/api/users/identity_providers");
assertPathIsIgnored("/api/l10n/index");
package org.sonar.server.platform.ws;
import org.junit.Test;
-import org.sonar.api.server.ws.RailsHandler;
+import org.sonar.api.platform.Server;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.ws.WsTester;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ServerWsTest {
- WsTester tester = new WsTester(new ServerWs());
+ private Server server = mock(Server.class);
+ private WsTester tester = new WsTester(new ServerWs(server));
@Test
- public void define_controller() {
+ public void define_version_action() {
WebService.Controller controller = tester.controller("api/server");
- assertThat(controller).isNotNull();
- assertThat(controller.since()).isEqualTo("2.10");
- assertThat(controller.description()).isNotEmpty();
- assertThat(controller.actions()).hasSize(2);
+ assertThat(controller.actions()).hasSize(1);
+
+ WebService.Action versionAction = controller.action("version");
+ assertThat(versionAction.since()).isEqualTo("2.10");
+ assertThat(versionAction.description()).isNotEmpty();
+ assertThat(versionAction.isPost()).isFalse();
}
@Test
- public void define_index_action() {
- WebService.Controller controller = tester.controller("api/server");
-
- WebService.Action action = controller.action("index");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(1);
+ public void returns_version_as_plain_text() throws Exception {
+ when(server.getVersion()).thenReturn("6.4-SNAPSHOT");
+ WsTester.Result result = tester.newGetRequest("api/server", "version").execute();
+ assertThat(result.outputAsString()).isEqualTo("6.4-SNAPSHOT");
}
@Test
- public void define_setup_action() {
- WebService.Controller controller = tester.controller("api/server");
-
- WebService.Action action = controller.action("setup");
- assertThat(action).isNotNull();
- assertThat(action.handler()).isInstanceOf(RailsHandler.class);
- assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).hasSize(1);
+ public void test_example_of_version() throws Exception {
+ WebService.Action versionAction = tester.action("api/server", "version");
+ assertThat(versionAction.responseExampleAsString()).isEqualTo("6.3.0.1234");
}
-
}
+++ /dev/null
-#
-# SonarQube, open source software quality management tool.
-# Copyright (C) 2008-2016 SonarSource
-# mailto:contact AT sonarsource DOT com
-#
-# SonarQube 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.
-#
-# SonarQube 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.
-#
-class Api::ServerController < Api::ApiController
-
- skip_before_filter :check_authentication
-
- # prevent HTTP proxies from caching server status
- before_filter :set_cache_buster, :only => 'index'
-
- # execute database setup
- skip_before_filter :check_database_version, :setup
-
- def version
- render :text => Java::OrgSonarServerPlatform::Platform.getServer().getVersion()
- end
-
- def index
- hash={:id => Java::OrgSonarServerPlatform::Platform.getServer().getId(), :version => Java::OrgSonarServerPlatform::Platform.getServer().getVersion()}
- complete_with_status(hash)
- respond_to do |format|
- format.json{ render :json => jsonp(hash) }
- format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'server') }
- format.text { render :text => text_not_supported}
- end
- end
-
- def setup
- verify_post_request
- manager=DatabaseMigrationManager.instance
- begin
- # Ask the DB migration manager to start the migration
- # => No need to check for authorizations (actually everybody can run the upgrade)
- # nor concurrent calls (this is handled directly by DatabaseMigrationManager)
- manager.start_migration
-
- operational=manager.is_sonar_access_allowed?
- current_status = operational ? "ok" : "ko"
- hash={
- # deprecated fields
- :status => current_status,
- :migration_status => manager.status,
-
- # correct fields
- :operational => operational,
- :state => manager.status
- }
- hash[:message]=manager.message if manager.message
- hash[:startedAt]=manager.migration_start_time if manager.migration_start_time
-
- respond_to do |format|
- format.json{ render :json => jsonp(hash) }
- format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'setup') }
- format.text { render :text => hash[:status] }
- end
- rescue => e
- hash={
- # deprecated fields
- :status => 'ko',
- :msg => e.message,
-
- # correct fields
- :message => e.message,
- :state => manager.status
- }
- respond_to do |format|
- format.json{ render :json => jsonp(hash) }
- format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'setup') }
- format.text { render :text => hash[:status] }
- end
- end
- end
-
- private
-
- def server_properties_to_json(properties)
- hash={}
- properties.each do |prop|
- hash[prop[0].to_s]=prop[1].to_s
- end
- hash
- end
-
- def complete_with_status(hash)
- if DatabaseMigrationManager.instance.is_sonar_access_allowed?
- hash[:status]='UP'
- elsif DatabaseMigrationManager.instance.migration_running?
- hash[:status]='MIGRATION_RUNNING'
- elsif DatabaseMigrationManager.instance.requires_migration?
- hash[:status]='SETUP'
- else
- # migration failed or not connected to the database
- hash[:status]='DOWN'
- hash[:status_msg]=DatabaseMigrationManager.instance.message
- end
- end
-
- def set_cache_buster
- response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
- response.headers["Pragma"] = "no-cache"
- response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
- end
-end
+++ /dev/null
-#
-# SonarQube, open source software quality management tool.
-# Copyright (C) 2008-2016 SonarSource
-# mailto:contact AT sonarsource DOT com
-#
-# SonarQube 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.
-#
-# SonarQube 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.
-#
-
-#
-# Class that centralizes the management the DB migration
-#
-
-require 'singleton'
-require 'thread'
-
-class DatabaseMigrationManager
-
- # mixin the singleton module to ensure we have only one instance of the class
- # it will be accessible with "DatabaseMigrationManager.instance"
- include Singleton
-
- # the status of the migration
- @status
- MIGRATION_NEEDED = "MIGRATION_NEEDED"
- MIGRATION_RUNNING = "MIGRATION_RUNNING"
- MIGRATION_FAILED = "MIGRATION_FAILED"
- MIGRATION_SUCCEEDED = "MIGRATION_SUCCEEDED"
- NO_MIGRATION = "NO_MIGRATION"
-
- # the corresponding message that can be given to the user
- @message
-
- # the time when the migration was started
- @start_time
-
- def initialize
- if !ActiveRecord::Base.connected?
- @status = MIGRATION_FAILED
- @message = "Not connected to database."
- elsif DatabaseVersion.uptodate?
- @status = NO_MIGRATION
- @message = "Database is up-to-date, no migration needed."
- else
- if DatabaseVersion.production?
- @status = MIGRATION_NEEDED
- @message = "Migration required."
- else
- @status = MIGRATION_FAILED
- @message = "Upgrade is not supported. Please use a <a href=\"http://redirect.sonarsource.com/doc/requirements.html\">production-ready database</a>."
- end
- end
- end
-
- def message
- @message
- end
-
- def status
- @status
- end
-
- def requires_migration?
- @status==MIGRATION_NEEDED
- end
-
- def migration_running?
- @status==MIGRATION_RUNNING
- end
-
- def migration_failed?
- @status==MIGRATION_FAILED
- end
-
- def is_sonar_access_allowed?
- @status==NO_MIGRATION || @status==MIGRATION_SUCCEEDED
- end
-
- def migration_start_time
- @start_time
- end
-
- def start_migration
- # Use an exclusive block of code to ensure that only 1 thread will be able to proceed with the migration
- requires_migration = false
- Thread.exclusive do
- requires_migration = requires_migration?
- end
-
- if requires_migration
- Thread.new do
- begin
- @status = MIGRATION_RUNNING
- @message = "Database migration is running"
- Thread.current[:name] = "Database Upgrade"
- @start_time = Time.now
-
- DatabaseVersion.upgrade_and_start
-
- @status = MIGRATION_SUCCEEDED
- @message = "Migration succeeded."
- rescue Exception => e
- @status = MIGRATION_FAILED
- @message = "Migration failed: " + Api::Utils.exception_message(e) + ".<br/> Please check logs."
- Api::Utils.java_facade.logError("Fail to upgrade database\n#{Api::Utils.exception_message(e, :backtrace => true)}")
- end
- end
- end
- end
-
-end
map.connect 'api', :controller => 'api/java_ws', :action => 'redirect_to_ws_listing'
- map.connect 'api/server/:action', :controller => 'api/server'
map.connect 'api/resoures', :controller => 'api/resources', :action => 'index'
map.resources 'properties', :path_prefix => 'api', :controller => 'api/properties', :requirements => { :id => /.*/ }