Closed kdubb closed 6 months ago
The see the generated APIs you need to checkout the PR and at least run mvn compile
. This should generate the APIs in the client/target/generated-sources/vault
directory.
@vsevel The client now implements all the secret
& auth engines that are currently supported by the current client. It also supports all the sys
apis supported/used by the client and a few extra. Additionally, all the implemented apis are complete up to Vault version 1.15; making many of the much more complete than previously.
The apis follow the documentation pretty close and methods are named after the documented title (e.g. sys/leases/lookup
is accessed via sys().leases().read(...)
because the doc title is "Read Lease"). All of them include complete testing and you can look at the ample tests to see how each api works.
I'm interested to see what changes are suggested for generated code before this is merged and the apis become somewhat "locked".
Here's the complete list of supported apis:
auth
approle
kubernetes
token
userpass
secrets
database
kv1
kv2
pki
rabbitmq
totp
transit
sys
auth
health
init
leases
mounts
plugins
policies
remount
seal
tools
wrapping
@vsevel We should probably do a beta release (e.g 3.5.0-beta
) that has nothing but the new client added to allow people to use it with easy access. Once we're happy with the apis and usage of the client. After that we can switch the Quarkus implementation to use the new client.
@kdubb How does this change affect the backward compatibility of the extension API? Will I have to update my code that uses the extension after updating the extension to the version with the new client?
@aaronz-vipaso Currently this PR is purely additive. It doesn't touch the extension in any fashion.
When integrating it we can choose to re-implement the current "engines" with the new client or we can choose to remove them and have people use the new client instead.
Personally, I'm in favor or doing a major release (e.g. 4.0) and removing the current engine implementations and having the extension use the new client to implement Quarkus specific features like static configuration, configuration sourcing, and dynamic credentials.
For most users this will not be a source breaking change as the most common use seems to be to provide configuration values and/or dynamic credentials, not to interact directly with Vault via APIs.
For those of us interacting with Vault directly, the current engines are very limited and statically configured (except those that have been updated to allow dynamic mounting). Switching to the new client should only be a positive change and should be fairly simple.
For example, previously you might inject the VaultPKIManagerFactory
to manage a PKI engine mount like so:
@Inject VaultPKIManagerFactory pkiFactory;
void issueCertFromMount(String pkiMount) {
var pki = pkiFactory.engine(pkiMount);
pki.issue(...);
}
// or using the Quarkus "configured" PKI mount
@Inject VaultPKIManager pki;
void issueCert() {
pki.issue(...);
}
With the new client the code would look like:
@Inject VaultClient client;
void issueCertFromMount(String pkiMount) {
client.secrets().pki(pkiMount).issue(...);
}
// or using a configured mount
@ConfigProperty("app.pki.mount") String pkiMount;
@Inject VaultCleint client;
void issueCert() {
client.secrets().pki(pkiMount).issue(...);
}
While this will be a source breaking change, having multiple methods to do something is a maintenance nightmare and the new client is simpler to use for these tasks, has a uniform api, and naturally supports dynamic usage.
@aaronz-vipaso I've completed this PR by replacing the extension's client with the standalone client, leaving in place all the current engines. It does remove all the "internal" classes, but as long as your code uses the public classes it shouldn't require any changes.
@vsevel My suggested plan for this is as follows.
3.5.0
based on this PR as it only alters (by removal) "internal" classes this shouldn't be a source breaking change.
3.6.0
with deprecation.4.0.0
, remove all deprecations.are they not using a similar approach? can't we use the same source?
I look at all the current methods in the Vault ecosystem for getting a good source for the api request/response types and always found two problems...
Underspecification. They don't specify response types; e.g. OpenAPI only gives you the request parameters and specifies the response as a freeform object. Additionally a lot of the request parameters are freeform and/or missing.
Java Centricity To make a "nice" Java API I made the generator support a lot of "Java" stuff (e.g. generics, nested types, etc.). Reading from other languages would not allow this without manually editing the generated YAML or other structures.
one approach could have been to complement their specification. you do not repeat everything, you just extend their specification. just like SB does for kotlin, adding metadata when needed. I am not advocating to change it now that you have done it. just one thing to keep in mind.
you just extend their specification
My thought after looking at everything was a one-shot copy to start you off (it generates a basic YAML in spec format) and the we customize it. This would make re-running it for updates problematic but it seemed like the way to go to ensure we don't end up with a non-native feeling Java client.
why did you have to move io.quarkus.vault.runtime.client.VaultClientException
?
The client couldn't depend on a Quarkus package to be standalone.
I tried your branch in dev mode. the app starts ok. upon restart it does:
#################### PRESSING S ####################
...
2024-02-14 09:21:12,894 INFO [io.quarkus] (Quarkus Main Thread) bank-quarkus 2.8.0-SNAPSHOT on JVM (powered by Quarkus 3.7.1) started in 35.849s. Listening on: http://localhost:8092
2024-02-14 09:21:12,899 INFO [io.quarkus] (Quarkus Main Thread) Profiles dev,basedev activated. Live Coding activated.
2024-02-14 09:21:12,903 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cache, cdi, config-yaml, confluent-registry-avro, hibernate-validator, ironjacamar, kafka-client, micrometer, narayana-jta, opentelemetry, rest-client-reactive, rest-client-reactive-jackson, resteasy-reactive, resteasy-reactive-jackson, scheduler, security, smallrye-context-propagation, smallrye-fault-tolerance, smallrye-health, smallrye-openapi, smallrye-reactive-messaging, smallrye-reactive-messaging-kafka, swagger-ui, vault, vertx]
...
null
java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:113)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: io.quarkus.runtime.configuration.ConfigurationException: Failed to read configuration properties
at io.quarkus.deployment.steps.RuntimeConfigSetup.deploy(Unknown Source)
... 13 more
2024-02-14 09:21:29,693 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:21:29,736 DEBUG [io.qua.vau.run.cli.MutinyVertxClientFactory] (Quarkus Main Thread) configure tls with ca-cert.pem
2024-02-14 09:21:29,742 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:21:29,743 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:21:29,744 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
...
2024-02-14 09:21:30,020 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:21:30,022 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:27:04,232 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:27:04,233 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 09:27:04,351 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (Aesh InputStream Reader) Failed to start quarkus [Error Occurred After Shutdown]: io.quarkus.dev.appstate.ApplicationStartException: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.dev.appstate.ApplicationStateNotification.waitForApplicationStart(ApplicationStateNotification.java:58)
at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:132)
at io.quarkus.deployment.dev.IsolatedDevModeMain.restartApp(IsolatedDevModeMain.java:192)
at io.quarkus.deployment.dev.IsolatedDevModeMain.restartCallback(IsolatedDevModeMain.java:173)
at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:541)
at io.quarkus.deployment.console.ConsoleStateManager.forceRestart(ConsoleStateManager.java:175)
at io.quarkus.deployment.console.ConsoleStateManager.lambda$installBuiltins$0(ConsoleStateManager.java:112)
at io.quarkus.deployment.console.ConsoleStateManager$1.accept(ConsoleStateManager.java:77)
at io.quarkus.deployment.console.ConsoleStateManager$1.accept(ConsoleStateManager.java:49)
at io.quarkus.deployment.console.AeshConsole.lambda$setup$1(AeshConsole.java:278)
at org.aesh.terminal.EventDecoder.accept(EventDecoder.java:118)
at org.aesh.terminal.EventDecoder.accept(EventDecoder.java:31)
at org.aesh.terminal.io.Decoder.write(Decoder.java:133)
at org.aesh.readline.tty.terminal.TerminalConnection.openBlocking(TerminalConnection.java:216)
at org.aesh.readline.tty.terminal.TerminalConnection.openBlocking(TerminalConnection.java:203)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Suppressed: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:161)
... 16 more
Caused by: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.ArcContainer.instance(java.lang.Class, java.lang.annotation.Annotation[])" because "container" is null
at io.quarkus.vault.runtime.config.VaultConfigSourceFactory.getConfigSources(VaultConfigSourceFactory.java:19)
at io.quarkus.vault.runtime.config.VaultConfigSourceFactory.getConfigSources(VaultConfigSourceFactory.java:14)
at io.smallrye.config.ConfigSourceFactory$ConfigurableConfigSourceFactory.getConfigSources(ConfigSourceFactory.java:58)
at io.smallrye.config.ConfigurableConfigSource.getConfigSources(ConfigurableConfigSource.java:50)
at io.smallrye.config.SmallRyeConfig$ConfigSources.mapLateSources(SmallRyeConfig.java:832)
at io.smallrye.config.SmallRyeConfig$ConfigSources.<init>(SmallRyeConfig.java:722)
at io.smallrye.config.SmallRyeConfig.<init>(SmallRyeConfig.java:83)
at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:724)
at io.quarkus.runtime.generated.Config.readConfig(Unknown Source)
at io.quarkus.runtime.generated.Config.createRunTimeConfig(Unknown Source)
... 21 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:113)
... 1 more
Caused by: io.quarkus.runtime.configuration.ConfigurationException: Failed to read configuration properties
at io.quarkus.deployment.steps.RuntimeConfigSetup.deploy(Unknown Source)
... 13 more
Caused by: java.util.concurrent.RejectedExecutionException
at org.jboss.threads.RejectingExecutor.execute(RejectingExecutor.java:38)
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2136)
at org.jboss.threads.EnhancedQueueExecutor$SchedulerTask.schedule(EnhancedQueueExecutor.java:3094)
at org.jboss.threads.EnhancedQueueExecutor.schedule(EnhancedQueueExecutor.java:936)
at io.smallrye.mutiny.operators.uni.UniFailOnTimeout$UniFailOnTimeoutProcessor.onSubscribe(UniFailOnTimeout.java:50)
at io.smallrye.mutiny.vertx.AsyncResultUni.subscribe(AsyncResultUni.java:27)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniFailOnTimeout.subscribe(UniFailOnTimeout.java:36)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnFailureTransform.subscribe(UniOnFailureTransform.java:31)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.quarkus.vault.client.Retry.subscribe(VaultClient.java:297)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:60)
at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:65)
at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:46)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:132)
at io.quarkus.vault.runtime.config.VaultConfigSource.lambda$fetchSecrets$2(VaultConfigSource.java:127)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSour:127)va
at io.quarkus.vault.runtime.config.VaultConfigSource.lambda$fetchSecrets$1(VaultConfigSource.java:123)
at java.base/java.util.HashMap.forEach(HashMap.java:1421)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:123)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecretsFirstTime(VaultConfigSource.java:103)
at io.quarkus.vault.runtime.config.VaultConfigSource.getSecretConfig(VaultConfigSource.java:81)
at io.quarkus.vault.runtime.config.VaultConfigSource.getValue(VaultConfigSource.java:62)
at io.smallrye.config.ConfigValueConfigSourceWrapper.getConfigValue(ConfigValueConfigSourceWrapper.java:20)
at io.smallrye.config.SmallRyeConfigSources.getValue(SmallRyeConfigSources.java:29)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SecretKeysConfigSourceInterceptor.getValue(SecretKeysConfigSourceInterceptor.java:26)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.ProfileConfigSourceInterceptor.getProfileValue(ProfileConfigSourceInterceptor.java:51)
at io.smallrye.config.ProfileConfigSourceInterceptor.getValue(ProfileConfigSourceInterceptor.java:36)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.LoggingConfigSourceInterceptor.getValue(LoggingConfigSourceInterceptor.java:22)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.quarkus.smallrye.openapi.runtime.OpenApiConfigMapping.getValue(OpenApiConfigMapping.java:30)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.quarkus.smallrye.openapi.runtime.OpenApiConfigMapping.getValue(OpenApiConfigMapping.java:30)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.ExpressionConfigSourceInterceptor.getValue(ExpressionConfigSourceInterceptor.java:43)
at io.smallrye.config.ExpressionConfigSourceInterceptor.getValue(ExpressionConfigSourceInterceptor.java:35)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.quarkus.opentelemetry.runtime.config.OTelFallbackConfigSourceInterceptor.getValue(OTelFallbackConfigSourceInterceptor.java:44)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SecretKeysHandlerConfigSourceInterceptor.getValue(SecretKeysHandlerConfigSourceInterceptor.java:26)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SmallRyeConfig.getConfigValue(SmallRyeConfig.java:382)
at io.smallrye.config.SmallRyeConfig.getValue(SmallRyeConfig.java:289)
at io.smallrye.config.SmallRyeConfig.getOptionalValue(SmallRyeConfig.java:399)
at io.smallrye.config.ConfigMappingProvider.mapConfiguration(ConfigMappingProvider.java:67)
at io.smallrye.config.SmallRyeConfig.<init>(SmallRyeConfig.java:86)
at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:724)
at io.quarkus.runtime.generated.Config.readConfig(Unknown Source)
at io.quarkus.runtime.generated.Config.createRunTimeConfig(Unknown Source)
... 14 more
Suppressed: java.util.concurrent.RejectedExecutionException: Executor is being shut down
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2138)
... 96 more
2024-02-14 09:27:05,878 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Aesh InputStream Reader) Live reload total time: 6.027s
2024-02-14 09:27:05,899 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Aesh InputStream Reader) Live reload took more than 4 seconds, you may want to enable instrumentation based reload (quarkus.live-reload.instrumentation=true). This allows small changes to take effect without restarting Quarkus.
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.quarkus.vault.client.Retry.subscribe(VaultClient.java:297)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:60)
at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:65)
at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:46)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:132)
at io.quarkus.vault.runtime.config.VaultConfigSource.lambda$fetchSecrets$2(VaultConfigSource.java:127)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:127)
at io.quarkus.vault.runtime.config.VaultConfigSource.lambda$fetchSecrets$1(VaultConfigSource.java:123)
at java.base/java.util.HashMap.forEach(HashMap.java:1421)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:123)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecretsFirstTime(VaultConfigSource.java:103)
at io.quarkus.vault.runtime.config.VaultConfigSource.getSecretConfig(VaultConfigSource.java:81)
at io.quarkus.vault.runtime.config.VaultConfigSource.getValue(VaultConfigSource.java:62)
at io.smallrye.config.ConfigValueConfigSourceWrapper.getConfigValue(ConfigValueConfigSourceWrapper.java:20)
at io.smallrye.config.SmallRyeConfigSources.getValue(SmallRyeConfigSources.java:29)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SecretKeysConfigSourceInterceptor.getValue(SecretKeysConfigSourceInterceptor.java:26)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.ProfileConfigSourceInterceptor.getProfileValue(ProfileConfigSourceInterceptor.java:51)
at io.smallrye.config.ProfileConfigSourceInterceptor.getValue(ProfileConfigSourceInterceptor.java:36)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.LoggingConfigSourceInterceptor.getValue(LoggingConfigSourceInterceptor.java:22)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.quarkus.smallrye.openapi.runtime.OpenApiConfigMapping.getValue(OpenApiConfigMapping.java:30)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.quarkus.smallrye.openapi.runtime.OpenApiConfigMapping.getValue(OpenApiConfigMapping.java:30)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.ExpressionConfigSourceInterceptor.getValue(ExpressionConfigSourceInterceptor.java:43)
at io.smallrye.config.ExpressionConfigSourceInterceptor.getValue(ExpressionConfigSourceInterceptor.java:35)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.quarkus.opentelemetry.runtime.config.OTelFallbackConfigSourceInterceptor.getValue(OTelFallbackConfigSourceInterceptor.java:44)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SecretKeysHandlerConfigSourceInterceptor.getValue(SecretKeysHandlerConfigSourceInterceptor.java:26)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SmallRyeConfig.getConfigValue(SmallRyeConfig.java:382)
at io.smallrye.config.SmallRyeConfig.getValue(SmallRyeConfig.java:289)
at io.smallrye.config.SmallRyeConfig.getOptionalValue(SmallRyeConfig.java:399)
at io.smallrye.config.ConfigMappingProvider.mapConfiguration(ConfigMappingProvider.java:67)
at io.smallrye.config.SmallRyeConfig.<init>(SmallRyeConfig.java:86)
at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:724)
at io.quarkus.runtime.generated.Config.readConfig(Unknown Source)
at io.quarkus.runtime.generated.Config.createRunTimeConfig(Unknown Source)
... 14 more
Suppressed: java.util.concurrent.RejectedExecutionException: Executor is being shut down
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2138)
... 96 more
Does this happen with our current release? This is code I never changed; not that it can't be related.
@vsevel I switched to using the JDK client for configuration requests (anything that injects a client with the @Private
qualifier). I copied your SSL code but reused the X509Parsing
(in the PKI package) for parsing PEM.
I have not tested dev mode yet.
Does this happen with our current release? This is code I never changed; not that it can't be related.
your branch and 3.7.1
I have not tested dev mode yet.
let me rebuild and try out
same issue that I reported here: https://github.com/quarkiverse/quarkus-vault/issues/226
2024-02-14 15:25:18,290 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 15:25:18,293 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 15:25:18,295 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 15:25:18,295 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
2024-02-14 15:25:18,414 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (Aesh InputStream Reader) Failed to start quarkus [Error Occurred After Shutdown]: io.quarkus.dev.appstate.ApplicationStartException: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.dev.appstate.ApplicationStateNotification.waitForApplicationStart(ApplicationStateNotification.java:58)
at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:132)
at io.quarkus.deployment.dev.IsolatedDevModeMain.restartApp(IsolatedDevModeMain.java:192)
at io.quarkus.deployment.dev.IsolatedDevModeMain.restartCallback(IsolatedDevModeMain.java:173)
at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:541)
at io.quarkus.deployment.console.ConsoleStateManager.forceRestart(ConsoleStateManager.java:175)
at io.quarkus.deployment.console.ConsoleStateManager.lambda$installBuiltins$0(ConsoleStateManager.java:112)
at io.quarkus.deployment.console.ConsoleStateManager$1.accept(ConsoleStateManager.java:77)
at io.quarkus.deployment.console.ConsoleStateManager$1.accept(ConsoleStateManager.java:49)
at io.quarkus.deployment.console.AeshConsole.lambda$setup$1(AeshConsole.java:278)
at org.aesh.terminal.EventDecoder.accept(EventDecoder.java:118)
at org.aesh.terminal.EventDecoder.accept(EventDecoder.java:31)
at org.aesh.terminal.io.Decoder.write(Decoder.java:133)
at org.aesh.readline.tty.terminal.TerminalConnection.openBlocking(TerminalConnection.java:216)
at org.aesh.readline.tty.terminal.TerminalConnection.openBlocking(TerminalConnection.java:203)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Suppressed: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:161)
... 16 more
Caused by: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.ArcContainer.instance(java.lang.Class, java.lang.annotation.Annotation[])" because "container" is null
at io.quarkus.vault.runtime.config.VaultConfigSourceFactory.getConfigSources(VaultConfigSourceFactory.java:19)
at io.quarkus.vault.runtime.config.VaultConfigSourceFactory.getConfigSources(VaultConfigSourceFactory.java:14)
at io.smallrye.config.ConfigSourceFactory$ConfigurableConfigSourceFactory.getConfigSources(ConfigSourceFactory.java:58)
at io.smallrye.config.ConfigurableConfigSource.getConfigSources(ConfigurableConfigSource.java:50)
at io.smallrye.config.SmallRyeConfig$ConfigSources.mapLateSources(SmallRyeConfig.java:832)
at io.smallrye.config.SmallRyeConfig$ConfigSources.<init>(SmallRyeConfig.java:722)
at io.smallrye.config.SmallRyeConfig.<init>(SmallRyeConfig.java:83)
at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:724)
at io.quarkus.runtime.generated.Config.readConfig(Unknown Source)
at io.quarkus.runtime.generated.Config.createRunTimeConfig(Unknown Source)
... 21 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:113)
... 1 more
Caused by: io.quarkus.runtime.configuration.ConfigurationException: Failed to read configuration properties
at io.quarkus.deployment.steps.RuntimeConfigSetup.deploy(Unknown Source)
... 13 more
Caused by: java.util.concurrent.RejectedExecutionException
at org.jboss.threads.RejectingExecutor.execute(RejectingExecutor.java:38)
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2136)
at org.jboss.threads.EnhancedQueueExecutor$SchedulerTask.schedule(EnhancedQueueExecutor.java:3094)
at org.jboss.threads.EnhancedQueueExecutor.schedule(EnhancedQueueExecutor.java:936)
at io.smallrye.mutiny.operators.uni.UniFailOnTimeout$UniFailOnTimeoutProcessor.onSubscribe(UniFailOnTimeout.java:50)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage$CompletionStageUniSubscription.forward(UniCreateFromCompletionStage.java:50)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromCompletionStage.subscribe(UniCreateFromCompletionStage.java:35)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniFailOnTimeout.subscribe(UniFailOnTimeout.java:36)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
at io.smallrye.mutiny.operatorsctUni.subscribe(AbstractUni.java:36)
at io.quarkus.vault.client.Retry.subscribe(VaultClient.java:297)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:60)
at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:65)
at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:46)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:141)
at io.quarkus.vault.runtime.config.VaultConfigSource.lambda$fetchSecrets$2(VaultConfigSource.java:136)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:136)
at io.quarkus.vault.runtime.config.VaultConfigSource.lambda$fetchSecrets$1(VaultConfigSource.java:132)
at java.base/java.util.HashMap.forEach(HashMap.java:1421)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecrets(VaultConfigSource.java:132)
at io.quarkus.vault.runtime.config.VaultConfigSource.fetchSecretsFirstTime(VaultConfigSource.java:105)
at io.quarkus.vault.runtime.config.VaultConfigSource.getSecretConfig(VaultConfigSource.java:83)
at io.quarkus.vault.runtime.config.VaultConfigSource.getValue(VaultConfigSource.java:64)
at io.smallrye.config.ConfigValueConfigSourceWrapper.getConfigValue(ConfigValueConfigSourceWrapper.java:20)
at io.smallrye.config.SmallRyeConfigSources.getValue(SmallRyeConfigSources.java:29)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SecretKeysConfigSourceInterceptor.getValue(SecretKeysConfigSourceInterceptor.java:26)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.ProfileConfigSourceInterceptor.getProfileValue(ProfileConfigSourceInterceptor.java:51)
at io.smallrye.config.ProfileConfigSourceInterceptor.getValue(ProfileConfigSourceInterceptor.java:36)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.LoggingConfigSourceInterceptor.getValue(LoggingConfigSourceInterceptor.java:22)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.quarkus.smallrye.openapi.runtime.OpenApiConfigMapping.getValue(OpenApiConfigMapping.java:30)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.RelocateConfigSourceInterceptor.getValue(RelocateConfigSourceInterceptor.java:25)
at io.quarkus.smallrye.openapi.runtime.OpenApiConfigMapping.getValue(OpenApiConfigMapping.java:30)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.ExpressionConfigSourceInterceptor.getValue(ExpressionConfigSourceInterceptor.java:43)
at io.smallrye.config.ExpressionConfigSourceInterceptor.getValue(ExpressionConfigSourceInterceptor.java:35)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.quarkus.opentelemetry.runtime.config.OTelFallbackConfigSourceInterceptor.getValue(OTelFallbackConfigSourceInterceptor.java:44)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SecretKeysHandlerConfigSourceInterceptor.getValue(SecretKeysHandlerConfigSourceInterceptor.java:26)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.FallbackConfigSourceInterceptor.getValue(FallbackConfigSourceInterceptor.java:24)
at io.smallrye.config.SmallRyeConfigSourceInterceptorContext.proceed(SmallRyeConfigSourceInterceptorContext.java:20)
at io.smallrye.config.SmallRyeConfig.getConfigValue(SmallRyeConfig.java:382)
at io.smallrye.config.SmallRyeConfig.getValue(SmallRyeConfig.java:289)
at io.smallrye.config.SmallRyeConfig.getOptionalValue(SmallRyeConfig.java:399)
at io.smallrye.config.ConfigMappingProvider.mapConfiguration(ConfigMappingProvider.java:67)
at io.smallrye.config.SmallRyeConfig.<init>(SmallRyeConfig.java:86)
at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:724)
at io.quarkus.runtime.generated.Config.readConfig(Unknown Source)
at io.quarkus.runtime.generated.Config.createRunTimeConfig(Unknown Source)
... 14 more
Suppressed: java.util.concurrent.RejectedExecutionException: Executor is being shut down
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2138)
... 105 more
2024-02-14 15:25:20,582 INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Aesh InputStream Reader) Live reload total time: 8.012s
looking more closely at the exceptions, I can see first:
Caused by: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.ArcContainer.instance(java.lang.Class, java.lang.annotation.Annotation[])" because "container" is null
at io.quarkus.vault.runtime.config.VaultConfigSourceFactory.getConfigSources(VaultConfigSourceFactory.java:19)
at io.quarkus.vault.runtime.config.VaultConfigSourceFactory.getConfigSources(VaultConfigSourceFactory.java:14)
and after:
Suppressed: java.util.concurrent.RejectedExecutionException: Executor is being shut down
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2138)
... 105 more
it might be that the first exception is causing the next one: the second one happens because we are running: UniFailOnTimeout$UniFailOnTimeoutProcessor.onSubscribe(UniFailOnTimeout.java:50)
, which is probably caused by the other problem.
I tried some defensive code in VaultConfigSourceFactory.getConfigSources()
. I do not see the NPE anymore, but I am still getting the:
Caused by: io.quarkus.runtime.configuration.ConfigurationException: Failed to read configuration properties
at io.quarkus.deployment.steps.RuntimeConfigSetup.deploy(Unknown Source)
... 13 more
Caused by: java.util.concurrent.RejectedExecutionException
at org.jboss.threads.RejectingExecutor.execute(RejectingExecutor.java:38)
...
at io.smallrye.config.SmallRyeConfig.getOptionalValue(SmallRyeConfig.java:399)
at io.smallrye.config.ConfigMappingProvider.mapConfiguration(ConfigMappingProvider.java:67)
at io.smallrye.config.SmallRyeConfig.<init>(SmallRyeConfig.java:86)
at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:724)
at io.quarkus.runtime.generated.Config.readConfig(Unknown Source)
at io.quarkus.runtime.generated.Config.createRunTimeConfig(Unknown Source)
... 14 more
Suppressed: java.util.concurrent.RejectedExecutionException: Executor is being shut down
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2138)
... 105 more
I think the issue is that down below the JDKVaultHttpClient
is using the vertx infrastructure.
that is a difference with my implementation, which does not use Uni
.
https://github.com/quarkiverse/quarkus-vault/pull/235#issuecomment-1942548216
could you me point me toward the code where you have to honors the different vertx options?
my understanding is that we only have to support quarkus.vault.proxy-host
, quarkus.vault.proxy-port
and quarkus.vault.non-proxy-hosts
.
Configure the proxy as well as possible using the available Vert.x settings
this would be my feeling. if you are using the vertx client, you have more options. once you point me at the code I may be able to understand better.
I tried also running the fetch secret on a custom executor service:
private Map<String, String> fetchSecrets(String path, String prefix) {
System.out.println("=======> FETCH SECRETS RUNNING ON CUSTOM EXECUTOR SERVICE");
ExecutorService executorService = Executors.newFixedThreadPool(1);
Map<String, Object> secretJson = getVaultKVSecretEngine().readSecretJson(path)
.runSubscriptionOn(executorService)
.await().indefinitely();
but that does not resolve the issue:
2024-02-15 08:59:31,335 DEBUG [io.qua.vau.run.con.VaultConfigSource] (Quarkus Main Thread) fetch secrets first time with attempts = 3
=======> FETCH SECRETS RUNNING ON CUSTOM EXECUTOR SERVICE
null
java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:113)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: io.quarkus.runtime.configuration.ConfigurationException: Failed to read configuration properties
at io.quarkus.deployment.steps.RuntimeConfigSetup.deploy(Unknown Source)
... 13 more
Caused by: java.util.concurrent.RejectedExecutionException
at org.jboss.threads.RejectingExecutor.execute(RejectingExecutor.java:38)
at org.jboss.threads.EnhancedQueueExecutor.rejectShutdown(EnhancedQueueExecutor.java:2136)
at org.jboss.threads.EnhancedQueueExecutor$SchedulerTask.schedule(EnhancedQueueExecutor.java:3094)
at org.jboss.threads.EnhancedQueueExecutor.schedule(EnhancedQueueExecutor.java:936)
could you me point me toward the code where you have to honors the different vertx options? my understanding is that we only have to support quarkus.vault.proxy-host, quarkus.vault.proxy-port and quarkus.vault.non-proxy-hosts.
Code is in io.quarkus.vault.runtime.client.JDKClientFactory
. The only option not easily configurable is apparently quarkus.vault.non-proxy-hosts
(much like your code).
@vsevel I added support for non-proxy hosts; seems to not be a huge deal. I wrapped the default ProxySelector
and check against the configuration value in ProxySelector.select
.
I have no way of testing this but delving into Vert.x... this seem to be correct.
would you have a way to generate a pure jdk non Uni
client? because that is what we should be using from the config source. that would solve effectively the dev mode issue (unless we get quarkus to fix the shut down executor).
@vsevel I've looked into the restart issue and I'm not sure it has anything to do with Vault code.
This seems to be the real error:
Caused by: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.ArcContainer.instance(java.lang.Class, java.lang.annotation.Annotation[])" because "container" is null
It's thrown by VaultConfigSourceFactory
when trying to initialize the VaultConfigHolder
... Arc.container()
is null
. So, during restart this is getting called when there is no Arc container available but during the first boot it is.
I say we call this PR done and merge it. Then tackle the restart issue with the help of @radcortez.
that would solve effectively the dev mode issue (unless we get quarkus to fix the shut down executor).
The rejecting/shutdown executor appears to be a follow on exception caused by the null
container.
The rejecting/shutdown executor appears to be a follow on exception caused by the null container.
not sure. I added some defensive code around the NPE, and still got the same behavior as discussed a few hours ago. you can try to put back the defensive code.
@vsevel I removed Mutiny entirely from the standalone client. I had originally used some the the advcanded operators from Mutiny but after looking through the code I realized there was only two; and one (memoize) wasn't necessary.
And yes, this does fix the restart issue!
@vsevel I've looked into the restart issue and I'm not sure it has anything to do with Vault code.
This seems to be the real error:
Caused by: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.ArcContainer.instance(java.lang.Class, java.lang.annotation.Annotation[])" because "container" is null
It's thrown by
VaultConfigSourceFactory
when trying to initialize theVaultConfigHolder
...Arc.container()
isnull
. So, during restart this is getting called when there is no Arc container available but during the first boot it is.I say we call this PR done and merge it. Then tackle the restart issue with the help of @radcortez.
Ideally, a config source implementation should not use CDI. Some things will not work as expected.
Any calls to ConfigProvider.getConfig()
will provide the wrong Config
instance, because we need to remember that the Config
instance for runtime is being initialized (and the factory init is part of the Config init). CDI injection won't work properly for Runtime mappings (for the same reason). For things to work, we need to rely on workarounds like VaultConfigHolder
.
There are cases where a ConfigProvider.getConfig
may be called (even on a different CL), when Arc is already disposed, hence the error. I believe it may be possible to fix this by just storing the VaultRuntimeConfig
in a static class (instead of a bean) and using that one instead of CDI (at least for that specific class). That would avoid having a direct dependency on CDI code in the Config factory code.
Ideally, a config source implementation should not use CDI. Some things will not work as expected.
is this going to be achievable @kdubb ?
@vsevel Yes, I believe so. We should file an issue and implement it after this alpha is released. It will require reorganizing the code as almost everything is injected at this point.
I have no way of testing this but delving into Vert.x... this seem to be correct.
@patrice-conil can you give it a try?
@vsevel Just FYI, I removed all the references to Java version in the POMs; mostly because I had setup the client to be 17 but target 11 before the changeover. It now relies on the parent quarkiverse POM for this.
I verified in the logs that it compiles with Java 17.
TL;DR This implements a new standalone client as contemplated in #214. It aims to solve as many of the raised issues as possible while making the development easier as things move forward.
To see how it's used and some basic capabilities look at the very limited tests. There's some simple but good examples of its usage.
But... here's the headline...
Below is an overview of the implementation as it currently stands.
VaultRequest
&VaultReqeuestExecutor
The client is built around a
VaultRequest
. It is a class that models every feature of a Vault request like authentication tokens, namespaces, mounts, paths, etc; it ignores HTTP although there is some similarity due to the way Vault defines it's API.VaultRequest
s are processed by a simple single function interface theVaultRequestExecutor
. The interface is simple to implement and allows layering and progressively configuring the request as it's passed to the final executor, which will pass it to a Vault instance via an HTTP client implementation.This completely decouples all of the client from any specific HTTP implementation. Currently there are Vert.x and JDK implementations which are fairly small. I plan on breaking the Vertx client out into its own separate module. In the future modules for other HTTP clients can be added as requested (e.g. the Apache HttpClient).
This allows neat things like simplified mocking or adding a tracing logger to the chain.
The classes are located in
io.quarkus.vault.common
.Code Generation
I wrote a code generator using JavaPoet that reads from a YAML "spec" file. It's an all original YAML schema and associated generator designed to make it to generate Vault style APIs.
Vault does self report an OpenAPI schema but it is woefully underspecified and seemingly leaves properties un-types. Reading the documentation you get a much more complete picture of the apis. This is the reason for this dedicated generator. The positives are that it generates classes in the same style as we currently implement by hand and it is very easy to look at the Vault docs and transcribe a new API from them.
In the future we can look at generating the YAML files from some other source like scraping the web docs or if the OpenAPI schema starts to fill in the gaps.
I'll spare you the details in this PR of the YAML schema. I intend to write a document that fully explains it, until then you can see the specs in
src/main/specs
of the client module. Check outsecerets/kv1.yaml
!Generated APIs
For Each API spec two main classes are generated, a "Request Factory" where each method returns a partially configured
VaultRequest
and matching API where where each method returns an actual result from calling the API.This decoupling comes in very handy when implementing complicated authentication like using a wrapping token to retrieve a password to use in "auth/userpass" authentication.
As an example for the KV1 secrets engine an API class named
VaultSecretsKV1
is generated and a factory class namedVaultSecretsKV1RequestFactory
is generated.Each method in both these interfaces is named for the vault endpoint and takes the parameters appropriate to the method; and possibly a generated options class for methods with a lot of parameters.
These classes are vended by the vault client and it's "accessor" classes that allow user code to mimic the Vault API and docs.
See
VaultSecretsKV1
andVaultSecretsKV1RequestFactory
.Authentication via Token Providers
Authentication methods are implemented via
VaultTokenProvider
which simply vends a (possibly time limited)VaultToken
. Again these can be layered, for example token caching is implemented inVaultCachingTokenProvider
and simply wraps anotherVaultTokenProvider
.If the implementation needs to support unwrapping, it can be written to use a
VaultUnwrappedTokenProvider
for the unwrapped piece.Importantly, both
VaultTokenProvider
andVaultUnwrappedTokenProvider
are passed aVaultRequestExecutor
(viaVaultAuthRequest
) so they can execute Vault requests as needed.Altogether, this allows the token providers, using the generated request factories, to build and execute the required requests without needing a "client" or event the generated API object itself.
For example in the
VaultUserPassTokenProvider
here's how it calls Vault to login: