-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configure multiple clients/tenants #1296
Comments
You're totally right. Having multiple named client is currently not supported. If you want to tackle this one, this would be awesome. |
hmm it sounds like a cool thing to contribute with, but I am not sure where to even start from to be honest, as i never contributed to quarkus or any of its extensions. any suggestions on how to approach this? |
Side note for the security team, you may not use access key in the first place to consume queue and use IAM identity. Unfortunately, I don't know how to do it, but it should be possible to tweak the credential provider with a
@Named("mybean")
@Produces
@ApplicationScoped
public AwsCredentialsProvider credentialProvider() {
return // whatever is required to authenticate with IAM identity.
} That being said, I first thought it should be easy to produce a client for injection point annotated with a name attribute like
After reading them, make sure you understand the difference between a runtime module in the first hand and a deployment module with its build step processor and recorder on the other hand. If you are at ease with CDI mechanisms then, it will be a piece of cake to naviguate in the repository (at least what follows should make more sense). The very basics of the project is to produce a bean for each kind of aws sdk client. One extension per aws client. Each extension is a duplication of the same pattern where we strongly type the client type to be used in abstract classes and processors in the common module. Actually, a default bean is produced by a producer in the runtime module of each client extension. This producer is being injected with a aws client builder instance (both sync and async builder) of the type of the client it should produce. To resume, we scan the CDI context at build time and discover injection points of a client. If one is found, we produce a bean for the client builder. At runtime, the producer in the runtime module can produce the client bean to be injected in the injection point. To implement the requested feature, I think the general idea would be to generate named bean based on discovered injected points decorated with a new named-like attribute Let's take Sqs as an example. In the runtime module, you will find Config classes. The one that is of interest for this feature is quarkus-amazon-services/sqs/runtime/src/main/java/io/quarkus/amazon/sqs/runtime/SqsConfig.java Lines 16 to 27 in 4ecc717
Both allow to configure the endpoint and credentials. I think that it is enough for the needs. Others allow to configure how the underlying transport layer (netty/apache/url/crt) will behave and I don't think it is desirable to have different settings here. Looking at how quarkus DataSource implement the config part we can move these two properties in a containing interface and replace them in Now the harder part. Clients injection points are discovered in a build step Line 60 in 4ecc717
This step produces Lines 66 to 68 in 4ecc717
Note the pattern of matching Now, we will track the use of RequireAmazonClientBuildItem. In Line 109 in 4ecc717
The Then, finally, this Lines 354 to 368 in 4ecc717
Note that this whole path handles both sync and async injection points. As we saw, we need the transport builder instance not only for the default client bean, but now, for all the beans. So we cannot assume anymore that we should produce a single bean from You can inspire from agroal to apply qualifers For the configuration, it is actually retrived with a recorder. The recorder can now be passed a named argument and look for the configuration in the map. This is a long journey but we are not finished. Now we have collection of @ApplicationScoped
public class SqsClientProducer {
private final SqsClient syncClient;
SqsClientProducer(@Named("test") Instance<SqsClientBuilder> syncClientBuilderInstance) {
this.syncClient = syncClientBuilderInstance.isResolvable() ? syncClientBuilderInstance.get().build() : null;
}
@Named("test")
@Produces
@ApplicationScoped
public SqsClient client() {
if (syncClient == null) {
throw new IllegalStateException("The SqsClient is required but has not been detected/configured.");
}
return syncClient;
}
@PreDestroy
public void destroy() {
if (syncClient != null) {
syncClient.close();
}
}
} and inject the client bean in your class @Inject
@Named("test")
SqsClient sync; The last part if all goes well, is to produce this bean programmaticaly. This should be doable with a syntheticBean and a recorder injected with the builder instance. Something more or less like what is done for the S3Crt alternative (which do not require a producer in the runtime module of its extension. Lines 122 to 138 in 4ecc717
And voilà. If you are not lost in the wild. What you can try first, is to refactor the code but without supporting multiple clients. Then, try to update the createBuilder method so it take both a The next step, is to introduce the config map of clients and the named attribute. This is potentially the longer part to write, but it should be the easiest in code complexity. As a bonus, we will have to support dev services for named client. Let me know how things are going, I have limited time currently so things will go slowly from my side. |
I opened a PR to keep track of the progress. |
@jb-arpia This was more difficult than I expected. Good news is that I finally achieve a working PR. You can test it. I plan to merge it next week. |
@jb-arpia version |
Hi, opening a ticket as I didn't find a mention about multiple clients anywhere on the docs (maybe I'm blind).
I was using this extensions to inject SqsClient on my quarkus production app which is using around 10 different SQS queues.
Recently, people from security came up with a new requirement where basically each queue will need its own dedicated access key and secret to be accessed, and this was not up for debate :)
As far as I am aware, this extension is able to manage only a single SqsClient. On quarkus, it is common that extensions allow you to configure a global client, but also multiple other named clients. This can be observed on extensions such as OIDC, OIDC-CLIENT and DATASOURCE, etc.
If this was in place, I'd easily be able to comply with this new requirement, but right now I'm having to completely move away from the extension and go back to managing the SDK/Clients myself.
Am I missing something, or is this the current scenario?
The text was updated successfully, but these errors were encountered: