Currently migrating my application to Micronaut 3, I encountered one problem with micronaut-gcp. Especially with the google secret manager. I am using gradle with Kotlin DSL.
Actual configuration: (not working, using plugin io.micronaut.library
version 2.0.4
)
- gradle 7.2
- micronaut 3.0.1
Previous configuration: (working with no plugin, using micronaut-bom
)
- gradle 6.5.1
- micronaut 2.4.0
- micronautGcp 3.5.0
I/ The Problem
My goal is to load some secrets as key/value pairs into a property source.
I followed the documentation that says to use a bootstrap.yml
as follows:
micronaut: config-client: enabled: true gcp: secret-manager: keys: - MY_SECRET
Then in my class I should be able to inject that secret value using the @Value
annotation. Actually I am doing this in my tests. I am using the @MicronautTest
annotation from jUnit5 so I have something that looks like this:
@MicronautTest public class MyClass { @Value("${my.secret}") private String mySecret; }
then comes the problem, when running any test, it fails in the initialization saying this:
Error instantiating bean of type [io.micronaut.gcp.secretmanager.client.DefaultSecretManagerClient] Message: getTransportChannel() called when needsExecutor() is true Path Taken: new DistributedPropertySourceLocator(ConfigurationClient configurationClient,Duration readTimeout) --> new DistributedPropertySourceLocator([ConfigurationClient configurationClient],Duration readTimeout) --> new DefaultCompositeConfigurationClient([ConfigurationClient[] configurationClients]) --> new SecretManagerConfigurationClient([SecretManagerClient secretManagerClient],SecretManagerConfigurationProperties configurationProperties) --> new DefaultSecretManagerClient([SecretManagerServiceClient client],Environment environment,GoogleCloudConfiguration googleCloudConfiguration,ExecutorService executorService) io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type [io.micronaut.gcp.secretmanager.client.DefaultSecretManagerClient]
II/ What I’ve tried ?
When I’ve seen that, I was thinking that maybe the bootstrap.yaml
thing doesn’t work the I tried to use the lower lever access to secret manager using injecting SecretManagerServiceClient
as follows:
@MicronautTest public class MyClass { @Inject private SecretManagerServiceClient client; private void someTest() { String mySecret = client.getSecret("MY_SECRET"); } }
but got same error Message: getTransportChannel() called when needsExecutor() is true
with same path taken.
I also tried to upgrade to micronaut 3.0.1 but didn’t change anything.
III/ My solution to handle this
As my problem was to retrieve a secret during the testing stage of my ci/cd process and, as I am using Google Cloud Build. I could pass the secret using the availableSecrets feature in my cloudbuild.yaml
:
steps: ... - name: 'gradle' entrypoint: 'bash' args: ['./gradlew', 'test'] secretEnv: ['MY_SECRET'] ... availableSecrets: secretManager: - versionName: projects/PROJECT_ID/secrets/MY_SECRET/versions/latest env: 'MY_SECRET'
then passing it in my application.yml
:
my: secret: ${MY_SECRET}
and then in my code:
@MicronautTest public class MyClass { @Value("${my.secret}") private String mySecret; }
But I dont find this solution very satisfying as I find the bootstrap.yaml
one more convenient.
If someone gets a solution for me or an idea/advice, I’ll be happy to take it.
Have a nice day !
Advertisement
Answer
I’ve been down that rabbit hole. Long story short I got past this by upgrading the google-cloud-secretmanager
dependency from 1.6.4 to e.g. 2.0.2
Like so:
<dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-secretmanager</artifactId> <version>2.0.2</version> </dependency>