diff --git a/.gitignore b/.gitignore
index a73d098a..f172df5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,6 @@
.factorypath
.settings/
**/*.class
-dependency-reduced-pom.xml
build/
target/
bin/
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
new file mode 100644
index 00000000..10df6afc
--- /dev/null
+++ b/dependency-reduced-pom.xml
@@ -0,0 +1,318 @@
+
+
+ 4.0.0
+ io.cryostat
+ cryostat-agent
+ cryostat
+ 1.0.0-SNAPSHOT
+ http://maven.apache.org
+
+
+
+ maven-jar-plugin
+ ${org.apache.maven.plugins.jar.version}
+
+
+
+ true
+ ${mainClass}
+
+
+ ${mainClass}
+ ${mainClass}
+
+
+
+
+
+ maven-shade-plugin
+ ${org.apache.maven.plugins.shade.version}
+
+
+ package
+
+ shade
+
+
+
+
+
+ io.reactiverse
+ vertx-maven-plugin
+ ${io.reactiverse.plugin.version}
+
+ true
+ ${mainClass}
+
+
+
+ maven-compiler-plugin
+ ${org.apache.maven.plugins.compiler.version}
+
+ true
+ true
+ true
+
+
+ com.google.dagger
+ dagger-compiler
+ ${com.google.dagger.compiler.version}
+
+
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ ${com.github.spotbugs.plugin.version}
+
+
+ spotbugs
+ verify
+
+ check
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${org.jacoco.maven.plugin.version}
+
+
+
+ prepare-agent
+
+
+
+ report
+ verify
+
+ report
+
+
+
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ ${com.diffplug.spotless.maven.plugin.version}
+
+
+ spotless
+ verify
+
+ check
+
+
+
+
+
+
+ 1.15.0
+
+ true
+
+
+
+
+ java,javax,org.openjdk.jmc,io.cryostat,
+
+
+
+
+
+
+ maven-site-plugin
+ ${org.apache.maven.plugins.site.version}
+
+
+ maven-project-info-reports-plugin
+ ${org.apache.maven.plugins.info.reports.version}
+
+
+ com.mycila
+ license-maven-plugin
+ ${com.mycila.license.maven.plugin.version}
+
+
+ update-license
+ process-sources
+
+ check
+
+
+
+
+
+
+
+
+ src/main/**/*.java
+ src/test/**/*.java
+
+
+
+
+
+
+
+
+
+ dep-check
+
+
+
+ org.owasp
+ dependency-check-maven
+ ${org.owasp.dependency.check.version}
+
+
+ check-for-vulnerable-deps
+ validate
+
+ check
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.8.2
+ test
+
+
+ junit-jupiter-api
+ org.junit.jupiter
+
+
+ junit-jupiter-params
+ org.junit.jupiter
+
+
+ junit-jupiter-engine
+ org.junit.jupiter
+
+
+
+
+ org.hamcrest
+ hamcrest
+ 2.2
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 4.6.1
+ test
+
+
+ mockito-core
+ org.mockito
+
+
+ junit-jupiter-api
+ org.junit.jupiter
+
+
+
+
+ org.mockito
+ mockito-inline
+ 4.6.1
+ test
+
+
+ mockito-core
+ org.mockito
+
+
+
+
+ com.github.spotbugs
+ spotbugs-annotations
+ 4.5.3
+ provided
+
+
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ ${com.github.spotbugs.plugin.version}
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${org.jacoco.maven.plugin.version}
+
+
+ **/*_Factory.*
+ **/*_Provide*Factory.*
+ **/Dagger*.*
+ **/*Module_*Factory.*
+ **/*Module.*
+
+
+
+
+
+ report
+
+
+
+
+
+
+
+ io.cryostat.agent.Agent
+ 2.26
+ 2.8.0
+ 2.34.1
+ 4.0
+ 1.15
+ 3.1.0
+ 2.2
+ 1.7.30
+ ${org.apache.maven.plugins.surefire.version}
+ 3.2.0
+ 3.12.0
+ 4.5.13
+ UTF-8
+ 3.3.0
+ 3.9.1
+ 2.13.3
+ 2.22.7
+ 1.14.2
+ 2.22.2
+ 3.2.2
+ 17
+ 1.0.27
+ ${java.version}
+ 3.3.0
+ 6.1.5
+ 4.6.1
+ 0.8.8
+ 5.12.2
+ 4.5.3.0
+ 4.2.5
+ 5.8.2
+ ${java.version}
+ 3.1.1
+ 4.5.3
+ 3.8.1
+ 1.7
+
+
diff --git a/pom.xml b/pom.xml
index ae72629c..e1b4f1b3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,7 @@
4.5.13
5.12.2
4.2.5
+ 2.13.3
1.7.30
4.5.3
@@ -94,6 +95,11 @@
vertx-web-client
${io.vertx.web.version}
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${com.fasterxml.jackson.version}
+
org.slf4j
slf4j-jdk14
@@ -161,12 +167,16 @@
org.apache.maven.plugins
maven-shade-plugin
${org.apache.maven.plugins.shade.version}
+
package
shade
+
+ false
+
diff --git a/src/main/java/io/cryostat/agent/Agent.java b/src/main/java/io/cryostat/agent/Agent.java
index 971db27d..9225899b 100644
--- a/src/main/java/io/cryostat/agent/Agent.java
+++ b/src/main/java/io/cryostat/agent/Agent.java
@@ -39,17 +39,19 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
import javax.inject.Singleton;
import dagger.Component;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
+import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.Signal;
+import sun.misc.SignalHandler;
public class Agent {
@@ -59,36 +61,65 @@ public static void main(String[] args) {
List futures = new ArrayList<>();
final Client client = DaggerAgent_Client.builder().build();
- futures.add(client.vertx().deployVerticle(client.webServer()));
+ Consumer> shutdown =
+ promise -> {
+ log.info("Shutting down...");
+ client.vertx()
+ .close()
+ .onComplete(
+ ar -> {
+ log.info("Shutdown complete");
+ promise.complete();
+ });
+ };
- CompletableFuture cf = new CompletableFuture<>();
List.of(new Signal("INT"), new Signal("TERM"))
.forEach(
- signal ->
- Signal.handle(
- signal,
- s -> {
- log.info(
- "Caught SIG{}({})", s.getName(), s.getNumber());
- client.vertx().close();
- }));
+ signal -> {
+ SignalHandler oldHandler = Signal.handle(signal, s -> {});
+ SignalHandler handler =
+ s -> {
+ log.info("Caught SIG{}({})", s.getName(), s.getNumber());
+ client.registration()
+ .deregister()
+ .onComplete(
+ ar -> {
+ Promise promise =
+ Promise.promise();
+ shutdown.accept(promise);
+ promise.future()
+ .onComplete(
+ unused ->
+ oldHandler
+ .handle(
+ s));
+ });
+ };
+ Signal.handle(signal, handler);
+ });
+
+ futures.add(client.vertx().deployVerticle(client.webServer()));
+ futures.add(client.vertx().deployVerticle(client.registration()));
CompositeFuture.join(futures)
- .onComplete(
- ar -> {
- if (ar.failed()) {
- log.error("Verticle failure", ar.cause());
- client.vertx().close();
- }
+ .onSuccess(ar -> log.info("Startup complete"))
+ .onFailure(
+ t -> {
+ log.error("Verticle failure", t);
+ client.vertx().close();
});
}
public static void agentmain(String args) {
- log.info("Cryostat Agent starting...");
- if (args == null) {
- args = "";
- }
- main(args.split("\\s"));
+ Thread t =
+ new Thread(
+ () -> {
+ log.info("Cryostat Agent starting...");
+ main(args == null ? new String[0] : args.split("\\s"));
+ });
+ t.setDaemon(true);
+ t.setName("cryostat-agent");
+ t.start();
}
public static void premain(String args) {
@@ -102,6 +133,8 @@ interface Client {
WebServer webServer();
+ Registration registration();
+
@Component.Builder
interface Builder {
Client build();
diff --git a/src/main/java/io/cryostat/agent/CryostatClient.java b/src/main/java/io/cryostat/agent/CryostatClient.java
new file mode 100644
index 00000000..91a4dbfb
--- /dev/null
+++ b/src/main/java/io/cryostat/agent/CryostatClient.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright The Cryostat Authors
+ *
+ * The Universal Permissive License (UPL), Version 1.0
+ *
+ * Subject to the condition set forth below, permission is hereby granted to any
+ * person obtaining a copy of this software, associated documentation and/or data
+ * (collectively the "Software"), free of charge and under any and all copyright
+ * rights in the Software, and any and all patent rights owned or freely
+ * licensable by each licensor hereunder covering either (i) the unmodified
+ * Software as contributed to or provided by such licensor, or (ii) the Larger
+ * Works (as defined below), to deal in both
+ *
+ * (a) the Software, and
+ * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ * one is included with the Software (each a "Larger Work" to which the Software
+ * is contributed by such licensors),
+ *
+ * without restriction, including without limitation the rights to copy, create
+ * derivative works of, display, perform, and distribute the Software and make,
+ * use, sell, offer for sale, import, export, have made, and have sold the
+ * Software and the Larger Work(s), and to sublicense the foregoing rights on
+ * either these or other terms.
+ *
+ * This license is subject to the following condition:
+ * The above copyright notice and either this complete permission notice or at
+ * a minimum a reference to the UPL must be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.cryostat.agent;
+
+import java.io.Closeable;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.cryostat.agent.model.DiscoveryNode;
+import io.cryostat.agent.model.PluginInfo;
+import io.cryostat.agent.model.RegistrationInfo;
+import io.vertx.core.Future;
+import io.vertx.core.Vertx;
+import io.vertx.core.http.HttpHeaders;
+import io.vertx.ext.web.client.WebClient;
+import io.vertx.ext.web.client.WebClientOptions;
+import io.vertx.ext.web.client.predicate.ResponsePredicate;
+
+class CryostatClient implements Closeable {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private WebClient http;
+ private final UUID instanceId;
+
+ CryostatClient(Vertx vertx, UUID instanceId) {
+ WebClientOptions opts = new WebClientOptions();
+
+ // TODO make configurable
+ opts.setDefaultHost("localhost");
+ opts.setDefaultPort(8181);
+ opts.setSsl(true);
+ opts.setTrustAll(true);
+ opts.setVerifyHost(false);
+
+ this.http = WebClient.create(vertx, opts);
+ this.instanceId = instanceId;
+ }
+
+ Future register() {
+ String auth = System.getenv("CRYOSTAT_AGENT_AUTHORIZATION");
+ if (StringUtils.isBlank(auth)) {
+ auth = "None";
+ }
+ String realm = System.getenv("CRYOSTAT_AGENT_REALM");
+ if (StringUtils.isBlank(realm)) {
+ realm = "cryostat-agent-" + instanceId;
+ }
+ String callback = System.getenv("CRYOSTAT_AGENT_CALLBACK");
+ // do this at startup time
+ if (StringUtils.isBlank(callback)) {
+ throw new UndefinedVariableException("CRYOSTAT_AGENT_CALLBACK");
+ }
+ RegistrationInfo registrationInfo = new RegistrationInfo(realm, callback);
+ return http.post("/api/v2.2/discovery")
+ .putHeader(HttpHeaders.AUTHORIZATION.toString(), auth)
+ .expect(ResponsePredicate.SC_SUCCESS)
+ .expect(ResponsePredicate.JSON)
+ .timeout(1_000L)
+ .sendJson(registrationInfo)
+ .map(resp -> resp.bodyAsJsonObject())
+ .map(json -> json.getJsonObject("data").getJsonObject("result"))
+ .map(json -> json.mapTo(PluginInfo.class));
+ }
+
+ Future deregister(String id) {
+ String auth = System.getenv("CRYOSTAT_AGENT_AUTHORIZATION");
+ if (StringUtils.isBlank(auth)) {
+ auth = "None";
+ }
+ return http.delete("/api/v2.2/discovery/" + id)
+ .putHeader(HttpHeaders.AUTHORIZATION.toString(), auth)
+ .expect(ResponsePredicate.SC_SUCCESS)
+ .expect(ResponsePredicate.JSON)
+ .timeout(1_000L)
+ .send()
+ .map(t -> null);
+ }
+
+ Future update(String id, Set subtree) {
+ String auth = System.getenv("CRYOSTAT_AGENT_AUTHORIZATION");
+ if (StringUtils.isBlank(auth)) {
+ auth = "None";
+ }
+ return http.post("/api/v2.2/discovery/" + id)
+ .putHeader(HttpHeaders.AUTHORIZATION.toString(), auth)
+ .expect(ResponsePredicate.SC_SUCCESS)
+ .expect(ResponsePredicate.JSON)
+ .timeout(1_000L)
+ .sendJson(subtree)
+ .map(t -> null);
+ }
+
+ @Override
+ public void close() {
+ if (this.http != null) {
+ this.http.close();
+ }
+ }
+}
diff --git a/src/main/java/io/cryostat/agent/MainModule.java b/src/main/java/io/cryostat/agent/MainModule.java
index 6de178f2..5ec6d4a6 100644
--- a/src/main/java/io/cryostat/agent/MainModule.java
+++ b/src/main/java/io/cryostat/agent/MainModule.java
@@ -37,6 +37,8 @@
*/
package io.cryostat.agent;
+import java.util.UUID;
+
import javax.inject.Singleton;
import dagger.Module;
@@ -50,7 +52,7 @@ public abstract class MainModule {
@Provides
@Singleton
public static Vertx provideVertx() {
- return Vertx.vertx(new VertxOptions().setWorkerPoolSize(1).setEventLoopPoolSize(1));
+ return Vertx.vertx(new VertxOptions().setEventLoopPoolSize(1).setWorkerPoolSize(1));
}
@Provides
@@ -58,4 +60,22 @@ public static Vertx provideVertx() {
public static WebServer provideHttpServer() {
return new WebServer();
}
+
+ @Provides
+ @Singleton
+ public static CryostatClient provideCryostatClient(Vertx vertx, UUID instanceId) {
+ return new CryostatClient(vertx, instanceId);
+ }
+
+ @Provides
+ @Singleton
+ public static Registration provideRegistration(CryostatClient cryostat, UUID instanceId) {
+ return new Registration(cryostat, instanceId);
+ }
+
+ @Provides
+ @Singleton
+ public static UUID provideInstanceID() {
+ return UUID.randomUUID();
+ }
}
diff --git a/src/main/java/io/cryostat/agent/Registration.java b/src/main/java/io/cryostat/agent/Registration.java
new file mode 100644
index 00000000..d8d72f0b
--- /dev/null
+++ b/src/main/java/io/cryostat/agent/Registration.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright The Cryostat Authors
+ *
+ * The Universal Permissive License (UPL), Version 1.0
+ *
+ * Subject to the condition set forth below, permission is hereby granted to any
+ * person obtaining a copy of this software, associated documentation and/or data
+ * (collectively the "Software"), free of charge and under any and all copyright
+ * rights in the Software, and any and all patent rights owned or freely
+ * licensable by each licensor hereunder covering either (i) the unmodified
+ * Software as contributed to or provided by such licensor, or (ii) the Larger
+ * Works (as defined below), to deal in both
+ *
+ * (a) the Software, and
+ * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ * one is included with the Software (each a "Larger Work" to which the Software
+ * is contributed by such licensors),
+ *
+ * without restriction, including without limitation the rights to copy, create
+ * derivative works of, display, perform, and distribute the Software and make,
+ * use, sell, offer for sale, import, export, have made, and have sold the
+ * Software and the Larger Work(s), and to sublicense the foregoing rights on
+ * either these or other terms.
+ *
+ * This license is subject to the following condition:
+ * The above copyright notice and either this complete permission notice or at
+ * a minimum a reference to the UPL must be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.cryostat.agent;
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.cryostat.agent.model.DiscoveryNode;
+import io.cryostat.agent.model.PluginInfo;
+import io.vertx.core.AbstractVerticle;
+import io.vertx.core.Future;
+
+class Registration extends AbstractVerticle {
+
+ private static final String NODE_TYPE = "JVM";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final CryostatClient cryostat;
+ private final UUID instanceId;
+ private PluginInfo pluginInfo;
+
+ Registration(CryostatClient cryostat, UUID instanceId) {
+ this.cryostat = cryostat;
+ this.instanceId = instanceId;
+ }
+
+ @Override
+ public void start() {
+ getVertx().setTimer(1, this::tryRegister);
+ log.info("{} started", getClass().getName());
+ }
+
+ private void tryRegister(Long id) {
+ cryostat.register()
+ .onSuccess(
+ plugin -> {
+ String jmxhost = "localhost";
+ String appName = "cryostat-agent";
+ int port =
+ Integer.valueOf(
+ System.getProperty(
+ "com.sun.management.jmxremote.port"));
+
+ long pid = ProcessHandle.current().pid();
+ String hostname = null;
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException uhe) {
+ log.error("Could not determine own hostname", uhe);
+ }
+ String javaMain = System.getProperty("sun.java.command", System.getenv("JAVA_MAIN_CLASS"));
+ if (StringUtils.isBlank(javaMain)) {
+ javaMain = null;
+ }
+ long startTime = ProcessHandle.current().info().startInstant().orElse(Instant.EPOCH).getEpochSecond();
+ DiscoveryNode.Target target =
+ new DiscoveryNode.Target(
+ URI.create(
+ String.format(
+ "service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi",
+ jmxhost, port)),
+ appName,
+ instanceId,
+ pid, hostname, port, javaMain, startTime);
+
+ DiscoveryNode selfNode =
+ new DiscoveryNode(
+ "cryostat-agent-" + plugin.getId(), NODE_TYPE, target);
+
+ log.info("publishing self as {}", selfNode.getTarget().getConnectUrl());
+ cryostat.update(plugin.getId(), Set.of(selfNode))
+ .onSuccess(
+ ar -> {
+ this.pluginInfo = plugin;
+ getVertx().cancelTimer(id);
+ })
+ .onFailure(
+ t -> {
+ log.error("Update failure", t);
+ deregister()
+ .onComplete(
+ ar -> {
+ if (ar.failed()) {
+ Duration
+ registrationRetryPeriod =
+ Duration
+ .ofSeconds(
+ 5);
+ vertx.setTimer(
+ registrationRetryPeriod
+ .toMillis(),
+ this::tryRegister);
+ return;
+ }
+ });
+ });
+ })
+ .onFailure(
+ t -> {
+ log.error("Registration failure", t);
+ Duration registrationRetryPeriod = Duration.ofSeconds(5);
+ vertx.setTimer(registrationRetryPeriod.toMillis(), this::tryRegister);
+ });
+ }
+
+ @Override
+ public void stop() {
+ log.info("{} stopped", getClass().getName());
+ }
+
+ Future deregister() {
+ if (this.pluginInfo == null) {
+ return Future.succeededFuture();
+ }
+ return cryostat.deregister(pluginInfo.getId())
+ .onComplete(
+ ar -> {
+ if (ar.failed()) {
+ log.warn(
+ "Failed to deregister as Cryostat discovery plugin [{}]",
+ this.pluginInfo.getId());
+ } else {
+ log.info(
+ "Deregistered from Cryostat discovery plugin [{}]",
+ this.pluginInfo.getId());
+ }
+ this.pluginInfo = null;
+ });
+ }
+}
diff --git a/src/main/java/io/cryostat/agent/UndefinedVariableException.java b/src/main/java/io/cryostat/agent/UndefinedVariableException.java
new file mode 100644
index 00000000..1d06e652
--- /dev/null
+++ b/src/main/java/io/cryostat/agent/UndefinedVariableException.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright The Cryostat Authors
+ *
+ * The Universal Permissive License (UPL), Version 1.0
+ *
+ * Subject to the condition set forth below, permission is hereby granted to any
+ * person obtaining a copy of this software, associated documentation and/or data
+ * (collectively the "Software"), free of charge and under any and all copyright
+ * rights in the Software, and any and all patent rights owned or freely
+ * licensable by each licensor hereunder covering either (i) the unmodified
+ * Software as contributed to or provided by such licensor, or (ii) the Larger
+ * Works (as defined below), to deal in both
+ *
+ * (a) the Software, and
+ * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ * one is included with the Software (each a "Larger Work" to which the Software
+ * is contributed by such licensors),
+ *
+ * without restriction, including without limitation the rights to copy, create
+ * derivative works of, display, perform, and distribute the Software and make,
+ * use, sell, offer for sale, import, export, have made, and have sold the
+ * Software and the Larger Work(s), and to sublicense the foregoing rights on
+ * either these or other terms.
+ *
+ * This license is subject to the following condition:
+ * The above copyright notice and either this complete permission notice or at
+ * a minimum a reference to the UPL must be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package io.cryostat.agent;
+
+public class UndefinedVariableException extends RuntimeException {
+
+ public UndefinedVariableException(String name) {
+ super("Environment variable \"" + name + "\" must be defined and non-blank");
+ }
+}
diff --git a/src/main/java/io/cryostat/agent/WebServer.java b/src/main/java/io/cryostat/agent/WebServer.java
index 1b328f1c..c4b4d21b 100644
--- a/src/main/java/io/cryostat/agent/WebServer.java
+++ b/src/main/java/io/cryostat/agent/WebServer.java
@@ -49,7 +49,7 @@
class WebServer extends AbstractVerticle {
- private static final String DEFAULT_HTTP_HOST = "localhost";
+ private static final String DEFAULT_HTTP_HOST = "0.0.0.0";
private static final int DEFAULT_HTTP_PORT = 9977;
private final Logger log = LoggerFactory.getLogger(getClass());
diff --git a/src/main/java/io/cryostat/agent/model/DiscoveryNode.java b/src/main/java/io/cryostat/agent/model/DiscoveryNode.java
index a070a347..f1b01bcf 100644
--- a/src/main/java/io/cryostat/agent/model/DiscoveryNode.java
+++ b/src/main/java/io/cryostat/agent/model/DiscoveryNode.java
@@ -38,12 +38,17 @@
package io.cryostat.agent.model;
import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
public class DiscoveryNode {
- private final String name;
- private final String nodeType;
- private final Target target;
+ private String name;
+ private String nodeType;
+ private Target target;
+
+ DiscoveryNode() {}
public DiscoveryNode(String name, String nodeType, Target target) {
this.name = name;
@@ -63,14 +68,31 @@ public Target getTarget() {
return target;
}
+ void setName(String name) {
+ this.name = name;
+ }
+
+ void setNodeType(String nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ void setTarget(Target target) {
+ this.target = target;
+ }
+
public static class Target {
- private final URI connectUrl;
- private final String alias;
+ private URI connectUrl;
+ private String alias;
+ private Annotations annotations;
+
+ Target() {}
- public Target(URI connectUrl, String alias) {
+ public Target(URI connectUrl, String alias, UUID instanceId, long pid, String hostname, int port, String javaMain, long startTime) {
this.connectUrl = connectUrl;
this.alias = alias;
+ this.annotations = new Annotations();
+ annotations.setCryostat(Map.of("PID", pid, "HOST", hostname, "PORT", port, "JAVA_MAIN", javaMain, "START_TIME", startTime));
}
public URI getConnectUrl() {
@@ -80,5 +102,48 @@ public URI getConnectUrl() {
public String getAlias() {
return alias;
}
+
+ public Annotations getAnnotations() {
+ return annotations;
+ }
+
+ void setConnectUrl(URI connectUrl) {
+ this.connectUrl = connectUrl;
+ }
+
+ void setAlias(String alias) {
+ this.alias = alias;
+ }
+
+ void setAnnotations(Annotations annotations) {
+ this.annotations = annotations;
+ }
+ }
+
+ public static class Annotations {
+
+ private Map cryostat;
+ private Map platform;
+
+ Annotations() {
+ this.cryostat = new HashMap<>();
+ this.platform = new HashMap<>();
+ }
+
+ public Map getCryostat() {
+ return new HashMap<>(cryostat);
+ }
+
+ public Map getPlatform() {
+ return new HashMap<>(platform);
+ }
+
+ void setCryostat(Map cryostat) {
+ this.cryostat = new HashMap<>(cryostat);
+ }
+
+ void setPlatform(Map platform) {
+ this.platform = new HashMap<>(platform);
+ }
}
}
diff --git a/src/main/java/io/cryostat/agent/model/PluginInfo.java b/src/main/java/io/cryostat/agent/model/PluginInfo.java
index 58df437b..b87cd211 100644
--- a/src/main/java/io/cryostat/agent/model/PluginInfo.java
+++ b/src/main/java/io/cryostat/agent/model/PluginInfo.java
@@ -38,8 +38,11 @@
package io.cryostat.agent.model;
public class PluginInfo {
- private final String id;
- private final String token;
+
+ private String id;
+ private String token;
+
+ PluginInfo() {}
public PluginInfo(String id, String token) {
this.id = id;
@@ -53,4 +56,12 @@ public String getId() {
public String getToken() {
return token;
}
+
+ void setId(String id) {
+ this.id = id;
+ }
+
+ void setToken(String token) {
+ this.token = token;
+ }
}
diff --git a/src/main/java/io/cryostat/agent/model/RegistrationInfo.java b/src/main/java/io/cryostat/agent/model/RegistrationInfo.java
index 27b2f8cb..2605e0f0 100644
--- a/src/main/java/io/cryostat/agent/model/RegistrationInfo.java
+++ b/src/main/java/io/cryostat/agent/model/RegistrationInfo.java
@@ -38,8 +38,11 @@
package io.cryostat.agent.model;
public class RegistrationInfo {
- private final String realm;
- private final String callback;
+
+ private String realm;
+ private String callback;
+
+ RegistrationInfo() {}
public RegistrationInfo(String realm, String callback) {
this.realm = realm;
@@ -53,4 +56,12 @@ public String getRealm() {
public String getCallback() {
return callback;
}
+
+ void setRealm(String realm) {
+ this.realm = realm;
+ }
+
+ void setCallback(String callback) {
+ this.callback = callback;
+ }
}