docker-cmd hook switch to the paunch library

paunch is a library and utility which is now in OpenStack
under the TripleO umbrella. It contains the logic currently in the
docker-cmd hook exposed as a python library and command utility.

This change switches the docker-cmd hook to paunch.

Asserting --label arguments has been split out from the other docker
run arguments so that paunch can add new --label arguments in future
releases without breaking these tests.

paunch-1.1.0 has just been release which contains new idempotency
behaviour, so the tests have been modified to work with the new docker
command behaviour that idempotency requires.

Change-Id: I884c38ade06ab0e01432837c43f29b123e65fa3c
This commit is contained in:
Steve Baker 2017-04-12 10:09:06 +12:00
parent 3a86f8789c
commit 33241a84c1
6 changed files with 356 additions and 433 deletions

View File

@ -1,4 +1,5 @@
A hook which uses the `docker` command to deploy containers.
A hook which uses the `docker` command via
`paunch <https://docs.openstack.org/developer/paunch/>`_ to deploy containers.
The hook currently supports specifying containers in the `docker-compose v1
format <https://docs.docker.com/compose/compose-file/#/version-1>`_. The

View File

@ -12,15 +12,14 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import json
import logging
import os
import random
import string
import subprocess
import sys
import yaml
import paunch
import yaml
DOCKER_CMD = os.environ.get('HEAT_DOCKER_CMD', 'docker')
@ -36,135 +35,6 @@ def build_response(deploy_stdout, deploy_stderr, deploy_status_code):
}
def docker_run_args(cmd, container, config):
cconfig = config[container]
if cconfig.get('detach', True):
cmd.append('--detach=true')
if 'env_file' in cconfig:
if isinstance(cconfig['env_file'], list):
for f in cconfig.get('env_file', []):
if f:
cmd.append('--env-file=%s' % f)
else:
cmd.append('--env-file=%s' % cconfig['env_file'])
for v in cconfig.get('environment', []):
if v:
cmd.append('--env=%s' % v)
if 'net' in cconfig:
cmd.append('--net=%s' % cconfig['net'])
if 'pid' in cconfig:
cmd.append('--pid=%s' % cconfig['pid'])
if 'privileged' in cconfig:
cmd.append('--privileged=%s' % str(cconfig['privileged']).lower())
if 'restart' in cconfig:
cmd.append('--restart=%s' % cconfig['restart'])
if 'user' in cconfig:
cmd.append('--user=%s' % cconfig['user'])
for v in cconfig.get('volumes', []):
if v:
cmd.append('--volume=%s' % v)
for v in cconfig.get('volumes_from', []):
if v:
cmd.append('--volumes_from=%s' % v)
cmd.append(cconfig.get('image', ''))
cmd.extend(command_argument(cmd, cconfig.get('command')))
def docker_exec_args(cmd, container, config, cid):
cconfig = config[container]
if 'privileged' in cconfig:
cmd.append('--privileged=%s' % str(cconfig['privileged']).lower())
if 'user' in cconfig:
cmd.append('--user=%s' % cconfig['user'])
command = command_argument(cmd, cconfig.get('command'))
# for exec, the first argument is the container name,
# make sure the correct one is used
command[0] = discover_container_name(command[0], cid)
cmd.extend(command)
def command_argument(cmd, command):
if not command:
return []
if not isinstance(command, list):
return command.split()
return command
def execute(cmd):
log.debug(' '.join(cmd))
subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cmd_stdout, cmd_stderr = subproc.communicate()
log.debug(cmd_stdout)
log.debug(cmd_stderr)
return cmd_stdout, cmd_stderr, subproc.returncode
def label_arguments(cmd, container, cid, iv):
cmd.extend([
'--label',
'deploy_stack_id=%s' % iv.get('deploy_stack_id'),
'--label',
'deploy_resource_name=%s' % iv.get('deploy_resource_name'),
'--label',
'config_id=%s' % cid,
'--label',
'container_name=%s' % container,
'--label',
'managed_by=docker-cmd'
])
def inspect(container, format=None):
cmd = [DOCKER_CMD, 'inspect']
if format:
cmd.append('--format')
cmd.append(format)
cmd.append(container)
(cmd_stdout, cmd_stderr, returncode) = execute(cmd)
if returncode != 0:
return
try:
if format:
return cmd_stdout
else:
return json.loads(cmd_stdout)[0]
except Exception as e:
log.error('Problem parsing docker inspect: %s' % e)
def unique_container_name(container):
container_name = container
while inspect(container_name, format='exists'):
suffix = ''.join(random.choice(
string.ascii_lowercase + string.digits) for i in range(8))
container_name = '%s-%s' % (container, suffix)
return container_name
def discover_container_name(container, cid):
cmd = [
DOCKER_CMD,
'ps',
'-a',
'--filter',
'label=container_name=%s' % container,
'--filter',
'label=config_id=%s' % cid,
'--format',
'{{.Names}}'
]
(cmd_stdout, cmd_stderr, returncode) = execute(cmd)
if returncode != 0:
return container
names = cmd_stdout.split()
if names:
return names[0]
return container
def main(argv=sys.argv):
global log
log = logging.getLogger('heat-config')
@ -200,36 +70,16 @@ def main(argv=sys.argv):
if not isinstance(config, dict):
config = yaml.safe_load(config)
key_fltr = lambda k: config[k].get('start_order', 0)
for container in sorted(config, key=key_fltr):
log.debug("Running container: %s" % container)
action = config[container].get('action', 'run')
exit_codes = config[container].get('exit_codes', [0])
if action == 'run':
cmd = [
DOCKER_CMD,
'run',
'--name',
unique_container_name(container)
]
label_arguments(cmd, container, cid, input_values)
docker_run_args(cmd, container, config)
elif action == 'exec':
cmd = [DOCKER_CMD, 'exec']
docker_exec_args(cmd, container, config, cid)
(cmd_stdout, cmd_stderr, returncode) = execute(cmd)
if cmd_stdout:
stdout.append(cmd_stdout)
if cmd_stderr:
stderr.append(cmd_stderr)
if returncode not in exit_codes:
log.error("Error running %s. [%s]\n" % (cmd, returncode))
deploy_status_code = returncode
else:
log.debug('Completed %s' % cmd)
labels = collections.OrderedDict()
labels['deploy_stack_id'] = input_values.get('deploy_stack_id')
labels['deploy_resource_name'] = input_values.get('deploy_resource_name')
(stdout, stderr, deploy_status_code) = paunch.apply(
cid,
config,
managed_by='docker-cmd',
labels=labels,
docker_cmd=DOCKER_CMD
)
json.dump(build_response(
'\n'.join(stdout), '\n'.join(stderr), deploy_status_code), sys.stdout)

