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

Use testcontainers to improve platform coverage #408

Merged

Conversation

pilosus
Copy link
Contributor

@pilosus pilosus commented Nov 21, 2023

Copy link
Member

@amotl amotl left a comment

Choose a reason for hiding this comment

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

Dear Vitaly,

this looks looks excellent, thank you very much.

CI says something about this:

ERROR: Could not find a version that satisfies the requirement click-aliases<2,>=1.0.3 (from cratedb-toolkit[test]) (from versions: 1.0.0, 1.0.1)
ERROR: No matching distribution found for click-aliases<2,>=1.0.3

-- https://github.com/crate/crash/actions/runs/6950117802/job/18922855944#step:4:124

... but that is totally not your fault. We recently needed to add crate/cratedb-toolkit@0a16a101cb45, and that will probably need some rebalancing we will take care about on behalf of the next iteration.

With kind regards,
Andreas.

@pilosus
Copy link
Contributor Author

pilosus commented Nov 22, 2023

@amotl yes, this is because of the Python version constraints in click-aliases. But the cratedb-toolkit itself has the same constraint of >=3.8, we simply don't see it, as the pip install fails before all the transitive deps are installed.
Tbh, I think Python 3.7 constraines can be lifted to 3.8 safely:

@pilosus pilosus changed the title Feature/402 testcontainers for integration testing Use testcontainers to improve plaform coverage Nov 22, 2023
@amotl
Copy link
Member

amotl commented Nov 22, 2023

Python 3.7 has reached the end of life this summer

urllib3 also just removed support, see https://github.com/urllib3/urllib3/releases/tag/2.1.0.

