From 1b521ac4e385505b7987034f9ece9041d9ebb97c Mon Sep 17 00:00:00 2001 From: Jonathon Reinhart Date: Wed, 5 Sep 2018 23:37:01 -0400 Subject: [PATCH] scuba: Don't run the entrypoint for each line in a multi-line script **This is a breaking change.** The previous logic was generally incorrect. For a multi-line script, Scuba would prepend each line with the entrypoint. This sort of makes sense, except the script is run within *one* `docker run` invocation. Many image entrypoints are wrappers which set up things in the container, and then execute the user command which is passed as arguments to the entrypoint (e.g. `exec "@"`). Thus, it isn't right to execute the entrypoint multiple times in the same container. This changes the behavior of Scuba to instead invoke the entrypoint, passing it the path of the scuba-generated script to be executed. In this way, the entrypoint is only run once. N.B. This means that Scuba no longer works with images which wrap a single command (e.g. an "application" image which sets some CLI application as the entrypoint). If this use case is needed in the future, an additional YAML option (e.g. `entrypoint_each_line`) could be added to restore the old behavior. Fixes #114 --- scuba/__main__.py | 10 ++++------ tests/test_main.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/scuba/__main__.py b/scuba/__main__.py index 3bcdd5b7..bd65dcad 100644 --- a/scuba/__main__.py +++ b/scuba/__main__.py @@ -291,20 +291,18 @@ def __setup_native_run(self): verbose_msg('{} Cmd: "{}"'.format(context.image, default_cmd)) context.script = [shell_quote_cmd(default_cmd)] - # Make scubainit the entrypoint, and manually insert an existing - # entrypoint before each user command - entrypoint = get_image_entrypoint(context.image) or [] + # Make scubainit the real entrypoint, and use the defined entrypoint as + # the docker command (if it exists) + self.docker_cmd = get_image_entrypoint(context.image) or [] self.add_option('--entrypoint={}'.format(scubainit_cpath)) # The user command is executed via a generated shell script with self.open_scubadir_file('command.sh', 'wt') as f: - self.docker_cmd = ['/bin/sh', f.container_path] + self.docker_cmd += ['/bin/sh', f.container_path] writeln(f, '#!/bin/sh') writeln(f, '# Auto-generated from scuba') writeln(f, 'set -e') for cmd in context.script: - if entrypoint: - cmd = shell_quote_cmd(entrypoint) + ' ' + cmd writeln(f, cmd) self.context = context diff --git a/tests/test_main.py b/tests/test_main.py index caa9b11e..141508e3 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -368,6 +368,22 @@ def test_image_entrypoint(self): assert_str_equalish('success', out) + def test_image_entrypoint_multiline(self): + '''Verify entrypoints are handled correctly with multi-line scripts''' + with open('.scuba.yml', 'w') as f: + f.write(''' + image: scuba/entrypoint-test + aliases: + testalias: + script: + - cat entrypoint_works.txt + - echo $ENTRYPOINT_WORKS + ''') + + out, _ = self.run_scuba(['testalias']) + assert_str_equalish('\n'.join(['success']*2), out) + + def test_image_override(self): '''Verify --image works'''