Skip to content
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

Add the ability to ask for devservices to use the shared network #39156

Closed
jtama opened this issue Mar 4, 2024 · 30 comments · Fixed by #39899 · May be fixed by #39177
Closed

Add the ability to ask for devservices to use the shared network #39156

jtama opened this issue Mar 4, 2024 · 30 comments · Fixed by #39899 · May be fixed by #39177
Labels
Milestone

Comments

@jtama
Copy link
Contributor

jtama commented Mar 4, 2024

Description

As of now, the only way to ask for dev services to be run in the shared network is to produce a DevServicesSharedNetworkBuildItem, which I think is only done here :

"io.quarkus.deployment.builditem.DevServicesSharedNetworkBuildItem$Factory", Collections.emptyMap());
.

It would be great to be able to ask for it through configuration. I first thought that was what quarkus..devservice.shared was for, it turned out it was not ;).

Implementation ideas

No response

@jtama jtama added the kind/enhancement New feature or request label Mar 4, 2024
Copy link

quarkus-bot bot commented Mar 4, 2024

/cc @geoand (devservices), @stuartwdouglas (devservices)

@geoand
Copy link
Contributor

geoand commented Mar 5, 2024

Can you give #39177 a try please?

The property to use is quarkus.devservices.launch-on-shared-network=true

@jtama
Copy link
Contributor Author

jtama commented Mar 5, 2024

The project for which I have the need is still using 3.4.3. I know it's bad, but we have a blocker for the moment.

I will to try to backport your patch though.

@jtama
Copy link
Contributor Author

jtama commented Mar 5, 2024

Ok I did backport your fix, that works as expected. Almost.

Devservices launched by extension use a different network because of this :

Which means If I launch a container configuring it via ConfigureUtil.configureSharedNetwork, that won't work, because they will be launched on an other network.

@geoand
Copy link
Contributor

geoand commented Mar 5, 2024

Which means If I launch a container configuring it via ConfigureUtil.configureSharedNetwork, that won't work, because they will be launched on an other network.

I am not sure I understand when this happens, can you elaborate?

@jtama
Copy link
Contributor Author

jtama commented Mar 5, 2024

When an extension such as oidc or postgresql launch devservices, they're thread is attached to the "deployment" classloader.
When an application launches a test container, let's say in a QuarkusTestResourceLifecycleManager instance, they use a thread which is attached a "test" classloader.

Thus they will not be attached to the same docker/podman network.

@geoand
Copy link
Contributor

geoand commented Mar 5, 2024

Oh, I see. I kinda doubt we'll be able to fix that though...

@jtama
Copy link
Contributor Author

jtama commented Mar 5, 2024

Coudn't we use the DevServicesContext ?

@geoand
Copy link
Contributor

geoand commented Mar 5, 2024

How?

@jtama
Copy link
Contributor Author

jtama commented Mar 5, 2024

not sure... I was just looking at the QuarkusTestResourceLifecycleManager interface and where it's used.

@jtama
Copy link
Contributor Author

jtama commented Mar 6, 2024

Ok so here's what I came up with to make it work. Be ware that's an ugly hack :

Class<?> networkClass = tccl.getParent().loadClass("org.testcontainers.containers.Network");
Object sharedNetwork = networkClass.getField("SHARED").get(null);
Consumer<CreateNetworkCmd> addDevservicesLabel = cmd -> cmd.withLabels(Map.of("quarkus.devservices.network", "shared"));
Field createNetworkCmdModifiersField = sharedNetwork.getClass().getSuperclass().getDeclaredField("createNetworkCmdModifiers");
createNetworkCmdModifiersField.setAccessible(true);
createNetworkCmdModifiersField.set(sharedNetwork, Set.of(addDevservicesLabel));
container.setNetwork((Network) sharedNetwork);

That code is the ConfigureUtil class, and in my QuarkusTestResourceLifecycleManager implementation :

com.github.dockerjava.api.model.Network lookedUpNetwork = DockerClientFactory.lazyClient().listNetworksCmd().exec().stream()
                .filter(network -> network.labels.containsKey("quarkus.devservices.network"))
                .findFirst()
                .orElseThrow();

sharedNetwork = new Network() {
   @Override
   public String getId() {
       return lookedUpNetwork.getId();
   }

   @Override
   public void close() {
      /* NOOP */
   }

   @Override
   public Statement apply(Statement statement, Description description) {
       return null;
   }
};

@geoand
Copy link
Contributor

geoand commented Mar 6, 2024

Where did you put that hack? I didn't catch that part.

@jtama
Copy link
Contributor Author

jtama commented Mar 6, 2024

oups sorry I was a bit quick : Labeling the network is done here

The lookup is done in my application code.

I think the main point here is labeling the network. There is no easy identification of the devservice network as of today (its id is random)

@geoand
Copy link
Contributor

geoand commented Mar 6, 2024

I think the main point here is labeling the network. There is no easy identification of the devservice network as of today (its id is random)

That's an excellent point.
Would you like to contribute your code?

