-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Refactor environment variable processing for Docker #49612
Refactor environment variable processing for Docker #49612
Conversation
Closes elastic#45223. The current Docker entrypoint script picks up environment variables and translates them into -E command line arguments. However, since any tool executes via `docker exec` doesn't run the entrypoint, it results in a poorer user experience. Therefore, refactor the env var handling so that the -E options are generated in `elasticsearch-env`. These have to be appended to any existing command arguments, since some CLI tools have subcommands and -E arguments must come after the subcommand. Also extract the support for `_FILE` env vars into a separate script, so that it can be called from more than once place (the behaviour is idempotent). Finally, change `CronEvalTool` to extend `EnvironmentAwareCommand`, so that it can allow (but ignore) -E commands. This also brings the tool in line with our other CLI tools.
Pinging @elastic/es-core-infra (:Core/Infra/Packaging) |
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.
LGTM! Left a minor comment.
Changing `CronEvalTool` to extend `EnvironmentAwareCommand` broke the unit tests, and after further reflection I decided that this change was lazy. Actually, the tool should just accept `-E` params but do nothing with them, instead of pulling in all the reset of the env code.
So changing |
I've updated |
@tvernum I'd appreciate your thoughts on these changes if have capacity. |
@@ -45,6 +45,9 @@ | |||
*/ | |||
public MultiCommand(final String description, final Runnable beforeMain) { | |||
super(description, beforeMain); | |||
// Accepting -E here does not prevent subcommands receiving -E arguments, since we also set `posixlyCorrect` below. | |||
// This stops option parsing when the first non-option is encountered. | |||
parser.accepts("E", "Unused. Pass to a subcommand instead").withRequiredArg(); |
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 think this is a problem.
As you know, it's natural for people to expect that passing -E
as the first argument to a multi-command will behave correctly. Currently they get an error, and have to work out what they've done wrong.
With this change they will no longer get an error, they will just get something that silently ignores their parameter. This is surprising and trappy behaviour.
If we want to do this, then I think we need to either:
- make it an error to pass
-E
and also call a subcommand (so--help -E var.from.docker=true
works, but-E var=true auto
does not); OR - actually pass the
-E
values into the subcommand like people expect.
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.
Unless I'm misunderstanding the behaviour here, and this already does (2), in which case can we make the comment more explicit?
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, you're quite right. I was thinking primarily of the Docker case, but it would be much better if -E
was respected wherever it is supplied. I'll look at this again.
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.
Having MultiCommand silently accept and ignore -E arguments could be confusing, so instead pass those arguments along to subcommands.
@elasticmachine run elasticsearch-ci/packaging-matrix |
Although most environment variable handling related to Docker has already been moved from the entrypoint script to `elasticsearch-env`, there still remaining the setting of `ES_JAVA_OPTS` to override the cgroup hierarchy setting. Move this to the env script as well, so that Docker env var handling is done in one place.
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.
LGTM for the change in e43283e
@jkakavas would you have time to look over the Java parts of this PR from a security POV? |
@pugnascotia It dawned on me that with this PR we should adjust also the instructions in step 4. of configuring-tls-on-docker. It runs In a separate PR we can adjust the same instructions in step 3 of the stack-docs. |
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.
LGTM
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.
Thanks! While digging into this I realized there are some changes in the images (UBI) which make one docker-compose file in this doc file non functional.
At some point we need docs tests for this, but I left a comment that IMHO we should bundle unzip
in all our images (given the need to deal with artifacts from cli tools) and simplify the create-certs.yml
compose file in the docs.
@@ -206,9 +206,6 @@ WARNING: Windows users not running PowerShell will need to remove `\` and join l | |||
---- | |||
docker exec es01 /bin/bash -c "bin/elasticsearch-setup-passwords \ | |||
auto --batch \ | |||
-Expack.security.http.ssl.certificate=certificates/es01/es01.crt \ | |||
-Expack.security.http.ssl.certificate_authorities=certificates/ca/ca.crt \ | |||
-Expack.security.http.ssl.key=certificates/es01/es01.key \ |
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.
Thanks! This works, however -- at least this PR -- includes the UBI work and earlier in this file we rely on yum install unzip
. In order to simply things, given that unzip
is a fairly common requirement for handling certs, what if we include unzip
in our Dockerfile
i.e.bundle it in all Elasticsearch images and remove it from the the mentioned line above, so that examples and users don't have to pull it?
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 makes sense to me, and we already include gzip
.
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.
Great. Maybe, esp. given that we have abstracted the package manager invocation now, we could test for the present of unzip
/ zip
in the path in our test cases, if it's not too complex?
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.
Good call on the test - I was installing the CLI tools in the wrong part of the Dockefile!
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.
LGTM
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.
Great catch! Left a comment
// These are installed to help users who are working with certificates. | ||
Stream.of("zip", "unzip").forEach(cliTool -> { | ||
// `which` isn't installed in our image, so instead just try to call the command. | ||
final Shell.Result result = dockerShell.runIgnoreExitCode(cliTool + " -h"); |
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.
In bash you can also rely on type -P <thefile>
if you don't have which to ensure the file is in $PATH:
e.g. on the Ubi image:
[elasticsearch@0f6edc7f150a ~]$ type -P zip
[elasticsearch@0f6edc7f150a ~]$ echo $?
1
[elasticsearch@0f6edc7f150a ~]$ type -P ls
/usr/bin/ls
[elasticsearch@0f6edc7f150a ~]$ echo $?
0
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.
type -P
would work, but as it's a bash builtin, I'd have to run it through bash. That's a actually a bit cumbersome, because we're already running "bash -c 'docker blah blah commmand'". Instead, I'm now using rpm
to check if the package is installed.
Closes elastic#45223. The current Docker entrypoint script picks up environment variables and translates them into -E command line arguments. However, since any tool executes via `docker exec` doesn't run the entrypoint, it results in a poorer user experience. Therefore, refactor the env var handling so that the -E options are generated in `elasticsearch-env`. These have to be appended to any existing command arguments, since some CLI tools have subcommands and -E arguments must come after the subcommand. Also extract the support for `_FILE` env vars into a separate script, so that it can be called from more than once place (the behaviour is idempotent). Finally, add noop -E handling to CronEvalTool for parity, and support `-E` in MultiCommand before subcommands.
Backport of #49612. The current Docker entrypoint script picks up environment variables and translates them into -E command line arguments. However, since any tool executes via `docker exec` doesn't run the entrypoint, it results in a poorer user experience. Therefore, refactor the env var handling so that the -E options are generated in `elasticsearch-env`. These have to be appended to any existing command arguments, since some CLI tools have subcommands and -E arguments must come after the subcommand. Also extract the support for `_FILE` env vars into a separate script, so that it can be called from more than once place (the behaviour is idempotent). Finally, add noop -E handling to CronEvalTool for parity, and support `-E` in MultiCommand before subcommands.
Closes elastic#45223. The current Docker entrypoint script picks up environment variables and translates them into -E command line arguments. However, since any tool executes via `docker exec` doesn't run the entrypoint, it results in a poorer user experience. Therefore, refactor the env var handling so that the -E options are generated in `elasticsearch-env`. These have to be appended to any existing command arguments, since some CLI tools have subcommands and -E arguments must come after the subcommand. Also extract the support for `_FILE` env vars into a separate script, so that it can be called from more than once place (the behaviour is idempotent). Finally, add noop -E handling to CronEvalTool for parity, and support `-E` in MultiCommand before subcommands.
Closes #45223.
The current Docker entrypoint script picks up environment variables and
translates them into -E command line arguments. However, since any tool
executed via
docker exec
doesn't run the entrypoint, it results ina poorer user experience.
This PR refactors the env var handling so that the -E options are
generated in
elasticsearch-env
. These have to be appended to anyexisting command arguments, since some CLI tools have subcommands and
-E arguments must come after the subcommand.
Also extract the support for
_FILE
env vars into a separate script, sothat it can be called from more than once place (the behaviour is
idempotent).
Finally, add noop
-E
handling toCronEvalTool
for parity, and support-E
inMultiCommand
before subcommands.