Mercurial > hg > thermostat-ng > agent
changeset 2695:9dbdade820ce
AgentDao and backend should be in agent, not storage-core
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-June/023778.html
reviewed-by: jerboaa
line wrap: on
line diff
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/internal/Activator.java Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/internal/Activator.java Tue Jun 20 13:00:11 2017 +0200 @@ -36,6 +36,8 @@ package com.redhat.thermostat.agent.cli.internal; +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.dao.BackendInfoDAO; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -61,7 +63,9 @@ Class<?>[] deps = new Class<?>[] { ExitStatus.class, WriterID.class, - SSLConfiguration.class + SSLConfiguration.class, + AgentInfoDAO.class, + BackendInfoDAO.class, }; tracker = new MultipleServiceTracker(context, deps, new Action() {
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/internal/AgentApplication.java Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/internal/AgentApplication.java Tue Jun 20 13:00:11 2017 +0200 @@ -40,6 +40,8 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.dao.BackendInfoDAO; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; @@ -62,9 +64,6 @@ import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.shared.config.InvalidConfigurationException; import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; - import sun.misc.Signal; import sun.misc.SignalHandler;
--- a/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/internal/AgentApplicationTest.java Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/internal/AgentApplicationTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -48,6 +48,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.dao.BackendInfoDAO; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -73,8 +75,6 @@ import com.redhat.thermostat.common.cli.CommandException; import com.redhat.thermostat.shared.config.InvalidConfigurationException; import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; import com.redhat.thermostat.testutils.StubBundleContext; import com.redhat.thermostat.utils.management.internal.MXBeanConnectionPoolControl;
--- a/agent/core/pom.xml Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/core/pom.xml Tue Jun 20 13:00:11 2017 +0200 @@ -121,6 +121,7 @@ <Export-Package> com.redhat.thermostat.agent, com.redhat.thermostat.agent.config, + com.redhat.thermostat.agent.dao, com.redhat.thermostat.agent.utils, com.redhat.thermostat.agent.utils.management, com.redhat.thermostat.backend
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/Agent.java Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/Agent.java Tue Jun 20 13:00:11 2017 +0200 @@ -43,6 +43,8 @@ import java.util.logging.Logger; import com.redhat.thermostat.agent.config.AgentStartupConfiguration; +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.dao.BackendInfoDAO; import com.redhat.thermostat.backend.Backend; import com.redhat.thermostat.backend.BackendRegistry; import com.redhat.thermostat.common.ActionEvent; @@ -51,8 +53,6 @@ import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; import com.redhat.thermostat.storage.model.AgentInformation; import com.redhat.thermostat.storage.model.BackendInformation; import com.redhat.thermostat.utils.management.internal.MXBeanConnectionPoolControl;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/dao/AgentInfoDAO.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,94 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.dao; + +import java.util.List; +import java.util.Set; + +import com.redhat.thermostat.annotations.Service; +import com.redhat.thermostat.storage.core.AgentId; +import com.redhat.thermostat.storage.model.AgentInformation; + +/** + * Access information about agents that agents publish to storage. + */ +@Service +public interface AgentInfoDAO { + + /** + * Get information about all known agents. + * + * @return a {@link List} of {@link AgentInformation} for all agents + * who have published their information. Will be empty if there is no + * information. + */ + List<AgentInformation> getAllAgentInformation(); + + /** + * Get information about a specific agent. + * + * @return a {@link AgentInformation} describing information about the agent + * indicated by {@code agentId}. {@code null} if no information about the + * agent could be located. + */ + + AgentInformation getAgentInformation(AgentId agentId); + + /** + * + * @return A set of AgentIds, which may be empty. + */ + Set<AgentId> getAgentIds(); + + /** + * Publish information about agent into the storage. + */ + void addAgentInformation(AgentInformation agentInfo); + + /** + * Update information about an existing agent. No changes will be performed + * if there is no matching agent. + */ + void updateAgentInformation(AgentInformation agentInfo); + + /** + * Remove information about an agent that was published to storage. + */ + void removeAgentInformation(AgentInformation agentInfo); + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/dao/BackendInfoDAO.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.dao; + +import com.redhat.thermostat.annotations.Service; +import com.redhat.thermostat.storage.model.BackendInformation; + +@Service +public interface BackendInfoDAO { + + void addBackendInformation(BackendInformation info); + + void removeBackendInformation(BackendInformation info); + +} +
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java Tue Jun 20 13:00:11 2017 +0200 @@ -40,6 +40,8 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.dao.BackendInfoDAO; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -70,7 +72,7 @@ @Override public void start(final BundleContext context) throws Exception { - + // Track common paths separately and register storage credentials quickly // We need to do this since otherwise no storage credentials will be // available by the time they're used in DbService @@ -81,9 +83,7 @@ CommonPaths paths = context.getService(ref); try { AgentConfigsUtils.setConfigFiles(paths.getSystemAgentConfigurationFile(), paths.getUserAgentConfigurationFile()); -// VmBlacklistImpl blacklist = new VmBlacklistImpl(); -// blacklist.addVmFilter(new AgentProxyFilter()); -// context.registerService(VmBlacklist.class, blacklist, null); + } catch (InvalidConfigurationException e) { logger.log(Level.SEVERE, "Failed to start agent services", e); } @@ -107,6 +107,18 @@ @Override public void dependenciesAvailable(DependencyProvider services) { + + try { + AgentInfoDAO agentInfoDAO = new AgentInfoDAOImpl(); + context.registerService(AgentInfoDAO.class, agentInfoDAO, null); + + BackendInfoDAO backendInfoDAO = new BackendInfoDAOImpl(); + context.registerService(BackendInfoDAO.class, backendInfoDAO, null); + + } catch (Exception e) { + throw new RuntimeException(e); + } + AgentIPCService ipcService = services.get(AgentIPCService.class); CommonPaths paths = services.get(CommonPaths.class); UserNameUtil util = services.get(UserNameUtil.class);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/AgentInfoDAOImpl.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,255 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.internal.AgentInformationTypeAdapter.AgentInformationUpdateTypeAdapter; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpContentResponse; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; + +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.storage.core.AgentId; +import com.redhat.thermostat.storage.model.AgentInformation; + +public class AgentInfoDAOImpl implements AgentInfoDAO { + + private static final Logger logger = LoggingUtils.getLogger(AgentInfoDAOImpl.class); + + private static final String GATEWAY_URL = "http://localhost:26000/api/v100"; // TODO configurable + private static final String GATEWAY_PATH = "/agent-config/systems/*/agents/"; + private static final String CONTENT_TYPE = "application/json"; + + private final HttpHelper httpHelper; + private final JsonHelper jsonHelper; + + public AgentInfoDAOImpl() throws Exception { + this(new HttpHelper(new HttpClient()), new JsonHelper(new AgentInformationTypeAdapter(), + new AgentInformationUpdateTypeAdapter())); + } + + AgentInfoDAOImpl(HttpHelper httpHelper, JsonHelper jsonHelper) throws Exception { + this.httpHelper = httpHelper; + this.jsonHelper = jsonHelper; + + this.httpHelper.startClient(); + } + + @Override + public List<AgentInformation> getAllAgentInformation() { + return Collections.emptyList(); // TODO Remove once Agent Id completer is removed + } + + @Override + public AgentInformation getAgentInformation(final AgentId agentId) { + return null; // TODO Remove once VM Id completer is removed + } + + @Override + public Set<AgentId> getAgentIds() { + return Collections.emptySet(); // TODO Remove once VM Id completer is removed + } + + @Override + public void addAgentInformation(final AgentInformation agentInfo) { + try { + // Encode as JSON and send as POST request + String json = jsonHelper.toJson(Arrays.asList(agentInfo)); + StringContentProvider provider = httpHelper.createContentProvider(json); + + String url = getURL(agentInfo.getAgentId()); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.POST); + httpRequest.content(provider, CONTENT_TYPE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to send agent information to web gateway", e); + } + } + + @Override + public void removeAgentInformation(final AgentInformation agentInfo) { + try { + // Delete AgentInformation with matching Agent ID + String url = getURL(agentInfo.getAgentId()); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.DELETE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to delete agent information from web gateway", e); + } + } + + @Override + public void updateAgentInformation(final AgentInformation agentInfo) { + try { + // Encode as JSON and send as PUT request + AgentInformationUpdate update = new AgentInformationUpdate(agentInfo); + String json = jsonHelper.toJson(update); + StringContentProvider provider = httpHelper.createContentProvider(json); + + String url = getURL(agentInfo.getAgentId()); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.PUT); + httpRequest.content(provider, CONTENT_TYPE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to send agent information update to web gateway", e); + } + } + + private void sendRequest(Request httpRequest) + throws InterruptedException, TimeoutException, ExecutionException, IOException { + ContentResponse resp = httpRequest.send(); + int status = resp.getStatus(); + if (status != HttpStatus.OK_200) { + throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + resp.getReason()); + } + } + + private String getURL(String agentId) { + StringBuilder builder = new StringBuilder(); + builder.append(GATEWAY_URL); + builder.append(GATEWAY_PATH); + builder.append(agentId); + return builder.toString(); + } + + static class AgentInformationUpdate { + + private final AgentInformation info; + + AgentInformationUpdate(AgentInformation info) { + this.info = info; + } + + AgentInformation getInfo() { + return info; + } + + } + + // For testing purposes + static class JsonHelper { + + private final AgentInformationTypeAdapter typeAdapter; + private final AgentInformationUpdateTypeAdapter updateTypeAdapter; + + public JsonHelper(AgentInformationTypeAdapter typeAdapter, AgentInformationUpdateTypeAdapter updateTypeAdapter) { + this.typeAdapter = typeAdapter; + this.updateTypeAdapter = updateTypeAdapter; + } + + String toJson(List<AgentInformation> infos) throws IOException { + return typeAdapter.toJson(infos); + } + + String toJson(AgentInformationUpdate update) throws IOException { + return updateTypeAdapter.toJson(update); + } + + } + + // For testing purposes + static class HttpHelper { + + private final HttpClient httpClient; + + HttpHelper(HttpClient httpClient) { + this.httpClient = httpClient; + } + + void startClient() throws Exception { + httpClient.start(); + } + + StringContentProvider createContentProvider(String content) { + return new StringContentProvider(content); + } + + Request newRequest(String url) { + return new MockRequest(httpClient, URI.create(url)); + } + + } + + // FIXME This class should be removed when the web gateway has a microservice for this DAO + private static class MockRequest extends HttpRequest { + + MockRequest(HttpClient client, URI uri) { + super(client, uri); + } + + @Override + public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException { + return new MockResponse(); + } + + } + + // FIXME This class should be removed when the web gateway has a microservice for this DAO + private static class MockResponse extends HttpContentResponse { + + MockResponse() { + super(null, null, null); + } + + @Override + public int getStatus() { + return HttpStatus.OK_200; + } + + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/AgentInformationTypeAdapter.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,132 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import java.io.IOException; +import java.util.List; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.redhat.thermostat.agent.internal.AgentInfoDAOImpl.AgentInformationUpdate; +import com.redhat.thermostat.storage.model.AgentInformation; + +public class AgentInformationTypeAdapter extends TypeAdapter<List<AgentInformation>> { + + private static final String AGENT_ID = "agentId"; + private static final String START_TIME = "startTime"; + private static final String STOP_TIME = "stopTime"; + private static final String ALIVE = "alive"; + private static final String CONFIG_LISTEN_ADDRESS = "configListenAddress"; + private static final String TYPE_LONG = "$numberLong"; + + @Override + public void write(JsonWriter out, List<AgentInformation> value) throws IOException { + // Request is an array of AgentInformation objects + out.beginArray(); + + for (AgentInformation info : value) { + writeAgentInformation(out, info); + } + + out.endArray(); + } + + private void writeAgentInformation(JsonWriter out, AgentInformation info) throws IOException { + out.beginObject(); + + // Write each field of AgentInformation as part of a JSON object + out.name(AGENT_ID); + out.value(info.getAgentId()); + out.name(START_TIME); + writeLong(out, info.getStartTime()); + out.name(STOP_TIME); + writeLong(out, info.getStopTime()); + out.name(ALIVE); + out.value(info.isAlive()); + out.name(CONFIG_LISTEN_ADDRESS); + out.value(info.getConfigListenAddress()); + + out.endObject(); + } + + private static void writeLong(JsonWriter out, long value) throws IOException { + // Write MongoDB representation of a Long + out.beginObject(); + out.name(TYPE_LONG); + out.value(String.valueOf(value)); + out.endObject(); + } + + @Override + public List<AgentInformation> read(JsonReader in) throws IOException { + throw new UnsupportedOperationException(); + } + + static class AgentInformationUpdateTypeAdapter extends TypeAdapter<AgentInformationUpdate> { + + private static final String SET = "set"; + + @Override + public void write(JsonWriter out, AgentInformationUpdate value) throws IOException { + // List fields to update as part of a JSON object with name "set" + out.beginObject(); + out.name(SET); + + AgentInformation info = value.getInfo(); + out.beginObject(); + out.name(START_TIME); + writeLong(out, info.getStartTime()); + out.name(STOP_TIME); + writeLong(out, info.getStopTime()); + out.name(ALIVE); + out.value(info.isAlive()); + out.name(CONFIG_LISTEN_ADDRESS); + out.value(info.getConfigListenAddress()); + out.endObject(); + + out.endObject(); + } + + @Override + public AgentInformationUpdate read(JsonReader in) throws IOException { + throw new UnsupportedOperationException(); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/BackendInfoDAOImpl.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,214 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.agent.dao.BackendInfoDAO; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpContentResponse; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; + +import com.redhat.thermostat.common.utils.LoggingUtils; + +import com.redhat.thermostat.storage.model.BackendInformation; + +public class BackendInfoDAOImpl implements BackendInfoDAO { + + private static final Logger logger = LoggingUtils.getLogger(BackendInfoDAOImpl.class); + + private static final String GATEWAY_URL = "http://localhost:26000/api/v100"; // TODO configurable + private static final String GATEWAY_PATH = "/backend-info/systems/*/agents/"; + private static final String CONTENT_TYPE = "application/json"; + private static final String GATEWAY_QUERY = "?q="; + private static final String DELETE_QUERY_PARAM = "name=="; + + private final HttpHelper httpHelper; + private final JsonHelper jsonHelper; + + public BackendInfoDAOImpl() throws Exception { + this(new HttpHelper(new HttpClient()), new JsonHelper(new BackendInformationTypeAdapter())); + } + + BackendInfoDAOImpl(HttpHelper httpHelper, JsonHelper jsonHelper) throws Exception { + this.httpHelper = httpHelper; + this.jsonHelper = jsonHelper; + + this.httpHelper.startClient(); + } + + @Override + public void addBackendInformation(final BackendInformation info) { + try { + // Encode as JSON and send as POST request + String json = jsonHelper.toJson(Arrays.asList(info)); + StringContentProvider provider = httpHelper.createContentProvider(json); + + String url = getAddURL(info.getAgentId()); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.POST); + httpRequest.content(provider, CONTENT_TYPE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to send backend information to web gateway", e); + } + } + + @Override + public void removeBackendInformation(final BackendInformation info) { + try { + // Delete BackendInformation with matching name + String url = getRemoveURL(info.getAgentId(), info.getName()); + Request httpRequest = httpHelper.newRequest(url); + httpRequest.method(HttpMethod.DELETE); + sendRequest(httpRequest); + } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { + logger.log(Level.WARNING, "Failed to delete backend information from web gateway", e); + } + } + + private void sendRequest(Request httpRequest) + throws InterruptedException, TimeoutException, ExecutionException, IOException { + ContentResponse resp = httpRequest.send(); + int status = resp.getStatus(); + if (status != HttpStatus.OK_200) { + throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + resp.getReason()); + } + } + + private String getAddURL(String agentId) { + return buildURL(agentId).toString(); + } + + private String getRemoveURL(String agentId, String backendName) throws UnsupportedEncodingException { + StringBuilder builder = buildURL(agentId); + builder.append(GATEWAY_QUERY); + String query = DELETE_QUERY_PARAM.concat(backendName); + String encodedQuery = URLEncoder.encode(query, "UTF-8"); + builder.append(encodedQuery); + return builder.toString(); + } + + private StringBuilder buildURL(String agentId) { + StringBuilder builder = new StringBuilder(); + builder.append(GATEWAY_URL); + builder.append(GATEWAY_PATH); + builder.append(agentId); + return builder; + } + + // For testing purposes + static class JsonHelper { + + private final BackendInformationTypeAdapter typeAdapter; + + public JsonHelper(BackendInformationTypeAdapter typeAdapter) { + this.typeAdapter = typeAdapter; + } + + String toJson(List<BackendInformation> infos) throws IOException { + return typeAdapter.toJson(infos); + } + + } + + // For testing purposes + static class HttpHelper { + + private final HttpClient httpClient; + + HttpHelper(HttpClient httpClient) { + this.httpClient = httpClient; + } + + void startClient() throws Exception { + httpClient.start(); + } + + StringContentProvider createContentProvider(String content) { + return new StringContentProvider(content); + } + + Request newRequest(String url) { + return new MockRequest(httpClient, URI.create(url)); + } + + } + + // FIXME This class should be removed when the web gateway has a microservice for this DAO + private static class MockRequest extends HttpRequest { + + MockRequest(HttpClient client, URI uri) { + super(client, uri); + } + + @Override + public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException { + return new MockResponse(); + } + + } + + // FIXME This class should be removed when the web gateway has a microservice for this DAO + private static class MockResponse extends HttpContentResponse { + + MockResponse() { + super(null, null, null); + } + + @Override + public int getStatus() { + return HttpStatus.OK_200; + } + + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/BackendInformationTypeAdapter.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import java.io.IOException; +import java.util.List; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.redhat.thermostat.storage.model.BackendInformation; + +public class BackendInformationTypeAdapter extends TypeAdapter<List<BackendInformation>> { + + private static final String AGENT_ID = "agentId"; + private static final String NAME = "name"; + private static final String DESCRIPTION = "description"; + private static final String OBSERVE_NEW_JVM = "observeNewJvm"; + private static final String PIDS = "pids"; + private static final String ACTIVE = "active"; + private static final String ORDER_VALUE = "orderValue"; + + @Override + public void write(JsonWriter out, List<BackendInformation> value) throws IOException { + // Request is an array of BackendInformation objects + out.beginArray(); + + for (BackendInformation info : value) { + writeBackendInformation(out, info); + } + + out.endArray(); + } + + private void writeBackendInformation(JsonWriter out, BackendInformation info) throws IOException { + out.beginObject(); + + // Write each field of BackendInformation as part of a JSON object + out.name(AGENT_ID); + out.value(info.getAgentId()); + out.name(NAME); + out.value(info.getName()); + out.name(DESCRIPTION); + out.value(info.getDescription()); + out.name(OBSERVE_NEW_JVM); + out.value(info.isObserveNewJvm()); + out.name(PIDS); + writePidArray(out, info.getPids()); + out.name(ACTIVE); + out.value(info.isActive()); + out.name(ORDER_VALUE); + out.value(info.getOrderValue()); + + out.endObject(); + } + + private void writePidArray(JsonWriter out, int[] pids) throws IOException { + // Output JSON array of PIDs + out.beginArray(); + for (int pid : pids) { + out.value(pid); + } + out.endArray(); + } + + @Override + public List<BackendInformation> read(JsonReader in) throws IOException { + throw new UnsupportedOperationException(); + } + +}
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/AgentTest.java Mon Jun 19 20:10:51 2017 +0200 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/AgentTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -48,6 +48,8 @@ import java.util.UUID; +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.dao.BackendInfoDAO; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -59,8 +61,6 @@ import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ThermostatExtensionRegistry; import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; import com.redhat.thermostat.storage.model.AgentInformation; import com.redhat.thermostat.storage.model.BackendInformation; import com.redhat.thermostat.utils.management.internal.MXBeanConnectionPoolImpl;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/AgentInfoDAOTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,149 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; + +import com.redhat.thermostat.agent.dao.AgentInfoDAO; +import com.redhat.thermostat.agent.internal.AgentInfoDAOImpl.AgentInformationUpdate; +import com.redhat.thermostat.agent.internal.AgentInfoDAOImpl.HttpHelper; +import com.redhat.thermostat.agent.internal.AgentInfoDAOImpl.JsonHelper; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.storage.model.AgentInformation; + +public class AgentInfoDAOTest { + + private static final String URL = "http://localhost:26000/api/v100/agent-config/systems/*/agents/1234"; + private static final String SOME_JSON = "{\"some\" : \"json\"}"; + private static final String SOME_OTHER_JSON = "{\"some\" : {\"other\" : \"json\"}}"; + private static final String CONTENT_TYPE = "application/json"; + + private AgentInformation info; + private JsonHelper jsonHelper; + private HttpHelper httpHelper; + private StringContentProvider contentProvider; + private Request request; + private ContentResponse response; + + @Before + public void setUp() throws Exception { + info = new AgentInformation("1234"); + info.setAlive(true); + info.setConfigListenAddress("foobar:666"); + info.setStartTime(100); + info.setStopTime(10); + + httpHelper = mock(HttpHelper.class); + contentProvider = mock(StringContentProvider.class); + when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider); + request = mock(Request.class); + when(httpHelper.newRequest(anyString())).thenReturn(request); + response = mock(ContentResponse.class); + when(response.getStatus()).thenReturn(HttpStatus.OK_200); + when(request.send()).thenReturn(response); + + jsonHelper = mock(JsonHelper.class); + when(jsonHelper.toJson(anyListOf(AgentInformation.class))).thenReturn(SOME_JSON); + when(jsonHelper.toJson(any(AgentInformationUpdate.class))).thenReturn(SOME_OTHER_JSON); + } + + @Test + public void verifyAddAgentInformation() throws Exception { + AgentInfoDAO dao = new AgentInfoDAOImpl(httpHelper, jsonHelper); + + dao.addAgentInformation(info); + + verify(httpHelper).newRequest(URL); + verify(request).method(HttpMethod.POST); + verify(jsonHelper).toJson(eq(Arrays.asList(info))); + verify(httpHelper).createContentProvider(SOME_JSON); + verify(request).content(contentProvider, CONTENT_TYPE); + verify(request).send(); + verify(response).getStatus(); + } + + @Test + public void verifyUpdateAgentInformation() throws Exception { + AgentInfoDAO dao = new AgentInfoDAOImpl(httpHelper, jsonHelper); + + dao.updateAgentInformation(info); + + verify(httpHelper).newRequest(URL); + verify(request).method(HttpMethod.PUT); + + ArgumentCaptor<AgentInformationUpdate> updateCaptor = ArgumentCaptor.forClass(AgentInformationUpdate.class); + verify(jsonHelper).toJson(updateCaptor.capture()); + AgentInformationUpdate update = updateCaptor.getValue(); + assertEquals(info, update.getInfo()); + + verify(httpHelper).createContentProvider(SOME_OTHER_JSON); + verify(request).content(contentProvider, CONTENT_TYPE); + verify(request).send(); + verify(response).getStatus(); + } + + @Test + public void verifyRemoveAgentInformation() throws Exception { + AgentInfoDAO dao = new AgentInfoDAOImpl(httpHelper, jsonHelper); + + dao.removeAgentInformation(info); + + verify(httpHelper).newRequest(URL); + verify(request).method(HttpMethod.DELETE); + verify(request).send(); + verify(response).getStatus(); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/AgentInformationTypeAdapterTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; + +import com.redhat.thermostat.agent.internal.AgentInfoDAOImpl.AgentInformationUpdate; +import com.redhat.thermostat.agent.internal.AgentInformationTypeAdapter.AgentInformationUpdateTypeAdapter; +import org.junit.Test; + +import com.redhat.thermostat.storage.model.AgentInformation; + +public class AgentInformationTypeAdapterTest { + + @Test + public void testWrite() throws Exception { + AgentInformationTypeAdapter adapter = new AgentInformationTypeAdapter(); + final String expected = "[{\"agentId\":\"agent1\",\"startTime\":{\"$numberLong\":\"4000\"}," + + "\"stopTime\":{\"$numberLong\":\"6000\"},\"alive\":false,\"configListenAddress\":\"127.0.0.1:12000\"}," + + "{\"agentId\":\"agent2\",\"startTime\":{\"$numberLong\":\"5000\"},\"stopTime\":{\"$numberLong\":\"0\"}," + + "\"alive\":true,\"configListenAddress\":\"1.2.3.4:12000\"}]"; + + AgentInformation first = createAgentInformation("agent1", 4000L, 6000L, false, "127.0.0.1:12000"); + AgentInformation second = createAgentInformation("agent2", 5000L, 0L, true, "1.2.3.4:12000"); + List<AgentInformation> infos = Arrays.asList(first, second); + + String json = adapter.toJson(infos); + assertEquals(expected, json); + } + + @Test + public void testUpdate() throws Exception { + AgentInformationUpdateTypeAdapter adapter = new AgentInformationUpdateTypeAdapter(); + final String expected = "{\"set\":{\"startTime\":{\"$numberLong\":\"5000\"}," + + "\"stopTime\":{\"$numberLong\":\"7000\"},\"alive\":false,\"configListenAddress\":\"1.2.3.4:12000\"}}"; + + AgentInformation info = createAgentInformation("agent2", 5000L, 7000L, false, "1.2.3.4:12000"); + AgentInformationUpdate update = new AgentInformationUpdate(info); + + String json = adapter.toJson(update); + assertEquals(expected, json); + } + + private AgentInformation createAgentInformation(String agentId, long startTime, long stopTime, + boolean alive, String configListenAddress) { + AgentInformation info = new AgentInformation(agentId); + info.setStartTime(startTime); + info.setStopTime(stopTime); + info.setAlive(alive); + info.setConfigListenAddress(configListenAddress); + return info; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/BackendInfoDAOTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,127 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; + +import com.redhat.thermostat.agent.dao.BackendInfoDAO; +import com.redhat.thermostat.agent.internal.BackendInfoDAOImpl.JsonHelper; +import com.redhat.thermostat.agent.internal.BackendInfoDAOImpl.HttpHelper; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.storage.model.BackendInformation; + +public class BackendInfoDAOTest { + + private static final String URL = "http://localhost:26000/api/v100/backend-info/systems/*/agents/foo-agent1"; + private static final String REMOVE_URL = URL + "?q=name%3D%3DTest+Backend"; + private static final String SOME_JSON = "{\"some\" : \"json\"}"; + private static final String CONTENT_TYPE = "application/json"; + + private BackendInformation backendInfo1; + private JsonHelper jsonHelper; + private HttpHelper httpHelper; + private StringContentProvider contentProvider; + private Request request; + private ContentResponse response; + + @Before + public void setUp() throws Exception { + backendInfo1 = new BackendInformation("foo-agent1"); + + backendInfo1.setName("Test Backend"); + backendInfo1.setDescription("description"); + backendInfo1.setActive(true); + backendInfo1.setObserveNewJvm(true); + backendInfo1.setPids(new int[] { -1, 0, 1}); + backendInfo1.setOrderValue(100); + + httpHelper = mock(HttpHelper.class); + contentProvider = mock(StringContentProvider.class); + when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider); + request = mock(Request.class); + when(httpHelper.newRequest(anyString())).thenReturn(request); + response = mock(ContentResponse.class); + when(response.getStatus()).thenReturn(HttpStatus.OK_200); + when(request.send()).thenReturn(response); + + jsonHelper = mock(JsonHelper.class); + when(jsonHelper.toJson(anyListOf(BackendInformation.class))).thenReturn(SOME_JSON); + } + + @Test + public void verifyAddBackendInformation() throws Exception { + BackendInfoDAO dao = new BackendInfoDAOImpl(httpHelper, jsonHelper); + + dao.addBackendInformation(backendInfo1); + + verify(httpHelper).newRequest(URL); + verify(request).method(HttpMethod.POST); + verify(jsonHelper).toJson(eq(Arrays.asList(backendInfo1))); + verify(httpHelper).createContentProvider(SOME_JSON); + verify(request).content(contentProvider, CONTENT_TYPE); + verify(request).send(); + verify(response).getStatus(); + } + + @Test + public void verifyRemoveBackendInformation() throws Exception { + BackendInfoDAO dao = new BackendInfoDAOImpl(httpHelper, jsonHelper); + + dao.removeBackendInformation(backendInfo1); + + verify(httpHelper).newRequest(REMOVE_URL); + verify(request).method(HttpMethod.DELETE); + verify(request).send(); + verify(response).getStatus(); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/BackendInformationTypeAdapterTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -0,0 +1,87 @@ +/* + * Copyright 2012-2017 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.agent.internal; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.storage.model.BackendInformation; + +public class BackendInformationTypeAdapterTest { + + private BackendInformationTypeAdapter adapter; + + @Before + public void setup() { + adapter = new BackendInformationTypeAdapter(); + } + + @Test + public void testWrite() throws Exception { + final String expected = "[{\"agentId\":\"agent1\",\"name\":\"First Backend\",\"description\":\"Gathers something\"," + + "\"observeNewJvm\":true,\"pids\":[8000,9000],\"active\":true,\"orderValue\":280}," + + "{\"agentId\":\"agent2\",\"name\":\"Second Backend\",\"description\":\"Gathers something else\"," + + "\"observeNewJvm\":false,\"pids\":[],\"active\":false,\"orderValue\":200}]"; + + BackendInformation first = createBackendInformation("agent1", "First Backend", "Gathers something", true, + new int[] { 8000, 9000 }, true, 280); + BackendInformation second = createBackendInformation("agent2", "Second Backend", "Gathers something else", false, + new int[0], false, 200); + List<BackendInformation> infos = Arrays.asList(first, second); + + String json = adapter.toJson(infos); + assertEquals(expected, json); + } + + private BackendInformation createBackendInformation(String agentId, String name, String desc, + boolean observeNewJvm, int[] pids, boolean active, int orderValue) { + BackendInformation info = new BackendInformation(agentId); + info.setName(name); + info.setDescription(desc); + info.setObserveNewJvm(observeNewJvm); + info.setPids(pids); + info.setActive(active); + info.setOrderValue(orderValue); + return info; + } + +}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java Mon Jun 19 20:10:51 2017 +0200 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -45,7 +45,6 @@ import com.redhat.thermostat.launcher.BundleManager; import com.redhat.thermostat.launcher.Launcher; import com.redhat.thermostat.shared.config.CommonPaths; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; import com.redhat.thermostat.testutils.StubBundleContext; import org.junit.Before; import org.junit.Test; @@ -172,16 +171,7 @@ eq(launcherDeps), actionCaptor.capture()).thenReturn(launcherDepsTracker); MultipleServiceTracker unusedTracker = mock(MultipleServiceTracker.class); - Class<?>[] vmIdCompleterDeps = new Class[] { - AgentInfoDAO.class - }; - whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context), - eq(vmIdCompleterDeps), actionCaptor.capture()).thenReturn(unusedTracker); - Class<?>[] agentIdCompleterDeps = new Class[] { - AgentInfoDAO.class - }; - whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context), - eq(agentIdCompleterDeps), actionCaptor.capture()).thenReturn(unusedTracker); + Class<?>[] helpCommandDeps = new Class[] { CommandInfoSource.class, CommandGroupMetadataSource.class
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherImplTest.java Mon Jun 19 20:10:51 2017 +0200 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherImplTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -76,10 +76,8 @@ import com.redhat.thermostat.common.ApplicationService; import com.redhat.thermostat.common.ExitStatus; import com.redhat.thermostat.common.Version; -import com.redhat.thermostat.common.cli.AbstractStateNotifyingCommand; import com.redhat.thermostat.common.cli.Arguments; import com.redhat.thermostat.common.cli.CommandContext; -import com.redhat.thermostat.common.cli.CommandException; import com.redhat.thermostat.common.cli.CommandRegistry; import com.redhat.thermostat.common.internal.test.TestCommandContextFactory; import com.redhat.thermostat.common.internal.test.TestTimerFactory; @@ -88,7 +86,6 @@ import com.redhat.thermostat.launcher.BundleManager; import com.redhat.thermostat.launcher.internal.DisallowSystemExitSecurityManager.ExitException; import com.redhat.thermostat.shared.config.CommonPaths; -import com.redhat.thermostat.shared.locale.LocalizedString; import com.redhat.thermostat.testutils.StubBundleContext; public class LauncherImplTest {
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/dao/AgentInfoDAO.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.dao; - -import java.util.List; -import java.util.Set; - -import com.redhat.thermostat.annotations.Service; -import com.redhat.thermostat.storage.core.AgentId; -import com.redhat.thermostat.storage.model.AgentInformation; - -/** - * Access information about agents that agents publish to storage. - */ -@Service -public interface AgentInfoDAO { - - /** - * Get information about all known agents. - * - * @return a {@link List} of {@link AgentInformation} for all agents - * who have published their information. Will be empty if there is no - * information. - */ - List<AgentInformation> getAllAgentInformation(); - - /** - * Get information about a specific agent. - * - * @return a {@link AgentInformation} describing information about the agent - * indicated by {@code agentId}. {@code null} if no information about the - * agent could be located. - */ - - AgentInformation getAgentInformation(AgentId agentId); - - /** - * - * @return A set of AgentIds, which may be empty. - */ - Set<AgentId> getAgentIds(); - - /** - * Publish information about agent into the storage. - */ - void addAgentInformation(AgentInformation agentInfo); - - /** - * Update information about an existing agent. No changes will be performed - * if there is no matching agent. - */ - void updateAgentInformation(AgentInformation agentInfo); - - /** - * Remove information about an agent that was published to storage. - */ - void removeAgentInformation(AgentInformation agentInfo); - -} -
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/dao/BackendInfoDAO.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.dao; - -import com.redhat.thermostat.annotations.Service; -import com.redhat.thermostat.storage.model.BackendInformation; - -@Service -public interface BackendInfoDAO { - - void addBackendInformation(BackendInformation info); - - void removeBackendInformation(BackendInformation info); - -} -
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/Activator.java Mon Jun 19 20:10:51 2017 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/Activator.java Tue Jun 20 13:00:11 2017 +0200 @@ -45,11 +45,7 @@ import org.osgi.framework.ServiceRegistration; import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl; -import com.redhat.thermostat.storage.internal.dao.BackendInfoDAOImpl; import com.redhat.thermostat.storage.internal.dao.NetworkInterfaceInfoDAOImpl; public class Activator implements BundleActivator { @@ -70,14 +66,6 @@ final WriterID writerID = new WriterIDImpl(WRITER_UUID); ServiceRegistration<?> reg = context.registerService(WriterID.class, writerID, null); regs.add(reg); - - AgentInfoDAO agentInfoDao = new AgentInfoDAOImpl(); - reg = context.registerService(AgentInfoDAO.class.getName(), agentInfoDao, null); - regs.add(reg); - - BackendInfoDAO backendInfoDao = new BackendInfoDAOImpl(); - reg = context.registerService(BackendInfoDAO.class.getName(), backendInfoDao, null); - regs.add(reg); NetworkInterfaceInfoDAO networkInfoDao = new NetworkInterfaceInfoDAOImpl(); reg = context.registerService(NetworkInterfaceInfoDAO.class.getName(), networkInfoDao, null);
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/AgentInfoDAOImpl.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpContentResponse; -import org.eclipse.jetty.client.HttpRequest; -import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.util.StringContentProvider; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpStatus; - -import com.redhat.thermostat.common.utils.LoggingUtils; -import com.redhat.thermostat.storage.core.AgentId; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.internal.dao.AgentInformationTypeAdapter.AgentInformationUpdateTypeAdapter; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class AgentInfoDAOImpl implements AgentInfoDAO { - - private static final Logger logger = LoggingUtils.getLogger(AgentInfoDAOImpl.class); - - private static final String GATEWAY_URL = "http://localhost:26000/api/v100"; // TODO configurable - private static final String GATEWAY_PATH = "/agent-config/systems/*/agents/"; - private static final String CONTENT_TYPE = "application/json"; - - private final HttpHelper httpHelper; - private final JsonHelper jsonHelper; - - public AgentInfoDAOImpl() throws Exception { - this(new HttpHelper(new HttpClient()), new JsonHelper(new AgentInformationTypeAdapter(), - new AgentInformationUpdateTypeAdapter())); - } - - AgentInfoDAOImpl(HttpHelper httpHelper, JsonHelper jsonHelper) throws Exception { - this.httpHelper = httpHelper; - this.jsonHelper = jsonHelper; - - this.httpHelper.startClient(); - } - - @Override - public List<AgentInformation> getAllAgentInformation() { - return Collections.emptyList(); // TODO Remove once Agent Id completer is removed - } - - @Override - public AgentInformation getAgentInformation(final AgentId agentId) { - return null; // TODO Remove once VM Id completer is removed - } - - @Override - public Set<AgentId> getAgentIds() { - return Collections.emptySet(); // TODO Remove once VM Id completer is removed - } - - @Override - public void addAgentInformation(final AgentInformation agentInfo) { - try { - // Encode as JSON and send as POST request - String json = jsonHelper.toJson(Arrays.asList(agentInfo)); - StringContentProvider provider = httpHelper.createContentProvider(json); - - String url = getURL(agentInfo.getAgentId()); - Request httpRequest = httpHelper.newRequest(url); - httpRequest.method(HttpMethod.POST); - httpRequest.content(provider, CONTENT_TYPE); - sendRequest(httpRequest); - } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { - logger.log(Level.WARNING, "Failed to send agent information to web gateway", e); - } - } - - @Override - public void removeAgentInformation(final AgentInformation agentInfo) { - try { - // Delete AgentInformation with matching Agent ID - String url = getURL(agentInfo.getAgentId()); - Request httpRequest = httpHelper.newRequest(url); - httpRequest.method(HttpMethod.DELETE); - sendRequest(httpRequest); - } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { - logger.log(Level.WARNING, "Failed to delete agent information from web gateway", e); - } - } - - @Override - public void updateAgentInformation(final AgentInformation agentInfo) { - try { - // Encode as JSON and send as PUT request - AgentInformationUpdate update = new AgentInformationUpdate(agentInfo); - String json = jsonHelper.toJson(update); - StringContentProvider provider = httpHelper.createContentProvider(json); - - String url = getURL(agentInfo.getAgentId()); - Request httpRequest = httpHelper.newRequest(url); - httpRequest.method(HttpMethod.PUT); - httpRequest.content(provider, CONTENT_TYPE); - sendRequest(httpRequest); - } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { - logger.log(Level.WARNING, "Failed to send agent information update to web gateway", e); - } - } - - private void sendRequest(Request httpRequest) - throws InterruptedException, TimeoutException, ExecutionException, IOException { - ContentResponse resp = httpRequest.send(); - int status = resp.getStatus(); - if (status != HttpStatus.OK_200) { - throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + resp.getReason()); - } - } - - private String getURL(String agentId) { - StringBuilder builder = new StringBuilder(); - builder.append(GATEWAY_URL); - builder.append(GATEWAY_PATH); - builder.append(agentId); - return builder.toString(); - } - - static class AgentInformationUpdate { - - private final AgentInformation info; - - AgentInformationUpdate(AgentInformation info) { - this.info = info; - } - - AgentInformation getInfo() { - return info; - } - - } - - // For testing purposes - static class JsonHelper { - - private final AgentInformationTypeAdapter typeAdapter; - private final AgentInformationUpdateTypeAdapter updateTypeAdapter; - - public JsonHelper(AgentInformationTypeAdapter typeAdapter, AgentInformationUpdateTypeAdapter updateTypeAdapter) { - this.typeAdapter = typeAdapter; - this.updateTypeAdapter = updateTypeAdapter; - } - - String toJson(List<AgentInformation> infos) throws IOException { - return typeAdapter.toJson(infos); - } - - String toJson(AgentInformationUpdate update) throws IOException { - return updateTypeAdapter.toJson(update); - } - - } - - // For testing purposes - static class HttpHelper { - - private final HttpClient httpClient; - - HttpHelper(HttpClient httpClient) { - this.httpClient = httpClient; - } - - void startClient() throws Exception { - httpClient.start(); - } - - StringContentProvider createContentProvider(String content) { - return new StringContentProvider(content); - } - - Request newRequest(String url) { - return new MockRequest(httpClient, URI.create(url)); - } - - } - - // FIXME This class should be removed when the web gateway has a microservice for this DAO - private static class MockRequest extends HttpRequest { - - MockRequest(HttpClient client, URI uri) { - super(client, uri); - } - - @Override - public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException { - return new MockResponse(); - } - - } - - // FIXME This class should be removed when the web gateway has a microservice for this DAO - private static class MockResponse extends HttpContentResponse { - - MockResponse() { - super(null, null, null); - } - - @Override - public int getStatus() { - return HttpStatus.OK_200; - } - - } - -} -
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/AgentInformationTypeAdapter.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import java.io.IOException; -import java.util.List; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl.AgentInformationUpdate; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class AgentInformationTypeAdapter extends TypeAdapter<List<AgentInformation>> { - - private static final String AGENT_ID = "agentId"; - private static final String START_TIME = "startTime"; - private static final String STOP_TIME = "stopTime"; - private static final String ALIVE = "alive"; - private static final String CONFIG_LISTEN_ADDRESS = "configListenAddress"; - private static final String TYPE_LONG = "$numberLong"; - - @Override - public void write(JsonWriter out, List<AgentInformation> value) throws IOException { - // Request is an array of AgentInformation objects - out.beginArray(); - - for (AgentInformation info : value) { - writeAgentInformation(out, info); - } - - out.endArray(); - } - - private void writeAgentInformation(JsonWriter out, AgentInformation info) throws IOException { - out.beginObject(); - - // Write each field of AgentInformation as part of a JSON object - out.name(AGENT_ID); - out.value(info.getAgentId()); - out.name(START_TIME); - writeLong(out, info.getStartTime()); - out.name(STOP_TIME); - writeLong(out, info.getStopTime()); - out.name(ALIVE); - out.value(info.isAlive()); - out.name(CONFIG_LISTEN_ADDRESS); - out.value(info.getConfigListenAddress()); - - out.endObject(); - } - - private static void writeLong(JsonWriter out, long value) throws IOException { - // Write MongoDB representation of a Long - out.beginObject(); - out.name(TYPE_LONG); - out.value(String.valueOf(value)); - out.endObject(); - } - - @Override - public List<AgentInformation> read(JsonReader in) throws IOException { - throw new UnsupportedOperationException(); - } - - static class AgentInformationUpdateTypeAdapter extends TypeAdapter<AgentInformationUpdate> { - - private static final String SET = "set"; - - @Override - public void write(JsonWriter out, AgentInformationUpdate value) throws IOException { - // List fields to update as part of a JSON object with name "set" - out.beginObject(); - out.name(SET); - - AgentInformation info = value.getInfo(); - out.beginObject(); - out.name(START_TIME); - writeLong(out, info.getStartTime()); - out.name(STOP_TIME); - writeLong(out, info.getStopTime()); - out.name(ALIVE); - out.value(info.isAlive()); - out.name(CONFIG_LISTEN_ADDRESS); - out.value(info.getConfigListenAddress()); - out.endObject(); - - out.endObject(); - } - - @Override - public AgentInformationUpdate read(JsonReader in) throws IOException { - throw new UnsupportedOperationException(); - } - - } - -}
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/BackendInfoDAOImpl.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpContentResponse; -import org.eclipse.jetty.client.HttpRequest; -import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.util.StringContentProvider; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpStatus; - -import com.redhat.thermostat.common.utils.LoggingUtils; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; -import com.redhat.thermostat.storage.model.BackendInformation; - -public class BackendInfoDAOImpl implements BackendInfoDAO { - - private static final Logger logger = LoggingUtils.getLogger(BackendInfoDAOImpl.class); - - private static final String GATEWAY_URL = "http://localhost:26000/api/v100"; // TODO configurable - private static final String GATEWAY_PATH = "/backend-info/systems/*/agents/"; - private static final String CONTENT_TYPE = "application/json"; - private static final String GATEWAY_QUERY = "?q="; - private static final String DELETE_QUERY_PARAM = "name=="; - - private final HttpHelper httpHelper; - private final JsonHelper jsonHelper; - - public BackendInfoDAOImpl() throws Exception { - this(new HttpHelper(new HttpClient()), new JsonHelper(new BackendInformationTypeAdapter())); - } - - BackendInfoDAOImpl(HttpHelper httpHelper, JsonHelper jsonHelper) throws Exception { - this.httpHelper = httpHelper; - this.jsonHelper = jsonHelper; - - this.httpHelper.startClient(); - } - - @Override - public void addBackendInformation(final BackendInformation info) { - try { - // Encode as JSON and send as POST request - String json = jsonHelper.toJson(Arrays.asList(info)); - StringContentProvider provider = httpHelper.createContentProvider(json); - - String url = getAddURL(info.getAgentId()); - Request httpRequest = httpHelper.newRequest(url); - httpRequest.method(HttpMethod.POST); - httpRequest.content(provider, CONTENT_TYPE); - sendRequest(httpRequest); - } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { - logger.log(Level.WARNING, "Failed to send backend information to web gateway", e); - } - } - - @Override - public void removeBackendInformation(final BackendInformation info) { - try { - // Delete BackendInformation with matching name - String url = getRemoveURL(info.getAgentId(), info.getName()); - Request httpRequest = httpHelper.newRequest(url); - httpRequest.method(HttpMethod.DELETE); - sendRequest(httpRequest); - } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) { - logger.log(Level.WARNING, "Failed to delete backend information from web gateway", e); - } - } - - private void sendRequest(Request httpRequest) - throws InterruptedException, TimeoutException, ExecutionException, IOException { - ContentResponse resp = httpRequest.send(); - int status = resp.getStatus(); - if (status != HttpStatus.OK_200) { - throw new IOException("Gateway returned HTTP status " + String.valueOf(status) + " - " + resp.getReason()); - } - } - - private String getAddURL(String agentId) { - return buildURL(agentId).toString(); - } - - private String getRemoveURL(String agentId, String backendName) throws UnsupportedEncodingException { - StringBuilder builder = buildURL(agentId); - builder.append(GATEWAY_QUERY); - String query = DELETE_QUERY_PARAM.concat(backendName); - String encodedQuery = URLEncoder.encode(query, "UTF-8"); - builder.append(encodedQuery); - return builder.toString(); - } - - private StringBuilder buildURL(String agentId) { - StringBuilder builder = new StringBuilder(); - builder.append(GATEWAY_URL); - builder.append(GATEWAY_PATH); - builder.append(agentId); - return builder; - } - - // For testing purposes - static class JsonHelper { - - private final BackendInformationTypeAdapter typeAdapter; - - public JsonHelper(BackendInformationTypeAdapter typeAdapter) { - this.typeAdapter = typeAdapter; - } - - String toJson(List<BackendInformation> infos) throws IOException { - return typeAdapter.toJson(infos); - } - - } - - // For testing purposes - static class HttpHelper { - - private final HttpClient httpClient; - - HttpHelper(HttpClient httpClient) { - this.httpClient = httpClient; - } - - void startClient() throws Exception { - httpClient.start(); - } - - StringContentProvider createContentProvider(String content) { - return new StringContentProvider(content); - } - - Request newRequest(String url) { - return new MockRequest(httpClient, URI.create(url)); - } - - } - - // FIXME This class should be removed when the web gateway has a microservice for this DAO - private static class MockRequest extends HttpRequest { - - MockRequest(HttpClient client, URI uri) { - super(client, uri); - } - - @Override - public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException { - return new MockResponse(); - } - - } - - // FIXME This class should be removed when the web gateway has a microservice for this DAO - private static class MockResponse extends HttpContentResponse { - - MockResponse() { - super(null, null, null); - } - - @Override - public int getStatus() { - return HttpStatus.OK_200; - } - - } -} -
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/BackendInformationTypeAdapter.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import java.io.IOException; -import java.util.List; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import com.redhat.thermostat.storage.model.BackendInformation; - -public class BackendInformationTypeAdapter extends TypeAdapter<List<BackendInformation>> { - - private static final String AGENT_ID = "agentId"; - private static final String NAME = "name"; - private static final String DESCRIPTION = "description"; - private static final String OBSERVE_NEW_JVM = "observeNewJvm"; - private static final String PIDS = "pids"; - private static final String ACTIVE = "active"; - private static final String ORDER_VALUE = "orderValue"; - - @Override - public void write(JsonWriter out, List<BackendInformation> value) throws IOException { - // Request is an array of BackendInformation objects - out.beginArray(); - - for (BackendInformation info : value) { - writeBackendInformation(out, info); - } - - out.endArray(); - } - - private void writeBackendInformation(JsonWriter out, BackendInformation info) throws IOException { - out.beginObject(); - - // Write each field of BackendInformation as part of a JSON object - out.name(AGENT_ID); - out.value(info.getAgentId()); - out.name(NAME); - out.value(info.getName()); - out.name(DESCRIPTION); - out.value(info.getDescription()); - out.name(OBSERVE_NEW_JVM); - out.value(info.isObserveNewJvm()); - out.name(PIDS); - writePidArray(out, info.getPids()); - out.name(ACTIVE); - out.value(info.isActive()); - out.name(ORDER_VALUE); - out.value(info.getOrderValue()); - - out.endObject(); - } - - private void writePidArray(JsonWriter out, int[] pids) throws IOException { - // Output JSON array of PIDs - out.beginArray(); - for (int pid : pids) { - out.value(pid); - } - out.endArray(); - } - - @Override - public List<BackendInformation> read(JsonReader in) throws IOException { - throw new UnsupportedOperationException(); - } - -}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/ActivatorTest.java Mon Jun 19 20:10:51 2017 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/ActivatorTest.java Tue Jun 20 13:00:11 2017 +0200 @@ -48,11 +48,7 @@ import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.TimerFactory; import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.dao.BackendInfoDAO; import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl; -import com.redhat.thermostat.storage.internal.dao.BackendInfoDAOImpl; import com.redhat.thermostat.storage.internal.dao.NetworkInterfaceInfoDAOImpl; import com.redhat.thermostat.testutils.StubBundleContext; @@ -67,8 +63,6 @@ assertTrue(context.isServiceRegistered(WriterID.class.getName(), WriterIDImpl.class)); assertTrue(context.isServiceRegistered(NetworkInterfaceInfoDAO.class.getName(), NetworkInterfaceInfoDAOImpl.class)); - assertTrue(context.isServiceRegistered(AgentInfoDAO.class.getName(), AgentInfoDAOImpl.class)); - assertTrue(context.isServiceRegistered(BackendInfoDAO.class.getName(), BackendInfoDAOImpl.class)); activator.stop(context); @@ -87,8 +81,6 @@ activator.stop(context); assertFalse(context.isServiceRegistered(NetworkInterfaceInfoDAO.class.getName(), NetworkInterfaceInfoDAOImpl.class)); - assertFalse(context.isServiceRegistered(AgentInfoDAO.class.getName(), AgentInfoDAOImpl.class)); - assertFalse(context.isServiceRegistered(BackendInfoDAO.class.getName(), BackendInfoDAOImpl.class)); assertFalse(context.isServiceRegistered(WriterID.class.getName(), WriterIDImpl.class)); assertEquals(0, context.getServiceListeners().size()); @@ -110,8 +102,6 @@ activator.start(context); assertTrue(context.isServiceRegistered(NetworkInterfaceInfoDAO.class.getName(), NetworkInterfaceInfoDAOImpl.class)); - assertTrue(context.isServiceRegistered(AgentInfoDAO.class.getName(), AgentInfoDAOImpl.class)); - assertTrue(context.isServiceRegistered(BackendInfoDAO.class.getName(), BackendInfoDAOImpl.class)); assertTrue(context.isServiceRegistered(WriterID.class.getName(), WriterIDImpl.class)); activator.stop(context); @@ -122,8 +112,6 @@ activator.start(context); assertTrue(context.isServiceRegistered(NetworkInterfaceInfoDAO.class.getName(), NetworkInterfaceInfoDAOImpl.class)); - assertTrue(context.isServiceRegistered(AgentInfoDAO.class.getName(), AgentInfoDAOImpl.class)); - assertTrue(context.isServiceRegistered(BackendInfoDAO.class.getName(), BackendInfoDAOImpl.class)); assertTrue(context.isServiceRegistered(WriterID.class.getName(), WriterIDImpl.class)); activator.stop(context);
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/AgentInfoDAOTest.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.Arrays; - -import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.util.StringContentProvider; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpStatus; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.storage.dao.AgentInfoDAO; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl.AgentInformationUpdate; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl.HttpHelper; -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl.JsonHelper; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class AgentInfoDAOTest { - - private static final String URL = "http://localhost:26000/api/v100/agent-config/systems/*/agents/1234"; - private static final String SOME_JSON = "{\"some\" : \"json\"}"; - private static final String SOME_OTHER_JSON = "{\"some\" : {\"other\" : \"json\"}}"; - private static final String CONTENT_TYPE = "application/json"; - - private AgentInformation info; - private JsonHelper jsonHelper; - private HttpHelper httpHelper; - private StringContentProvider contentProvider; - private Request request; - private ContentResponse response; - - @Before - public void setUp() throws Exception { - info = new AgentInformation("1234"); - info.setAlive(true); - info.setConfigListenAddress("foobar:666"); - info.setStartTime(100); - info.setStopTime(10); - - httpHelper = mock(HttpHelper.class); - contentProvider = mock(StringContentProvider.class); - when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider); - request = mock(Request.class); - when(httpHelper.newRequest(anyString())).thenReturn(request); - response = mock(ContentResponse.class); - when(response.getStatus()).thenReturn(HttpStatus.OK_200); - when(request.send()).thenReturn(response); - - jsonHelper = mock(JsonHelper.class); - when(jsonHelper.toJson(anyListOf(AgentInformation.class))).thenReturn(SOME_JSON); - when(jsonHelper.toJson(any(AgentInformationUpdate.class))).thenReturn(SOME_OTHER_JSON); - } - - @Test - public void verifyAddAgentInformation() throws Exception { - AgentInfoDAO dao = new AgentInfoDAOImpl(httpHelper, jsonHelper); - - dao.addAgentInformation(info); - - verify(httpHelper).newRequest(URL); - verify(request).method(HttpMethod.POST); - verify(jsonHelper).toJson(eq(Arrays.asList(info))); - verify(httpHelper).createContentProvider(SOME_JSON); - verify(request).content(contentProvider, CONTENT_TYPE); - verify(request).send(); - verify(response).getStatus(); - } - - @Test - public void verifyUpdateAgentInformation() throws Exception { - AgentInfoDAO dao = new AgentInfoDAOImpl(httpHelper, jsonHelper); - - dao.updateAgentInformation(info); - - verify(httpHelper).newRequest(URL); - verify(request).method(HttpMethod.PUT); - - ArgumentCaptor<AgentInformationUpdate> updateCaptor = ArgumentCaptor.forClass(AgentInformationUpdate.class); - verify(jsonHelper).toJson(updateCaptor.capture()); - AgentInformationUpdate update = updateCaptor.getValue(); - assertEquals(info, update.getInfo()); - - verify(httpHelper).createContentProvider(SOME_OTHER_JSON); - verify(request).content(contentProvider, CONTENT_TYPE); - verify(request).send(); - verify(response).getStatus(); - } - - @Test - public void verifyRemoveAgentInformation() throws Exception { - AgentInfoDAO dao = new AgentInfoDAOImpl(httpHelper, jsonHelper); - - dao.removeAgentInformation(info); - - verify(httpHelper).newRequest(URL); - verify(request).method(HttpMethod.DELETE); - verify(request).send(); - verify(response).getStatus(); - } - -} -
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/AgentInformationTypeAdapterTest.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; - -import com.redhat.thermostat.storage.internal.dao.AgentInfoDAOImpl.AgentInformationUpdate; -import com.redhat.thermostat.storage.internal.dao.AgentInformationTypeAdapter.AgentInformationUpdateTypeAdapter; -import com.redhat.thermostat.storage.model.AgentInformation; - -public class AgentInformationTypeAdapterTest { - - @Test - public void testWrite() throws Exception { - AgentInformationTypeAdapter adapter = new AgentInformationTypeAdapter(); - final String expected = "[{\"agentId\":\"agent1\",\"startTime\":{\"$numberLong\":\"4000\"}," - + "\"stopTime\":{\"$numberLong\":\"6000\"},\"alive\":false,\"configListenAddress\":\"127.0.0.1:12000\"}," - + "{\"agentId\":\"agent2\",\"startTime\":{\"$numberLong\":\"5000\"},\"stopTime\":{\"$numberLong\":\"0\"}," - + "\"alive\":true,\"configListenAddress\":\"1.2.3.4:12000\"}]"; - - AgentInformation first = createAgentInformation("agent1", 4000L, 6000L, false, "127.0.0.1:12000"); - AgentInformation second = createAgentInformation("agent2", 5000L, 0L, true, "1.2.3.4:12000"); - List<AgentInformation> infos = Arrays.asList(first, second); - - String json = adapter.toJson(infos); - assertEquals(expected, json); - } - - @Test - public void testUpdate() throws Exception { - AgentInformationUpdateTypeAdapter adapter = new AgentInformationUpdateTypeAdapter(); - final String expected = "{\"set\":{\"startTime\":{\"$numberLong\":\"5000\"}," - + "\"stopTime\":{\"$numberLong\":\"7000\"},\"alive\":false,\"configListenAddress\":\"1.2.3.4:12000\"}}"; - - AgentInformation info = createAgentInformation("agent2", 5000L, 7000L, false, "1.2.3.4:12000"); - AgentInformationUpdate update = new AgentInformationUpdate(info); - - String json = adapter.toJson(update); - assertEquals(expected, json); - } - - private AgentInformation createAgentInformation(String agentId, long startTime, long stopTime, - boolean alive, String configListenAddress) { - AgentInformation info = new AgentInformation(agentId); - info.setStartTime(startTime); - info.setStopTime(stopTime); - info.setAlive(alive); - info.setConfigListenAddress(configListenAddress); - return info; - } - -}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/BackendInfoDAOTest.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.Arrays; - -import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.util.StringContentProvider; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpStatus; -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.storage.dao.BackendInfoDAO; -import com.redhat.thermostat.storage.internal.dao.BackendInfoDAOImpl.HttpHelper; -import com.redhat.thermostat.storage.internal.dao.BackendInfoDAOImpl.JsonHelper; -import com.redhat.thermostat.storage.model.BackendInformation; - -public class BackendInfoDAOTest { - - private static final String URL = "http://localhost:26000/api/v100/backend-info/systems/*/agents/foo-agent1"; - private static final String REMOVE_URL = URL + "?q=name%3D%3DTest+Backend"; - private static final String SOME_JSON = "{\"some\" : \"json\"}"; - private static final String CONTENT_TYPE = "application/json"; - - private BackendInformation backendInfo1; - private JsonHelper jsonHelper; - private HttpHelper httpHelper; - private StringContentProvider contentProvider; - private Request request; - private ContentResponse response; - - @Before - public void setUp() throws Exception { - backendInfo1 = new BackendInformation("foo-agent1"); - - backendInfo1.setName("Test Backend"); - backendInfo1.setDescription("description"); - backendInfo1.setActive(true); - backendInfo1.setObserveNewJvm(true); - backendInfo1.setPids(new int[] { -1, 0, 1}); - backendInfo1.setOrderValue(100); - - httpHelper = mock(HttpHelper.class); - contentProvider = mock(StringContentProvider.class); - when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider); - request = mock(Request.class); - when(httpHelper.newRequest(anyString())).thenReturn(request); - response = mock(ContentResponse.class); - when(response.getStatus()).thenReturn(HttpStatus.OK_200); - when(request.send()).thenReturn(response); - - jsonHelper = mock(JsonHelper.class); - when(jsonHelper.toJson(anyListOf(BackendInformation.class))).thenReturn(SOME_JSON); - } - - @Test - public void verifyAddBackendInformation() throws Exception { - BackendInfoDAO dao = new BackendInfoDAOImpl(httpHelper, jsonHelper); - - dao.addBackendInformation(backendInfo1); - - verify(httpHelper).newRequest(URL); - verify(request).method(HttpMethod.POST); - verify(jsonHelper).toJson(eq(Arrays.asList(backendInfo1))); - verify(httpHelper).createContentProvider(SOME_JSON); - verify(request).content(contentProvider, CONTENT_TYPE); - verify(request).send(); - verify(response).getStatus(); - } - - @Test - public void verifyRemoveBackendInformation() throws Exception { - BackendInfoDAO dao = new BackendInfoDAOImpl(httpHelper, jsonHelper); - - dao.removeBackendInformation(backendInfo1); - - verify(httpHelper).newRequest(REMOVE_URL); - verify(request).method(HttpMethod.DELETE); - verify(request).send(); - verify(response).getStatus(); - } - -} -
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/BackendInformationTypeAdapterTest.java Mon Jun 19 20:10:51 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright 2012-2017 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.storage.internal.dao; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.storage.model.BackendInformation; - -public class BackendInformationTypeAdapterTest { - - private BackendInformationTypeAdapter adapter; - - @Before - public void setup() { - adapter = new BackendInformationTypeAdapter(); - } - - @Test - public void testWrite() throws Exception { - final String expected = "[{\"agentId\":\"agent1\",\"name\":\"First Backend\",\"description\":\"Gathers something\"," - + "\"observeNewJvm\":true,\"pids\":[8000,9000],\"active\":true,\"orderValue\":280}," - + "{\"agentId\":\"agent2\",\"name\":\"Second Backend\",\"description\":\"Gathers something else\"," - + "\"observeNewJvm\":false,\"pids\":[],\"active\":false,\"orderValue\":200}]"; - - BackendInformation first = createBackendInformation("agent1", "First Backend", "Gathers something", true, - new int[] { 8000, 9000 }, true, 280); - BackendInformation second = createBackendInformation("agent2", "Second Backend", "Gathers something else", false, - new int[0], false, 200); - List<BackendInformation> infos = Arrays.asList(first, second); - - String json = adapter.toJson(infos); - assertEquals(expected, json); - } - - private BackendInformation createBackendInformation(String agentId, String name, String desc, - boolean observeNewJvm, int[] pids, boolean active, int orderValue) { - BackendInformation info = new BackendInformation(agentId); - info.setName(name); - info.setDescription(desc); - info.setObserveNewJvm(observeNewJvm); - info.setPids(pids); - info.setActive(active); - info.setOrderValue(orderValue); - return info; - } - -}