From 33538bb6c2903c4a8acabad895f1cf822a8f56ce Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 15 Aug 2022 16:52:28 -0400 Subject: [PATCH] implement registration and self-publishing flow --- .gitignore | 1 - dependency-reduced-pom.xml | 318 ++++++++++++++++++ pom.xml | 10 + src/main/java/io/cryostat/agent/Agent.java | 77 +++-- .../io/cryostat/agent/CryostatClient.java | 139 ++++++++ .../java/io/cryostat/agent/MainModule.java | 22 +- .../java/io/cryostat/agent/Registration.java | 175 ++++++++++ .../agent/UndefinedVariableException.java | 45 +++ .../java/io/cryostat/agent/WebServer.java | 2 +- .../cryostat/agent/model/DiscoveryNode.java | 77 ++++- .../io/cryostat/agent/model/PluginInfo.java | 15 +- .../agent/model/RegistrationInfo.java | 15 +- 12 files changed, 861 insertions(+), 35 deletions(-) create mode 100644 dependency-reduced-pom.xml create mode 100644 src/main/java/io/cryostat/agent/CryostatClient.java create mode 100644 src/main/java/io/cryostat/agent/Registration.java create mode 100644 src/main/java/io/cryostat/agent/UndefinedVariableException.java 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 + + + + + + +
LICENSE
+ + 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; + } }