changeset 2654:06a11539266a

Add configurable URL to jvm-gc microservice Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-May/023133.html
author Elliott Baron <ebaron@redhat.com>
date Wed, 17 May 2017 18:13:48 -0400
parents f2abfc4cfc93
children 6d9c3f8c910f
files distribution/assembly/plugin-assembly.xml distribution/pom.xml plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/Activator.java plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatConfiguration.java plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOImpl.java plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/ActivatorTest.java plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatConfigurationTest.java plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOTest.java plugins/vm-gc/distribution/assemblies/plugin-assembly.xml plugins/vm-gc/distribution/configFiles/gateway.properties
diffstat 10 files changed, 257 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/distribution/assembly/plugin-assembly.xml	Wed May 17 18:12:02 2017 -0400
+++ b/distribution/assembly/plugin-assembly.xml	Wed May 17 18:13:48 2017 -0400
@@ -67,6 +67,12 @@
 <!--        <include>com.redhat.thermostat:thermostat-killvm-distribution</include>-->
 <!--        <include>com.redhat.thermostat:thermostat-vm-numa-distribution</include>-->
       </includes>
+      <unpackOptions>
+        <includes>
+          <include>plugins/**</include>
+          <include>etc/plugins.d/**</include>
+        </includes>
+      </unpackOptions>
     </dependencySet>  
   </dependencySets>
   
--- a/distribution/pom.xml	Wed May 17 18:12:02 2017 -0400
+++ b/distribution/pom.xml	Wed May 17 18:13:48 2017 -0400
@@ -279,7 +279,7 @@
               <descriptors>
                 <descriptor>assembly/plugin-assembly.xml</descriptor>
               </descriptors>
-              <finalName>image/plugins</finalName>
+              <finalName>image</finalName>
               <attach>false</attach>
             </configuration>
             <phase>package</phase>
--- a/plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/Activator.java	Wed May 17 18:12:02 2017 -0400
+++ b/plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/Activator.java	Wed May 17 18:13:48 2017 -0400
@@ -36,23 +36,70 @@
 
 package com.redhat.thermostat.vm.gc.common.internal;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
 
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.vm.gc.common.VmGcStatDAO;
 
 public class Activator implements BundleActivator {
+    
+    private static final Logger logger = LoggingUtils.getLogger(Activator.class);
+    
+    private final VmGcStatDAOCreator creator;
+    private ServiceTracker tracker;
+    private ServiceRegistration reg;
+    
+    public Activator() {
+        this(new VmGcStatDAOCreator());
+    }
+    
+    Activator(VmGcStatDAOCreator creator) {
+        this.creator = creator;
+    }
 
     @Override
     public void start(BundleContext context) throws Exception {
-        VmGcStatDAO vmGcStatDao = new VmGcStatDAOImpl();
-        context.registerService(VmGcStatDAO.class.getName(), vmGcStatDao, null);
+        tracker = new ServiceTracker(context, ConfigurationInfoSource.class.getName(), null) {
+            @Override
+            public Object addingService(ServiceReference reference) {
+                ConfigurationInfoSource source = (ConfigurationInfoSource) super.addingService(reference);
+                try {
+                    VmGcStatDAO vmGcStatDao = creator.createDAO(new VmGcStatConfiguration(source));
+                    reg = context.registerService(VmGcStatDAO.class.getName(), vmGcStatDao, null);
+                } catch (Exception e) {
+                    logger.log(Level.SEVERE, "Failed to create " + VmGcStatDAO.class.getSimpleName(), e);
+                }
+                return source;
+            }
+            
+            @Override
+            public void removedService(ServiceReference reference, Object service) {
+                if (reg != null) {
+                    reg.unregister();
+                }
+                super.removedService(reference, service);
+            }
+        };
+        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        // Nothing to do here. The OSGi framework will automatically
-        // unregister the service when the bundle is stopped.
+        tracker.close();
+    }
+    
+    static class VmGcStatDAOCreator {
+        VmGcStatDAOImpl createDAO(VmGcStatConfiguration config) throws Exception {
+            return new VmGcStatDAOImpl(config);
+        }
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatConfiguration.java	Wed May 17 18:13:48 2017 -0400
@@ -0,0 +1,74 @@
+/*
+ * 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.vm.gc.common.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+
+class VmGcStatConfiguration {
+    
+    private static final String PLUGIN_ID = "vm-gc";
+    private static final String CONFIG_FILE = "gateway.properties";
+    private static final String URL_PROP = "gatewayURL";
+    
+    private final ConfigurationInfoSource source;
+    
+    VmGcStatConfiguration(ConfigurationInfoSource source) {
+        this.source = source;
+    }
+    
+    String getGatewayURL() throws IOException {
+        Map<String, String> props = source.getConfiguration(PLUGIN_ID, CONFIG_FILE);
+        String url = props.get(URL_PROP);
+        if (url == null) {
+            throw new IOException("No gateway URL found for " + PLUGIN_ID + " in " + getConfigFilePath());
+        }
+        return url;
+    }
+    
+    private String getConfigFilePath() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("$THERMOSTAT_HOME").append(File.separator).append("etc").append(File.separator)
+                .append("plugins.d").append(File.separator).append(PLUGIN_ID).append(File.separator)
+                .append(CONFIG_FILE);
+        return builder.toString();
+    }
+
+}
--- a/plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOImpl.java	Wed May 17 18:12:02 2017 -0400
+++ b/plugins/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOImpl.java	Wed May 17 18:13:48 2017 -0400
@@ -57,20 +57,21 @@
 
 public class VmGcStatDAOImpl extends AbstractDao implements VmGcStatDAO {
     
-    private static Logger logger = LoggingUtils.getLogger(VmGcStatDAOImpl.class);
+    private static final Logger logger = LoggingUtils.getLogger(VmGcStatDAOImpl.class);
+    
+    private final String gatewayURL;
     private final JsonHelper jsonHelper;
     private final HttpHelper httpHelper;
     private final HttpClient httpClient;
 
-    static final String GATEWAY_URL = "http://localhost:30000"; // TODO configurable
-    static final String GATEWAY_PATH = "/jvm-gc/0.0.2/";
     static final String CONTENT_TYPE = "application/json";
 
-    VmGcStatDAOImpl() throws Exception {
-        this(new HttpClient(), new JsonHelper(new VmGcStatTypeAdapter()), new HttpHelper());
+    VmGcStatDAOImpl(VmGcStatConfiguration config) throws Exception {
+        this(config, new HttpClient(), new JsonHelper(new VmGcStatTypeAdapter()), new HttpHelper());
     }
 
-    VmGcStatDAOImpl(HttpClient client, JsonHelper jh, HttpHelper hh) throws Exception {
+    VmGcStatDAOImpl(VmGcStatConfiguration config, HttpClient client, JsonHelper jh, HttpHelper hh) throws Exception {
+        this.gatewayURL = config.getGatewayURL();
         this.httpClient = client;
         this.jsonHelper = jh;
         this.httpHelper = hh;
@@ -84,8 +85,7 @@
             String json = jsonHelper.toJson(Arrays.asList(stat));
             StringContentProvider provider = httpHelper.createContentProvider(json);
 
-            String url = buildUrl();
-            Request httpRequest = httpClient.newRequest(url);
+            Request httpRequest = httpClient.newRequest(gatewayURL);
             httpRequest.method(HttpMethod.POST);
             httpRequest.content(provider, CONTENT_TYPE);
             sendRequest(httpRequest);
@@ -99,13 +99,6 @@
         return logger;
     }
 
-    private String buildUrl() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(GATEWAY_URL);
-        builder.append(GATEWAY_PATH);
-        return builder.toString();
-    }
-
     private void sendRequest(Request httpRequest)
             throws InterruptedException, TimeoutException, ExecutionException, IOException {
         ContentResponse resp = httpRequest.send();
--- a/plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/ActivatorTest.java	Wed May 17 18:12:02 2017 -0400
+++ b/plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/ActivatorTest.java	Wed May 17 18:13:48 2017 -0400
@@ -37,24 +37,33 @@
 package com.redhat.thermostat.vm.gc.common.internal;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import org.junit.Test;
 
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
 import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.vm.gc.common.VmGcStatDAO;
+import com.redhat.thermostat.vm.gc.common.internal.Activator.VmGcStatDAOCreator;
 
 public class ActivatorTest {
 
     @Test
     public void verifyActivatorRegistersServices() throws Exception {
+        VmGcStatDAOCreator creator = mock(VmGcStatDAOCreator.class);
+        VmGcStatDAOImpl dao = mock(VmGcStatDAOImpl.class);
+        when(creator.createDAO(any(VmGcStatConfiguration.class))).thenReturn(dao);
+        
+        ConfigurationInfoSource source = mock(ConfigurationInfoSource.class);
         StubBundleContext context = new StubBundleContext();
+        context.registerService(ConfigurationInfoSource.class.getName(), source, null);
 
-        Activator activator = new Activator();
+        Activator activator = new Activator(creator);
 
         activator.start(context);
 
-        assertTrue(context.isServiceRegistered(VmGcStatDAO.class.getName(), VmGcStatDAOImpl.class));
+        assertEquals(2, context.getAllServices().size());
 
         activator.stop(context);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatConfigurationTest.java	Wed May 17 18:13:48 2017 -0400
@@ -0,0 +1,77 @@
+/*
+ * 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.vm.gc.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+
+public class VmGcStatConfigurationTest {
+    
+    private static final String PLUGIN_ID = "vm-gc";
+    private static final String CONFIG_FILE = "gateway.properties";
+    private static final String URL_PROP = "gatewayURL";
+
+    @Test
+    public void testGetGatewayURL() throws Exception {
+        ConfigurationInfoSource source = mock(ConfigurationInfoSource.class);
+        Map<String, String> props = new HashMap<>();
+        props.put(URL_PROP, "urlToGateway");
+        when(source.getConfiguration(PLUGIN_ID, CONFIG_FILE)).thenReturn(props);
+        VmGcStatConfiguration config = new VmGcStatConfiguration(source);
+        
+        assertEquals("urlToGateway", config.getGatewayURL());
+    }
+    
+    @Test(expected=IOException.class)
+    public void testGetGatewayURLMissing() throws Exception {
+        ConfigurationInfoSource source = mock(ConfigurationInfoSource.class);
+        Map<String, String> props = new HashMap<>();
+        when(source.getConfiguration(PLUGIN_ID, CONFIG_FILE)).thenReturn(props);
+        VmGcStatConfiguration config = new VmGcStatConfiguration(source);
+        config.getGatewayURL();
+    }
+
+}
--- a/plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOTest.java	Wed May 17 18:12:02 2017 -0400
+++ b/plugins/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOTest.java	Wed May 17 18:13:48 2017 -0400
@@ -65,6 +65,10 @@
 
 public class VmGcStatDAOTest {
 
+    private static final String AGENT_ID = "some-agent";
+    private static final String JSON = "{\"this\":\"is\",\"also\":\"JSON\"}";
+    private static final String GATEWAY_URL = "http://example.com/jvm-gc";
+    
     private VmGcStat stat;
     private HttpClient httpClient;
     private HttpHelper httpHelper;
@@ -72,8 +76,7 @@
     private StringContentProvider contentProvider;
     private Request request;
     private ContentResponse response;
-    private static final String AGENT_ID = "some-agent";
-    private static final String JSON = "{\"this\":\"is\",\"also\":\"JSON\"}";
+    private VmGcStatDAO dao;
 
     @Before
     public void setup() throws Exception {
@@ -97,16 +100,17 @@
         httpHelper = mock(HttpHelper.class);
         contentProvider = mock(StringContentProvider.class);
         when(httpHelper.createContentProvider(anyString())).thenReturn(contentProvider);
+        
+        VmGcStatConfiguration config = mock(VmGcStatConfiguration.class);
+        when(config.getGatewayURL()).thenReturn(GATEWAY_URL);
+        dao = new VmGcStatDAOImpl(config, httpClient, jsonHelper, httpHelper);
     }
 
     @Test
     public void verifyAddVmGcStat() throws Exception {
-        VmGcStatDAO dao = new VmGcStatDAOImpl(httpClient, jsonHelper, httpHelper);
-
         dao.putVmGcStat(stat);
 
-        final String url = VmGcStatDAOImpl.GATEWAY_URL + VmGcStatDAOImpl.GATEWAY_PATH;
-        verify(httpClient).newRequest(url);
+        verify(httpClient).newRequest(GATEWAY_URL);
         verify(request).method(HttpMethod.POST);
         verify(jsonHelper).toJson(eq(Arrays.asList(stat)));
         verify(httpHelper).createContentProvider(JSON);
--- a/plugins/vm-gc/distribution/assemblies/plugin-assembly.xml	Wed May 17 18:12:02 2017 -0400
+++ b/plugins/vm-gc/distribution/assemblies/plugin-assembly.xml	Wed May 17 18:13:48 2017 -0400
@@ -43,8 +43,7 @@
   <formats>
     <format>zip</format>
   </formats>
-  <baseDirectory>${thermostat.plugin}</baseDirectory>
-  <includeBaseDirectory>true</includeBaseDirectory>
+  <includeBaseDirectory>false</includeBaseDirectory>
   
   <dependencySets>
     <dependencySet>
@@ -56,15 +55,23 @@
       </includes>
       <useProjectArtifact>false</useProjectArtifact>
       <useStrictFiltering>true</useStrictFiltering>
+      <outputDirectory>plugins/${thermostat.plugin}</outputDirectory>
     </dependencySet>
   </dependencySets>
   
-  <files>
-    <file>
-      <source>thermostat-plugin.xml</source>
-      <outputDirectory>/</outputDirectory>
+  <fileSets>
+    <fileSet>
+      <includes>
+        <include>thermostat-plugin.xml</include>
+      </includes>
+      <outputDirectory>plugins/${thermostat.plugin}</outputDirectory>
       <filtered>true</filtered>
-    </file>
-  </files>
+    </fileSet>
+    <fileSet>
+      <directory>configFiles</directory>
+      <outputDirectory>etc/plugins.d/${thermostat.plugin}</outputDirectory>
+      <filtered>true</filtered>
+    </fileSet>
+  </fileSets>
 </assembly>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/vm-gc/distribution/configFiles/gateway.properties	Wed May 17 18:13:48 2017 -0400
@@ -0,0 +1,2 @@
+# URL to the jvm-gc microservice provided by the Thermostat web gateway
+gatewayURL=http://localhost:30000/jvm-gc/0.0.2/