Skip to content

Commit 30f3a13

Browse files
committed
Add docker_compose_v2_build module (#956)
1 parent 8b55159 commit 30f3a13

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

meta/runtime.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ requires_ansible: '>=2.15.0'
77
action_groups:
88
docker:
99
- docker_compose_v2
10+
- docker_compose_v2_build
1011
- docker_compose_v2_exec
1112
- docker_compose_v2_pull
1213
- docker_compose_v2_run
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/python
2+
#
3+
# Copyright (c) 2023, Felix Fontein <[email protected]>
4+
# Copyright (c) 2025, Maciej Bogusz (@mjbogusz)
5+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
6+
# SPDX-License-Identifier: GPL-3.0-or-later
7+
8+
from __future__ import absolute_import, division, print_function
9+
__metaclass__ = type
10+
11+
12+
DOCUMENTATION = r"""
13+
module: docker_compose_v2_build
14+
15+
short_description: Build a Docker compose project
16+
17+
version_added: 4.7.0
18+
19+
description:
20+
- Uses Docker Compose to build images for a project.
21+
extends_documentation_fragment:
22+
- community.docker.compose_v2
23+
- community.docker.compose_v2.minimum_version
24+
- community.docker.docker.cli_documentation
25+
- community.docker.attributes
26+
- community.docker.attributes.actiongroup_docker
27+
28+
attributes:
29+
check_mode:
30+
support: full
31+
diff_mode:
32+
support: none
33+
idempotent:
34+
support: full
35+
36+
options:
37+
no_cache:
38+
description:
39+
- If set to V(true), will not use cache when building the images.
40+
type: bool
41+
default: false
42+
pull:
43+
description:
44+
- If set to V(true), will attempt to pull newer version of the image
45+
type: bool
46+
default: false
47+
with_dependencies:
48+
description:
49+
- If set to V(true), also build services that are declared as dependencies.
50+
- This only makes sense if O(services) is used.
51+
type: bool
52+
default: false
53+
memory_limit:
54+
description:
55+
- Memory limit for the build container, in bytes. Not supported by BuildKit
56+
type: int
57+
services:
58+
description:
59+
- Specifies a subset of services to be targeted.
60+
type: list
61+
elements: str
62+
63+
author:
64+
- Maciej Bogusz (@mjbogusz)
65+
66+
seealso:
67+
- module: community.docker.docker_compose_v2
68+
"""
69+
70+
EXAMPLES = r"""
71+
---
72+
- name: Build images for flask project
73+
community.docker.docker_compose_v2_build:
74+
project_src: /path/to/flask
75+
"""
76+
77+
RETURN = r"""
78+
actions:
79+
description:
80+
- A list of actions that have been applied.
81+
returned: success
82+
type: list
83+
elements: dict
84+
contains:
85+
what:
86+
description:
87+
- What kind of resource was changed.
88+
type: str
89+
sample: container
90+
choices:
91+
- image
92+
- unknown
93+
id:
94+
description:
95+
- The ID of the resource that was changed.
96+
type: str
97+
sample: container
98+
status:
99+
description:
100+
- The status change that happened.
101+
type: str
102+
sample: Building
103+
choices:
104+
- Building
105+
"""
106+
107+
import traceback
108+
109+
from ansible.module_utils.common.text.converters import to_native
110+
111+
from ansible_collections.community.docker.plugins.module_utils.common_cli import (
112+
AnsibleModuleDockerClient,
113+
DockerException,
114+
)
115+
116+
from ansible_collections.community.docker.plugins.module_utils.compose_v2 import (
117+
BaseComposeManager,
118+
common_compose_argspec_ex,
119+
)
120+
121+
122+
class BuildManager(BaseComposeManager):
123+
def __init__(self, client):
124+
super(BuildManager, self).__init__(client)
125+
parameters = self.client.module.params
126+
127+
self.no_cache = parameters['no_cache']
128+
self.pull = parameters['pull']
129+
self.with_dependencies = parameters['with_dependencies']
130+
self.memory_limit = parameters['memory_limit']
131+
self.services = parameters['services'] or []
132+
133+
def get_build_cmd(self, dry_run):
134+
args = self.get_base_args() + ['build']
135+
if self.no_cache:
136+
args.append('--no-cache')
137+
if self.pull:
138+
args.append('--pull')
139+
if self.with_dependencies:
140+
args.append('--with-dependencies')
141+
if self.memory_limit:
142+
args.extend(['--memory', str(self.memory_limit)])
143+
if dry_run:
144+
args.append('--dry-run')
145+
args.append('--')
146+
for service in self.services:
147+
args.append(service)
148+
return args
149+
150+
def run(self):
151+
result = dict()
152+
args = self.get_build_cmd(self.check_mode)
153+
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
154+
events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0)
155+
self.emit_warnings(events)
156+
self.update_result(result, events, stdout, stderr, ignore_ignore_build_events=not self.check_mode)
157+
self.update_failed(result, events, args, stdout, stderr, rc)
158+
self.cleanup_result(result)
159+
return result
160+
161+
162+
def main():
163+
argument_spec = dict(
164+
no_cache=dict(type='bool', default=False),
165+
pull=dict(type='bool', default=False),
166+
with_dependencies=dict(type='bool', default=False),
167+
memory_limit=dict(type='int'),
168+
services=dict(type='list', elements='str'),
169+
)
170+
argspec_ex = common_compose_argspec_ex()
171+
argument_spec.update(argspec_ex.pop('argspec'))
172+
173+
client = AnsibleModuleDockerClient(
174+
argument_spec=argument_spec,
175+
supports_check_mode=True,
176+
needs_api_version=False,
177+
**argspec_ex
178+
)
179+
180+
try:
181+
manager = BuildManager(client)
182+
result = manager.run()
183+
manager.cleanup()
184+
client.module.exit_json(**result)
185+
except DockerException as e:
186+
client.fail('An unexpected docker error occurred: {0}'.format(to_native(e)), exception=traceback.format_exc())
187+
188+
189+
if __name__ == '__main__':
190+
main()

0 commit comments

Comments
 (0)