From ded745dc8f1be55bbbafd3c7364203e776c08c2e Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Mon, 30 Sep 2024 11:41:28 -0400 Subject: [PATCH 1/7] build(deps): update Quarkus to 3.8 LTS (#609) * build(deps): update Quarkus to 3.8 LTS * add hibernate format mapper override * remove no longer necessary lazy init * disable openapi management / swagger UI unless in dev mode * remove duplicate healthcheck override * reduce healthcheck start periods * correct healthcheck URL * use authproxy image which contains wget for healthcheck * correct healthchecks for vertx agent test applications --- compose/auth_proxy.yml | 21 +-- compose/cryostat-grafana.yml | 2 +- compose/cryostat.yml | 14 +- compose/db.yml | 2 +- compose/jfr-datasource.yml | 2 +- compose/sample_apps/vertx-cryostat-agent.yml | 133 ++++++++++++++++++ pom.xml | 23 ++- schema/openapi.yaml | 17 +-- .../HibernateFormatMapperCustomization.java | 46 ++++++ .../io/cryostat/credentials/Credentials.java | 3 - .../credentials/CredentialsFinder.java | 3 - .../discovery/ContainerDiscovery.java | 9 +- .../cryostat/discovery/CustomDiscovery.java | 4 +- .../java/io/cryostat/discovery/Discovery.java | 68 +++++---- .../io/cryostat/discovery/DiscoveryNode.java | 9 +- .../io/cryostat/discovery/JDPDiscovery.java | 9 +- .../cryostat/discovery/KubeApiDiscovery.java | 19 +-- .../expressions/MatchExpressionEvaluator.java | 2 - .../io/cryostat/graphql/ActiveRecordings.java | 12 -- .../cryostat/graphql/ArchivedRecordings.java | 3 - .../io/cryostat/graphql/EnvironmentNodes.java | 2 - .../java/io/cryostat/graphql/RootNode.java | 3 - .../java/io/cryostat/graphql/TargetNodes.java | 11 -- .../RecordingOptionsBuilderFactory.java | 2 - .../java/io/cryostat/rules/RuleService.java | 10 +- .../io/cryostat/targets/AgentConnection.java | 3 - .../io/cryostat/targets/AgentJFRService.java | 12 -- src/main/java/io/cryostat/targets/Target.java | 24 ++-- src/main/resources/application-dev.properties | 3 + src/main/resources/application.properties | 2 + src/test/java/itest/GraphQLTest.java | 44 +++--- 31 files changed, 330 insertions(+), 187 deletions(-) create mode 100644 compose/sample_apps/vertx-cryostat-agent.yml create mode 100644 src/main/java/io/cryostat/HibernateFormatMapperCustomization.java diff --git a/compose/auth_proxy.yml b/compose/auth_proxy.yml index 649489867..bf1bc757f 100644 --- a/compose/auth_proxy.yml +++ b/compose/auth_proxy.yml @@ -5,12 +5,14 @@ services: - "${CRYOSTAT_HTTP_PORT}" environment: CRYOSTAT_HTTP_PROXY_HOST: auth - CRYOSTAT_HTTP_PROXY_PORT: '8080' - QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDING: 'true' - QUARKUS_HTTP_PROXY_ALLOW_X_FORWARDED: 'true' - QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_HOST: 'true' - QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_PREFIX: 'true' + CRYOSTAT_HTTP_PROXY_PORT: "${CRYOSTAT_HTTP_PORT}" + QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDING: "true" + QUARKUS_HTTP_PROXY_ALLOW_X_FORWARDED: "true" + 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} + QUARKUS_HTTP_ACCESS_LOG_PATTERN: long + QUARKUS_HTTP_ACCESS_LOG_ENABLED: "true" healthcheck: test: curl --fail http://cryostat:8181/health/liveness || exit 1 interval: 10s @@ -30,8 +32,9 @@ services: limits: cpus: '0.1' memory: 32m - image: ${OAUTH2_PROXY_IMAGE:-quay.io/oauth2-proxy/oauth2-proxy:latest} - command: --alpha-config=/tmp/auth_proxy_alpha_config.yaml + image: ${OAUTH2_PROXY_IMAGE:-quay.io/oauth2-proxy/oauth2-proxy:latest-alpine} + command: + - --alpha-config=/tmp/auth_proxy_alpha_config.yml volumes: - auth_proxy_cfg:/tmp hostname: auth @@ -47,10 +50,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 ${CRYOSTAT_PROXY_PROTOCOL}://localhost:${CRYOSTAT_PROXY_PORT}/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/compose/sample_apps/vertx-cryostat-agent.yml b/compose/sample_apps/vertx-cryostat-agent.yml new file mode 100644 index 000000000..cdcdf6179 --- /dev/null +++ b/compose/sample_apps/vertx-cryostat-agent.yml @@ -0,0 +1,133 @@ +version: "3" +services: + vertx-agent-1: + depends_on: + cryostat: + condition: service_healthy + image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} + hostname: vertx-cryostat-agent-1 + environment: + HTTP_PORT: 8081 + JMX_PORT: 9093 + USE_JDP: "true" + CRYOSTAT_AGENT_APP_NAME: vertx-cryostat-agent-1 + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUST_ALL: "true" + CRYOSTAT_AGENT_WEBCLIENT_TLS_VERIFY_HOSTNAME: "false" + CRYOSTAT_AGENT_WEBSERVER_HOST: "vertx-agent-1" + CRYOSTAT_AGENT_WEBSERVER_PORT: "8910" + CRYOSTAT_AGENT_CALLBACK: "http://vertx-agent-1:8910/" + CRYOSTAT_AGENT_BASEURI: "${CRYOSTAT_PROXY_PROTOCOL}://${CRYOSTAT_HTTP_HOST}:${CRYOSTAT_PROXY_PORT}/" + CRYOSTAT_AGENT_BASEURI_RANGE: public + CRYOSTAT_AGENT_TRUST_ALL: "true" + CRYOSTAT_AGENT_AUTHORIZATION_TYPE: basic + CRYOSTAT_AGENT_AUTHORIZATION_VALUE: user:pass + ports: + - "8081:8081" + expose: + - "8910" + restart: always + healthcheck: + test: curl --fail http://localhost:8081 || exit 1 + interval: 10s + retries: 3 + start_period: 30s + timeout: 5s + + vertx-agent-2: + depends_on: + cryostat: + condition: service_healthy + image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} + hostname: vertx-cryostat-agent-2 + environment: + HTTP_PORT: 8082 + JMX_PORT: 9094 + USE_JDP: "true" + USE_AUTH: "true" + CRYOSTAT_AGENT_APP_NAME: "vertx-cryostat-agent-2" + CRYOSTAT_AGENT_WEBSERVER_HOST: "vertx-agent-2" + CRYOSTAT_AGENT_WEBSERVER_PORT: "8911" + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_PATH: /auth_certs/certificate.pem + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_TYPE: X.509 + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_ALIAS: cryostat + CRYOSTAT_AGENT_CALLBACK: "http://vertx-agent-2:8911/" + CRYOSTAT_AGENT_API_WRITES_ENABLED: "true" + CRYOSTAT_AGENT_BASEURI: "${CRYOSTAT_PROXY_PROTOCOL}://${CRYOSTAT_HTTP_HOST}:${CRYOSTAT_PROXY_PORT}/" + CRYOSTAT_AGENT_BASEURI_RANGE: public + CRYOSTAT_AGENT_TRUST_ALL: "true" + CRYOSTAT_AGENT_AUTHORIZATION_TYPE: basic + CRYOSTAT_AGENT_AUTHORIZATION_VALUE: user:pass + ports: + - "8082:8082" + expose: + - "8911" + restart: always + healthcheck: + test: curl --fail http://localhost:8082 || exit 1 + interval: 10s + retries: 3 + start_period: 30s + timeout: 5s + volumes: + - ${DIR}/compose/auth_certs:/auth_certs:z + + vertx-agent-3: + depends_on: + cryostat: + condition: service_healthy + image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} + hostname: vertx-cryostat-agent-3 + environment: + HTTP_PORT: 8083 + JMX_PORT: 9095 + USE_JDP: "true" + USE_AUTH: "true" + USE_SSL: "true" + CRYOSTAT_AGENT_APP_NAME: "vertx-cryostat-agent-3" + CRYOSTAT_AGENT_WEBSERVER_HOST: "vertx-agent-3" + CRYOSTAT_AGENT_WEBSERVER_PORT: "8912" + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_PATH: /auth_certs/certificate.pem + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_TYPE: X.509 + CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_ALIAS: cryostat + CRYOSTAT_AGENT_CALLBACK: "http://vertx-agent-3:8912/" + CRYOSTAT_AGENT_API_WRITES_ENABLED: "true" + CRYOSTAT_AGENT_BASEURI: "${CRYOSTAT_PROXY_PROTOCOL}://${CRYOSTAT_HTTP_HOST}:${CRYOSTAT_PROXY_PORT}/" + CRYOSTAT_AGENT_BASEURI_RANGE: public + CRYOSTAT_AGENT_TRUST_ALL: "true" + CRYOSTAT_AGENT_AUTHORIZATION_TYPE: basic + CRYOSTAT_AGENT_AUTHORIZATION_VALUE: user:pass + ports: + - "8083:8083" + expose: + - "8912" + restart: always + healthcheck: + test: curl --fail http://localhost:8083 || exit 1 + interval: 10s + retries: 3 + start_period: 30s + timeout: 5s + volumes: + - ${DIR}/compose/auth_certs:/auth_certs:z + + vertx-agent-4: + depends_on: + cryostat: + condition: service_healthy + image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} + hostname: vertx-cryostat-agent-4 + environment: + HTTP_PORT: 8084 + JMX_PORT: 9096 + USE_JDP: "true" + USE_AUTH: "false" + USE_SSL: "false" + ports: + - "8084:8084" + restart: always + healthcheck: + test: curl --fail http://localhost:8084 || exit 1 + interval: 10s + retries: 3 + start_period: 30s + timeout: 5s diff --git a/pom.xml b/pom.xml index 4baaa0bab..50848cf08 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 @@ -72,13 +71,6 @@ - - io.netty - netty-bom - ${io.netty.version} - pom - import - ${quarkus.platform.group-id} ${quarkus.platform.artifact-id} @@ -162,6 +154,10 @@ io.quarkus quarkus-vertx + + io.quarkus + quarkus-netty + io.quarkus quarkus-smallrye-openapi @@ -210,12 +206,10 @@ org.apache.commons commons-lang3 - ${org.apache.commons.lang3.version} commons-codec commons-codec - ${org.apache.commons.codec.version} commons-io @@ -541,7 +535,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..ebb047028 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 @@ -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..c75b51d74 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; @@ -213,7 +212,6 @@ void onStart(@Observes StartupEvent evt) { } logger.debugv("Starting {0} client", getRealm()); - queryContainers(); this.timerId = vertx.setPeriodic(pollPeriod.toMillis(), unused -> queryContainers()); } @@ -278,10 +276,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..5ae776339 100644 --- a/src/main/java/io/cryostat/discovery/CustomDiscovery.java +++ b/src/main/java/io/cryostat/discovery/CustomDiscovery.java @@ -217,9 +217,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..7f3d4e819 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,45 @@ 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(); + + 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..491bf8576 100644 --- a/src/main/java/io/cryostat/discovery/JDPDiscovery.java +++ b/src/main/java/io/cryostat/discovery/JDPDiscovery.java @@ -65,7 +65,6 @@ static JvmDiscoveryClient produceJvmDiscoveryClient() { @ConfigProperty(name = "cryostat.discovery.jdp.enabled") boolean enabled; - @Transactional void onStart(@Observes StartupEvent evt) { if (!enabled) { return; @@ -130,11 +129,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..a98ff35af 100644 --- a/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java +++ b/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java @@ -127,7 +127,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; @@ -153,7 +152,6 @@ void onStart(@Observes @Priority(1) StartupEvent evt) { logger.debugv("Starting {0} client", REALM); } - @Transactional void onAfterStart(@Observes StartupEvent evt) { if (!enabled() || !available()) { return; @@ -488,12 +486,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); @@ -638,14 +637,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 fn) { - // Set observed = ConcurrentHashMap.newKeySet(); - // return t -> observed.add(fn.apply(t)); - // } - - @Blocking @Transactional public ActiveRecordings activeRecordings( @Source Target target, @Nullable ActiveRecordingsFilter filter) { @@ -90,7 +82,6 @@ public ActiveRecordings activeRecordings( return recordings; } - @Blocking public ArchivedRecordings archivedRecordings( @Source Target target, @Nullable ArchivedRecordingsFilter filter) { var fTarget = Target.getTargetById(target.id); @@ -105,7 +96,6 @@ public ArchivedRecordings archivedRecordings( return recordings; } - @Blocking @Transactional @Description("Get the active and archived recordings belonging to this target") public Recordings recordings(@Source Target target, Context context) { @@ -133,7 +123,6 @@ public Recordings recordings(@Source Target target, Context context) { return recordings; } - @Blocking @Description("Get live MBean metrics snapshot from the specified Target") public MBeanMetrics mbeanMetrics(@Source Target target) { var fTarget = Target.getTargetById(target.id); diff --git a/src/main/java/io/cryostat/recordings/RecordingOptionsBuilderFactory.java b/src/main/java/io/cryostat/recordings/RecordingOptionsBuilderFactory.java index 9b0dde250..ad77024e9 100644 --- a/src/main/java/io/cryostat/recordings/RecordingOptionsBuilderFactory.java +++ b/src/main/java/io/cryostat/recordings/RecordingOptionsBuilderFactory.java @@ -21,7 +21,6 @@ import io.cryostat.targets.Target; import io.cryostat.targets.TargetConnectionManager; -import io.smallrye.common.annotation.Blocking; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -31,7 +30,6 @@ public class RecordingOptionsBuilderFactory { @Inject RecordingOptionsCustomizerFactory customizerFactory; @Inject TargetConnectionManager connectionManager; - @Blocking public RecordingOptionsBuilder create(Target target) throws QuantityConversionException { return connectionManager.executeConnectedTask( target, diff --git a/src/main/java/io/cryostat/rules/RuleService.java b/src/main/java/io/cryostat/rules/RuleService.java index 7b2e2b3f1..daa1151cf 100644 --- a/src/main/java/io/cryostat/rules/RuleService.java +++ b/src/main/java/io/cryostat/rules/RuleService.java @@ -42,7 +42,6 @@ import io.quarkus.narayana.jta.QuarkusTransaction; import io.quarkus.runtime.StartupEvent; import io.quarkus.vertx.ConsumeEvent; -import io.smallrye.common.annotation.Blocking; import io.smallrye.mutiny.infrastructure.Infrastructure; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; @@ -77,11 +76,14 @@ public class RuleService { private final List jobs = new CopyOnWriteArrayList<>(); - @Transactional - @Blocking void onStart(@Observes StartupEvent ev) { logger.trace("RuleService started"); - Rule.streamAll().filter(r -> r.enabled).forEach(this::applyRuleToMatchingTargets); + QuarkusTransaction.joiningExisting() + .run( + () -> + Rule.streamAll() + .filter(r -> r.enabled) + .forEach(this::applyRuleToMatchingTargets)); } @ConsumeEvent(value = Target.TARGET_JVM_DISCOVERY, blocking = true) diff --git a/src/main/java/io/cryostat/targets/AgentConnection.java b/src/main/java/io/cryostat/targets/AgentConnection.java index 27cac8481..e23c26b01 100644 --- a/src/main/java/io/cryostat/targets/AgentConnection.java +++ b/src/main/java/io/cryostat/targets/AgentConnection.java @@ -38,7 +38,6 @@ import io.cryostat.core.templates.TemplateService; import io.cryostat.events.S3TemplateService; -import io.smallrye.common.annotation.Blocking; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.jboss.logging.Logger; @@ -57,7 +56,6 @@ class AgentConnection implements JFRConnection { @Override public void close() throws Exception {} - @Blocking @Override public void connect() throws ConnectionException { if (!client.ping().await().atMost(client.getTimeout())) { @@ -129,7 +127,6 @@ public boolean isConnected() { return true; } - @Blocking @Override public MBeanMetrics getMBeanMetrics() throws ConnectionException, diff --git a/src/main/java/io/cryostat/targets/AgentJFRService.java b/src/main/java/io/cryostat/targets/AgentJFRService.java index b54949aa9..1d5b88435 100644 --- a/src/main/java/io/cryostat/targets/AgentJFRService.java +++ b/src/main/java/io/cryostat/targets/AgentJFRService.java @@ -51,7 +51,6 @@ import io.cryostat.core.templates.TemplateService; import io.cryostat.core.templates.TemplateType; -import io.smallrye.common.annotation.Blocking; import io.smallrye.mutiny.Uni; import io.vertx.mutiny.core.buffer.Buffer; import org.jboss.logging.Logger; @@ -82,7 +81,6 @@ public String getVersion() { return "agent"; // TODO } - @Blocking @Override public void close(IRecordingDescriptor descriptor) throws FlightRecorderException { client.deleteRecording(descriptor.getId()).await().atMost(client.getTimeout()); @@ -93,7 +91,6 @@ public void enable() throws FlightRecorderException { throw new UnimplementedException(); } - @Blocking @Override public Collection getAvailableEventTypes() throws FlightRecorderException { @@ -106,13 +103,11 @@ public Map> getAvailableRecordingOptions() return KnownRecordingOptions.DESCRIPTORS_BY_KEY_V2; } - @Blocking @Override public List getAvailableRecordings() throws FlightRecorderException { return client.activeRecordings().await().atMost(client.getTimeout()); } - @Blocking @Override public IConstrainedMap getCurrentEventTypeSettings() throws FlightRecorderException { @@ -138,13 +133,11 @@ public IConstrainedMap getRecordingOptions(IRecordingDescriptor descript return new DefaultValueMap<>(Map.of()); } - @Blocking @Override public List getServerTemplates() throws FlightRecorderException { return client.eventTemplates().await().atMost(client.getTimeout()); } - @Blocking @Override public IRecordingDescriptor getSnapshotRecording() throws FlightRecorderException { return client.startSnapshot().await().atMost(client.getTimeout()); @@ -161,7 +154,6 @@ public boolean isEnabled() { return true; } - @Blocking @Override public InputStream openStream(IRecordingDescriptor descriptor, boolean removeOnClose) throws FlightRecorderException { @@ -194,7 +186,6 @@ public IRecordingDescriptor start( throw new UnimplementedException(); } - @Blocking @Override public void stop(IRecordingDescriptor descriptor) throws FlightRecorderException { client.stopRecording(descriptor.getId()).await().atMost(client.getTimeout()); @@ -207,7 +198,6 @@ public void updateEventOptions( throw new UnimplementedException(); } - @Blocking @Override public void updateRecordingOptions( IRecordingDescriptor descriptor, IConstrainedMap newSettings) @@ -217,7 +207,6 @@ public void updateRecordingOptions( .atMost(client.getTimeout()); } - @Blocking @Override public IRecordingDescriptor start(IConstrainedMap recordingOptions, String template) throws FlightRecorderException, @@ -256,7 +245,6 @@ public IRecordingDescriptor start(IConstrainedMap recordingOptions, Stri return client.startRecording(req).await().atMost(client.getTimeout()); } - @Blocking @Override public IRecordingDescriptor start(IConstrainedMap recordingOptions, Template template) throws io.cryostat.core.FlightRecorderException, diff --git a/src/main/java/io/cryostat/targets/Target.java b/src/main/java/io/cryostat/targets/Target.java index 89f902940..c4c95a4c9 100644 --- a/src/main/java/io/cryostat/targets/Target.java +++ b/src/main/java/io/cryostat/targets/Target.java @@ -21,6 +21,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -46,7 +47,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.quarkus.hibernate.orm.panache.PanacheEntity; import io.quarkus.vertx.ConsumeEvent; -import io.smallrye.common.annotation.Blocking; import io.vertx.mutiny.core.eventbus.EventBus; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -170,14 +170,13 @@ public static record Annotations(Map platform, Map(), new HashMap<>()); + this(null, null); } public Map merged() { - Map merged = new HashMap<>(); - cryostat().entrySet().forEach((e) -> merged.put(e.getKey(), e.getValue())); - merged.putAll(platform()); - return merged; + Map merged = new HashMap<>(cryostat); + merged.putAll(platform); + return Collections.unmodifiableMap(merged); } } @@ -322,7 +321,6 @@ void onMessage(TargetDiscovery event) { @ConsumeEvent(value = Credential.CREDENTIALS_STORED, blocking = true) @Transactional - @Blocking void updateCredential(Credential credential) { Target.stream("#Target.unconnected") .forEach( @@ -341,7 +339,6 @@ void updateCredential(Credential credential) { }); } - @Blocking @PrePersist void prePersist(Target target) { if (StringUtils.isBlank(target.alias)) { @@ -352,6 +349,16 @@ void prePersist(Target target) { target.alias = encodedAlias; } + if (target.labels == null) { + target.labels = new HashMap<>(); + } + if (target.annotations == null) { + target.annotations = new Annotations(); + } + if (target.activeRecordings == null) { + target.activeRecordings = new ArrayList<>(); + } + try { if (StringUtils.isBlank(target.jvmId)) { updateTargetJvmId(target, null); @@ -361,7 +368,6 @@ void prePersist(Target target) { } } - @Blocking private void updateTargetJvmId(Target t, Credential credential) { try { t.jvmId = diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 1c45fc6f0..720a64c0c 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,6 +1,9 @@ quarkus.http.host=localhost quarkus.smallrye-openapi.info-title=Cryostat API (development) +quarkus.swagger-ui.enable=true +quarkus.smallrye-openapi.enable=true +quarkus.smallrye-openapi.management.enabled=true quarkus.http.cors=true # quarkus.http.cors.origins=http://localhost:9000,http://0.0.0.0:9000 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 65f2d373d..8dc99f2e1 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -57,6 +57,8 @@ quarkus.http.limits.max-body-size=1G quarkus.vertx.prefer-native-transport=true quarkus.smallrye-openapi.path=/api +quarkus.swagger-ui.enable=false +quarkus.smallrye-openapi.management.enabled=false quarkus.smallrye-openapi.info-title=Cryostat API quarkus.smallrye-openapi.info-version=${quarkus.application.version} quarkus.smallrye-openapi.info-description=Cloud-Native JDK Flight Recorder diff --git a/src/test/java/itest/GraphQLTest.java b/src/test/java/itest/GraphQLTest.java index 4acfab581..88416b560 100644 --- a/src/test/java/itest/GraphQLTest.java +++ b/src/test/java/itest/GraphQLTest.java @@ -70,6 +70,8 @@ class GraphQLTest extends StandardSelfTest { private final ExecutorService worker = ForkJoinPool.commonPool(); + static final long DELAY = 5_000L; + static final String TEST_RECORDING_NAME = "archivedRecording"; @Test @@ -227,7 +229,7 @@ void testStartRecordingMutationOnSpecificTarget() throws Exception { } }); - Thread.sleep(5000); + Thread.sleep(DELAY); HttpResponse resp = webClient @@ -284,8 +286,9 @@ void testStartRecordingMutationOnSpecificTarget() throws Exception { @Test @Order(4) void testArchiveMutation() throws Exception { - Thread.sleep(5000); - JsonObject notificationRecording = createRecording(); + Thread.sleep(DELAY); + String recordingName = "test"; + JsonObject notificationRecording = createRecording(recordingName); Assertions.assertEquals("test", notificationRecording.getString("name")); Assertions.assertEquals("RUNNING", notificationRecording.getString("state")); @@ -323,9 +326,10 @@ void testArchiveMutation() throws Exception { @Test @Order(5) void testActiveRecordingMetadataMutation() throws Exception { - Thread.sleep(5000); - JsonObject notificationRecording = createRecording(); - Assertions.assertEquals("test", notificationRecording.getString("name")); + Thread.sleep(DELAY); + String recordingName = "test"; + JsonObject notificationRecording = createRecording(recordingName); + Assertions.assertEquals(recordingName, notificationRecording.getString("name")); JsonObject variables = new JsonObject(); JsonArray labels = new JsonArray(); @@ -387,7 +391,8 @@ void testActiveRecordingMetadataMutation() throws Exception { @Test @Order(6) void testArchivedRecordingMetadataMutation() throws Exception { - Thread.sleep(5000); + Thread.sleep(DELAY); + String recordingName = "test"; // Create a Recording JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); @@ -480,7 +485,8 @@ void testArchivedRecordingMetadataMutation() throws Exception { @Order(7) void testDeleteMutation() throws Exception { // this will delete all Active and Archived recordings that match the filter input. - Thread.sleep(5000); + Thread.sleep(DELAY); + String recordingName = "test"; // Create a Recording JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); @@ -638,7 +644,8 @@ void testQueryForSpecificTargetsByNames() throws Exception { @Test @Order(10) public void testQueryForFilteredActiveRecordingsByNames() throws Exception { - Thread.sleep(5000); + Thread.sleep(DELAY); + String recordingName1 = "test"; // Create a Recording 1 name (test) JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); @@ -669,7 +676,7 @@ public void testQueryForFilteredActiveRecordingsByNames() throws Exception { } }); - Thread.sleep(5000); + Thread.sleep(DELAY); HttpResponse resp = webClient @@ -753,9 +760,10 @@ public void shouldReturnArchivedRecordingsFilteredByNames() throws Exception { Assertions.assertTrue(listResp.isEmpty()); // Create a new recording - Thread.sleep(5000); - JsonObject notificationRecording = createRecording(); - Assertions.assertEquals("test", notificationRecording.getString("name")); + Thread.sleep(DELAY); + String recordingName = "test"; + JsonObject notificationRecording = createRecording(recordingName); + Assertions.assertEquals(recordingName, notificationRecording.getString("name")); // Archive the recording JsonObject query1 = new JsonObject(); @@ -2682,7 +2690,7 @@ private JsonObject createRecording() throws Exception { } }); - Thread.sleep(5000); + Thread.sleep(DELAY); HttpResponse resp = webClient @@ -2722,7 +2730,7 @@ private JsonObject stopRecording() throws Exception { } }); - Thread.sleep(5000); + Thread.sleep(DELAY); HttpResponse resp = webClient @@ -2781,7 +2789,7 @@ private JsonObject restartRecording(String replace) throws Exception { } }); - Thread.sleep(5000); + Thread.sleep(DELAY); HttpResponse resp = webClient @@ -2806,8 +2814,8 @@ private JsonObject restartRecordingWithError(String replace) throws Exception { + " { name target { doStartRecording ( recording: { name: \"test\"," + " template: \"Profiling\", templateType: \"TARGET\", replace: \"%s\"" + " }) { name state } } } }", - replace)); - Thread.sleep(5000); + name, replace)); + Thread.sleep(DELAY); HttpResponse resp = webClient .extensions() From 0a5d598cb4c79f987b82fb10df149b2bc786abb2 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Wed, 14 Aug 2024 11:53:11 -0400 Subject: [PATCH 2/7] build(deps): replace direct fabric8 kubernetes-client with quarkus kubernetes-client (#606) --- pom.xml | 36 +++++++++---------- .../cryostat/discovery/KubeApiDiscovery.java | 20 +++-------- 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/pom.xml b/pom.xml index 50848cf08..5c032b73b 100644 --- a/pom.xml +++ b/pom.xml @@ -65,8 +65,7 @@ 4.5 3.2.5 2 - 3.2.5 - 6.7.2 + 3.3.1 ${surefire.rerunFailingTestsCount} @@ -183,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 @@ -199,6 +210,10 @@ io.quarkiverse.amazonservices quarkus-amazon-s3 + + io.quarkus + quarkus-kubernetes-client + software.amazon.awssdk url-connection-client @@ -245,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 diff --git a/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java b/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java index a98ff35af..98f21f417 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(), @@ -188,16 +190,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()); @@ -469,7 +461,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( @@ -549,10 +541,6 @@ String getOwnNamespace() { boolean kubeApiAvailable() { return StringUtils.isNotBlank(serviceHost.orElse("")); } - - KubernetesClient kubeClient() throws ConcurrentException { - return kubeClient.get(); - } } private final class EndpointsHandler implements ResourceEventHandler { From 158ac8fa3fa2ea9f1a17784490e56c25d603d54a Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Tue, 8 Oct 2024 16:10:08 -0400 Subject: [PATCH 3/7] compose fixup --- compose/auth_proxy.yml | 2 +- compose/sample_apps/vertx-cryostat-agent.yml | 133 ------------------- 2 files changed, 1 insertion(+), 134 deletions(-) delete mode 100644 compose/sample_apps/vertx-cryostat-agent.yml diff --git a/compose/auth_proxy.yml b/compose/auth_proxy.yml index bf1bc757f..6724ecdc0 100644 --- a/compose/auth_proxy.yml +++ b/compose/auth_proxy.yml @@ -50,7 +50,7 @@ services: # OAUTH2_PROXY_SKIP_AUTH_ROUTES: .* restart: unless-stopped healthcheck: - test: wget --no-check-certificate -q --spider ${CRYOSTAT_PROXY_PROTOCOL}://localhost:${CRYOSTAT_PROXY_PORT}/ping || exit 1 + test: wget --no-check-certificate -q --spider http://localhost:8080/ping || exit 1 interval: 10s retries: 3 start_period: 10s diff --git a/compose/sample_apps/vertx-cryostat-agent.yml b/compose/sample_apps/vertx-cryostat-agent.yml deleted file mode 100644 index cdcdf6179..000000000 --- a/compose/sample_apps/vertx-cryostat-agent.yml +++ /dev/null @@ -1,133 +0,0 @@ -version: "3" -services: - vertx-agent-1: - depends_on: - cryostat: - condition: service_healthy - image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} - hostname: vertx-cryostat-agent-1 - environment: - HTTP_PORT: 8081 - JMX_PORT: 9093 - USE_JDP: "true" - CRYOSTAT_AGENT_APP_NAME: vertx-cryostat-agent-1 - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUST_ALL: "true" - CRYOSTAT_AGENT_WEBCLIENT_TLS_VERIFY_HOSTNAME: "false" - CRYOSTAT_AGENT_WEBSERVER_HOST: "vertx-agent-1" - CRYOSTAT_AGENT_WEBSERVER_PORT: "8910" - CRYOSTAT_AGENT_CALLBACK: "http://vertx-agent-1:8910/" - CRYOSTAT_AGENT_BASEURI: "${CRYOSTAT_PROXY_PROTOCOL}://${CRYOSTAT_HTTP_HOST}:${CRYOSTAT_PROXY_PORT}/" - CRYOSTAT_AGENT_BASEURI_RANGE: public - CRYOSTAT_AGENT_TRUST_ALL: "true" - CRYOSTAT_AGENT_AUTHORIZATION_TYPE: basic - CRYOSTAT_AGENT_AUTHORIZATION_VALUE: user:pass - ports: - - "8081:8081" - expose: - - "8910" - restart: always - healthcheck: - test: curl --fail http://localhost:8081 || exit 1 - interval: 10s - retries: 3 - start_period: 30s - timeout: 5s - - vertx-agent-2: - depends_on: - cryostat: - condition: service_healthy - image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} - hostname: vertx-cryostat-agent-2 - environment: - HTTP_PORT: 8082 - JMX_PORT: 9094 - USE_JDP: "true" - USE_AUTH: "true" - CRYOSTAT_AGENT_APP_NAME: "vertx-cryostat-agent-2" - CRYOSTAT_AGENT_WEBSERVER_HOST: "vertx-agent-2" - CRYOSTAT_AGENT_WEBSERVER_PORT: "8911" - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_PATH: /auth_certs/certificate.pem - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_TYPE: X.509 - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_ALIAS: cryostat - CRYOSTAT_AGENT_CALLBACK: "http://vertx-agent-2:8911/" - CRYOSTAT_AGENT_API_WRITES_ENABLED: "true" - CRYOSTAT_AGENT_BASEURI: "${CRYOSTAT_PROXY_PROTOCOL}://${CRYOSTAT_HTTP_HOST}:${CRYOSTAT_PROXY_PORT}/" - CRYOSTAT_AGENT_BASEURI_RANGE: public - CRYOSTAT_AGENT_TRUST_ALL: "true" - CRYOSTAT_AGENT_AUTHORIZATION_TYPE: basic - CRYOSTAT_AGENT_AUTHORIZATION_VALUE: user:pass - ports: - - "8082:8082" - expose: - - "8911" - restart: always - healthcheck: - test: curl --fail http://localhost:8082 || exit 1 - interval: 10s - retries: 3 - start_period: 30s - timeout: 5s - volumes: - - ${DIR}/compose/auth_certs:/auth_certs:z - - vertx-agent-3: - depends_on: - cryostat: - condition: service_healthy - image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} - hostname: vertx-cryostat-agent-3 - environment: - HTTP_PORT: 8083 - JMX_PORT: 9095 - USE_JDP: "true" - USE_AUTH: "true" - USE_SSL: "true" - CRYOSTAT_AGENT_APP_NAME: "vertx-cryostat-agent-3" - CRYOSTAT_AGENT_WEBSERVER_HOST: "vertx-agent-3" - CRYOSTAT_AGENT_WEBSERVER_PORT: "8912" - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_PATH: /auth_certs/certificate.pem - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_TYPE: X.509 - CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERT[0]_ALIAS: cryostat - CRYOSTAT_AGENT_CALLBACK: "http://vertx-agent-3:8912/" - CRYOSTAT_AGENT_API_WRITES_ENABLED: "true" - CRYOSTAT_AGENT_BASEURI: "${CRYOSTAT_PROXY_PROTOCOL}://${CRYOSTAT_HTTP_HOST}:${CRYOSTAT_PROXY_PORT}/" - CRYOSTAT_AGENT_BASEURI_RANGE: public - CRYOSTAT_AGENT_TRUST_ALL: "true" - CRYOSTAT_AGENT_AUTHORIZATION_TYPE: basic - CRYOSTAT_AGENT_AUTHORIZATION_VALUE: user:pass - ports: - - "8083:8083" - expose: - - "8912" - restart: always - healthcheck: - test: curl --fail http://localhost:8083 || exit 1 - interval: 10s - retries: 3 - start_period: 30s - timeout: 5s - volumes: - - ${DIR}/compose/auth_certs:/auth_certs:z - - vertx-agent-4: - depends_on: - cryostat: - condition: service_healthy - image: ${VERTX_FIB_DEMO_IMAGE:-quay.io/redhat-java-monitoring/vertx-cryostat-agent:latest} - hostname: vertx-cryostat-agent-4 - environment: - HTTP_PORT: 8084 - JMX_PORT: 9096 - USE_JDP: "true" - USE_AUTH: "false" - USE_SSL: "false" - ports: - - "8084:8084" - restart: always - healthcheck: - test: curl --fail http://localhost:8084 || exit 1 - interval: 10s - retries: 3 - start_period: 30s - timeout: 5s From 22f904ee10269a11b0f74e2dff324b5752de30a9 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Tue, 8 Oct 2024 16:10:20 -0400 Subject: [PATCH 4/7] graphql test fixup --- src/test/java/itest/GraphQLTest.java | 44 ++++++++++++---------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/test/java/itest/GraphQLTest.java b/src/test/java/itest/GraphQLTest.java index 88416b560..4acfab581 100644 --- a/src/test/java/itest/GraphQLTest.java +++ b/src/test/java/itest/GraphQLTest.java @@ -70,8 +70,6 @@ class GraphQLTest extends StandardSelfTest { private final ExecutorService worker = ForkJoinPool.commonPool(); - static final long DELAY = 5_000L; - static final String TEST_RECORDING_NAME = "archivedRecording"; @Test @@ -229,7 +227,7 @@ void testStartRecordingMutationOnSpecificTarget() throws Exception { } }); - Thread.sleep(DELAY); + Thread.sleep(5000); HttpResponse resp = webClient @@ -286,9 +284,8 @@ void testStartRecordingMutationOnSpecificTarget() throws Exception { @Test @Order(4) void testArchiveMutation() throws Exception { - Thread.sleep(DELAY); - String recordingName = "test"; - JsonObject notificationRecording = createRecording(recordingName); + Thread.sleep(5000); + JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); Assertions.assertEquals("RUNNING", notificationRecording.getString("state")); @@ -326,10 +323,9 @@ void testArchiveMutation() throws Exception { @Test @Order(5) void testActiveRecordingMetadataMutation() throws Exception { - Thread.sleep(DELAY); - String recordingName = "test"; - JsonObject notificationRecording = createRecording(recordingName); - Assertions.assertEquals(recordingName, notificationRecording.getString("name")); + Thread.sleep(5000); + JsonObject notificationRecording = createRecording(); + Assertions.assertEquals("test", notificationRecording.getString("name")); JsonObject variables = new JsonObject(); JsonArray labels = new JsonArray(); @@ -391,8 +387,7 @@ void testActiveRecordingMetadataMutation() throws Exception { @Test @Order(6) void testArchivedRecordingMetadataMutation() throws Exception { - Thread.sleep(DELAY); - String recordingName = "test"; + Thread.sleep(5000); // Create a Recording JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); @@ -485,8 +480,7 @@ void testArchivedRecordingMetadataMutation() throws Exception { @Order(7) void testDeleteMutation() throws Exception { // this will delete all Active and Archived recordings that match the filter input. - Thread.sleep(DELAY); - String recordingName = "test"; + Thread.sleep(5000); // Create a Recording JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); @@ -644,8 +638,7 @@ void testQueryForSpecificTargetsByNames() throws Exception { @Test @Order(10) public void testQueryForFilteredActiveRecordingsByNames() throws Exception { - Thread.sleep(DELAY); - String recordingName1 = "test"; + Thread.sleep(5000); // Create a Recording 1 name (test) JsonObject notificationRecording = createRecording(); Assertions.assertEquals("test", notificationRecording.getString("name")); @@ -676,7 +669,7 @@ public void testQueryForFilteredActiveRecordingsByNames() throws Exception { } }); - Thread.sleep(DELAY); + Thread.sleep(5000); HttpResponse resp = webClient @@ -760,10 +753,9 @@ public void shouldReturnArchivedRecordingsFilteredByNames() throws Exception { Assertions.assertTrue(listResp.isEmpty()); // Create a new recording - Thread.sleep(DELAY); - String recordingName = "test"; - JsonObject notificationRecording = createRecording(recordingName); - Assertions.assertEquals(recordingName, notificationRecording.getString("name")); + Thread.sleep(5000); + JsonObject notificationRecording = createRecording(); + Assertions.assertEquals("test", notificationRecording.getString("name")); // Archive the recording JsonObject query1 = new JsonObject(); @@ -2690,7 +2682,7 @@ private JsonObject createRecording() throws Exception { } }); - Thread.sleep(DELAY); + Thread.sleep(5000); HttpResponse resp = webClient @@ -2730,7 +2722,7 @@ private JsonObject stopRecording() throws Exception { } }); - Thread.sleep(DELAY); + Thread.sleep(5000); HttpResponse resp = webClient @@ -2789,7 +2781,7 @@ private JsonObject restartRecording(String replace) throws Exception { } }); - Thread.sleep(DELAY); + Thread.sleep(5000); HttpResponse resp = webClient @@ -2814,8 +2806,8 @@ private JsonObject restartRecordingWithError(String replace) throws Exception { + " { name target { doStartRecording ( recording: { name: \"test\"," + " template: \"Profiling\", templateType: \"TARGET\", replace: \"%s\"" + " }) { name state } } } }", - name, replace)); - Thread.sleep(DELAY); + replace)); + Thread.sleep(5000); HttpResponse resp = webClient .extensions() From 59bb1d41b0257833aecf4ade1b049288f0af2bcc Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Tue, 8 Oct 2024 16:17:52 -0400 Subject: [PATCH 5/7] auth proxy fixup --- compose/auth_proxy.yml | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/compose/auth_proxy.yml b/compose/auth_proxy.yml index 6724ecdc0..c656cc2f1 100644 --- a/compose/auth_proxy.yml +++ b/compose/auth_proxy.yml @@ -5,20 +5,14 @@ services: - "${CRYOSTAT_HTTP_PORT}" environment: CRYOSTAT_HTTP_PROXY_HOST: auth - CRYOSTAT_HTTP_PROXY_PORT: "${CRYOSTAT_HTTP_PORT}" - QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDING: "true" - QUARKUS_HTTP_PROXY_ALLOW_X_FORWARDED: "true" - QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_HOST: "true" - QUARKUS_HTTP_PROXY_ENABLE_FORWARDED_PREFIX: "true" + CRYOSTAT_HTTP_PROXY_PORT: '8080' + QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDING: 'true' + QUARKUS_HTTP_PROXY_ALLOW_X_FORWARDED: 'true' + 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} QUARKUS_HTTP_ACCESS_LOG_PATTERN: long - QUARKUS_HTTP_ACCESS_LOG_ENABLED: "true" - healthcheck: - test: curl --fail http://cryostat:8181/health/liveness || exit 1 - interval: 10s - retries: 3 - start_period: 30s - timeout: 5s + 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 @@ -33,8 +27,7 @@ services: cpus: '0.1' memory: 32m image: ${OAUTH2_PROXY_IMAGE:-quay.io/oauth2-proxy/oauth2-proxy:latest-alpine} - command: - - --alpha-config=/tmp/auth_proxy_alpha_config.yml + command: --alpha-config=/tmp/auth_proxy_alpha_config.yaml volumes: - auth_proxy_cfg:/tmp hostname: auth From a4fdd2a9315f15d35c763f1f404ae58366498839 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Tue, 8 Oct 2024 16:23:03 -0400 Subject: [PATCH 6/7] startup discovery transactions --- .../discovery/ContainerDiscovery.java | 36 +++++++++------ .../cryostat/discovery/CustomDiscovery.java | 30 +++++++----- .../java/io/cryostat/discovery/Discovery.java | 1 + .../io/cryostat/discovery/JDPDiscovery.java | 46 +++++++++++-------- .../cryostat/discovery/KubeApiDiscovery.java | 31 +++++++------ 5 files changed, 87 insertions(+), 57 deletions(-) diff --git a/src/main/java/io/cryostat/discovery/ContainerDiscovery.java b/src/main/java/io/cryostat/discovery/ContainerDiscovery.java index c75b51d74..35805723c 100644 --- a/src/main/java/io/cryostat/discovery/ContainerDiscovery.java +++ b/src/main/java/io/cryostat/discovery/ContainerDiscovery.java @@ -199,21 +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(); - } + 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(); + } - logger.debugv("Starting {0} client", getRealm()); - queryContainers(); - this.timerId = vertx.setPeriodic(pollPeriod.toMillis(), unused -> queryContainers()); + queryContainers(); + this.timerId = + vertx.setPeriodic( + pollPeriod.toMillis(), unused -> queryContainers()); + }); } void onStop(@Observes ShutdownEvent evt) { diff --git a/src/main/java/io/cryostat/discovery/CustomDiscovery.java b/src/main/java/io/cryostat/discovery/CustomDiscovery.java index 5ae776339..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}) diff --git a/src/main/java/io/cryostat/discovery/Discovery.java b/src/main/java/io/cryostat/discovery/Discovery.java index 7f3d4e819..773b2420d 100644 --- a/src/main/java/io/cryostat/discovery/Discovery.java +++ b/src/main/java/io/cryostat/discovery/Discovery.java @@ -113,6 +113,7 @@ void onStart(@Observes StartupEvent evt) { () -> { // ensure lazily initialized entries are created DiscoveryNode.getUniverse(); + logger.debugv("Initializing {0} onStart", getClass()); DiscoveryPlugin.findAll().list().stream() .filter(p -> !p.builtin) diff --git a/src/main/java/io/cryostat/discovery/JDPDiscovery.java b/src/main/java/io/cryostat/discovery/JDPDiscovery.java index 491bf8576..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; @@ -70,25 +71,32 @@ void onStart(@Observes 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.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) { diff --git a/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java b/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java index 98f21f417..0d1839c2d 100644 --- a/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java +++ b/src/main/java/io/cryostat/discovery/KubeApiDiscovery.java @@ -139,19 +139,24 @@ 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(); + } + }); } void onAfterStart(@Observes StartupEvent evt) { From d522ca09672dfbb8c72f08cf79cdb2e86f8b6a22 Mon Sep 17 00:00:00 2001 From: Cryostat CI Date: Tue, 8 Oct 2024 20:29:24 +0000 Subject: [PATCH 7/7] chore(schema): automatic update --- schema/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema/openapi.yaml b/schema/openapi.yaml index ebb047028..207ef131f 100644 --- a/schema/openapi.yaml +++ b/schema/openapi.yaml @@ -359,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}: