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
)
Previous configuration: (working with no plugin, using micronaut-bom
)
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 !
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>