Skip to content

Commit

Permalink
Implement build and pull
Browse files Browse the repository at this point in the history
Also refactor how stopped and restarted are handled
  • Loading branch information
lel-amri committed Feb 12, 2023
1 parent 1ed98fb commit af6218a
Showing 1 changed file with 139 additions and 65 deletions.
204 changes: 139 additions & 65 deletions plugins/modules/docker_compose2.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,21 @@
state:
description:
- Desired state of the project.
- Specifying C(present) is the same as running C(docker-compose up) resp. C(docker-compose stop) (with I(stopped)) resp. C(docker-compose restart)
(with I(restarted)).
- Specifying C(pulled) is the same as running C(docker-compose pull).
- Specifying C(built) is the same as running C(docker-compose build).
- Specifying C(stopped) is the same as running C(docker-compose stop).
- Specifying C(present) is the same as running C(docker-compose up).
- Specifying C(restarted) is the same as running C(docker-compose restart).
- Specifying C(absent) is the same as running C(docker-compose down).
type: str
default: present
choices:
- absent
- built
- present
- pulled
- restarted
- stopped
services:
description:
- When I(state) is C(present) run C(docker-compose up) resp. C(docker-compose stop) (with I(stopped)) resp. C(docker-compose restart) (with I(restarted))
Expand All @@ -80,6 +87,8 @@
description:
- When I(state) is C(present) specify whether or not to include linked services.
- When false, equivalent to C(docker-compose up --no-deps).
- When I(state) is C(pull) specify whether or not to also pull for linked services.
- When true, equivalent to C(docker-compose pull --include-deps).
type: bool
default: true
definition:
Expand All @@ -103,23 +112,22 @@
build:
description:
- Use with I(state) C(present) to always build images prior to starting the application.
- Same as running C(docker-compose build) with the pull option.
- Equivalent to C(docker-compose up --build).
- Images will only be rebuilt if Docker detects a change in the Dockerfile or build directory contents.
- Use the I(nocache) option to ignore the image cache when performing the build.
- If an existing image is replaced, services using the image will be recreated unless I(recreate) is C(never).
- Equivalent to C(docker-compose --profile).
type: bool
default: false
pull:
description:
- Use with I(state) C(present) to always pull images prior to starting the application.
- Same as running C(docker-compose pull).
- Equivalent to C(docker-compose up --pull always).
- When a new image is pulled, services using the image will be recreated unless I(recreate) is C(never).
type: bool
default: false
nocache:
description:
- Use with the I(build) option to ignore the cache during the image build process.
- Equivalent to C(docker-compose build --no-cache).
type: bool
default: false
remove_images:
Expand All @@ -136,18 +144,6 @@
- Equivalent to C(docker-compose down --volumes).
type: bool
default: false
stopped:
description:
- Use with I(state) C(present) to stop all containers defined in the Compose file.
- If I(services) is defined, only the containers listed there will be stopped.
type: bool
default: false
restarted:
description:
- Use with I(state) C(present) to restart all containers defined in the Compose file.
- If I(services) is defined, only the containers listed there will be restarted.
type: bool
default: false
remove_orphans:
description:
- Remove containers for services not defined in the Compose file.
Expand Down Expand Up @@ -491,15 +487,15 @@ def _run_subcommand(
) -> Tuple[int, str, str, List[ResourceEvent]]:
command = [DOCKER_COMPOSE_EXECUTABLE, '--ansi', 'never']
for file in files:
command += ['-f', file]
command.extend(['-f', file])
if project_name is not None:
command += ['-p', project_name]
command.extend(['-p', project_name])
if project_directory is not None:
command += ['--project-directory', project_directory]
command.extend(['--project-directory', project_directory])
if env_file is not None:
subcommand += ['--env-file', env_file]
command.extend(['--env-file', env_file])
for profile in profiles:
command += ['--profile', profile]
command.extend(['--profile', profile])
command += subcommand
kwargs = {}
if content is not None:
Expand Down Expand Up @@ -544,19 +540,19 @@ def up(
) -> Tuple[int, str, str, List[ResourceEvent]]:
subcommand = ['up', '-d']
if no_deps:
subcommand += ['--no-deps']
subcommand.append('--no-deps')
if pull:
subcommand += ['--pull', pull]
subcommand.extend(['--pull', pull])
if build:
subcommand += ['--build']
subcommand.append('--build')
if force_recreate:
subcommand += ['--force-recreate']
subcommand.append('--force-recreate')
if no_recreate:
subcommand += ['--no-recreate']
subcommand.append('--no-recreate')
if remove_orphans:
subcommand += ['--remove-orphans']
subcommand.append('--remove-orphans')
if timeout is not None:
subcommand += ['--timeout', '{:d}'.format(timeout)]
subcommand.extend(['--timeout', '{:d}'.format(timeout)])
for service in services:
subcommand.append(service)
return self._run_subcommand(
Expand Down Expand Up @@ -588,13 +584,13 @@ def down(
) -> Tuple[int, str, str, List[ResourceEvent]]:
subcommand = ['down']
if remove_orphans:
subcommand += ['--remove-orphans']
subcommand.append('--remove-orphans')
if rmi:
subcommand += ['--rmi', rmi]
subcommand.extend(['--rmi', rmi])
if volumes:
subcommand += ['--volumes']
subcommand.extend(['--volumes'])
if timeout is not None:
subcommand += ['--timeout', '{:d}'.format(timeout)]
subcommand.extend(['--timeout', '{:d}'.format(timeout)])
return self._run_subcommand(
subcommand,
files,
Expand All @@ -621,7 +617,7 @@ def stop(
) -> Tuple[int, str, str, List[ResourceEvent]]:
subcommand = ['stop']
if timeout is not None:
subcommand += ['--timeout', '{:d}'.format(timeout)]
subcommand.extend(['--timeout', '{:d}'.format(timeout)])
return self._run_subcommand(
subcommand,
files,
Expand Down Expand Up @@ -649,7 +645,70 @@ def restart(
) -> Tuple[int, str, str, List[ResourceEvent]]:
subcommand = ['restart']
if timeout is not None:
subcommand += ['--timeout', '{:d}'.format(timeout)]
subcommand.extend(['--timeout', '{:d}'.format(timeout)])
for service in services:
subcommand.append(service)
return self._run_subcommand(
subcommand,
files,
content,
project_name=project_name,
project_directory=project_directory,
profiles=profiles,
env_file=env_file,
)

def build(
self,
# Common arguments
files: List[str],
/,
content: Optional[str] = None,
*,
project_name: Optional[str] = None,
project_directory: Optional[str] = None,
profiles: List[str] = [],
env_file: Optional[str],
# Specific arguments
services: List[str] = [],
no_cache: bool = False,
pull: bool = False,
) -> Tuple[int, str, str, List[ResourceEvent]]:
subcommand = ['build']
if no_cache:
subcommand.append('--no-cache')
if pull:
subcommand.append('--pull')
for service in services:
subcommand.append(service)
return self._run_subcommand(
subcommand,
files,
content,
project_name=project_name,
project_directory=project_directory,
profiles=profiles,
env_file=env_file,
)

def pull(
self,
# Common arguments
files: List[str],
/,
content: Optional[str] = None,
*,
project_name: Optional[str] = None,
project_directory: Optional[str] = None,
profiles: List[str] = [],
env_file: Optional[str],
# Specific arguments
services: List[str] = [],
include_deps: bool = False,
) -> Tuple[int, str, str, List[ResourceEvent]]:
subcommand = ['pull']
if include_deps:
subcommand.append('--include-deps')
for service in services:
subcommand.append(service)
return self._run_subcommand(
Expand All @@ -672,7 +731,7 @@ def main():
env_file=dict(type='path'),
files=dict(type='list', elements='path'),
profiles=dict(type='list', elements='str'),
state=dict(type='str', default='present', choices=['absent', 'present']),
state=dict(type='str', default='present', choices=['absent', 'present', 'built', 'pulled', 'restarted', 'stopped']),
definition=dict(type='dict'),
recreate=dict(type='str', default='smart', choices=['always', 'never', 'smart']),
build=dict(type='bool', default=False),
Expand All @@ -699,6 +758,7 @@ def main():
)
if bool(module.params['stopped']) and bool(module.params['restarted']):
module.fail_json(changed=False, msg='Cannot use restarted and stopped at the same time.')
changed = False
compose = ComposeManager(module, module.params['docker_host'])
if module.params['definition'] is not None:
if not HAS_YAML:
Expand All @@ -718,32 +778,47 @@ def main():
env_file=module.params['env_file'],
)
if module.params['state'] == 'present':
if module.params['stopped']:
rc, out, err, events = compose.stop(
*common_args,
**common_kwargs,
timeout=module.params['timeout'],
)
elif module.params['restarted']:
rc, out, err, events = compose.restart(
*common_args,
**common_kwargs,
services=module.params['services'] or [],
timeout=module.params['timeout'],
)
else:
rc, out, err, events = compose.up(
*common_args,
**common_kwargs,
services=module.params['services'] or [],
no_deps=not module.params['dependencies'],
pull='always' if module.params['pull'] else None,
build=module.params['build'],
force_recreate=module.params['recreate'] == "always",
no_recreate=module.params['recreate'] == "never",
remove_orphans=module.params['remove_orphans'],
timeout=module.params['timeout'],
)
rc, out, err, events = compose.up(
*common_args,
**common_kwargs,
services=module.params['services'] or [],
no_deps=not module.params['dependencies'],
pull='always' if module.params['pull'] else None,
build=module.params['build'],
force_recreate=module.params['recreate'] == "always",
no_recreate=module.params['recreate'] == "never",
remove_orphans=module.params['remove_orphans'],
timeout=module.params['timeout'],
)
elif module.params['state'] == 'stopped':
rc, out, err, events = compose.stop(
*common_args,
**common_kwargs,
timeout=module.params['timeout'],
)
elif module.params['state'] == 'restarted':
rc, out, err, events = compose.restart(
*common_args,
**common_kwargs,
services=module.params['services'] or [],
timeout=module.params['timeout'],
)
elif module.params['state'] == 'built':
rc, out, err, events = compose.build(
*common_args,
**common_kwargs,
services=module.params['services'] or [],
no_cache=not module.params['nocache'],
pull=module.params['pull'],
)
elif module.params['state'] == 'pulled':
rc, out, err, events = compose.pull(
*common_args,
**common_kwargs,
services=module.params['services'] or [],
include_deps=module.params['dependencies'],
)
changed = True # We cannot detect change from docker-compose stderr
elif module.params['state'] == 'absent':
rc, out, err, events = compose.down(
*common_args,
Expand All @@ -754,12 +829,11 @@ def main():
timeout=module.params['timeout'],
)
else:
assert False
assert False # DEAD CODE
networks_states = defaultdict(list)
images_states = defaultdict(list)
volumes_states = defaultdict(list)
containers_states = defaultdict(list)
changed = False
for event in events:
collection = {
ResourceType.NETWORK: networks_states,
Expand Down

0 comments on commit af6218a

Please sign in to comment.