-
Notifications
You must be signed in to change notification settings - Fork 297
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
fix(core): running testcontainer inside container #714
fix(core): running testcontainer inside container #714
Conversation
bcfb770
to
51ec378
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #714 +/- ##
=======================================
Coverage ? 85.62%
=======================================
Files ? 12
Lines ? 654
Branches ? 102
=======================================
Hits ? 560
Misses ? 72
Partials ? 22 ☔ View full report in Codecov by Sentry. |
53f8d09
to
e0d969e
Compare
also use utils for platform detection
see testcontainers#475 (comment) for a summary
d80b3b1
to
341bd03
Compare
required to finally figure out how github actions actually work
341bd03
to
9f4d1ba
Compare
I am happy to announce that I was able to add some DinD and DooD directly into the test suite that work even within the github action here. I think this is a good starting point to tackle more issues arising from running testonctainer within a container itself. Following the discussion with @alexanderankin on #720 I am aware that testing non core thing inside the core test is not really wanted. |
def pytest_configure(config: pytest.Config) -> None: | ||
""" | ||
Add configuration for custom pytest markers. | ||
""" | ||
config.addinivalue_line( | ||
"markers", | ||
"inside_docker_check: test used to validate DinD/DooD are working as expected", | ||
) |
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.
is this just for filtering in/out dind/dod tests?
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.
That is to filter out tests that run within the test_dind
and test_dood
tests.
Inside this tests now the docker container is build and executed in a dind
and dood
environment.
This way we have proper test that dind
and dood
actually works.
I left the old make test-dind
(which is not correct because it's acutall DooD) untouched.
It would actually be better to remove it not only because of the wrong name.
It also doesn't succeed because some things as some auth tests seem to have troubles with TLS settings.
I don't think the complete test suit has to pass inside a dind/dood env.
In the end these test are integration tests and should be treated as such.
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.
lets remove the things that don't make sense
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.
perhaps in a separate PR maybe to make the history clearer
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 is great! I still have a couple things I want to figure out before merging because its a lot. in particular I don't like the breaking change with the returning int instead of string because if I'm not mixing it up there is a method somewhere in there that returns str but actually returns int or str but i dont want to do that without a version bump (4.9 or just v5).
To be frank, that doesn't matter as all, as long the packages is not marked as typed (#305), it is not considered by type checkers from end users anyway. |
def get_container_host_ip(self) -> str: | ||
# infer from docker host | ||
host = self.get_docker_client().host() | ||
if not host: | ||
return "localhost" | ||
# see https://github.com/testcontainers/testcontainers-python/issues/415 | ||
if host == "localnpipe" and system() == "Windows": | ||
return "localhost" | ||
|
||
# # check testcontainers itself runs inside docker container | ||
# if inside_container() and not os.getenv("DOCKER_HOST") and not host.startswith("http://"): | ||
# # If newly spawned container's gateway IP address from the docker | ||
# # "bridge" network is equal to detected host address, we should use | ||
# # container IP address, otherwise fall back to detected host | ||
# # address. Even it's inside container, we need to double check, | ||
# # because docker host might be set to docker:dind, usually in CI/CD environment | ||
# gateway_ip = self.get_docker_client().gateway_ip(self._container.id) | ||
|
||
# if gateway_ip == host: | ||
# return self.get_docker_client().bridge_ip(self._container.id) | ||
# return gateway_ip | ||
return host | ||
connection_mode: ConnectionMode | ||
connection_mode = self.get_docker_client().get_connection_mode() | ||
if connection_mode == ConnectionMode.docker_host: | ||
return self.get_docker_client().host() |
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.
Btw: one could argue that this is incorrect.
self.get_docker_client().host()
does return a DNS name instead of an IP especially localhost
.
Indeed for some containers this has a negative effect: I tried to create a MariaDB container that failed. Using localhost
instead of 127.0.0.1
it was trying to connect through the unix socket.
But this is the old behaviour so I kept it the way it is.
We might want to change this in the future.
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.
ah yes, as it says "container_ip" in the method name but it returns a domain name instead, hm.
they both have been replaced by proper `pytest` tests follow up of #714
🤖 I have created a release *beep* *boop* --- ## [4.9.0](testcontainers-v4.8.2...testcontainers-v4.9.0) (2024-11-26) ### Features * **compose:** support for setting profiles ([#738](#738)) ([3e00e71](3e00e71)) * **core:** Support working with env files ([#737](#737)) ([932ee30](932ee30)) ### Bug Fixes * allow running all tests ([#721](#721)) ([f958cf9](f958cf9)) * **core:** Avoid hanging upon bad docker host connection ([#742](#742)) ([4ced198](4ced198)) * **core:** running testcontainer inside container ([#714](#714)) ([85a6666](85a6666)) * **generic:** Also catch URLError waiting for ServerContainer ([#743](#743)) ([24e354f](24e354f)) * update wait_for_logs to not throw on 'created', and an optimization ([#719](#719)) ([271ca9a](271ca9a)) * Vault health check ([#734](#734)) ([79434d6](79434d6)) ### Documentation * Documentation fix for ServerContainer ([#671](#671)) ([0303d47](0303d47)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
py_version = ".".join(map(str, sys.version_info[:2])) | ||
image_name = f"testcontainers-python:{py_version}" | ||
subprocess.run( | ||
[*("docker", "build"), *("--build-arg", f"PYTHON_VERSION={py_version}"), *("-t", image_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.
@CarliJoy @alexanderankin
I know this is already in, but I have to wonder doesn't this breaks anywhere that dosn't uses sudoless docker?
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.
Then is still as good as before, as the Makefile also was using sudoless docker.
Only difference people will know that there is an issue because before they probably never cared to run make test-dind
.
So I would say dosn't matter.
Either people will be so smart and see that if subprocess fails that it is there setup in which they required sudo
and locally adopt the test or they will simply ignore the failing test and still create an MR that run properly in the pipeline.
Or they will create an Issue at which point we can take care of 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.
cool, let me try it on a vm :)
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.
Or put in other words: This is only relevant for testing and as long as people who want to contribute don't run into problems and it works in the pipeline I would not invest time into this.
There are many more pressuring open issues inside the project.
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'm asking because I had some unrelated issues that made me rerun all the tests and now (once I fixed the other stuff) I'm left with this, in any case I'll try and recreate all the env as sudoless.
So sadly I assume this does break :( and currently I'm effected.
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.
Sorry to hear.
So on your dev machince you only can run docker with sudo docker
?
Does is brake also in the pipeline here in gitlab?
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.
ok, so updating if anyone needs in the future, the workaround is very trivial just run with
[*("sudo", "docker", "build"), *("--build-arg", f"PYTHON_VERSION={py_version}"), *("-t", image_name), "."],
once and you should be good :) as the image will be created and available.
- We should consider adding some remark in the docs about assuming all devs are using sudoless docker.
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.
No not once -> everytime you update the code.
As the code is included in the docker image.
If you already have the error in front of you, why not catch it and rerun it with sudo?
I assume there is permission error or similar?
First try without sudo and when running into the troubles, just add it.
What do you think of this idea?
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.
Created an issue to document this #749
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.
Just to clarify, once is just to get the tests working, if I don't change anything dind
related I tend to trust the CI for those kind of changes, but as a safety net I'll try and move my env to use sudoless.
The correct approach in my options is to stop using subprocess.run
for docker related activity, as we have the docker SDK :) I also noted this in the ticket for the long run.
closes #475
One step closer to solve #517
Replaces #622
According to the data collected this should fix issues running testcontainers inside a container in almost all cases.
There is still an issue when running it within docker desktop, that is probably easily solved which checking for the existence of
host.docker.internal
.But I have to recollect the data to ensure this, so this will be added at later point in time, as with with setting
-e TESTCONTAINERS_HOST_OVERRIDE=host.docker.internal
an easy workaround exists as well.