Skip to content

Commit

Permalink
docker-compose exec doesn't have -e option (fixes docker#4551)
Browse files Browse the repository at this point in the history
Signed-off-by: Guillermo Arribas <garribas@gmail.com>
  • Loading branch information
garribas authored and shin- committed Oct 25, 2017
1 parent 8c0b03a commit b30cb77
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 21 deletions.
59 changes: 38 additions & 21 deletions compose/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from inspect import getdoc
from operator import attrgetter

import docker

from . import errors
from . import signals
from .. import __version__
Expand Down Expand Up @@ -402,7 +404,7 @@ def exec_command(self, options):
"""
Execute a command in a running container
Usage: exec [options] SERVICE COMMAND [ARGS...]
Usage: exec [options] [-e KEY=VAL...] SERVICE COMMAND [ARGS...]
Options:
-d Detached mode: Run command in the background.
Expand All @@ -412,11 +414,16 @@ def exec_command(self, options):
allocates a TTY.
--index=index index of the container if there are multiple
instances of a service [default: 1]
-e, --env KEY=VAL Set environment variables (can be used multiple times,
not supported in API < 1.25)
"""
index = int(options.get('--index'))
service = self.project.get_service(options['SERVICE'])
detach = options['-d']

if options['--env'] and docker.utils.version_lt(self.project.client.api_version, '1.25'):
raise UserError("Setting environment for exec is not supported in API < 1.25'")

try:
container = service.get_container(number=index)
except ValueError as e:
Expand All @@ -425,26 +432,7 @@ def exec_command(self, options):
tty = not options["-T"]

if IS_WINDOWS_PLATFORM and not detach:
args = ["exec"]

if options["-d"]:
args += ["--detach"]
else:
args += ["--interactive"]

if not options["-T"]:
args += ["--tty"]

if options["--privileged"]:
args += ["--privileged"]

if options["--user"]:
args += ["--user", options["--user"]]

args += [container.id]
args += command

sys.exit(call_docker(args))
sys.exit(call_docker(build_exec_command(options, container.id, command)))

create_exec_options = {
"privileged": options["--privileged"],
Expand All @@ -453,6 +441,9 @@ def exec_command(self, options):
"stdin": tty,
}

if docker.utils.version_gte(self.project.client.api_version, '1.25'):
create_exec_options["environment"] = options["--env"]

exec_id = container.create_exec(command, **create_exec_options)

if detach:
Expand Down Expand Up @@ -1295,3 +1286,29 @@ def parse_scale_args(options):
)
res[service_name] = num
return res


def build_exec_command(options, container_id, command):
args = ["exec"]

if options["-d"]:
args += ["--detach"]
else:
args += ["--interactive"]

if not options["-T"]:
args += ["--tty"]

if options["--privileged"]:
args += ["--privileged"]

if options["--user"]:
args += ["--user", options["--user"]]

if options["--env"]:
for env_variable in options["--env"]:
args += ["--env", env_variable]

args += [container_id]
args += command
return args
26 changes: 26 additions & 0 deletions tests/acceptance/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from tests.integration.testcases import pull_busybox
from tests.integration.testcases import SWARM_SKIP_RM_VOLUMES
from tests.integration.testcases import v2_1_only
from tests.integration.testcases import v2_2_only
from tests.integration.testcases import v2_only
from tests.integration.testcases import v3_only

Expand Down Expand Up @@ -1369,6 +1370,31 @@ def test_exec_custom_user(self):
self.assertEqual(stdout, "operator\n")
self.assertEqual(stderr, "")

@v2_2_only()
def test_exec_service_with_environment_overridden(self):
name = 'service'
self.base_dir = 'tests/fixtures/environment-exec'
self.dispatch(['up', '-d'])
self.assertEqual(len(self.project.containers()), 1)

stdout, stderr = self.dispatch([
'exec',
'-T',
'-e', 'foo=notbar',
'--env', 'alpha=beta',
name,
'env',
])

# env overridden
assert 'foo=notbar' in stdout
# keep environment from yaml
assert 'hello=world' in stdout
# added option from command line
assert 'alpha=beta' in stdout

self.assertEqual(stderr, '')

def test_run_service_without_links(self):
self.base_dir = 'tests/fixtures/links-composefile'
self.dispatch(['run', 'console', '/bin/true'])
Expand Down
10 changes: 10 additions & 0 deletions tests/fixtures/environment-exec/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: "2.2"

services:
service:
image: busybox:latest
command: top

environment:
foo: bar
hello: world

0 comments on commit b30cb77

Please sign in to comment.