View File

@ -15,9 +15,10 @@
import json
import logging
import os
import subprocess
import sys
import paunch
CONF_FILE = os.environ.get('HEAT_SHELL_CONFIG',
'/var/run/heat-config/heat-config')
@ -49,100 +50,12 @@ def main(argv=sys.argv):
cmd_config_ids = [c['id'] for c in configs
if c['group'] == 'docker-cmd']
try:
delete_missing_configs(cmd_config_ids)
except Exception as e:
log.exception(e)
try:
rename_containers()
except Exception as e:
log.exception(e)
def delete_missing_configs(config_ids):
for conf_id in current_config_ids():
if conf_id not in config_ids:
log.debug('%s no longer exists, deleting containers' % conf_id)
remove_containers(conf_id)
def execute(cmd):
log.debug(' '.join(cmd))
subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cmd_stdout, cmd_stderr = subproc.communicate()
return cmd_stdout, cmd_stderr, subproc.returncode
def current_config_ids():
# List all config_id labels for containers managed by docker-cmd
cmd = [
DOCKER_CMD, 'ps', '-a',
'--filter', 'label=managed_by=docker-cmd',
'--format', '{{.Label "config_id"}}'
]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode != 0:
return set()
return set(cmd_stdout.split())
def remove_containers(conf_id):
cmd = [
DOCKER_CMD, 'ps', '-q', '-a',
'--filter', 'label=managed_by=docker-cmd',
'--filter', 'label=config_id=%s' % conf_id
]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode == 0:
for container in cmd_stdout.split():
remove_container(container)
def remove_container(container):
cmd = [DOCKER_CMD, 'rm', '-f', container]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode != 0:
log.error('Error removing container: %s' % container)
log.error(cmd_stderr)
def rename_containers():
# list every container name, and its container_name label
cmd = [
DOCKER_CMD, 'ps', '-a',
'--format', '{{.Names}} {{.Label "container_name"}}'
]
cmd_stdout, cmd_stderr, returncode = execute(cmd)
if returncode != 0:
return
lines = cmd_stdout.split("\n")
current_containers = []
need_renaming = {}
for line in lines:
entry = line.split()
if not entry:
continue
current_containers.append(entry[0])
# ignore if container_name label not set
if len(entry) < 2:
continue
# ignore if desired name is already actual name
if entry[0] == entry[-1]:
continue
need_renaming[entry[0]] = entry[-1]
for current, desired in sorted(need_renaming.items()):
if desired in current_containers:
log.info('Cannot rename "%s" since "%s" still exists' % (
current, desired))
else:
cmd = [DOCKER_CMD, 'rename', current, desired]
execute(cmd)
paunch.cleanup(
cmd_config_ids,
managed_by='docker-cmd',
docker_cmd=DOCKER_CMD
)
if __name__ == '__main__':