@jtama
Copy link
Contributor Author

jtama commented Mar 6, 2024

yes of course, directly to your branch ? via a fork/pr to it ?

@geoand
Copy link
Contributor

geoand commented Mar 6, 2024

Whatever you like :)

@jtama
Copy link
Contributor Author

jtama commented Mar 6, 2024

I don't have write access to your repo.

@geoand
Copy link
Contributor

geoand commented Mar 6, 2024

2 options:

  • Create a new PR against this which includes my commit
  • Do a PR against my repo

@jtama
Copy link
Contributor Author

jtama commented Mar 6, 2024

This will be done by tomorrow !

@geoand
Copy link
Contributor

geoand commented Mar 6, 2024

👌

@jtama
Copy link
Contributor Author

jtama commented Mar 6, 2024

geoand#84

@gsmet
Copy link
Member

gsmet commented Mar 6, 2024

The project for which I have the need is still using 3.4.3. I know it's bad, but we have a blocker for the moment.

@jtama could you elaborate on that? Is this something that needs fixing on our side?

@jtama
Copy link
Contributor Author

jtama commented Mar 7, 2024

@gsmet I am not sure whether you should do something or I should. Let me explain.

We have this module that depends on kafka-stream extension, and that may or not depending on runtime event, in anyway, the kstream topolgy initialized at start time. The 3.6.0 version of the extension added devui related code that need a topology to be defined at startup otherwise it will trigger a NullPointerException if I recall correctly.
We could update to 3.5.3, but we would be blocked there anyway.

@lbroudoux
Copy link
Contributor

Hi @jtama and @geoand,
I'm currently struggling with the shared network on DevServices as well, as explained here: #38398
I'll read thoroughly this thread but I can already guess some kind of side effects with what I'm trying to do at the moment. As I understand it, relying on the proposed quarkus.devservices.launch-on-shared-network=true property to determine what should be launched on the shared network will probably help me a lot...
Any thoughts if (and how) we could converge would be greatly appreciated!

@jtama
Copy link
Contributor Author

jtama commented Mar 20, 2024

Hi @lbroudoux
Certainly we can, there is a draft PR here #39177. It allows application to ask devservices to be run on the shared network (without having to produce SharedNetworkBuildItem), AND labels the created network so it can be found (network ids are random)

@lbroudoux
Copy link
Contributor

Sorry if I'm polluting this thread a bit but as I'm having issues on a very related topic, I'd like to share findings to see if we can find a common solution...

As explained in this other thread comment, I'm facing problems in dev and test modes because database-related devservices are automatically joining the shared network when it exists.

Combining the existing, this issue and mine, there are now 3 different situations where a shared network can be created:

I think there's a situation where:

  1. quarkus.devservices.launch-on-shared-network is false or undefined,
  2. We're not running containerized artifact (we're in regular dev or test mode),
  3. Microcks (or others) devservices is running and has created a shared network for its devservices needs

and where database-related services should still not join the available shared network (otherwise, they would become unreachable for the application.)

I started exploring things to see what can be used LaunchModeBuildItem or ArtifactResultBuildItem. But I can't find a way to establish we're in the above-mentioned situation when deciding whether or not the database devservices must join the shared network. I saw that IntegrationTestUtil is reading property from the quarkus-artifact.properties file but this file actually does not exist when running in dev or test mode...

Maybe we should have a way to differentiate between a shared network created because of quarkus.devservices.launch-on-shared-network=true and a shared network required by a devservice? Another additional build property that can be reused later on?

What do you think?

@jtama
Copy link
Contributor Author

jtama commented Mar 22, 2024

and where database-related services should still not join the available shared network (otherwise, they would become unreachable for the application.)

A container launched in a shared network can still be used by code running on the host. The only subtlety is the devservice would have to configure url using the host ip instead of the network alias (that's what I've done).

@lbroudoux
Copy link
Contributor

lbroudoux commented Mar 22, 2024

Hum... maybe that could be another way to solve this issue: having the database devservices setting the connection url properties to use the container IP and not the randomly generated host alias 🤔 ...

@geoand
Copy link
Contributor

geoand commented Mar 27, 2024

and where database-related services should still not join the available shared network (otherwise, they would become unreachable for the application.)

A container launched in a shared network can still be used by code running on the host. The only subtlety is the devservice would have to configure url using the host ip instead of the network alias (that's what I've done).

I agree with as I wrote here, so I am not sure I understand the original problem.

@lbroudoux
Copy link
Contributor

I submitted a PR embedding the quarkus.devservices.launch-on-shared-network change I built upon. See #39899

lbroudoux added a commit to lbroudoux/quarkus that referenced this issue Apr 11, 2024
@quarkus-bot quarkus-bot bot added this to the 3.10 - main milestone Apr 12, 2024
zZHorizonZz pushed a commit to zZHorizonZz/quarkus-grpc-transcode that referenced this issue Apr 24, 2024
poldinik pushed a commit to poldinik/quarkus that referenced this issue Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants