-
-
Notifications
You must be signed in to change notification settings - Fork 523
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
chore: move host-config and endpoint settings to a specific modifiers #633
chore: move host-config and endpoint settings to a specific modifiers #633
Conversation
…gs before container creation
Callback suggests execution after an operation. Using hook following what git does with commit hooks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to match the levels against the current Java implementations. Some are for sure up to discussion, for some we know about their usage, especially in the context of container modules.
Every container module is a direct use case.
container.go
Outdated
@@ -101,28 +102,29 @@ type ContainerRequest struct { | |||
Cmd []string | |||
Labels map[string]string | |||
Mounts ContainerMounts | |||
Tmpfs map[string]string | |||
Tmpfs map[string]string // Deprecated: Use PreCreationHook instead | |||
RegistryCred string | |||
WaitingFor wait.Strategy | |||
Name string // for specifying container name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would deprecate this, risk for collisions and generally not needed in the context of TC usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. But I'd do it as part of a new PR, to make it even clearer that passing a name could be seen as an antipattern from testing standpoint
container.go
Outdated
@@ -101,28 +102,29 @@ type ContainerRequest struct { | |||
Cmd []string | |||
Labels map[string]string | |||
Mounts ContainerMounts | |||
Tmpfs map[string]string | |||
Tmpfs map[string]string // Deprecated: Use PreCreationHook instead | |||
RegistryCred string | |||
WaitingFor wait.Strategy | |||
Name string // for specifying container name | |||
Hostname string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have this in 1st level in Java. What are use cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto: used in one single test verifying that the hostname was changed.
container.go
Outdated
Privileged bool // Deprecated: Use PreCreationHook instead. For starting privileged container | ||
Networks []string // for specifying network names | ||
NetworkAliases map[string][]string // for specifying network aliases | ||
NetworkMode container.NetworkMode // Deprecated: Use PreCreationHook instead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this in 1st level, but I think it is not appropriate there.
container.go
Outdated
NetworkMode container.NetworkMode // Deprecated: Use PreCreationHook instead | ||
Resources container.Resources // Deprecated: Use PreCreationHook instead | ||
Files []ContainerFile // files which will be copied when container starts | ||
User string // for specifying uid:gid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in 1st level in Java, are there good use cases for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This User is not used at all by the library, only in a test that verifies that running id -u
returns the defined user. I'd use a follow-up PR to discuss whether a field is actually in use or not.
Preparation for the future
* main: Add toxiproxy example (testcontainers#643) Add spanner example (testcontainers#642) chore: sync governance files (testcontainers#641) Add pubsub example (#640) chore: adjust generator for the docs site (#639) Add datastore example (#638) Add firestore example (#637) fix: avoid panics when checking container state and container.raw is nil (#635) feat: provide a tool to generate examples from code (#618) chore: bump version in mkdocs (#630) docs: remove code snippets from main README (#631) docs: document replace directive for Docker Compose (#632)
* main: (44 commits) feat: support passing registry credentials to the reaper (testcontainers#647) fix: close response body in http strategy (testcontainers#718) chore: move e2e module to postgres example module (testcontainers#717) chore: bump containerd transitive dep in examples (testcontainers#715) chore(deps): bump github.com/containerd/containerd from 1.6.12 to 1.6.14 (testcontainers#703) chore(deps): bump github.com/compose-spec/compose-go in /modules/compose (testcontainers#710) chore: bump testcontainers-go to 0.17.0 in examples (testcontainers#714) chore(deps): bump github.com/docker/compose/v2 in /modules/compose (testcontainers#711) chore: support running MySQL compose in ARM (testcontainers#712) chore: simplify compose replace directives (testcontainers#713) chore: add compose module to dependabot (testcontainers#709) chore: move compose code to a separate module (testcontainers#650) docs: refine onboarding process with quickstart guide (testcontainers#706) chore: move redis-specific tests to the example module (testcontainers#701) chore: bump transitive dependencies (#527) chore: reduce concurrent builds (testcontainers#702) chore: add mysql example (testcontainers#700) chore(deps): bump google.golang.org/api from 0.104.0 to 0.105.0 (testcontainers#699) chore(deps): bump google.golang.org/api in /examples/firestore (testcontainers#683) chore(deps): bump cloud.google.com/go/spanner in /examples/spanner (testcontainers#688) ...
✅ Deploy Preview for testcontainers-go ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
As discussed offline with @HofmeisterAn and @eddumelendez having another modifier for the |
In the case of advanced setups, a user would be able to modify anything in the Docker config
@@ -87,6 +87,17 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { | |||
} | |||
``` | |||
|
|||
### Advanced Settings | |||
|
|||
The aforementioned `GenericContainer` function and the `ContainerRequest` struct represent a straightforward manner to configure the containers, but you could need to create your containers with more advance settings regarding the config, host config and endpoint settings Docker types. For those more advance settings, _Testcontainers for Go_ offers a way to fully customise the container request and those internal Docker types. These customisations, called _modifiers_, will be applied just before the internal call to the Docker client to create the container. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The aforementioned `GenericContainer` function and the `ContainerRequest` struct represent a straightforward manner to configure the containers, but you could need to create your containers with more advance settings regarding the config, host config and endpoint settings Docker types. For those more advance settings, _Testcontainers for Go_ offers a way to fully customise the container request and those internal Docker types. These customisations, called _modifiers_, will be applied just before the internal call to the Docker client to create the container. | |
The aforementioned `GenericContainer` function and the `ContainerRequest` struct represent a straightforward manner to configure the containers, but you might need to create your containers with more advance settings regarding the config, host config and endpoint settings Docker types. For those more advance settings, _Testcontainers for Go_ offers a way to fully customize the container request and access those internal Docker types. These customizations, called _modifiers_, will be applied just before the internal call to the Docker client to create the container. |
<!--/codeinclude--> | ||
|
||
!!!warning | ||
The only special case where the modifiers are not applied last, is when there are no exposed ports in the container request and the container does not use a network mode from a container (e.g. `req.NetworkMode = container.NetworkMode("container:$CONTAINER_ID")`). In that case, _Testcontainers for Go_ will extract the ports from the underliying Docker image and export them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only special case where the modifiers are not applied last, is when there are no exposed ports in the container request and the container does not use a network mode from a container (e.g. `req.NetworkMode = container.NetworkMode("container:$CONTAINER_ID")`). In that case, _Testcontainers for Go_ will extract the ports from the underliying Docker image and export them. | |
The only special case where the modifiers are not applied last, occurs when there are no exposed ports in the container request and the container does not use a network mode from a container (e.g. `req.NetworkMode = container.NetworkMode("container:$CONTAINER_ID")`). In that case, _Testcontainers for Go_ will implicitly extract the ports from the underlying Docker image and export them. |
provider, err := NewDockerProvider() | ||
require.Nil(t, err) | ||
|
||
t.Run("No exposed ports", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t.Run("No exposed ports", func(t *testing.T) { | |
t.Run("No configured exposed ports should expose default port of image", func(t *testing.T) { |
) | ||
}) | ||
|
||
t.Run("No exposed ports and network mode IsContainer", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t.Run("No exposed ports and network mode IsContainer", func(t *testing.T) { | |
t.Run("No exposed ports and network mode IsContainer should not implicitly expose ports", func(t *testing.T) { |
What does this PR do?
This PR addresses the need of separating concerns when creating a container, as we want to distinguish between basic and advanced settings.
With basic, we mean settings that are used by the vast majority of our users, exposed as part of the public API of Testcontainers for Go. And with advanced, we mean settings that should still be still available in the public API, but in a hidden manner.
Therefore, we are adding the concept of a
Modifier
to theContainerRequest
: a user will be able to define what advanced configurations should be processed before a container is created.The advanced settings that we have identified at this moment are those that are related to 3 elements:
container.Config
Docker typecontainer.HostConfig
Docker typenetwork.EndpointSettings
Therefore, we have defined three modifiers:
ConfigModifier
,HostConfigModifier
andEndpointSettingsModifier
.From Docker docs:
On the contrary, we chose basic settings to be related to the portable information of a container, under the
container.Config
Docker type:The technical implementation of this PR comes with:
ConfigModifier
,HostConfigModifier
andEndpointSettingsModifier
. These fields in the request are part of the public API of the container request.Modifiers
functions are executed before the container is created using the Docker client.Modifiers
function allow users modify the config, hostConfig and endpointSettings Docker types when they request a container, handy for advances use cases.Deprecated
in favor of the differentModifiers
.Config
Docker type, are still present in the container request. The modifier will take precedence, as we are going to merge the struct in the modifier with the already created one (from the container request).Modifier
, and provide a default hook including the deprecated fields if it's not present in the request. This way we are keeping backwards compatibility until we remove those fields.Modifiers
when needed, removing the deprecated fields from the tests.Why is it important?
We want to allow users configure their containers, but helping them not to commit mistakes caused by a wrong configuration. If the public API directly exposes Docker types in a way that they are easy to consume, a user trying to configure a container with basic settings could be tempted to use advanced setting.
More info about this can be found in the #628 discussion.
Another benefit that comes here is reducing the size of the container request: we do not need to add fields to the public API to map a Docker type: anything can be modified with the Modifiers. We should provide a simple public API, but for advanced use cases, the modifiers assist.
Related issues
How to test this PR
Running the tests would not represent a change in the previous behavior.
Another test could be using a custom project that replaces the testcontainers-go dependency for the one containing this PR in the local workspace. The dependent project must compile and its tests must pass.