View File

@ -0,0 +1,5 @@
---
features:
- |
The logic for the docker-cmd hook is now provided by the paunch library,
where further feature work will occur.

View File

@ -5,6 +5,7 @@ fixtures>=3.0.0 # Apache-2.0/BSD
# Hacking already pins down pep8, pyflakes and flake8
hacking>=0.12.0,!=0.13.0,<0.14 # Apache-2.0
mock>=2.0 # BSD
paunch>=1.0.0 # Apache-2.0
requests>=2.10.0,!=2.12.2,!=2.13.0 # Apache-2.0
requests-mock>=1.1 # Apache-2.0
salt

View File

@ -112,28 +112,54 @@ class HookDockerCmdTest(common.RunScriptTest):
'TEST_STATE_PATH': self.test_state_path,
})
def assert_args_and_labels(self, expected_args, expected_labels, observed):
'''Assert the labels arguments separately to other arguments.
Tests that each expected_labels label exists, and remaining
expected arguments match exactly.
This allows paunch to add new label arguments without breaking these
tests.
'''
args = []
labels = []
j = 0
while j < len(observed):
if observed[j] == '--label':
j += 1
labels.append(observed[j])
else:
args.append(observed[j])
j += 1
self.assertEqual(expected_args, args)
for label in expected_labels:
self.assertIn(label, labels)
def test_hook(self):
self.env.update({
'TEST_RESPONSE': json.dumps([{
'stderr': 'Error: No such image, container or task: db',
'returncode': 1
}, {
'stdout': '',
'stderr': 'Creating db...'
}, {
'stderr': 'Error: No such image, container or task: web',
'returncode': 1
}, {
'stdout': '',
'stderr': 'Creating web...'
}, {
'stdout': 'web',
}, {
'stdout': '',
'stderr': 'one.txt\ntwo.txt\nthree.txt'
}])
'TEST_RESPONSE': json.dumps([
# ps for delete missing
{},
# ps for renames
{},
# ps for currently running containers
{},
# inspect for db unique container name
{},
# docker run db
{'stderr': 'Creating db...'},
# inspect for web unique container name
{},
# docker run web
{'stderr': 'Creating web...'},
# name lookup for exec web
{'stdout': 'web'},
# docker exec web
{'stderr': 'one.txt\ntwo.txt\nthree.txt'},
])
})
returncode, stdout, stderr = self.run_cmd(
[self.hook_path], self.env, json.dumps(self.data))
@ -148,58 +174,75 @@ class HookDockerCmdTest(common.RunScriptTest):
'deploy_status_code': 0
}, json.loads(stdout))
state = list(self.json_from_files(self.test_state_path, 6))
state = list(self.json_from_files(self.test_state_path, 9))
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[0]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[2]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
'db',
], state[0]['args'])
self.assertEqual([
'db'
], state[3]['args'])
self.assert_args_and_labels([
self.fake_tool_path,
'run',
'--name',
'db',
'--label',
'deploy_stack_id=the_stack',
'--label',
'deploy_resource_name=the_deployment',
'--label',
'config_id=abc123',
'--label',
'container_name=db',
'--label',
'managed_by=docker-cmd',
'--detach=true',
'--env-file=env.file',
'--env=foo=bar',
'--privileged=false',
'xxx'
''
], state[1]['args'])
], [
'deploy_stack_id=the_stack',
'deploy_resource_name=the_deployment',
'config_id=abc123',
'container_name=db',
'managed_by=docker-cmd',
], state[4]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
'web',
], state[2]['args'])
self.assertEqual([
], state[5]['args'])
self.assert_args_and_labels([
self.fake_tool_path,
'run',
'--name',
'web',
'--label',
'deploy_stack_id=the_stack',
'--label',
'deploy_resource_name=the_deployment',
'--label',
'config_id=abc123',
'--label',
'container_name=web',
'--label',
'managed_by=docker-cmd',
'--detach=true',
'--env-file=foo.env',
'--env-file=bar.conf',
@ -214,7 +257,13 @@ class HookDockerCmdTest(common.RunScriptTest):
'yyy',
'/bin/webserver',
'start'
], state[3]['args'])
], [
'deploy_stack_id=the_stack',
'deploy_resource_name=the_deployment',
'config_id=abc123',
'container_name=web',
'managed_by=docker-cmd',
], state[6]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
@ -225,25 +274,32 @@ class HookDockerCmdTest(common.RunScriptTest):
'label=config_id=abc123',
'--format',
'{{.Names}}',
], state[4]['args'])
], state[7]['args'])
self.assertEqual([
self.fake_tool_path,
'exec',
'web',
'/bin/ls',
'-l'
], state[5]['args'])
], state[8]['args'])
def test_hook_exit_codes(self):
self.env.update({
'TEST_RESPONSE': json.dumps([{
'stdout': 'web',
}, {
'stdout': '',
'stderr': 'Warning: custom exit code',
'returncode': 1
}])
'TEST_RESPONSE': json.dumps([
# ps for delete missing
{},
# ps for renames
{},
# ps for currently running containers
{},
{'stdout': 'web'},
{
'stdout': '',
'stderr': 'Warning: custom exit code',
'returncode': 1
}
])
})
returncode, stdout, stderr = self.run_cmd(
[self.hook_path], self.env, json.dumps(self.data_exit_code))
@ -254,7 +310,38 @@ class HookDockerCmdTest(common.RunScriptTest):
'deploy_status_code': 0
}, json.loads(stdout))
state = list(self.json_from_files(self.test_state_path, 2))
state = list(self.json_from_files(self.test_state_path, 5))
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[0]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[2]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
@ -265,37 +352,42 @@ class HookDockerCmdTest(common.RunScriptTest):
'label=config_id=abc123',
'--format',
'{{.Names}}',
], state[0]['args'])
], state[3]['args'])
self.assertEqual([
self.fake_tool_path,
'exec',
'web',
'/bin/ls',
'-l'
], state[1]['args'])
], state[4]['args'])
def test_hook_failed(self):
self.env.update({
'TEST_RESPONSE': json.dumps([{
'stderr': 'Error: No such image, container or task: db',
'returncode': 1
}, {
'stdout': '',
'stderr': 'Creating db...'
}, {
'stderr': 'Error: No such image, container or task: web',
'returncode': 1
}, {
'stdout': '',
'stderr': 'Creating web...'
}, {
'stdout': 'web',
}, {
'stdout': '',
'stderr': 'No such file or directory',
'returncode': 2
}])
'TEST_RESPONSE': json.dumps([
# ps for delete missing
{},
# ps for renames
{},
# ps for currently running containers
{},
# inspect for db unique container name
{},
# docker run db
{'stderr': 'Creating db...'},
# inspect for web unique container name
{},
# docker run web
{'stderr': 'Creating web...'},
# name lookup for exec web
{'stdout': 'web'},
# docker exec web fails
{
'stdout': '',
'stderr': 'No such file or directory',
'returncode': 2
}
])
})
returncode, stdout, stderr = self.run_cmd(
[self.hook_path], self.env, json.dumps(self.data))
@ -308,57 +400,75 @@ class HookDockerCmdTest(common.RunScriptTest):
'deploy_status_code': 2
}, json.loads(stdout))
state = list(self.json_from_files(self.test_state_path, 6))
state = list(self.json_from_files(self.test_state_path, 9))
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[0]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[2]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
'db',
], state[0]['args'])
self.assertEqual([
'db'
], state[3]['args'])
self.assert_args_and_labels([
self.fake_tool_path,
'run',
'--name',
'db',
'--label',
'deploy_stack_id=the_stack',
'--label',
'deploy_resource_name=the_deployment',
'--label',
'config_id=abc123',
'--label',
'container_name=db',
'--label',
'managed_by=docker-cmd',
'--detach=true',
'--env-file=env.file',
'--env=foo=bar',
'--privileged=false',
'xxx'
], state[1]['args'])
''
], [
'deploy_stack_id=the_stack',
'deploy_resource_name=the_deployment',
'config_id=abc123',
'container_name=db',
'managed_by=docker-cmd',
], state[4]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
'web',
], state[2]['args'])
self.assertEqual([
], state[5]['args'])
self.assert_args_and_labels([
self.fake_tool_path,
'run',
'--name',
'web',
'--label',
'deploy_stack_id=the_stack',
'--label',
'deploy_resource_name=the_deployment',
'--label',
'config_id=abc123',
'--label',
'container_name=web',
'--label',
'managed_by=docker-cmd',
'--detach=true',
'--env-file=foo.env',
'--env-file=bar.conf',
@ -373,7 +483,13 @@ class HookDockerCmdTest(common.RunScriptTest):
'yyy',
'/bin/webserver',
'start'
], state[3]['args'])
], [
'deploy_stack_id=the_stack',
'deploy_resource_name=the_deployment',
'config_id=abc123',
'container_name=web',
'managed_by=docker-cmd',
], state[6]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
@ -384,43 +500,47 @@ class HookDockerCmdTest(common.RunScriptTest):
'label=config_id=abc123',
'--format',
'{{.Names}}',
], state[4]['args'])
], state[7]['args'])
self.assertEqual([
self.fake_tool_path,
'exec',
'web',
'/bin/ls',
'-l'
], state[5]['args'])
], state[8]['args'])
def test_hook_unique_names(self):
self.env.update({
'TEST_RESPONSE': json.dumps([{
'stdout': 'exists\n',
'returncode': 0
}, {
'stderr': 'Error: No such image, container or task: db-blah',
'returncode': 1
}, {
'stdout': '',
'stderr': 'Creating db...'
}, {
'stdout': 'exists\n',
'returncode': 0
}, {
'stderr': 'Error: No such image, container or task: web-blah',
'returncode': 1
}, {
'stdout': '',
'stderr': 'Creating web...'
}, {
'stdout': 'web-asdf1234',
}, {
'stdout': '',
'stderr': 'one.txt\ntwo.txt\nthree.txt'
}])
'TEST_RESPONSE': json.dumps([
# ps for delete missing in this config id
{},
# ps for renames
{'stdout': 'web web\ndb db\n'},
# ps for currently running containers in this config id
{},
# inspect for db unique container name
{'stdout': 'exists'},
{
'stderr': 'Error: No such container: db-blah',
'returncode': 1
},
# docker run db
{'stderr': 'Creating db...'},
# # inspect for web unique container name
{'stdout': 'exists'},
{
'stderr': 'Error: No such container: web-blah',
'returncode': 1
},
# # docker run web
{'stderr': 'Creating web...'},
# name lookup for exec web
{'stdout': 'web-asdf1234'},
# docker exec web-asdf1234
{'stderr': 'one.txt\ntwo.txt\nthree.txt'},
])
})
returncode, stdout, stderr = self.run_cmd(
[self.hook_path], self.env, json.dumps(self.data))
@ -434,75 +554,92 @@ class HookDockerCmdTest(common.RunScriptTest):
'deploy_status_code': 0
}, json.loads(stdout))
state = list(self.json_from_files(self.test_state_path, 8))
db_container_name = state[1]['args'][4]
web_container_name = state[4]['args'][4]
state = list(self.json_from_files(self.test_state_path, 11))
db_container_name = state[4]['args'][4]
web_container_name = state[7]['args'][4]
self.assertRegex(db_container_name, 'db-[0-9a-z]{8}')
self.assertRegex(web_container_name, 'web-[0-9a-z]{8}')
self.assertEqual([
self.fake_tool_path,
'inspect',
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'exists',
'db',
'{{.Names}} {{.Label "container_name"}}'
], state[0]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'exists',
db_container_name,
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])
self.assertEqual([
self.fake_tool_path,
'run',
'--name',
db_container_name,
'--label',
'deploy_stack_id=the_stack',
'--label',
'deploy_resource_name=the_deployment',
'--label',
'config_id=abc123',
'--label',
'container_name=db',
'--label',
'managed_by=docker-cmd',
'--detach=true',
'--env-file=env.file',
'--env=foo=bar',
'--privileged=false',
'xxx'
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--filter',
'label=config_id=abc123',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[2]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
'web',
'db'
], state[3]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
web_container_name,
db_container_name,
], state[4]['args'])
self.assert_args_and_labels([
self.fake_tool_path,
'run',
'--name',
db_container_name,
'--detach=true',
'--env-file=env.file',
'--env=foo=bar',
'--privileged=false',
'xxx'
], [
'deploy_stack_id=the_stack',
'deploy_resource_name=the_deployment',
'config_id=abc123',
'container_name=db',
'managed_by=docker-cmd',
], state[5]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
'web',
], state[6]['args'])
self.assertEqual([
self.fake_tool_path,
'inspect',
'--format',
'exists',
web_container_name,
], state[7]['args'])
self.assert_args_and_labels([
self.fake_tool_path,
'run',
'--name',
web_container_name,
'--label',
'deploy_stack_id=the_stack',
'--label',
'deploy_resource_name=the_deployment',
'--label',
'config_id=abc123',
'--label',
'container_name=web',
'--label',
'managed_by=docker-cmd',
'--detach=true',
'--env-file=foo.env',
'--env-file=bar.conf',
@ -517,7 +654,13 @@ class HookDockerCmdTest(common.RunScriptTest):
'yyy',
'/bin/webserver',
'start'
], state[5]['args'])
], [
'deploy_stack_id=the_stack',
'deploy_resource_name=the_deployment',
'config_id=abc123',
'container_name=web',
'managed_by=docker-cmd',
], state[8]['args'])
self.assertEqual([
self.fake_tool_path,
'ps',
@ -528,14 +671,14 @@ class HookDockerCmdTest(common.RunScriptTest):
'label=config_id=abc123',
'--format',
'{{.Names}}',
], state[6]['args'])
], state[9]['args'])
self.assertEqual([
self.fake_tool_path,
'exec',
'web-asdf1234',
'/bin/ls',
'-l'
], state[7]['args'])
], state[10]['args'])
def test_cleanup_deleted(self):
self.env.update({
@ -571,6 +714,8 @@ class HookDockerCmdTest(common.RunScriptTest):
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])
@ -647,6 +792,8 @@ class HookDockerCmdTest(common.RunScriptTest):
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[5]['args'])
@ -687,6 +834,8 @@ class HookDockerCmdTest(common.RunScriptTest):
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])
@ -765,6 +914,8 @@ class HookDockerCmdTest(common.RunScriptTest):
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[5]['args'])
@ -805,6 +956,8 @@ class HookDockerCmdTest(common.RunScriptTest):
self.fake_tool_path,
'ps',
'-a',
'--filter',
'label=managed_by=docker-cmd',
'--format',
'{{.Names}} {{.Label "container_name"}}'
], state[1]['args'])