aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-11-16 15:51:13 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-11-17 07:36:51 +0100
commitb612813d06583cb5021469afb6a06c15ecdc3662 (patch)
treea521ed1c5d728180f509fd41fc9822f8a7df9b9e /server/sonar-server
parent75bae1e0539dd6504c898814621262f1739d08d4 (diff)
downloadsonarqube-b612813d06583cb5021469afb6a06c15ecdc3662.tar.gz
sonarqube-b612813d06583cb5021469afb6a06c15ecdc3662.zip
SONAR-8383 add param "process" to api/system/logs
Diffstat (limited to 'server/sonar-server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java33
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java92
2 files changed, 111 insertions, 14 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java
index 545144d697c..141f0d84938 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java
@@ -20,16 +20,23 @@
package org.sonar.server.platform.ws;
import java.io.File;
+import java.net.HttpURLConnection;
import org.apache.commons.io.FileUtils;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
+import org.sonar.core.util.stream.Collectors;
+import org.sonar.process.ProcessId;
import org.sonar.server.platform.ServerLogging;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.MediaTypes;
+import static java.util.Arrays.stream;
+
public class LogsAction implements SystemWsAction {
+ private static final String PROCESS_PROPERTY = "process";
+
private final UserSession userSession;
private final ServerLogging serverLogging;
@@ -40,21 +47,39 @@ public class LogsAction implements SystemWsAction {
@Override
public void define(WebService.NewController controller) {
- controller.createAction("logs")
+ WebService.NewAction action = controller.createAction("logs")
.setDescription("Get system logs in plain-text format. Requires system administration permission.")
.setResponseExample(getClass().getResource("logs-example.log"))
.setSince("5.2")
.setHandler(this);
+
+ action
+ .createParam(PROCESS_PROPERTY)
+ .setPossibleValues(stream(ProcessId.values())
+ .map(ProcessId::getKey)
+ .sorted()
+ .collect(Collectors.toList(ProcessId.values().length)))
+ .setDefaultValue(ProcessId.APP.getKey())
+ .setSince("6.2")
+ .setDescription("Process to get logs from");
}
@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
userSession.checkIsRoot();
- wsResponse.stream().setMediaType(MediaTypes.TXT);
- File file = serverLogging.getCurrentLogFile();
- if (file.exists()) {
+ String processKey = wsRequest.mandatoryParam(PROCESS_PROPERTY);
+ ProcessId processId = ProcessId.fromKey(processKey);
+
+ File logsDir = serverLogging.getLogsDir();
+ File file = new File(logsDir, processId.getLogFilenamePrefix() + ".log");
+ // filenames are defined in the enum LogProcess. Still to prevent any vulnerability,
+ // path is double-checked to prevent returning any file present on the file system.
+ if (file.exists() && file.getParentFile().equals(logsDir)) {
+ wsResponse.stream().setMediaType(MediaTypes.TXT);
FileUtils.copyFile(file, wsResponse.stream().output());
+ } else {
+ wsResponse.stream().setStatus(HttpURLConnection.HTTP_NOT_FOUND);
}
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java
index feac4ff14fd..a894e880bfa 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/LogsActionTest.java
@@ -21,6 +21,7 @@ package org.sonar.server.platform.ws;
import java.io.File;
import java.io.IOException;
+import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
@@ -51,6 +52,13 @@ public class LogsActionTest {
private WsActionTester actionTester = new WsActionTester(underTest);
@Test
+ public void values_of_process_parameter_are_names_of_processes() {
+ Set<String> values = actionTester.getDef().param("process").possibleValues();
+ // values are lower-case and alphabetically ordered
+ assertThat(values).containsExactly("app", "ce", "es", "web");
+ }
+
+ @Test
public void request_fails_with_ForbiddenException_when_user_is_not_logged_in() {
expectedException.expect(ForbiddenException.class);
@@ -67,29 +75,93 @@ public class LogsActionTest {
}
@Test
- public void get_logs() throws IOException {
+ public void get_app_logs_by_default() throws IOException {
makeAuthenticatedUserRoot();
- File file = temp.newFile();
- FileUtils.write(file, "{logs}");
- when(serverLogging.getCurrentLogFile()).thenReturn(file);
+ createAllLogsFiles();
TestResponse response = actionTester.newRequest().execute();
assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
- assertThat(response.getInput()).isEqualTo("{logs}");
+ assertThat(response.getInput()).isEqualTo("{app}");
}
@Test
- public void get_empty_logs_if_file_does_not_exist() throws IOException {
+ public void return_404_not_found_if_file_does_not_exist() throws IOException {
makeAuthenticatedUserRoot();
- File file = temp.newFile();
- file.delete();
- when(serverLogging.getCurrentLogFile()).thenReturn(file);
+ createLogsDir();
TestResponse response = actionTester.newRequest().execute();
+ assertThat(response.getStatus()).isEqualTo(404);
+ }
+
+ @Test
+ public void get_ce_logs() throws IOException {
+ makeAuthenticatedUserRoot();
+
+ createAllLogsFiles();
+
+ TestResponse response = actionTester.newRequest()
+ .setParam("process", "ce")
+ .execute();
+ assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
+ assertThat(response.getInput()).isEqualTo("{ce}");
+ }
+
+ @Test
+ public void get_es_logs() throws IOException {
+ makeAuthenticatedUserRoot();
+
+ createAllLogsFiles();
+
+ TestResponse response = actionTester.newRequest()
+ .setParam("process", "es")
+ .execute();
+ assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
+ assertThat(response.getInput()).isEqualTo("{es}");
+ }
+
+ @Test
+ public void get_web_logs() throws IOException {
+ makeAuthenticatedUserRoot();
+
+ createAllLogsFiles();
+
+ TestResponse response = actionTester.newRequest()
+ .setParam("process", "web")
+ .execute();
assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
- assertThat(response.getInput()).isEqualTo("");
+ assertThat(response.getInput()).isEqualTo("{web}");
+ }
+
+ @Test
+ public void do_not_return_rotated_files() throws IOException {
+ makeAuthenticatedUserRoot();
+
+ File dir = createLogsDir();
+ FileUtils.write(new File(dir, "sonar.1.log"), "{old}");
+ FileUtils.write(new File(dir, "sonar.log"), "{recent}");
+
+ TestResponse response = actionTester.newRequest()
+ .setParam("process", "app")
+ .execute();
+ assertThat(response.getMediaType()).isEqualTo(MediaTypes.TXT);
+ assertThat(response.getInput()).isEqualTo("{recent}");
+ }
+
+ private File createAllLogsFiles() throws IOException {
+ File dir = createLogsDir();
+ FileUtils.write(new File(dir, "sonar.log"), "{app}");
+ FileUtils.write(new File(dir, "ce.log"), "{ce}");
+ FileUtils.write(new File(dir, "es.log"), "{es}");
+ FileUtils.write(new File(dir, "web.log"), "{web}");
+ return dir;
+ }
+
+ private File createLogsDir() throws IOException {
+ File dir = temp.newFolder();
+ when(serverLogging.getLogsDir()).thenReturn(dir);
+ return dir;
}
private void makeAuthenticatedUserRoot() {