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

feat: Connection to host network from LocalStack container #1198

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.stream.Stream;

import org.jboss.logging.Logger;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.EnabledService;
Expand Down Expand Up @@ -304,6 +305,10 @@ public String getSecretKey() {
.toArray(EnabledService[]::new))
.withLabel(DEV_SERVICE_LABEL, devServiceName);

if (localStackDevServicesBuildTimeConfig.accessToHost()) {
Testcontainers.exposeHostPorts(localStackDevServicesBuildTimeConfig.hostPort());
}
Comment on lines +308 to +310
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (localStackDevServicesBuildTimeConfig.accessToHost()) {
Testcontainers.exposeHostPorts(localStackDevServicesBuildTimeConfig.hostPort());
}
container.withAccessToHost(localStackDevServicesBuildTimeConfig.accessToHost);

This would force the host access setup and let users configure exposed host port themself.

Copy link
Author

@dabg3 dabg3 Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would users be able to configure exposed port?
I've tried by intercepting the quarkus startup event on my application:

@ApplicationScoped
@IfBuildProfile("dev")
public class DevLifecycleBean {

    @ConfigProperty(name = "quarkus.http.port")
    int port;

    void onStart(@Observes StartupEvent ev) {
        Testcontainers.exposeHostPorts(port);
    }
}

exposeHostPorts() gets called with the right port as argument but then connection to host is refused, I've not investigated why though.

Apart from the difficulties, I do not like much this solution because a seamless integration is being traded for boilerplate code + testcontainers runtime dependency on the application side.
In my solution the host port is user-configurable via host-port property, however most of the time would be retrieved from quarkus.http.port property without requiring tweaks.
An edit I could make is accepting multiple ports instead of just 1, if that's useful.
The same approach is used on the Quarkus Jib extension.

https://github.com/quarkusio/quarkus/blob/0f776ad0434619b428439c1d97257cf1555dd76c/extensions/container-image/container-image-jib/deployment/src/main/java/io/quarkus/container/image/jib/deployment/ContainerImageJibConfig.java#L116-L120


localStackDevServicesBuildTimeConfig.port().ifPresent(
port -> container.setPortBindings(Collections.singletonList("%s:%s".formatted(port, PORT))));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,17 @@ public interface LocalStackDevServicesBuildTimeConfig {
* Optional fixed port localstack will listen to.
*/
Optional<Integer> port();

/**
* Indicates if the container would make a connection to the host network.
*/
@WithDefault("false")
boolean accessToHost();

/**
* port which the application listen to.
*/
@WithDefault("${quarkus.http.port:8080}")
int hostPort();

}
18 changes: 18 additions & 0 deletions docs/modules/ROOT/pages/dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ The key is the name of the service to enable and must be a valid LocalStack serv

Some extensions support additional configuration to be applied at startup. Refer to the extension documentation.

== Connect to host network

Dev Services for Amazon Services can support communication from the localstack container to the host network.

If the container needs to communicate with the application running in dev mode, the property `quarkus.http.host` must be set to make the application listen on `0.0.0.0`.
Otherwise, network traffic must be forwarded somehow to `127.0.0.1` which is the default listening address.

By default, the host exposes port `8080` or the one set via `quarkus.http.port` property to the LocalStack container.
In case the exposed port is incorrectly evaluated, it can be manually forced by specifying the desired value via `quarkus.aws.devservices.localstack.host-port`.

[source, properties]
----
quarkus.http.host=0.0.0.0
quarkus.aws.devservices.localstack.access-to-host=true
----

Connection to host network DOES NOT support `quarkus.http.port=0`

== Cognito

The Cognito extension is not using LocalStack but Moto.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,40 @@ endif::add-copy-button-to-env-var[]
|


a|icon:lock[title=Fixed at build time] [[quarkus-aws-devservices-localstack-local-stack-dev-services-build-time-config_quarkus-aws-devservices-localstack-access-to-host]]`link:#quarkus-aws-devservices-localstack-local-stack-dev-services-build-time-config_quarkus-aws-devservices-localstack-access-to-host[quarkus.aws.devservices.localstack.access-to-host]`


[.description]
--
Indicates if the container would make a connection to the host network.

ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_AWS_DEVSERVICES_LOCALSTACK_ACCESS_TO_HOST+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_AWS_DEVSERVICES_LOCALSTACK_ACCESS_TO_HOST+++`
endif::add-copy-button-to-env-var[]
--|boolean
|`false`


a|icon:lock[title=Fixed at build time] [[quarkus-aws-devservices-localstack-local-stack-dev-services-build-time-config_quarkus-aws-devservices-localstack-host-port]]`link:#quarkus-aws-devservices-localstack-local-stack-dev-services-build-time-config_quarkus-aws-devservices-localstack-host-port[quarkus.aws.devservices.localstack.host-port]`


[.description]
--
port which the application listen to.

ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_AWS_DEVSERVICES_LOCALSTACK_HOST_PORT+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_AWS_DEVSERVICES_LOCALSTACK_HOST_PORT+++`
endif::add-copy-button-to-env-var[]
--|int
|`${quarkus.http.port:8080}`


a|icon:lock[title=Fixed at build time] [[quarkus-aws-devservices-localstack-local-stack-dev-services-build-time-config_quarkus-aws-devservices-localstack-container-properties-container-properties]]`link:#quarkus-aws-devservices-localstack-local-stack-dev-services-build-time-config_quarkus-aws-devservices-localstack-container-properties-container-properties[quarkus.aws.devservices.localstack.container-properties]`


Expand Down