-
Notifications
You must be signed in to change notification settings - Fork 15
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
DockerRunner: Enable background container to run commands against #51
base: main
Are you sure you want to change the base?
Conversation
Is it possible to retain the single-shot run method so that we can separate framework updates from test updates? |
Sure |
I restored run commands. I used exec everywhere for now, where would you use run ? What kind of difference are you thinking of ? |
Currently, there is a difference between exec and run: run uses entry point which de-escalates the uid, exec does not have an entry point and we don't Additionally, you're changing the version test right now, that's not needed with this enhancement. |
Exec commands are also using entrypoint. Using verbose to show tests commands:
Actually, I also add the entrypoint manually when using
EDIT: My runs commands sucks With my fix, docker run launch the following commands:
|
That's not what we'd recommend a user to do though, right? I'll later on comment on that when I review the code. |
Yes, it builds manually the command created by ENTRYPOINT + CMD. |
|
||
def __del__(self): | ||
"""Remove test container""" | ||
stop_command = ["docker", "rm", "-f", self.container_id] |
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.
If we want to retain the container (to investigate because an error happened) it's useful to have a 2-step process: docker stop
the container, and then docker rm
the container. We can then choose to not rm on test failure, allowing a docker start
and perhaps exec
into a shell to investigate.
Can we split this up into 2 commands that are called independent from the destructor?
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.
With our 2 type of command, exec
& run
:
run
commands outputs (stdout + stderr) are direclty handled. Stdout is returned, stderr displayed when error occurs (seeDockerRunner._shell
). Logs are already caught.exec
commands do not add any logs, they seem to handle only main process outputs.
We can do this, but logs are already displayed, not sure where we would use docker log
.
stop_command = ["docker", "rm", "-f", self.container_id] | ||
self._shell(stop_command, silent=True) | ||
|
||
def _start(self): |
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.
Why protected?
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 a habit because it wasn't used by outside. It was designed with the idea that DockerRunner will always start a container for a test. If the design change and we do not use it necessary as you suggest, it needs to change.
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 okay with it when it's designed to not be ran from outside ever because <reason>
, but I do not really agree with the reasoning.
It was designed with the idea that DockerRunner will always start a container for a test.
That's a design change of DockerRunner introduced with this PR, my comment is based on original design that is more permissive. The reason why I didn't design it like that with the initial build of the framework is because I can think of tests where we want to just docker run
a single command and check the output, to check the exact, automated behavior of that (as was done with the version test), or, to run multiple docker containers to test an end-to-end use case, e.g. doing development on regtest, where there are scenarios where you need at least 2 nodes that connect to each other, for example when you want to work with getblocktemplate or auxpow RPC interfaces.
|
||
def run_interactive_command(self, envs, args): |
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.
could you please bring this method back so that the tests don't have to change?
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.
Related to #51 (comment)
self.container = DockerRunner(self.options.platform, | ||
self.options.image, self.options.verbose) | ||
|
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 forces all tests to run/exec a container. should leave it up to the individual tests in their run_test
method, by putting this in a separate method that can be overridden by child classes and then call that method here.
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.
Fine
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 changed it, the line is still (almost) the same, but it does not start automatically a background container.
It will start automatically on the first docker exec
command, making background containers optional without the need to start the container manually when writing 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.
what if I want to change the way the container starts? i.e. test for permission escalation?
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.
Any example ? No idea how to perform this kind of test.
But you have the docker run
interface as normally, and even if using entrypoint through docker exec
any commands will run as root (outside of Dogecoin executables), as entrypoint is designed to accept arbitrary bash command.
@@ -25,15 +25,22 @@ def run_test(self): | |||
"""Actual test, must be implemented by the final class""" | |||
raise NotImplementedError | |||
|
|||
def run_command(self, envs, args): |
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.
Please restore this so that version test doesn't have to change
@@ -27,21 +27,21 @@ def run_test(self): | |||
self.version_expr = re.compile(f".*{ self.options.version }.*") | |||
|
|||
# check dogecoind with only env | |||
dogecoind = self.run_command(["VERSION=1"], []) |
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.
Please revert all changes to this file.
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.
Using self.docker_run
would be fine for you ?
Also, methods TestRunner.docker_run
and TestRunner.docker_exec
return directly the output to avoid the use of .stdout
access & encoding/decoding stuff. Error messages are directly handled on command execution (DockerRunner._shell) and create test failure, not used in tests (at least for now). You would like to restore this also ?
I did some fixes to reproduce real
|
Following a comment where @patricklodder was speaking about having a mechanism to start/stop a container for the entire test.
Implemented it in the idea to add some tests who can need it, at least datadir test from #50.
It changes the way commands are proceeded : A single background container is started for the entire test of a TestRunner subclass, and all commands for the test are executed with
docker exec
(calling the entrypoint directly).Run CI tests
Will need some documentation to facilitate usage, but for now it's possible to run it using: