123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- #!/usr/bin/python3
- """Re-runs a docker container using the same arguments as before.
-
- Given the name of a container, the previous arguments are determined
- and reconstructed by looking at the `docker inspect` output.
-
- Each function named `handle_*` handles one configuration option,
- reading the relevant information from the inspect output and adding
- the relevant command line flags to the config.
- """
-
- import argparse
- import inspect
- import json
- import subprocess
- import sys
-
-
- def inspect_container(container):
- """Uses `docker inspect` to get details about the given container.
-
- Args:
- container (str): The name of the container to inspect.
-
- Returns:
- dict: Detailed information about the container.
-
- Raises:
- CalledProcessError: An error occurred talking to Docker.
- """
- output = subprocess.check_output(['docker', 'inspect',
- '--type=container', container])
- return json.loads(output.decode('utf-8'))[0]
-
-
- def handle_binds(container, config):
- """Copies the volume bind (--volume/-v) arguments."""
- if container['HostConfig']['Binds']:
- config['args'].extend(['--volume=%s' % bind
- for bind in container['HostConfig']['Binds']])
-
-
- def handle_image(container, config):
- """Copies the image argument."""
- config['image'] = container['Config']['Image']
-
-
- def handle_name(container, config):
- """Copies the name (--name) argument."""
- # Trim the leading / off the name. They're equivalent from docker's point
- # of view, but having the plain name looks nicer from a human point of view.
- config['args'].append('--name=%s' % container['Name'][1:])
-
-
- def handle_network_mode(container, config):
- """Copies the network mode (--net) argument."""
- network = container['HostConfig']['NetworkMode']
- if network != 'default':
- config['args'].append('--net=%s' % network)
-
-
- def handle_ports(container, config):
- """Copies the port publication (-p) arguments."""
- ports = container['HostConfig']['PortBindings']
- if ports:
- for port, bindings in ports.items():
- for binding in bindings:
- if binding['HostIp']:
- config['args'].append('-p=%s:%s:%s' % (binding['HostIp'],
- binding['HostPort'],
- port))
- elif binding['HostPort']:
- config['args'].append('-p=%s:%s' % (binding['HostPort'],
- port))
- else:
- config['args'].append('-p=%s' % port)
-
-
- def handle_restart(container, config):
- """Copies the restart policy (--restart) argument."""
- policy = container['HostConfig']['RestartPolicy']
- if policy and policy['Name'] != 'no':
- arg = '--restart=%s' % policy['Name']
- if policy['MaximumRetryCount'] > 0:
- arg += ':%s' % policy['MaximumRetryCount']
- config['args'].append(arg)
-
-
- def handle_volumes_from(container, config):
- """Copies the volumes from (--volumes-from) argument."""
- if container['HostConfig']['VolumesFrom']:
- config['args'].extend(['--volumes-from=%s' % cont for
- cont in container['HostConfig']['VolumesFrom']])
-
-
- def functions():
- """Lists all functions defined in this module.
-
- Returns:
- list of (str,function): List of (name, function) pairs for each
- function defined in this module.
- """
- return [m for m
- in inspect.getmembers(sys.modules[__name__])
- if inspect.isfunction(m[1])]
-
-
- def handlers():
- """Lists all handlers defined in this module.
-
- Returns:
- list of function: All handlers (handle_* funcs) defined in this module.
- """
- return [func for (name, func) in functions() if name.startswith('handle_')]
-
-
- def main():
- """Script entry point."""
- parser = argparse.ArgumentParser(description='Reruns docker containers ' \
- 'with different parameters.')
- parser.add_argument('container', type=str, help='The container to rerun')
- parser.add_argument('-d', '--dry-run', action='store_true',
- help='Don\'t actually re-run the container, just ' \
- 'print what would happen.')
- args = parser.parse_args()
- container = inspect_container(args.container)
-
- docker_config = {'args': ['-d'], 'image': ''}
- for handler in handlers():
- handler(container, docker_config)
-
- docker_config['args'].sort()
- commands = [
- ['docker', 'stop', args.container],
- ['docker', 'rm', args.container],
- ['docker', 'run'] + docker_config['args'] + [docker_config['image']],
- ]
-
- if args.dry_run:
- print('Performing dry run for container %s. The following would be ' \
- 'executed:' % args.container)
- for command in commands:
- print(' '.join(command))
- else:
- print('Re-running container %s...' % args.container)
- for command in commands:
- subprocess.check_call(command)
-
-
- if __name__ == "__main__":
- main()
|