mirror of
https://github.com/ansible-collections/community.docker.git
synced 2026-04-07 10:43:03 +00:00
Extract more common code and docs fragment for Docker Compose. (#748)
This commit is contained in:
parent
cb4dd2fed1
commit
8ca5e2f810
38
plugins/doc_fragments/compose_v2.py
Normal file
38
plugins/doc_fragments/compose_v2.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023, Felix Fontein <felix@fontein.de>
|
||||||
|
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleDocFragment(object):
|
||||||
|
|
||||||
|
# Docker doc fragment
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
options:
|
||||||
|
project_src:
|
||||||
|
description:
|
||||||
|
- Path to a directory containing a C(docker-compose.yml) or C(docker-compose.yaml) file.
|
||||||
|
type: path
|
||||||
|
required: true
|
||||||
|
project_name:
|
||||||
|
description:
|
||||||
|
- Provide a project name. If not provided, the project name is taken from the basename of O(project_src).
|
||||||
|
type: str
|
||||||
|
env_files:
|
||||||
|
description:
|
||||||
|
- By default environment files are loaded from a C(.env) file located directly under the O(project_src) directory.
|
||||||
|
- O(env_files) can be used to specify the path of one or multiple custom environment files instead.
|
||||||
|
- The path is relative to the O(project_src) directory.
|
||||||
|
type: list
|
||||||
|
elements: path
|
||||||
|
profiles:
|
||||||
|
description:
|
||||||
|
- List of profiles to enable when starting services.
|
||||||
|
- Equivalent to C(docker compose --profile).
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
'''
|
||||||
@ -7,12 +7,18 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
|
|
||||||
|
from ansible_collections.community.docker.plugins.module_utils.util import DockerBaseClass
|
||||||
|
from ansible_collections.community.docker.plugins.module_utils.version import LooseVersion
|
||||||
|
|
||||||
|
|
||||||
|
DOCKER_COMPOSE_FILES = 'docker-compose.yml', 'docker-compose.yaml'
|
||||||
|
|
||||||
DOCKER_STATUS_DONE = frozenset((
|
DOCKER_STATUS_DONE = frozenset((
|
||||||
'Started',
|
'Started',
|
||||||
@ -269,3 +275,129 @@ def update_failed(result, events, args, stdout, stderr, rc, cli):
|
|||||||
result['stderr'] = to_native(stderr)
|
result['stderr'] = to_native(stderr)
|
||||||
result['rc'] = rc
|
result['rc'] = rc
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def common_compose_argspec():
|
||||||
|
return dict(
|
||||||
|
project_src=dict(type='path', required=True),
|
||||||
|
project_name=dict(type='str'),
|
||||||
|
env_files=dict(type='list', elements='path'),
|
||||||
|
profiles=dict(type='list', elements='str'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def combine_binary_output(*outputs):
|
||||||
|
return b'\n'.join(out for out in outputs if out)
|
||||||
|
|
||||||
|
|
||||||
|
def combine_text_output(*outputs):
|
||||||
|
return '\n'.join(out for out in outputs if out)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseComposeManager(DockerBaseClass):
|
||||||
|
def __init__(self, client, min_version='2.18.0'):
|
||||||
|
super(BaseComposeManager, self).__init__()
|
||||||
|
self.client = client
|
||||||
|
self.check_mode = self.client.check_mode
|
||||||
|
parameters = self.client.module.params
|
||||||
|
|
||||||
|
self.project_src = parameters['project_src']
|
||||||
|
self.project_name = parameters['project_name']
|
||||||
|
self.env_files = parameters['env_files']
|
||||||
|
self.profiles = parameters['profiles']
|
||||||
|
|
||||||
|
compose = self.client.get_client_plugin_info('compose')
|
||||||
|
if compose is None:
|
||||||
|
self.client.fail('Docker CLI {0} does not have the compose plugin installed'.format(self.client.get_cli()))
|
||||||
|
compose_version = compose['Version'].lstrip('v')
|
||||||
|
self.compose_version = LooseVersion(compose_version)
|
||||||
|
if self.compose_version < LooseVersion(min_version):
|
||||||
|
self.client.fail('Docker CLI {cli} has the compose plugin with version {version}; need version {min_version} or later'.format(
|
||||||
|
cli=self.client.get_cli(),
|
||||||
|
version=compose_version,
|
||||||
|
min_version=min_version,
|
||||||
|
))
|
||||||
|
|
||||||
|
if not os.path.isdir(self.project_src):
|
||||||
|
self.client.fail('"{0}" is not a directory'.format(self.project_src))
|
||||||
|
|
||||||
|
if all(not os.path.isfile(os.path.join(self.project_src, f)) for f in DOCKER_COMPOSE_FILES):
|
||||||
|
self.client.fail('"{0}" does not contain {1}'.format(self.project_src, ' or '.join(DOCKER_COMPOSE_FILES)))
|
||||||
|
|
||||||
|
def get_base_args(self):
|
||||||
|
args = ['compose', '--ansi', 'never']
|
||||||
|
if self.compose_version >= LooseVersion('2.19.0'):
|
||||||
|
# https://github.com/docker/compose/pull/10690
|
||||||
|
args.extend(['--progress', 'plain'])
|
||||||
|
args.extend(['--project-directory', self.project_src])
|
||||||
|
if self.project_name:
|
||||||
|
args.extend(['--project-name', self.project_name])
|
||||||
|
for env_file in self.env_files or []:
|
||||||
|
args.extend(['--env-file', env_file])
|
||||||
|
for profile in self.profiles or []:
|
||||||
|
args.extend(['--profile', profile])
|
||||||
|
return args
|
||||||
|
|
||||||
|
def list_containers_raw(self):
|
||||||
|
args = self.get_base_args() + ['ps', '--format', 'json', '--all']
|
||||||
|
if self.compose_version >= LooseVersion('2.23.0'):
|
||||||
|
# https://github.com/docker/compose/pull/11038
|
||||||
|
args.append('--no-trunc')
|
||||||
|
kwargs = dict(cwd=self.project_src, check_rc=True)
|
||||||
|
if self.compose_version >= LooseVersion('2.21.0'):
|
||||||
|
# Breaking change in 2.21.0: https://github.com/docker/compose/pull/10918
|
||||||
|
dummy, containers, dummy = self.client.call_cli_json_stream(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
dummy, containers, dummy = self.client.call_cli_json(*args, **kwargs)
|
||||||
|
return containers
|
||||||
|
|
||||||
|
def list_containers(self):
|
||||||
|
result = []
|
||||||
|
for container in self.list_containers_raw():
|
||||||
|
labels = {}
|
||||||
|
if container.get('Labels'):
|
||||||
|
for part in container['Labels'].split(','):
|
||||||
|
label_value = part.split('=', 1)
|
||||||
|
labels[label_value[0]] = label_value[1] if len(label_value) > 1 else ''
|
||||||
|
container['Labels'] = labels
|
||||||
|
container['Names'] = container.get('Names', container['Name']).split(',')
|
||||||
|
container['Networks'] = container.get('Networks', '').split(',')
|
||||||
|
container['Publishers'] = container.get('Publishers') or []
|
||||||
|
result.append(container)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def list_images(self):
|
||||||
|
args = self.get_base_args() + ['images', '--format', 'json']
|
||||||
|
kwargs = dict(cwd=self.project_src, check_rc=True)
|
||||||
|
dummy, images, dummy = self.client.call_cli_json(*args, **kwargs)
|
||||||
|
return images
|
||||||
|
|
||||||
|
def parse_events(self, stderr, dry_run=False):
|
||||||
|
return parse_events(stderr, dry_run=dry_run, warn_function=self.client.warn)
|
||||||
|
|
||||||
|
def emit_warnings(self, events):
|
||||||
|
emit_warnings(events, warn_function=self.client.warn)
|
||||||
|
|
||||||
|
def update_result(self, result, events, stdout, stderr):
|
||||||
|
result['changed'] = result.get('changed', False) or has_changes(events)
|
||||||
|
result['actions'] = result.get('actions', []) + extract_actions(events)
|
||||||
|
result['stdout'] = combine_text_output(result.get('stdout'), to_native(stdout))
|
||||||
|
result['stderr'] = combine_text_output(result.get('stderr'), to_native(stderr))
|
||||||
|
|
||||||
|
def update_failed(self, result, events, args, stdout, stderr, rc):
|
||||||
|
return update_failed(
|
||||||
|
result,
|
||||||
|
events,
|
||||||
|
args=args,
|
||||||
|
stdout=stdout,
|
||||||
|
stderr=stderr,
|
||||||
|
rc=rc,
|
||||||
|
cli=self.client.get_cli(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def cleanup_result(self, result):
|
||||||
|
if not result.get('failed'):
|
||||||
|
# Only return stdout and stderr if it's not empty
|
||||||
|
for res in ('stdout', 'stderr'):
|
||||||
|
if result.get(res) == '':
|
||||||
|
result.pop(res)
|
||||||
|
|||||||
@ -22,6 +22,7 @@ description:
|
|||||||
- Uses Docker Compose to start or shutdown services.
|
- Uses Docker Compose to start or shutdown services.
|
||||||
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
|
- community.docker.compose_v2
|
||||||
- community.docker.docker.cli_documentation
|
- community.docker.docker.cli_documentation
|
||||||
- community.docker.attributes
|
- community.docker.attributes
|
||||||
- community.docker.attributes.actiongroup_docker
|
- community.docker.attributes.actiongroup_docker
|
||||||
@ -33,28 +34,6 @@ attributes:
|
|||||||
support: none
|
support: none
|
||||||
|
|
||||||
options:
|
options:
|
||||||
project_src:
|
|
||||||
description:
|
|
||||||
- Path to a directory containing a C(docker-compose.yml) or C(docker-compose.yaml) file.
|
|
||||||
type: path
|
|
||||||
required: true
|
|
||||||
project_name:
|
|
||||||
description:
|
|
||||||
- Provide a project name. If not provided, the project name is taken from the basename of O(project_src).
|
|
||||||
type: str
|
|
||||||
env_files:
|
|
||||||
description:
|
|
||||||
- By default environment files are loaded from a C(.env) file located directly under the O(project_src) directory.
|
|
||||||
- O(env_files) can be used to specify the path of one or multiple custom environment files instead.
|
|
||||||
- The path is relative to the O(project_src) directory.
|
|
||||||
type: list
|
|
||||||
elements: path
|
|
||||||
profiles:
|
|
||||||
description:
|
|
||||||
- List of profiles to enable when starting services.
|
|
||||||
- Equivalent to C(docker compose --profile).
|
|
||||||
type: list
|
|
||||||
elements: str
|
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- Desired state of the project.
|
- Desired state of the project.
|
||||||
@ -388,7 +367,6 @@ actions:
|
|||||||
- Pulling
|
- Pulling
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
@ -399,33 +377,20 @@ from ansible_collections.community.docker.plugins.module_utils.common_cli import
|
|||||||
)
|
)
|
||||||
|
|
||||||
from ansible_collections.community.docker.plugins.module_utils.compose_v2 import (
|
from ansible_collections.community.docker.plugins.module_utils.compose_v2 import (
|
||||||
parse_events,
|
BaseComposeManager,
|
||||||
has_changes,
|
common_compose_argspec,
|
||||||
extract_actions,
|
|
||||||
emit_warnings,
|
|
||||||
is_failed,
|
is_failed,
|
||||||
update_failed,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from ansible_collections.community.docker.plugins.module_utils.util import DockerBaseClass
|
|
||||||
from ansible_collections.community.docker.plugins.module_utils.version import LooseVersion
|
|
||||||
|
|
||||||
|
|
||||||
DOCKER_COMPOSE_MINIMAL_VERSION = '2.18.0'
|
DOCKER_COMPOSE_MINIMAL_VERSION = '2.18.0'
|
||||||
DOCKER_COMPOSE_FILES = 'docker-compose.yml', 'docker-compose.yaml'
|
|
||||||
|
|
||||||
|
|
||||||
class ContainerManager(DockerBaseClass):
|
class ServicesManager(BaseComposeManager):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
super(ContainerManager, self).__init__()
|
super(ServicesManager, self).__init__(client, min_version=DOCKER_COMPOSE_MINIMAL_VERSION)
|
||||||
self.client = client
|
|
||||||
self.check_mode = self.client.check_mode
|
|
||||||
parameters = self.client.module.params
|
parameters = self.client.module.params
|
||||||
|
|
||||||
self.project_src = parameters['project_src']
|
|
||||||
self.project_name = parameters['project_name']
|
|
||||||
self.env_files = parameters['env_files']
|
|
||||||
self.profiles = parameters['profiles']
|
|
||||||
self.state = parameters['state']
|
self.state = parameters['state']
|
||||||
self.dependencies = parameters['dependencies']
|
self.dependencies = parameters['dependencies']
|
||||||
self.pull = parameters['pull']
|
self.pull = parameters['pull']
|
||||||
@ -435,72 +400,6 @@ class ContainerManager(DockerBaseClass):
|
|||||||
self.remove_orphans = parameters['remove_orphans']
|
self.remove_orphans = parameters['remove_orphans']
|
||||||
self.timeout = parameters['timeout']
|
self.timeout = parameters['timeout']
|
||||||
|
|
||||||
compose = self.client.get_client_plugin_info('compose')
|
|
||||||
if compose is None:
|
|
||||||
self.client.fail('Docker CLI {0} does not have the compose plugin installed'.format(self.client.get_cli()))
|
|
||||||
compose_version = compose['Version'].lstrip('v')
|
|
||||||
self.compose_version = LooseVersion(compose_version)
|
|
||||||
if self.compose_version < LooseVersion(DOCKER_COMPOSE_MINIMAL_VERSION):
|
|
||||||
self.client.fail('Docker CLI {cli} has the compose plugin with version {version}; need version {min_version} or later'.format(
|
|
||||||
cli=self.client.get_cli(),
|
|
||||||
version=compose_version,
|
|
||||||
min_version=DOCKER_COMPOSE_MINIMAL_VERSION,
|
|
||||||
))
|
|
||||||
|
|
||||||
if not os.path.isdir(self.project_src):
|
|
||||||
self.client.fail('"{0}" is not a directory'.format(self.project_src))
|
|
||||||
|
|
||||||
if all(not os.path.isfile(os.path.join(self.project_src, f)) for f in DOCKER_COMPOSE_FILES):
|
|
||||||
self.client.fail('"{0}" does not contain {1}'.format(self.project_src, ' or '.join(DOCKER_COMPOSE_FILES)))
|
|
||||||
|
|
||||||
def get_base_args(self):
|
|
||||||
args = ['compose', '--ansi', 'never']
|
|
||||||
if self.compose_version >= LooseVersion('2.19.0'):
|
|
||||||
# https://github.com/docker/compose/pull/10690
|
|
||||||
args.extend(['--progress', 'plain'])
|
|
||||||
args.extend(['--project-directory', self.project_src])
|
|
||||||
if self.project_name:
|
|
||||||
args.extend(['--project-name', self.project_name])
|
|
||||||
for env_file in self.env_files or []:
|
|
||||||
args.extend(['--env-file', env_file])
|
|
||||||
for profile in self.profiles or []:
|
|
||||||
args.extend(['--profile', profile])
|
|
||||||
return args
|
|
||||||
|
|
||||||
def list_containers_raw(self):
|
|
||||||
args = self.get_base_args() + ['ps', '--format', 'json', '--all']
|
|
||||||
if self.compose_version >= LooseVersion('2.23.0'):
|
|
||||||
# https://github.com/docker/compose/pull/11038
|
|
||||||
args.append('--no-trunc')
|
|
||||||
kwargs = dict(cwd=self.project_src, check_rc=True)
|
|
||||||
if self.compose_version >= LooseVersion('2.21.0'):
|
|
||||||
# Breaking change in 2.21.0: https://github.com/docker/compose/pull/10918
|
|
||||||
dummy, containers, dummy = self.client.call_cli_json_stream(*args, **kwargs)
|
|
||||||
else:
|
|
||||||
dummy, containers, dummy = self.client.call_cli_json(*args, **kwargs)
|
|
||||||
return containers
|
|
||||||
|
|
||||||
def list_containers(self):
|
|
||||||
result = []
|
|
||||||
for container in self.list_containers_raw():
|
|
||||||
labels = {}
|
|
||||||
if container.get('Labels'):
|
|
||||||
for part in container['Labels'].split(','):
|
|
||||||
label_value = part.split('=', 1)
|
|
||||||
labels[label_value[0]] = label_value[1] if len(label_value) > 1 else ''
|
|
||||||
container['Labels'] = labels
|
|
||||||
container['Names'] = container.get('Names', container['Name']).split(',')
|
|
||||||
container['Networks'] = container.get('Networks', '').split(',')
|
|
||||||
container['Publishers'] = container.get('Publishers') or []
|
|
||||||
result.append(container)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def list_images(self):
|
|
||||||
args = self.get_base_args() + ['images', '--format', 'json']
|
|
||||||
kwargs = dict(cwd=self.project_src, check_rc=True)
|
|
||||||
dummy, images, dummy = self.client.call_cli_json(*args, **kwargs)
|
|
||||||
return images
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.state == 'present':
|
if self.state == 'present':
|
||||||
result = self.cmd_up()
|
result = self.cmd_up()
|
||||||
@ -513,30 +412,9 @@ class ContainerManager(DockerBaseClass):
|
|||||||
|
|
||||||
result['containers'] = self.list_containers()
|
result['containers'] = self.list_containers()
|
||||||
result['images'] = self.list_images()
|
result['images'] = self.list_images()
|
||||||
if not result.get('failed'):
|
self.cleanup_result(result)
|
||||||
# Only return stdout and stderr if it's not empty
|
|
||||||
for res in ('stdout', 'stderr'):
|
|
||||||
if result.get(res) == '':
|
|
||||||
result.pop(res)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def parse_events(self, stderr, dry_run=False):
|
|
||||||
return parse_events(stderr, dry_run=dry_run, warn_function=self.client.warn)
|
|
||||||
|
|
||||||
def emit_warnings(self, events):
|
|
||||||
emit_warnings(events, warn_function=self.client.warn)
|
|
||||||
|
|
||||||
def update_failed(self, result, events, args, stdout, stderr, rc):
|
|
||||||
return update_failed(
|
|
||||||
result,
|
|
||||||
events,
|
|
||||||
args=args,
|
|
||||||
stdout=stdout,
|
|
||||||
stderr=stderr,
|
|
||||||
rc=rc,
|
|
||||||
cli=self.client.get_cli(),
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_up_cmd(self, dry_run, no_start=False):
|
def get_up_cmd(self, dry_run, no_start=False):
|
||||||
args = self.get_base_args() + ['up', '--detach', '--no-color', '--quiet-pull']
|
args = self.get_base_args() + ['up', '--detach', '--no-color', '--quiet-pull']
|
||||||
if self.pull != 'policy':
|
if self.pull != 'policy':
|
||||||
@ -564,10 +442,7 @@ class ContainerManager(DockerBaseClass):
|
|||||||
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
|
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
|
||||||
events = self.parse_events(stderr, dry_run=self.check_mode)
|
events = self.parse_events(stderr, dry_run=self.check_mode)
|
||||||
self.emit_warnings(events)
|
self.emit_warnings(events)
|
||||||
result['changed'] = has_changes(events)
|
self.update_result(result, events, stdout, stderr)
|
||||||
result['actions'] = extract_actions(events)
|
|
||||||
result['stdout'] = to_native(stdout)
|
|
||||||
result['stderr'] = to_native(stderr)
|
|
||||||
self.update_failed(result, events, args, stdout, stderr, rc)
|
self.update_failed(result, events, args, stdout, stderr, rc)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -586,10 +461,6 @@ class ContainerManager(DockerBaseClass):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _combine_output(*outputs):
|
|
||||||
return b'\n'.join(out for out in outputs if out)
|
|
||||||
|
|
||||||
def cmd_stop(self):
|
def cmd_stop(self):
|
||||||
# Since 'docker compose stop' **always** claims its stopping containers, even if they are already
|
# Since 'docker compose stop' **always** claims its stopping containers, even if they are already
|
||||||
# stopped, we have to do this a bit more complicated.
|
# stopped, we have to do this a bit more complicated.
|
||||||
@ -600,6 +471,7 @@ class ContainerManager(DockerBaseClass):
|
|||||||
rc_1, stdout_1, stderr_1 = self.client.call_cli(*args_1, cwd=self.project_src)
|
rc_1, stdout_1, stderr_1 = self.client.call_cli(*args_1, cwd=self.project_src)
|
||||||
events_1 = self.parse_events(stderr_1, dry_run=self.check_mode)
|
events_1 = self.parse_events(stderr_1, dry_run=self.check_mode)
|
||||||
self.emit_warnings(events_1)
|
self.emit_warnings(events_1)
|
||||||
|
self.update_result(result, events_1, stdout_1, stderr_1)
|
||||||
is_failed_1 = is_failed(events_1, rc_1)
|
is_failed_1 = is_failed(events_1, rc_1)
|
||||||
if not is_failed_1 and not self._are_containers_stopped():
|
if not is_failed_1 and not self._are_containers_stopped():
|
||||||
# Make sure all containers are stopped
|
# Make sure all containers are stopped
|
||||||
@ -607,15 +479,12 @@ class ContainerManager(DockerBaseClass):
|
|||||||
rc_2, stdout_2, stderr_2 = self.client.call_cli(*args_2, cwd=self.project_src)
|
rc_2, stdout_2, stderr_2 = self.client.call_cli(*args_2, cwd=self.project_src)
|
||||||
events_2 = self.parse_events(stderr_2, dry_run=self.check_mode)
|
events_2 = self.parse_events(stderr_2, dry_run=self.check_mode)
|
||||||
self.emit_warnings(events_2)
|
self.emit_warnings(events_2)
|
||||||
|
self.update_result(result, events_2, stdout_2, stderr_2)
|
||||||
else:
|
else:
|
||||||
args_2 = []
|
args_2 = []
|
||||||
rc_2, stdout_2, stderr_2 = 0, b'', b''
|
rc_2, stdout_2, stderr_2 = 0, b'', b''
|
||||||
events_2 = []
|
events_2 = []
|
||||||
# Compose result
|
# Compose result
|
||||||
result['changed'] = has_changes(events_1) or has_changes(events_2)
|
|
||||||
result['actions'] = extract_actions(events_1) + extract_actions(events_2)
|
|
||||||
result['stdout'] = to_native(self._combine_output(stdout_1, stdout_2))
|
|
||||||
result['stderr'] = to_native(self._combine_output(stderr_1, stderr_2))
|
|
||||||
self.update_failed(
|
self.update_failed(
|
||||||
result,
|
result,
|
||||||
events_1 + events_2,
|
events_1 + events_2,
|
||||||
@ -643,10 +512,7 @@ class ContainerManager(DockerBaseClass):
|
|||||||
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
|
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
|
||||||
events = self.parse_events(stderr, dry_run=self.check_mode)
|
events = self.parse_events(stderr, dry_run=self.check_mode)
|
||||||
self.emit_warnings(events)
|
self.emit_warnings(events)
|
||||||
result['changed'] = has_changes(events)
|
self.update_result(result, events, stdout, stderr)
|
||||||
result['actions'] = extract_actions(events)
|
|
||||||
result['stdout'] = to_native(stdout)
|
|
||||||
result['stderr'] = to_native(stderr)
|
|
||||||
self.update_failed(result, events, args, stdout, stderr, rc)
|
self.update_failed(result, events, args, stdout, stderr, rc)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -671,20 +537,13 @@ class ContainerManager(DockerBaseClass):
|
|||||||
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
|
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
|
||||||
events = self.parse_events(stderr, dry_run=self.check_mode)
|
events = self.parse_events(stderr, dry_run=self.check_mode)
|
||||||
self.emit_warnings(events)
|
self.emit_warnings(events)
|
||||||
result['changed'] = has_changes(events)
|
self.update_result(result, events, stdout, stderr)
|
||||||
result['actions'] = extract_actions(events)
|
|
||||||
result['stdout'] = to_native(stdout)
|
|
||||||
result['stderr'] = to_native(stderr)
|
|
||||||
self.update_failed(result, events, args, stdout, stderr, rc)
|
self.update_failed(result, events, args, stdout, stderr, rc)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
project_src=dict(type='path', required=True),
|
|
||||||
project_name=dict(type='str'),
|
|
||||||
env_files=dict(type='list', elements='path'),
|
|
||||||
profiles=dict(type='list', elements='str'),
|
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present', 'stopped', 'restarted']),
|
state=dict(type='str', default='present', choices=['absent', 'present', 'stopped', 'restarted']),
|
||||||
dependencies=dict(type='bool', default=True),
|
dependencies=dict(type='bool', default=True),
|
||||||
pull=dict(type='str', choices=['always', 'missing', 'never', 'policy'], default='policy'),
|
pull=dict(type='str', choices=['always', 'missing', 'never', 'policy'], default='policy'),
|
||||||
@ -694,6 +553,7 @@ def main():
|
|||||||
remove_orphans=dict(type='bool', default=False),
|
remove_orphans=dict(type='bool', default=False),
|
||||||
timeout=dict(type='int'),
|
timeout=dict(type='int'),
|
||||||
)
|
)
|
||||||
|
argument_spec.update(common_compose_argspec())
|
||||||
|
|
||||||
client = AnsibleModuleDockerClient(
|
client = AnsibleModuleDockerClient(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
@ -701,7 +561,7 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = ContainerManager(client).run()
|
result = ServicesManager(client).run()
|
||||||
client.module.exit_json(**result)
|
client.module.exit_json(**result)
|
||||||
except DockerException as e:
|
except DockerException as e:
|
||||||
client.fail('An unexpected docker error occurred: {0}'.format(to_native(e)), exception=traceback.format_exc())
|
client.fail('An unexpected docker error occurred: {0}'.format(to_native(e)), exception=traceback.format_exc())
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user