@pilosus pilosus force-pushed the feature/402-testcontainers-for-integration-testing branch from cc142eb to 0446f7d Compare November 22, 2023 23:44
setup.py Outdated
@@ -76,7 +76,9 @@ def read(path):
extras_require=dict(
test=[
'crate[test]',
'zc.customdoctests<2'
'zc.customdoctests<2',
# FIXME once tested and merged, fix the name
Copy link
Contributor Author

Choose a reason for hiding this comment

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

NB! Needs to be updated before the merge

Copy link
Member

Choose a reason for hiding this comment

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

Thank you. See also #410 (comment):

  1. @pilosus: When following the (in my opinion) right strategy outlined at 2., I am humbly asking for your patience on this. It would need to wait a bit for the testcontainers code to be upstreamed beforehand, [...]

[ on which you have worked on behalf of crate/cratedb-toolkit#82 ].

Copy link
Member

@amotl amotl Feb 10, 2024

Choose a reason for hiding this comment

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

We observe that the test adapter may need a few more improvements, so we postponed the plan about the upstreaming. We released the most recent updates with cratedb-toolkit 0.0.4. Can I ask you to upgrade, and, while being at it, also rebase on top of master?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@pilosus pilosus marked this pull request as ready for review November 22, 2023 23:45
@pilosus
Copy link
Contributor Author

pilosus commented Nov 22, 2023

@amotl I think I am ready for the review, please let me know if I missed something.

@pilosus pilosus requested a review from amotl November 22, 2023 23:57


node = CrateDBFixture(crate_version=EntrypointOpts.version)
Copy link
Member

@amotl amotl Nov 23, 2023

Choose a reason for hiding this comment

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

With respect to your question on the other patch, could this spot also be used to optionally register table names for resetting, on behalf of a second argument to the fixture manager here? In this way, it can be managed by CrateDBFixture, but the user has control about which tables need to be defined here, matching their test environment.

The list of tables could be supplied to the constructor, or optionally by using a dedicated method, or both. It is just an idea, I don't have any strong opinions about the "how", and I am also sure you will find a better way of "naming things". ;]

node.register_tables_for_reset(*tablenames: t.List[str])
node = CrateDBFixture(
    crate_version=EntrypointOpts.version,
    reset_tables=["foo", "bar", '"testdrive"."qux"'],
)

Copy link
Member

@amotl amotl Nov 23, 2023

Choose a reason for hiding this comment

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

You already responded to this at crate/cratedb-toolkit#82 (comment) while I was writing this down. Your proposed interface is perfectly lean. Thanks!

cratedb_service.reset(tables=RESET_TABLES)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think passing the table list to the reset method is even better than using it in the class constructor/class method, as you can adjust the list with more flexibility with no need to change the main fixture.

@pilosus pilosus requested a review from amotl November 23, 2023 13:41
@amotl amotl changed the title Use testcontainers to improve plaform coverage Use testcontainers to improve platform coverage Nov 23, 2023
@amotl amotl requested review from seut and matriv November 23, 2023 20:05
tests/test_integration.py Outdated Show resolved Hide resolved
@@ -286,7 +292,7 @@ def test_multiple_hosts(self):
output = output.getvalue()
lines = output.split('\n')
self.assertRegex(lines[3], r'^\| http://[\d\.:]+ .*\| NULL .*\| FALSE .*\| Server not available')
self.assertRegex(lines[4], r'^\| http://[\d\.:]+. *\| crate .*\| TRUE .*\| OK')
self.assertRegex(lines[4], r'^\| http://.*@?localhost:\d+ *\| crate .*\| TRUE .*\| OK')
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this always localhost because of testcontainers now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it really depends on two things:

  1. if you pass host explicitly or rely on the default None value, when invoking get_connection_url method of the CrateDBTestAdapter
  2. where the code is running, on the host or Docker-in-Docker, see the logic here. In our case, both for local development and in the CI pipelines, it will always be localhost

so, I'd say, it's safe to assume localhost won't break anything, unless testcontainers upstream or CI/CD pipelines in crash repo will be changed

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, thx!

@pilosus pilosus force-pushed the feature/402-testcontainers-for-integration-testing branch from bff8dac to 7e20b38 Compare November 24, 2023 10:48
@pilosus pilosus requested review from matriv and amotl November 24, 2023 10:48
Copy link
Contributor

@matriv matriv left a comment

Choose a reason for hiding this comment

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

Thank you! Please wait for other reviewers though.

Copy link
Member

@seut seut left a comment

Choose a reason for hiding this comment

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

Nice work and thank you a lot for your efforts @pilosus!
But related to the discussion we had about adding dependencies to incubating projects and the future of the testcontainers, please do not merge this until the testcontainer is merged upstream.
See #410 (comment).

@amotl
Copy link
Member

amotl commented Jan 19, 2024

Hi.

I just invoked the test harness, and while it succeeds:

python -m unittest -v
Ran 103 tests in 8.408s

.... it clutters the log with such messages:

2024-01-19 21:30:31,578 [urllib3.connectionpool              ] WARNING : Retrying (Retry(total=8, connect=None, read=0, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x113ba4d50>: Failed to establish a new connection: [Errno 61] Connection refused')': /
2024-01-19 21:30:31,579 [urllib3.connectionpool              ] WARNING : Retrying (Retry(total=7, connect=None, read=0, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x113b4f590>: Failed to establish a new connection: [Errno 61] Connection refused')': /
2024-01-19 21:30:31,580 [urllib3.connectionpool              ] WARNING : Retrying (Retry(total=6, connect=None, read=0, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x113b3eed0>: Failed to establish a new connection: [Errno 61] Connection refused')': /

There was also another error on a single build, at »Python 3.12, CrateDB 5.5.0 on macos-latest«:

  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1025, in send
    self.connect()
  File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/docker/transport/unixconn.py", line 27, in connect
    sock.connect(self.unix_socket)
FileNotFoundError: [Errno 2] No such file or directory

Do you know where this might be coming from, @pilosus?

With kind regards,
Andreas.

@amotl amotl force-pushed the feature/402-testcontainers-for-integration-testing branch from 7e20b38 to 4ab569c Compare January 19, 2024 20:33
@amotl amotl force-pushed the feature/402-testcontainers-for-integration-testing branch 2 times, most recently from 7e55274 to 2ce2313 Compare January 19, 2024 21:59
@pilosus
Copy link
Contributor Author

pilosus commented Jan 21, 2024

.... it clutters the log with such messages:

Hi @amotl

My educated guess is that since the PR was open, a new major version of docker was released. It has requests package bumped to a new version, which in turns uses urllib3 of version 2 distributed rather than vendored as it used to be in earlier versions. Here's a longer discussion:
docker/docker-py#3113

Since testcontainers use docker package with no pinned upper bound, the behaviour from requests has changed in crash too.

From what I see, it's not only testcontainers-related tests that are emitting these annoying warnings, but some others, like tests/test_commands.py since they are instantiating crate.crash.command.CrateShell which is invoking crate.crash.command.CrateShell._connect.

I think it's better to use either:

urllib3.disable_warnings()

or a module-wide fixtures like:

def setUpModule():
    import logging
    logging.getLogger("urllib3").propagate = False

Python 3.12, CrateDB 5.5.0 on macos-latest

Not sure what's happening here, but again, probably it has something to do with the new docker-py.

@pilosus
Copy link
Contributor Author

pilosus commented Jan 21, 2024

@amotl reg. MacOS tests failing. It's because Docker isn't pre-installed on the GitHub-runners!
https://github.com/orgs/community/discussions/25777

If you open a job, then click on Set up job -> Runner Image -> Included Software, you'll see the link to a list of preinstalled runner software.
Compare ubuntu with macos-12, docker is not installed because of the licensing issues.

So, testcontainers won't work on MacOS runner, unfortunately :-/

@amotl
Copy link
Member

amotl commented Feb 7, 2024

@pilosus:

reg. MacOS tests failing. It's because Docker isn't pre-installed on the GitHub-runners!

Yeah right, thanks for the reminder. That's also why the code skip integration tests on all other OS than Linux, so it will fortunately not be a regression.

if sys.platform != "linux":
raise SkipTest("Integration tests only supported on Linux")

Apparently, the raise SkipTest(...) would need to (additionally?) go into setUpModule() now?

def setUpModule():
node.start()

Otherwise, it apparently tries to dial the Docker API, which goes south.

@amotl
Copy link
Member

amotl commented Feb 7, 2024

.... it clutters the log with such messages:

My educated guess is that since the PR was open, a new major version of docker was released. It has requests package bumped to a new version, which in turns uses urllib3 of version 2 distributed rather than vendored as it used to be in earlier versions. Here's a longer discussion: [...]

Oh wow, thanks for digging into this. I hadn't expected that. Instead, I was expecting that the CrateDB HTTP driver might have a flaw, and is responsible for the log flodding coming from urllib3. Without reading docker/docker-py#3113 yet, can you rule out that the HTTP driver needs to be investigated, and that it's definitively coming from Docker?

If so, I will be happy to disable corresponding warnings as you suggested. However, it would be nicer if this could only be masked for requests to the Docker API, if that is the culprit here, in order not to obfuscate any other warnings originating at urllib3. Do you see a chance to achieve this?

@pilosus
Copy link
Contributor Author

pilosus commented Feb 10, 2024

Yeah right, thanks for the reminder. That's also why the code skip integration tests on all other OS than Linux, so it will fortunately not be a regression.

if sys.platform != "linux":
raise SkipTest("Integration tests only supported on Linux")

Apparently, the raise SkipTest(...) would need to (additionally?) go into setUpModule() now?

@amotl Check out how I've impemented it in d83177f

@pilosus
Copy link
Contributor Author

pilosus commented Feb 10, 2024

Oh wow, thanks for digging into this. I hadn't expected that. Instead, I was expecting that the CrateDB HTTP driver might have a flaw, and is responsible for the log flodding coming from urllib3. Without reading docker/docker-py#3113 yet, can you rule out that the HTTP driver needs to be investigated, and that it's definitively coming from Docker?

If so, I will be happy to disable corresponding warnings as you suggested. However, it would be nicer if this could only be masked for requests to the Docker API, if that is the culprit here, in order not to obfuscate any other warnings originating at urllib3. Do you see a chance to achieve this?

@amotl hmm, all this flood of urllib3 warning logs are coming from the CrateShell when we forgot pass in proper hosts so that it falls back to the default localhost:4200. I've fixed that in 58b0aef, except (obviously) for the case where we check multi hosts connection with one URL not available.

There's the same problem in some other, non-integration tests like tests.test_commands.ShowTablesCommandTest.test_pre_0_57 and tests.test_commands.MultipleStatementsTest.test_single_sql_statement_multiple_lines just to name a few. It seems we don't mock them properly. I haven't fixed those, I guess it's better to do in a separate PR.

@amotl
Copy link
Member

amotl commented Feb 10, 2024

Thank you very much for improving the test skipping on unsupported OS, and for tracking down the reason for the flood of urllib3 warnings, and fixing it. Excellent job! 💯

@pilosus pilosus force-pushed the feature/402-testcontainers-for-integration-testing branch from 7dba3fc to b87f929 Compare February 11, 2024 08:12
@pilosus
Copy link
Contributor Author

pilosus commented Mar 3, 2024

Hi @amotl let me know if there's anything else I need to do to get this PR merged?
If there's a blocker may be it's worth to mention it here as well :-)

@amotl
Copy link
Member

amotl commented Mar 3, 2024

Thanks @pilosus. I think it will be good to go. Let us have @seut a final voice about it, and then we will probably just merge, when no other objections come up. Thanks again for your efforts!

@amotl amotl requested a review from seut March 3, 2024 16:05
Copy link
Member

@seut seut left a comment

Choose a reason for hiding this comment

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

Nice, thx!
I think some commits would makes sense to be squashed, but will leave that up to you.

pilosus and others added 6 commits March 5, 2024 23:21
GitHub Runner don't support Docker on MacOS for licensing issues. We
want to skip integration tests that require Docker though
testcontainers. We still may want to be able to run such test for
local development.
CrateShell invocation in integration tests relied on the default
localhost:4200 instead of the custom host urls used in Docker
containers. That resulted in a flood of urllib3 warning logs coming
from the crate client. This change fix the hosts urls.
@pilosus pilosus force-pushed the feature/402-testcontainers-for-integration-testing branch from b87f929 to 4640109 Compare March 5, 2024 22:26
@pilosus
Copy link
Contributor Author

pilosus commented Mar 5, 2024

I think some commits would makes sense to be squashed, but will leave that up to you.

@amotl @seut I've squashed 6 commits. Feel free to squash even more if needed.

@amotl amotl merged commit eb4c386 into crate:master Mar 18, 2024
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants