diff --git a/compose/auth_proxy.yml b/compose/auth_proxy.yml
index 649489867..c656cc2f1 100644
--- a/compose/auth_proxy.yml
+++ b/compose/auth_proxy.yml
@@ -11,12 +11,8 @@ services:
QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_HOST: 'true'
QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_PREFIX: 'true'
QUARKUS_HTTP_PROXY_TRUSTED_PROXIES: 127.0.0.1:${CRYOSTAT_HTTP_PORT}
- healthcheck:
- test: curl --fail http://cryostat:8181/health/liveness || exit 1
- interval: 10s
- retries: 3
- start_period: 30s
- timeout: 5s
+ QUARKUS_HTTP_ACCESS_LOG_PATTERN: long
+ QUARKUS_HTTP_ACCESS_LOG_ENABLED: 'true'
auth:
# the proxy does not actually depend on cryostat being up, but we use this
# to ensure that when the smoketest tries to open the auth login page in a
@@ -30,7 +26,7 @@ services:
limits:
cpus: '0.1'
memory: 32m
- image: ${OAUTH2_PROXY_IMAGE:-quay.io/oauth2-proxy/oauth2-proxy:latest}
+ image: ${OAUTH2_PROXY_IMAGE:-quay.io/oauth2-proxy/oauth2-proxy:latest-alpine}
command: --alpha-config=/tmp/auth_proxy_alpha_config.yaml
volumes:
- auth_proxy_cfg:/tmp
@@ -47,10 +43,10 @@ services:
# OAUTH2_PROXY_SKIP_AUTH_ROUTES: .*
restart: unless-stopped
healthcheck:
- test: wget -q --spider http://localhost:8080/ping || exit 1
+ test: wget --no-check-certificate -q --spider http://localhost:8080/ping || exit 1
interval: 10s
retries: 3
- start_period: 30s
+ start_period: 10s
timeout: 5s
volumes:
diff --git a/compose/cryostat-grafana.yml b/compose/cryostat-grafana.yml
index 1ae75b868..2127838b2 100644
--- a/compose/cryostat-grafana.yml
+++ b/compose/cryostat-grafana.yml
@@ -26,5 +26,5 @@ services:
test: curl --fail http://localhost:3000/ || exit 1
retries: 3
interval: 30s
- start_period: 30s
+ start_period: 10s
timeout: 1s
diff --git a/compose/cryostat.yml b/compose/cryostat.yml
index 2bc5a14b8..b21c04302 100644
--- a/compose/cryostat.yml
+++ b/compose/cryostat.yml
@@ -27,12 +27,14 @@ services:
CRYOSTAT_DISCOVERY_DOCKER_ENABLED: ${CRYOSTAT_DISCOVERY_DOCKER_ENABLED:-true}
JAVA_OPTS_APPEND: "-XX:+FlightRecorder -XX:StartFlightRecording=name=onstart,settings=default,disk=true,maxage=5m -XX:StartFlightRecording=name=startup,settings=profile,disk=true,duration=30s -Dcom.sun.management.jmxremote.autodiscovery=true -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9091 -Dcom.sun.management.jmxremote.rmi.port=9091 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false"
restart: unless-stopped
- healthcheck:
- test: curl --fail http://cryostat:${CRYOSTAT_HTTP_PORT}/health/liveness || exit 1
- interval: 10s
- retries: 3
- start_period: 30s
- timeout: 5s
+ # FIXME reenable this check. Somehow after upgrading to Quarkus 3.8, this check fails with 'connection refused',
+ # but the container comes up successfully without it and shelling into the container later to run curl succeeds
+ # healthcheck:
+ # test: curl --fail http://cryostat:${CRYOSTAT_HTTP_PORT}/health/liveness || exit 1
+ # interval: 10s
+ # retries: 3
+ # start_period: 30s
+ # timeout: 5s
volumes:
jmxtls_cfg:
diff --git a/compose/db.yml b/compose/db.yml
index 098bf2961..4adc6fd6a 100644
--- a/compose/db.yml
+++ b/compose/db.yml
@@ -26,7 +26,7 @@ services:
test: pg_isready -U cryostat3 -d cryostat3 || exit 1
interval: 10s
retries: 3
- start_period: 30s
+ start_period: 10s
timeout: 5s
volumes:
diff --git a/compose/jfr-datasource.yml b/compose/jfr-datasource.yml
index c0e847485..965c53701 100644
--- a/compose/jfr-datasource.yml
+++ b/compose/jfr-datasource.yml
@@ -25,5 +25,5 @@ services:
test: curl --fail http://localhost:8080/ || exit 1
retries: 3
interval: 30s
- start_period: 30s
+ start_period: 10s
timeout: 1s
diff --git a/pom.xml b/pom.xml
index 4baaa0bab..5c032b73b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,20 +42,19 @@
9.0.0
1.16.1
- 2.13.0
+ 2.16.1
4.4
5.2.1
3.13.0
- 1.7
+ 1.8.0
0.4.4
3.25.5
9.37.3
1.19.8
quarkus-bom
io.quarkus.platform
- 3.2.12.Final
- 2.3.6
- 4.1.108.Final
+ 3.8.6
+ 2.3.10
3.6.0
3.7.1
@@ -66,19 +65,11 @@
4.5
3.2.5
2
- 3.2.5
- 6.7.2
+ 3.3.1
${surefire.rerunFailingTestsCount}
-
- io.netty
- netty-bom
- ${io.netty.version}
- pom
- import
-
${quarkus.platform.group-id}
${quarkus.platform.artifact-id}
@@ -162,6 +153,10 @@
io.quarkus
quarkus-vertx
+
+ io.quarkus
+ quarkus-netty
+
io.quarkus
quarkus-smallrye-openapi
@@ -187,6 +182,18 @@
io.quarkus
quarkus-websockets
+
+ io.quarkus
+ quarkus-rest-client-reactive-jackson
+
+
+ io.quarkus
+ quarkus-cache
+
+
+ io.quarkus
+ quarkus-quartz
+
io.quarkus
quarkus-hibernate-orm-panache
@@ -203,6 +210,10 @@
io.quarkiverse.amazonservices
quarkus-amazon-s3
+
+ io.quarkus
+ quarkus-kubernetes-client
+
software.amazon.awssdk
url-connection-client
@@ -210,12 +221,10 @@
org.apache.commons
commons-lang3
- ${org.apache.commons.lang3.version}
commons-codec
commons-codec
- ${org.apache.commons.codec.version}
commons-io
@@ -251,29 +260,12 @@
nimbus-jose-jwt
${com.nimbusds.jose.jwt.version}
-
- io.quarkus
- quarkus-rest-client-reactive-jackson
-
-
- io.quarkus
- quarkus-cache
-
-
- io.quarkus
- quarkus-quartz
-
com.google.googlejavaformat
google-java-format
${com.google.java-format.version}
provided
-
- io.fabric8
- kubernetes-client
- ${io.fabric8.client.version}
-
io.quarkus
@@ -541,7 +533,6 @@
io.netty
netty-transport-native-epoll
- ${io.netty.version}
${io.netty.netty-transport-native-epoll.classifier}
${io.netty.netty-transport-native-epoll.scope}
diff --git a/schema/openapi.yaml b/schema/openapi.yaml
index 776f3ae73..207ef131f 100644
--- a/schema/openapi.yaml
+++ b/schema/openapi.yaml
@@ -85,6 +85,7 @@ components:
DiscoveryPlugin:
properties:
builtin:
+ readOnly: true
type: boolean
callback:
format: uri
@@ -296,6 +297,7 @@ components:
Target:
properties:
agent:
+ readOnly: true
type: boolean
alias:
pattern: \S
@@ -347,11 +349,6 @@ components:
meta:
$ref: '#/components/schemas/Meta'
type: object
- securitySchemes:
- SecurityScheme:
- description: Authentication
- scheme: basic
- type: http
info:
contact:
email: cryostat-development@googlegroups.com
@@ -362,7 +359,7 @@ info:
name: Apache 2.0
url: https://github.com/cryostatio/cryostat3/blob/main/LICENSE
title: Cryostat API
- version: 3.0.1-snapshot
+ version: 3.0.2-snapshot
openapi: 3.0.3
paths:
/api/beta/credentials/{connectUrl}:
@@ -913,7 +910,7 @@ paths:
type: string
requestBody:
content:
- application/json:
+ text/plain:
schema:
type: string
responses:
@@ -1906,7 +1903,7 @@ paths:
responses:
"200":
content:
- application/json:
+ text/plain:
schema:
type: string
description: OK
@@ -2393,13 +2390,13 @@ paths:
type: integer
requestBody:
content:
- application/json:
+ text/plain:
schema:
type: string
responses:
"200":
content:
- application/json:
+ text/plain:
schema:
type: string
description: OK
@@ -2429,7 +2426,7 @@ paths:
responses:
"200":
content:
- application/json:
+ text/plain:
schema:
type: string
description: OK
diff --git a/src/main/java/io/cryostat/HibernateFormatMapperCustomization.java b/src/main/java/io/cryostat/HibernateFormatMapperCustomization.java
new file mode 100644
index 000000000..dd390869d
--- /dev/null
+++ b/src/main/java/io/cryostat/HibernateFormatMapperCustomization.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright The Cryostat Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.cryostat;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.quarkus.hibernate.orm.JsonFormat;
+import io.quarkus.hibernate.orm.PersistenceUnitExtension;
+import org.hibernate.type.descriptor.WrapperOptions;
+import org.hibernate.type.descriptor.java.JavaType;
+import org.hibernate.type.format.FormatMapper;
+import org.hibernate.type.format.jackson.JacksonJsonFormatMapper;
+
+@JsonFormat
+@PersistenceUnitExtension
+/**
+ * @see https://github.com/quarkusio/quarkus/issues/42596
+ */
+public class HibernateFormatMapperCustomization implements FormatMapper {
+
+ private final JacksonJsonFormatMapper delegate =
+ new JacksonJsonFormatMapper(new ObjectMapper().findAndRegisterModules());
+
+ @Override
+ public T fromString(
+ CharSequence charSequence, JavaType javaType, WrapperOptions wrapperOptions) {
+ return delegate.fromString(charSequence, javaType, wrapperOptions);
+ }
+
+ @Override
+ public String toString(T value, JavaType javaType, WrapperOptions wrapperOptions) {
+ return delegate.toString(value, javaType, wrapperOptions);
+ }
+}
diff --git a/src/main/java/io/cryostat/credentials/Credentials.java b/src/main/java/io/cryostat/credentials/Credentials.java
index 7f840be92..4d81ab6d4 100644
--- a/src/main/java/io/cryostat/credentials/Credentials.java
+++ b/src/main/java/io/cryostat/credentials/Credentials.java
@@ -25,7 +25,6 @@
import io.cryostat.expressions.MatchExpression;
import io.cryostat.expressions.MatchExpression.TargetMatcher;
-import io.smallrye.common.annotation.Blocking;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
@@ -113,7 +112,6 @@ static Map notificationResult(Credential credential) throws Scri
return result;
}
- @Blocking
static Map safeResult(Credential credential, TargetMatcher matcher)
throws ScriptException {
Map result = new HashMap<>();
@@ -124,7 +122,6 @@ static Map safeResult(Credential credential, TargetMatcher match
return result;
}
- @Blocking
static Map safeMatchedResult(Credential credential, TargetMatcher matcher)
throws ScriptException {
Map result = new HashMap<>();
diff --git a/src/main/java/io/cryostat/credentials/CredentialsFinder.java b/src/main/java/io/cryostat/credentials/CredentialsFinder.java
index a8f1bda00..52239c820 100644
--- a/src/main/java/io/cryostat/credentials/CredentialsFinder.java
+++ b/src/main/java/io/cryostat/credentials/CredentialsFinder.java
@@ -24,7 +24,6 @@
import io.cryostat.targets.Target.TargetDiscovery;
import io.quarkus.vertx.ConsumeEvent;
-import io.smallrye.common.annotation.Blocking;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.apache.commons.collections4.BidiMap;
@@ -52,7 +51,6 @@ void onMessage(TargetDiscovery event) {
}
}
- @Blocking
public Optional getCredentialsForTarget(Target target) {
return Optional.ofNullable(
cache.computeIfAbsent(
@@ -73,7 +71,6 @@ public Optional getCredentialsForTarget(Target target) {
.orElse(null)));
}
- @Blocking
public Optional getCredentialsForConnectUrl(URI connectUrl) {
return Target.find("connectUrl", connectUrl)
.singleResultOptional()
diff --git a/src/main/java/io/cryostat/discovery/ContainerDiscovery.java b/src/main/java/io/cryostat/discovery/ContainerDiscovery.java
index 3243b27a0..35805723c 100644
--- a/src/main/java/io/cryostat/discovery/ContainerDiscovery.java
+++ b/src/main/java/io/cryostat/discovery/ContainerDiscovery.java
@@ -187,7 +187,6 @@ public abstract class ContainerDiscovery {
protected long timerId;
- @Transactional
void onStart(@Observes StartupEvent evt) {
if (!enabled()) {
return;
@@ -200,22 +199,29 @@ void onStart(@Observes StartupEvent evt) {
return;
}
- DiscoveryNode universe = DiscoveryNode.getUniverse();
- if (DiscoveryNode.getRealm(getRealm()).isEmpty()) {
- DiscoveryPlugin plugin = new DiscoveryPlugin();
- DiscoveryNode node = DiscoveryNode.environment(getRealm(), BaseNodeType.REALM);
- plugin.realm = node;
- plugin.builtin = true;
- universe.children.add(node);
- node.parent = universe;
- plugin.persist();
- universe.persist();
- }
-
- logger.debugv("Starting {0} client", getRealm());
+ QuarkusTransaction.requiringNew()
+ .run(
+ () -> {
+ logger.debugv("Starting {0} client", getRealm());
+
+ DiscoveryNode universe = DiscoveryNode.getUniverse();
+ if (DiscoveryNode.getRealm(getRealm()).isEmpty()) {
+ DiscoveryPlugin plugin = new DiscoveryPlugin();
+ DiscoveryNode node =
+ DiscoveryNode.environment(getRealm(), BaseNodeType.REALM);
+ plugin.realm = node;
+ plugin.builtin = true;
+ universe.children.add(node);
+ node.parent = universe;
+ plugin.persist();
+ universe.persist();
+ }
- queryContainers();
- this.timerId = vertx.setPeriodic(pollPeriod.toMillis(), unused -> queryContainers());
+ queryContainers();
+ this.timerId =
+ vertx.setPeriodic(
+ pollPeriod.toMillis(), unused -> queryContainers());
+ });
}
void onStop(@Observes ShutdownEvent evt) {
@@ -278,10 +284,9 @@ private Target toTarget(ContainerSpec desc) {
target.connectUrl = connectUrl;
target.alias = Optional.ofNullable(desc.Names.get(0)).orElse(desc.Id);
target.labels = desc.Labels;
- target.annotations = new Annotations();
- target.annotations
- .cryostat()
- .putAll(
+ target.annotations =
+ new Annotations(
+ null,
Map.of(
"REALM", // AnnotationKey.REALM,
getRealm(),
diff --git a/src/main/java/io/cryostat/discovery/CustomDiscovery.java b/src/main/java/io/cryostat/discovery/CustomDiscovery.java
index bbcd6d26a..2110e5105 100644
--- a/src/main/java/io/cryostat/discovery/CustomDiscovery.java
+++ b/src/main/java/io/cryostat/discovery/CustomDiscovery.java
@@ -35,6 +35,7 @@
import io.cryostat.targets.TargetConnectionManager;
import io.cryostat.util.URIUtil;
+import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.runtime.StartupEvent;
import io.vertx.mutiny.core.eventbus.EventBus;
import jakarta.annotation.security.RolesAllowed;
@@ -76,17 +77,24 @@ public class CustomDiscovery {
@Transactional
void onStart(@Observes StartupEvent evt) {
- DiscoveryNode universe = DiscoveryNode.getUniverse();
- if (DiscoveryNode.getRealm(REALM).isEmpty()) {
- DiscoveryPlugin plugin = new DiscoveryPlugin();
- DiscoveryNode node = DiscoveryNode.environment(REALM, BaseNodeType.REALM);
- plugin.realm = node;
- plugin.builtin = true;
- universe.children.add(node);
- node.parent = universe;
- plugin.persist();
- universe.persist();
- }
+ QuarkusTransaction.requiringNew()
+ .run(
+ () -> {
+ logger.debugv("Starting {0} client", REALM);
+
+ DiscoveryNode universe = DiscoveryNode.getUniverse();
+ if (DiscoveryNode.getRealm(REALM).isEmpty()) {
+ DiscoveryPlugin plugin = new DiscoveryPlugin();
+ DiscoveryNode node =
+ DiscoveryNode.environment(REALM, BaseNodeType.REALM);
+ plugin.realm = node;
+ plugin.builtin = true;
+ universe.children.add(node);
+ node.parent = universe;
+ plugin.persist();
+ universe.persist();
+ }
+ });
}
@Transactional(rollbackOn = {JvmIdException.class})
@@ -217,9 +225,7 @@ Response doV2Create(
credential.ifPresent(c -> c.persist());
target.activeRecordings = new ArrayList<>();
- target.labels = Map.of();
- target.annotations = new Annotations();
- target.annotations.cryostat().putAll(Map.of("REALM", REALM));
+ target.annotations = new Annotations(null, Map.of("REALM", REALM));
DiscoveryNode node = DiscoveryNode.target(target, BaseNodeType.JVM);
target.discoveryNode = node;
diff --git a/src/main/java/io/cryostat/discovery/Discovery.java b/src/main/java/io/cryostat/discovery/Discovery.java
index 62f5b5269..773b2420d 100644
--- a/src/main/java/io/cryostat/discovery/Discovery.java
+++ b/src/main/java/io/cryostat/discovery/Discovery.java
@@ -42,6 +42,7 @@
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jwt.proc.BadJWTException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import io.vertx.core.json.JsonObject;
@@ -106,36 +107,46 @@ public class Discovery {
@Inject Scheduler scheduler;
@Inject URIUtil uriUtil;
- @Transactional
void onStart(@Observes StartupEvent evt) {
- // ensure lazily initialized entries are created
- DiscoveryNode.getUniverse();
-
- DiscoveryPlugin.findAll().list().stream()
- .filter(p -> !p.builtin)
- .forEach(
- plugin -> {
- var dataMap = new JobDataMap();
- dataMap.put(PLUGIN_ID_MAP_KEY, plugin.id);
- dataMap.put(REFRESH_MAP_KEY, true);
- JobDetail jobDetail =
- JobBuilder.newJob(RefreshPluginJob.class)
- .withIdentity(plugin.id.toString(), JOB_STARTUP)
- .usingJobData(dataMap)
- .build();
- var trigger =
- TriggerBuilder.newTrigger()
- .usingJobData(jobDetail.getJobDataMap())
- .startNow()
- .withSchedule(
- SimpleScheduleBuilder.simpleSchedule()
- .withRepeatCount(0))
- .build();
- try {
- scheduler.scheduleJob(jobDetail, trigger);
- } catch (SchedulerException e) {
- logger.warn("Failed to schedule plugin prune job", e);
- }
+ QuarkusTransaction.requiringNew()
+ .run(
+ () -> {
+ // ensure lazily initialized entries are created
+ DiscoveryNode.getUniverse();
+ logger.debugv("Initializing {0} onStart", getClass());
+
+ DiscoveryPlugin.findAll().list().stream()
+ .filter(p -> !p.builtin)
+ .forEach(
+ plugin -> {
+ var dataMap = new JobDataMap();
+ dataMap.put(PLUGIN_ID_MAP_KEY, plugin.id);
+ dataMap.put(REFRESH_MAP_KEY, true);
+ JobDetail jobDetail =
+ JobBuilder.newJob(RefreshPluginJob.class)
+ .withIdentity(
+ plugin.id.toString(),
+ JOB_STARTUP)
+ .usingJobData(dataMap)
+ .build();
+ var trigger =
+ TriggerBuilder.newTrigger()
+ .usingJobData(
+ jobDetail.getJobDataMap())
+ .startNow()
+ .withSchedule(
+ SimpleScheduleBuilder
+ .simpleSchedule()
+ .withRepeatCount(0))
+ .build();
+ try {
+ scheduler.scheduleJob(jobDetail, trigger);
+ } catch (SchedulerException e) {
+ logger.warn(
+ "Failed to schedule plugin prune job",
+ e);
+ }
+ });
});
}
diff --git a/src/main/java/io/cryostat/discovery/DiscoveryNode.java b/src/main/java/io/cryostat/discovery/DiscoveryNode.java
index f2f229410..461d411b1 100644
--- a/src/main/java/io/cryostat/discovery/DiscoveryNode.java
+++ b/src/main/java/io/cryostat/discovery/DiscoveryNode.java
@@ -198,7 +198,14 @@ static class Listener {
@Inject EventBus bus;
@PrePersist
- void prePersist(DiscoveryNode node) {}
+ void prePersist(DiscoveryNode node) {
+ if (node.children == null) {
+ node.children = new ArrayList<>();
+ }
+ if (node.labels == null) {
+ node.labels = new HashMap<>();
+ }
+ }
@PostPersist
void postPersist(DiscoveryNode node) {}
diff --git a/src/main/java/io/cryostat/discovery/JDPDiscovery.java b/src/main/java/io/cryostat/discovery/JDPDiscovery.java
index ee6ccd8b9..8033e1b8f 100644
--- a/src/main/java/io/cryostat/discovery/JDPDiscovery.java
+++ b/src/main/java/io/cryostat/discovery/JDPDiscovery.java
@@ -31,6 +31,7 @@
import io.cryostat.targets.Target.Annotations;
import io.cryostat.util.URIUtil;
+import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import io.quarkus.vertx.ConsumeEvent;
@@ -65,31 +66,37 @@ static JvmDiscoveryClient produceJvmDiscoveryClient() {
@ConfigProperty(name = "cryostat.discovery.jdp.enabled")
boolean enabled;
- @Transactional
void onStart(@Observes StartupEvent evt) {
if (!enabled) {
return;
}
- DiscoveryNode universe = DiscoveryNode.getUniverse();
- if (DiscoveryNode.getRealm(REALM).isEmpty()) {
- DiscoveryPlugin plugin = new DiscoveryPlugin();
- DiscoveryNode node = DiscoveryNode.environment(REALM, BaseNodeType.REALM);
- plugin.realm = node;
- plugin.builtin = true;
- universe.children.add(node);
- node.parent = universe;
- plugin.persist();
- universe.persist();
- }
-
- logger.debug("Starting JDP client");
- jdp.addListener(this);
- try {
- jdp.start();
- } catch (IOException ioe) {
- logger.error("Failure starting JDP client", ioe);
- }
+ QuarkusTransaction.requiringNew()
+ .run(
+ () -> {
+ logger.debugv("Starting {0} client", REALM);
+
+ DiscoveryNode universe = DiscoveryNode.getUniverse();
+ if (DiscoveryNode.getRealm(REALM).isEmpty()) {
+ DiscoveryPlugin plugin = new DiscoveryPlugin();
+ DiscoveryNode node =
+ DiscoveryNode.environment(REALM, BaseNodeType.REALM);
+ plugin.realm = node;
+ plugin.builtin = true;
+ universe.children.add(node);
+ node.parent = universe;
+ plugin.persist();
+ universe.persist();
+ }
+
+ logger.debug("Starting JDP client");
+ jdp.addListener(this);
+ try {
+ jdp.start();
+ } catch (IOException ioe) {
+ logger.error("Failure starting JDP client", ioe);
+ }
+ });
}
void onStop(@Observes ShutdownEvent evt) {
@@ -130,11 +137,9 @@ void handleJdpEvent(JvmDiscoveryEvent evt) {
target.activeRecordings = new ArrayList<>();
target.connectUrl = connectUrl;
target.alias = evt.getJvmDescriptor().getMainClass();
- target.labels = Map.of();
- target.annotations = new Annotations();
- target.annotations
- .cryostat()
- .putAll(
+ target.annotations =
+ new Annotations(
+ null,
Map.of(
"REALM", // AnnotationKey.REALM,
REALM,
diff --git a/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java b/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java
index 5a57bfe5f..0d1839c2d 100644
--- a/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java
+++ b/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java
@@ -82,6 +82,8 @@ public class KubeApiDiscovery {
@Inject KubeConfig kubeConfig;
+ @Inject KubernetesClient client;
+
@Inject EventBus bus;
@ConfigProperty(name = "cryostat.discovery.kubernetes.enabled")
@@ -111,7 +113,7 @@ protected HashMap> initialize()
ns -> {
result.put(
ns,
- client().endpoints()
+ client.endpoints()
.inNamespace(ns)
.inform(
new EndpointsHandler(),
@@ -127,7 +129,6 @@ protected HashMap> initialize()
// Priority is set higher than default 0 such that onStart is called first before onAfterStart
// This ensures realm node is persisted before initializing informers
- @Transactional
void onStart(@Observes @Priority(1) StartupEvent evt) {
if (!enabled()) {
return;
@@ -138,22 +139,26 @@ void onStart(@Observes @Priority(1) StartupEvent evt) {
return;
}
- DiscoveryNode universe = DiscoveryNode.getUniverse();
- if (DiscoveryNode.getRealm(REALM).isEmpty()) {
- DiscoveryPlugin plugin = new DiscoveryPlugin();
- DiscoveryNode node = DiscoveryNode.environment(REALM, BaseNodeType.REALM);
- plugin.realm = node;
- plugin.builtin = true;
- universe.children.add(node);
- node.parent = universe;
- plugin.persist();
- universe.persist();
- }
-
- logger.debugv("Starting {0} client", REALM);
+ QuarkusTransaction.requiringNew()
+ .run(
+ () -> {
+ logger.debugv("Starting {0} client", REALM);
+
+ DiscoveryNode universe = DiscoveryNode.getUniverse();
+ if (DiscoveryNode.getRealm(REALM).isEmpty()) {
+ DiscoveryPlugin plugin = new DiscoveryPlugin();
+ DiscoveryNode node =
+ DiscoveryNode.environment(REALM, BaseNodeType.REALM);
+ plugin.realm = node;
+ plugin.builtin = true;
+ universe.children.add(node);
+ node.parent = universe;
+ plugin.persist();
+ universe.persist();
+ }
+ });
}
- @Transactional
void onAfterStart(@Observes StartupEvent evt) {
if (!enabled() || !available()) {
return;
@@ -190,16 +195,6 @@ boolean available() {
return false;
}
- KubernetesClient client() {
- KubernetesClient client;
- try {
- client = kubeConfig.kubeClient();
- } catch (ConcurrentException e) {
- throw new IllegalStateException(e);
- }
- return client;
- }
-
private boolean isCompatiblePort(EndpointPort port) {
return jmxPortNames.orElse(EMPTY_PORT_NAMES).contains(port.getName())
|| jmxPortNumbers.orElse(EMPTY_PORT_NUMBERS).contains(port.getPort());
@@ -471,7 +466,7 @@ private Pair queryForNode(
}
HasMetadata kubeObj =
- nodeType.getQueryFunction().apply(client()).apply(namespace).apply(name);
+ nodeType.getQueryFunction().apply(client).apply(namespace).apply(name);
DiscoveryNode node =
DiscoveryNode.getNode(
@@ -488,12 +483,13 @@ private Pair queryForNode(
newNode.nodeType = nodeType.getKind();
newNode.children = new ArrayList<>();
newNode.target = null;
- newNode.labels =
+ Map labels =
kubeObj != null
? kubeObj.getMetadata().getLabels()
: new HashMap<>();
// Add namespace to label to retrieve node later
- newNode.labels.put(DISCOVERY_NAMESPACE_LABEL_KEY, namespace);
+ labels.put(DISCOVERY_NAMESPACE_LABEL_KEY, namespace);
+ newNode.labels = labels;
return newNode;
});
return Pair.of(kubeObj, node);
@@ -550,10 +546,6 @@ String getOwnNamespace() {
boolean kubeApiAvailable() {
return StringUtils.isNotBlank(serviceHost.orElse(""));
}
-
- KubernetesClient kubeClient() throws ConcurrentException {
- return kubeClient.get();
- }
}
private final class EndpointsHandler implements ResourceEventHandler {
@@ -638,14 +630,10 @@ public Target toTarget() {
target.activeRecordings = new ArrayList<>();
target.connectUrl = connectUrl;
target.alias = objRef.getName();
- target.labels = obj != null ? obj.getMetadata().getLabels() : new HashMap<>();
- target.annotations = new Annotations();
- target.annotations
- .platform()
- .putAll(obj != null ? obj.getMetadata().getAnnotations() : Map.of());
- target.annotations
- .cryostat()
- .putAll(
+ target.labels = (obj != null ? obj.getMetadata().getLabels() : new HashMap<>());
+ target.annotations =
+ new Annotations(
+ obj != null ? obj.getMetadata().getAnnotations() : Map.of(),
Map.of(
"REALM",
REALM,
diff --git a/src/main/java/io/cryostat/expressions/MatchExpressionEvaluator.java b/src/main/java/io/cryostat/expressions/MatchExpressionEvaluator.java
index 1ec68bb0f..c9ad2c81e 100644
--- a/src/main/java/io/cryostat/expressions/MatchExpressionEvaluator.java
+++ b/src/main/java/io/cryostat/expressions/MatchExpressionEvaluator.java
@@ -33,7 +33,6 @@
import io.quarkus.cache.CacheResult;
import io.quarkus.cache.CompositeCacheKey;
import io.quarkus.vertx.ConsumeEvent;
-import io.smallrye.common.annotation.Blocking;
import jakarta.annotation.Nullable;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@@ -77,7 +76,6 @@ void onMessage(ExpressionEvent event) {
}
@Transactional
- @Blocking
@ConsumeEvent(value = Target.TARGET_JVM_DISCOVERY, blocking = true)
void onMessage(TargetDiscovery event) {
var target = Target.find("id", event.serviceRef().id).singleResultOptional();
diff --git a/src/main/java/io/cryostat/graphql/ActiveRecordings.java b/src/main/java/io/cryostat/graphql/ActiveRecordings.java
index a9877ee20..e8fb5b145 100644
--- a/src/main/java/io/cryostat/graphql/ActiveRecordings.java
+++ b/src/main/java/io/cryostat/graphql/ActiveRecordings.java
@@ -42,7 +42,6 @@
import io.cryostat.targets.Target;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
@@ -64,7 +63,6 @@ public class ActiveRecordings {
@ConfigProperty(name = ConfigProperties.CONNECTIONS_FAILED_TIMEOUT)
Duration timeout;
- @Blocking
@Transactional
@Mutation
@Description(
@@ -106,7 +104,6 @@ public List createRecording(
return recordings;
}
- @Blocking
@Transactional
@Mutation
@Description(
@@ -138,7 +135,6 @@ public List archiveRecording(
return archives;
}
- @Blocking
@Transactional
@Mutation
@Description(
@@ -169,7 +165,6 @@ public List stopRecording(
return list;
}
- @Blocking
@Transactional
@Mutation
@Description(
@@ -199,7 +194,6 @@ public List deleteRecording(
return list;
}
- @Blocking
@Transactional
@Mutation
@Description(
@@ -222,7 +216,6 @@ public List createSnapshot(@NonNull DiscoveryNodeFilter nodes)
return snapshots;
}
- @Blocking
@Transactional
@Description("Start a new Flight Recording on the specified Target")
public ActiveRecording doStartRecording(
@@ -245,7 +238,6 @@ public ActiveRecording doStartRecording(
.atMost(timeout);
}
- @Blocking
@Transactional
@Description("Create a new Flight Recorder Snapshot on the specified Target")
public ActiveRecording doSnapshot(@Source Target target) {
@@ -253,7 +245,6 @@ public ActiveRecording doSnapshot(@Source Target target) {
return recordingHelper.createSnapshot(fTarget).await().atMost(timeout);
}
- @Blocking
@Transactional
@Description("Stop the specified Flight Recording")
public ActiveRecording doStop(@Source ActiveRecording recording) throws Exception {
@@ -261,7 +252,6 @@ public ActiveRecording doStop(@Source ActiveRecording recording) throws Exceptio
return recordingHelper.stopRecording(ar).await().atMost(timeout);
}
- @Blocking
@Transactional
@Description("Delete the specified Flight Recording")
public ActiveRecording doDelete(@Source ActiveRecording recording) {
@@ -269,7 +259,6 @@ public ActiveRecording doDelete(@Source ActiveRecording recording) {
return recordingHelper.deleteRecording(ar).await().atMost(timeout);
}
- @Blocking
@Description("Archive the specified Flight Recording")
public ArchivedRecording doArchive(@Source ActiveRecording recording) throws Exception {
var ar = ActiveRecording.find("id", recording.id).singleResult();
@@ -317,7 +306,6 @@ public RecordingOptions asOptions() {
}
}
- @Blocking
@Transactional
@Description("Updates the metadata labels for an existing Flight Recording.")
public ActiveRecording doPutMetadata(
diff --git a/src/main/java/io/cryostat/graphql/ArchivedRecordings.java b/src/main/java/io/cryostat/graphql/ArchivedRecordings.java
index 171b355de..941dcfc64 100644
--- a/src/main/java/io/cryostat/graphql/ArchivedRecordings.java
+++ b/src/main/java/io/cryostat/graphql/ArchivedRecordings.java
@@ -29,7 +29,6 @@
import io.cryostat.recordings.Recordings.Metadata;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import jakarta.inject.Inject;
import org.eclipse.microprofile.graphql.GraphQLApi;
@@ -42,7 +41,6 @@ public class ArchivedRecordings {
@Inject RecordingHelper recordingHelper;
- @Blocking
@Query("archivedRecordings")
public TargetNodes.ArchivedRecordings listArchivedRecordings(ArchivedRecordingsFilter filter) {
var r = new TargetNodes.ArchivedRecordings();
@@ -78,7 +76,6 @@ public ArchivedRecording doDelete(@Source ArchivedRecording recording) {
return recording;
}
- @Blocking
@NonNull
public ArchivedRecording doPutMetadata(
@Source ArchivedRecording recording, MetadataLabels metadataInput) {
diff --git a/src/main/java/io/cryostat/graphql/EnvironmentNodes.java b/src/main/java/io/cryostat/graphql/EnvironmentNodes.java
index c5615312a..d70859989 100644
--- a/src/main/java/io/cryostat/graphql/EnvironmentNodes.java
+++ b/src/main/java/io/cryostat/graphql/EnvironmentNodes.java
@@ -20,7 +20,6 @@
import io.cryostat.discovery.DiscoveryNode;
import io.cryostat.graphql.RootNode.DiscoveryNodeFilter;
-import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import org.eclipse.microprofile.graphql.Description;
import org.eclipse.microprofile.graphql.GraphQLApi;
@@ -29,7 +28,6 @@
@GraphQLApi
public class EnvironmentNodes {
- @Blocking
@Query("environmentNodes")
@Description("Get all environment nodes in the discovery tree with optional filtering")
public List environmentNodes(@Nullable DiscoveryNodeFilter filter) {
diff --git a/src/main/java/io/cryostat/graphql/RootNode.java b/src/main/java/io/cryostat/graphql/RootNode.java
index 4af6eefa8..670bbb99f 100644
--- a/src/main/java/io/cryostat/graphql/RootNode.java
+++ b/src/main/java/io/cryostat/graphql/RootNode.java
@@ -24,7 +24,6 @@
import io.cryostat.graphql.matchers.LabelSelectorMatcher;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import org.eclipse.microprofile.graphql.Description;
import org.eclipse.microprofile.graphql.GraphQLApi;
@@ -34,14 +33,12 @@
@GraphQLApi
public class RootNode {
- @Blocking
@Query("rootNode")
@Description("Get the root target discovery node")
public DiscoveryNode getRootNode() {
return DiscoveryNode.getUniverse();
}
- @Blocking
@Description(
"Get target nodes that are descendants of this node. That is, get the set of leaf nodes"
+ " from anywhere below this node's subtree.")
diff --git a/src/main/java/io/cryostat/graphql/TargetNodes.java b/src/main/java/io/cryostat/graphql/TargetNodes.java
index 7c77c68a8..a572d287b 100644
--- a/src/main/java/io/cryostat/graphql/TargetNodes.java
+++ b/src/main/java/io/cryostat/graphql/TargetNodes.java
@@ -33,7 +33,6 @@
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import graphql.schema.DataFetchingEnvironment;
-import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Context;
import io.smallrye.graphql.api.Nullable;
import jakarta.inject.Inject;
@@ -51,7 +50,6 @@ public class TargetNodes {
@Inject RecordingHelper recordingHelper;
@Inject TargetConnectionManager connectionManager;
- @Blocking
@Query("targetNodes")
@Description("Get the Target discovery nodes, i.e. the leaf nodes of the discovery tree")
public List getTargetNodes(DiscoveryNodeFilter filter) {
@@ -69,12 +67,6 @@ public List getTargetNodes(DiscoveryNodeFilter filter) {
.toList();
}
- // private static Predicate distinctWith(Function super T, ?> fn) {
- // Set