*/
package org.sonar.ce;
-import org.sonar.ce.http.CeHttpClient;
+import org.sonar.ce.http.CeHttpClientImpl;
import org.sonar.ce.log.CeLogging;
import org.sonar.ce.queue.CeQueueImpl;
import org.sonar.ce.taskprocessor.ReportTaskProcessorDeclaration;
@Override
protected void configureModule() {
add(CeLogging.class,
- CeHttpClient.class,
+ CeHttpClientImpl.class,
// Queue
CeQueueImpl.class,
*/
package org.sonar.ce.http;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
import java.util.Optional;
-import okhttp3.OkHttpClient;
-import okhttp3.RequestBody;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.config.Configuration;
import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.process.DefaultProcessCommands;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
-import static org.sonar.process.ProcessId.COMPUTE_ENGINE;
+public interface CeHttpClient {
+ Optional<ProtobufSystemInfo.SystemInfo> retrieveSystemInfo();
-/**
- * Client for the HTTP server of the Compute Engine.
- */
-public class CeHttpClient {
-
- private static final String PATH_CHANGE_LOG_LEVEL = "changeLogLevel";
- private static final String PATH_SYSTEM_INFO = "systemInfo";
-
- private final File ipcSharedDir;
-
- public CeHttpClient(Configuration config) {
- this.ipcSharedDir = new File(config.get(PROPERTY_SHARED_PATH).get());
- }
-
- /**
- * Connects to the specified JVM process and requests system information.
- * @return the system info, or absent if the process is not up or if its HTTP URL
- * is not registered into IPC.
- */
- public Optional<ProtobufSystemInfo.SystemInfo> retrieveSystemInfo() {
- return call(SystemInfoActionClient.INSTANCE);
- }
-
- private enum SystemInfoActionClient implements ActionClient<Optional<ProtobufSystemInfo.SystemInfo>> {
- INSTANCE;
-
- @Override
- public String getPath() {
- return PATH_SYSTEM_INFO;
- }
-
- @Override
- public Optional<ProtobufSystemInfo.SystemInfo> getDefault() {
- return Optional.empty();
- }
-
- @Override
- public Optional<ProtobufSystemInfo.SystemInfo> call(String url) throws Exception {
- byte[] protobuf = IOUtils.toByteArray(new URI(url));
- return Optional.of(ProtobufSystemInfo.SystemInfo.parseFrom(protobuf));
- }
- }
-
- public void changeLogLevel(LoggerLevel level) {
- requireNonNull(level, "level can't be null");
- call(new ChangeLogLevelActionClient(level));
- }
-
- private static final class ChangeLogLevelActionClient implements ActionClient<Void> {
- private final LoggerLevel newLogLevel;
-
- private ChangeLogLevelActionClient(LoggerLevel newLogLevel) {
- this.newLogLevel = newLogLevel;
- }
-
- @Override
- public String getPath() {
- return PATH_CHANGE_LOG_LEVEL;
- }
-
- @Override
- public Void getDefault() {
- return null;
- }
-
- @Override
- public Void call(String url) throws Exception {
- okhttp3.Request request = new okhttp3.Request.Builder()
- .post(RequestBody.create(null, new byte[0]))
- .url(url + "?level=" + newLogLevel.name())
- .build();
- okhttp3.Response response = new OkHttpClient().newCall(request).execute();
- if (response.code() != 200) {
- throw new IOException(
- String.format(
- "Failed to change log level in Compute Engine. Code was '%s' and response was '%s' for url '%s'",
- response.code(),
- response.body().string(),
- url));
- }
- return null;
- }
- }
-
- public void refreshCeWorkerCount() {
- call(RefreshCeWorkerCountActionClient.INSTANCE);
- }
-
- private enum RefreshCeWorkerCountActionClient implements ActionClient<Void> {
- INSTANCE;
-
- @Override
- public String getPath() {
- return "refreshWorkerCount";
- }
-
- @Override
- public Void getDefault() {
- return null;
- }
-
- @Override
- public Void call(String url) throws Exception {
- okhttp3.Request request = new okhttp3.Request.Builder()
- .post(RequestBody.create(null, new byte[0]))
- .url(url)
- .build();
- okhttp3.Response response = new OkHttpClient().newCall(request).execute();
- if (response.code() != 200) {
- throw new IOException(
- String.format(
- "Failed to trigger refresh of CE Worker count. Code was '%s' and response was '%s' for url '%s'",
- response.code(),
- response.body().string(),
- url));
- }
- return null;
- }
- }
-
- private <T> T call(ActionClient<T> actionClient) {
- try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(ipcSharedDir, COMPUTE_ENGINE.getIpcIndex())) {
- if (commands.isUp()) {
- return actionClient.call(commands.getHttpUrl() + "/" + actionClient.getPath());
- }
- return actionClient.getDefault();
- } catch (Exception e) {
- throw new IllegalStateException("Failed to call HTTP server of process " + COMPUTE_ENGINE, e);
- }
- }
-
- private interface ActionClient<T> {
- /**
- * Path of the action.
- */
- String getPath();
-
- /**
- * Value to return when the Compute Engine is not ready.
- */
- T getDefault();
+ void changeLogLevel(LoggerLevel level);
- /**
- * Delegates to perform the call to the Compute Engine's specified absolute URL.
- */
- T call(String url) throws Exception;
- }
+ void refreshCeWorkerCount();
}
--- /dev/null
+/*
+ * 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.ce.http;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Optional;
+import okhttp3.OkHttpClient;
+import okhttp3.RequestBody;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.process.DefaultProcessCommands;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
+import static org.sonar.process.ProcessId.COMPUTE_ENGINE;
+
+/**
+ * Client for the HTTP server of the Compute Engine.
+ */
+public class CeHttpClientImpl implements CeHttpClient {
+
+ private static final String PATH_CHANGE_LOG_LEVEL = "changeLogLevel";
+ private static final String PATH_SYSTEM_INFO = "systemInfo";
+
+ private final File ipcSharedDir;
+
+ public CeHttpClientImpl(Configuration config) {
+ this.ipcSharedDir = new File(config.get(PROPERTY_SHARED_PATH).get());
+ }
+
+ /**
+ * Connects to the specified JVM process and requests system information.
+ * @return the system info, or absent if the process is not up or if its HTTP URL
+ * is not registered into IPC.
+ */
+ @Override
+ public Optional<ProtobufSystemInfo.SystemInfo> retrieveSystemInfo() {
+ return call(SystemInfoActionClient.INSTANCE);
+ }
+
+ private enum SystemInfoActionClient implements ActionClient<Optional<ProtobufSystemInfo.SystemInfo>> {
+ INSTANCE;
+
+ @Override
+ public String getPath() {
+ return PATH_SYSTEM_INFO;
+ }
+
+ @Override
+ public Optional<ProtobufSystemInfo.SystemInfo> getDefault() {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<ProtobufSystemInfo.SystemInfo> call(String url) throws Exception {
+ byte[] protobuf = IOUtils.toByteArray(new URI(url));
+ return Optional.of(ProtobufSystemInfo.SystemInfo.parseFrom(protobuf));
+ }
+ }
+
+ @Override
+ public void changeLogLevel(LoggerLevel level) {
+ requireNonNull(level, "level can't be null");
+ call(new ChangeLogLevelActionClient(level));
+ }
+
+ private static final class ChangeLogLevelActionClient implements ActionClient<Void> {
+ private final LoggerLevel newLogLevel;
+
+ private ChangeLogLevelActionClient(LoggerLevel newLogLevel) {
+ this.newLogLevel = newLogLevel;
+ }
+
+ @Override
+ public String getPath() {
+ return PATH_CHANGE_LOG_LEVEL;
+ }
+
+ @Override
+ public Void getDefault() {
+ return null;
+ }
+
+ @Override
+ public Void call(String url) throws Exception {
+ okhttp3.Request request = new okhttp3.Request.Builder()
+ .post(RequestBody.create(null, new byte[0]))
+ .url(url + "?level=" + newLogLevel.name())
+ .build();
+ okhttp3.Response response = new OkHttpClient().newCall(request).execute();
+ if (response.code() != 200) {
+ throw new IOException(
+ String.format(
+ "Failed to change log level in Compute Engine. Code was '%s' and response was '%s' for url '%s'",
+ response.code(),
+ response.body().string(),
+ url));
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public void refreshCeWorkerCount() {
+ call(RefreshCeWorkerCountActionClient.INSTANCE);
+ }
+
+ private enum RefreshCeWorkerCountActionClient implements ActionClient<Void> {
+ INSTANCE;
+
+ @Override
+ public String getPath() {
+ return "refreshWorkerCount";
+ }
+
+ @Override
+ public Void getDefault() {
+ return null;
+ }
+
+ @Override
+ public Void call(String url) throws Exception {
+ okhttp3.Request request = new okhttp3.Request.Builder()
+ .post(RequestBody.create(null, new byte[0]))
+ .url(url)
+ .build();
+ okhttp3.Response response = new OkHttpClient().newCall(request).execute();
+ if (response.code() != 200) {
+ throw new IOException(
+ String.format(
+ "Failed to trigger refresh of CE Worker count. Code was '%s' and response was '%s' for url '%s'",
+ response.code(),
+ response.body().string(),
+ url));
+ }
+ return null;
+ }
+ }
+
+ private <T> T call(ActionClient<T> actionClient) {
+ try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(ipcSharedDir, COMPUTE_ENGINE.getIpcIndex())) {
+ if (commands.isUp()) {
+ return actionClient.call(commands.getHttpUrl() + "/" + actionClient.getPath());
+ }
+ return actionClient.getDefault();
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to call HTTP server of process " + COMPUTE_ENGINE, e);
+ }
+ }
+
+ private interface ActionClient<T> {
+ /**
+ * Path of the action.
+ */
+ String getPath();
+
+ /**
+ * Value to return when the Compute Engine is not ready.
+ */
+ T getDefault();
+
+ /**
+ * Delegates to perform the call to the Compute Engine's specified absolute URL.
+ */
+ T call(String url) throws Exception;
+ }
+}
ipcSharedDir = temp.newFolder();
MapSettings settings = new MapSettings();
settings.setProperty(ProcessEntryPoint.PROPERTY_SHARED_PATH, ipcSharedDir.getAbsolutePath());
- underTest = new CeHttpClient(settings.asConfig());
+ underTest = new CeHttpClientImpl(settings.asConfig());
}
@Test
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.ce.http.CeHttpClient;
+import org.sonar.ce.http.CeHttpClientImpl;
import org.sonar.db.Database;
import org.sonar.server.app.WebServerProcessLogging;
import org.sonar.server.exceptions.ForbiddenException;
private ServerLogging serverLogging = mock(ServerLogging.class);
private Database db = mock(Database.class);
- private CeHttpClient ceHttpClient = mock(CeHttpClient.class);
+ private CeHttpClient ceHttpClient = mock(CeHttpClientImpl.class);
private WebServerProcessLogging webServerProcessLogging = new WebServerProcessLogging();
private ChangeLogLevelAction underTest = new ChangeLogLevelAction(userSession, serverLogging, db, ceHttpClient, webServerProcessLogging);
private WsActionTester actionTester = new WsActionTester(underTest);
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.sonar.ce.http.CeHttpClient;
+import org.sonar.ce.http.CeHttpClientImpl;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.platform.monitoring.Monitor;
import org.sonar.server.tester.UserSessionRule;
private Monitor monitor1 = mock(Monitor.class);
private Monitor monitor2 = mock(Monitor.class);
- private CeHttpClient ceHttpClient = mock(CeHttpClient.class, Mockito.RETURNS_MOCKS);
+ private CeHttpClient ceHttpClient = mock(CeHttpClientImpl.class, Mockito.RETURNS_MOCKS);
private InfoAction underTest = new InfoAction(userSessionRule, ceHttpClient, monitor1, monitor2);
private WsActionTester actionTester = new WsActionTester(underTest);
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ws.WebService;
import org.sonar.ce.http.CeHttpClient;
+import org.sonar.ce.http.CeHttpClientImpl;
import org.sonar.server.app.ProcessCommandWrapper;
import org.sonar.server.app.RestartFlagHolder;
import org.sonar.server.platform.Platform;
public class SystemWsTest {
- CeHttpClient ceHttpClient = mock(CeHttpClient.class);
+ CeHttpClient ceHttpClient = mock(CeHttpClientImpl.class);
@Test
public void define() {