Skip to content

Commit cb6df6d

Browse files
author
Alan Christie
committed
refactor: Adjusts the Compose logic
Use of entrypoint and command in compose Sets group ID in compose
1 parent 518315b commit cb6df6d

File tree

1 file changed

+37
-27
lines changed

1 file changed

+37
-27
lines changed

src/jote/compose.py

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,42 @@
11
"""The Job Tester 'compose' module.
22
3-
This module is responsible for injecting a docker-compose file into the
3+
This module is responsible for injecting a 'docker-compose.yml' file into the
44
repository of the Data Manager Job repository under test. It also
5-
executes docker-compose and can remove the test directory.
5+
created project and instance directories, and executes 'docker-compose up'
6+
to run the Job, and can remove the test directory.
7+
8+
This module is designed to simulate the actions of the Data Manager
9+
and Job Operator that are running in the DM kubernetes deployment.
610
"""
711
import copy
812
import os
913
import shutil
1014
import subprocess
1115
from typing import Any, Dict, Optional, Tuple
1216

17+
# The 'simulated' instance directory,
18+
# created by the Data Manager prior to launching the corresponding Job.
19+
# Jobs know this directory because their container has this set via
20+
# the environment variable 'DM_INSTANCE_DIRECTORY'.
1321
INSTANCE_DIRECTORY: str = ".instance-88888888-8888-8888-8888-888888888888"
1422

15-
# A default test execution timeout
23+
# A default test execution timeout (minutes)
1624
DEFAULT_TEST_TIMEOUT_M: int = 10
1725

18-
# The user id containers will be started as
19-
_USER_ID: int = 8888
20-
26+
# The docker-compose file template.
27+
# A multi-line string with variable mapping,
28+
# expanded and written to the test directory in 'create()'.
2129
_COMPOSE_CONTENT: str = """---
30+
# We use compose v2
31+
# because we're relying on 'mem_limit' and 'cpus',
32+
# which are ignored (moved to swarm) in v3.
2233
version: '2.4'
2334
services:
2435
job:
2536
image: {image}
2637
container_name: {job}-{test}-jote
27-
user: '{uid}'
28-
entrypoint: {working_directory}/{instance_directory}/command
38+
user: '{uid}:{gid}'
39+
entrypoint: {command}
2940
command: []
3041
working_dir: {working_directory}
3142
volumes:
@@ -35,8 +46,7 @@
3546
cpus: {cpus}.0
3647
environment:
3748
- DM_INSTANCE_DIRECTORY={instance_directory}
38-
{additional_environment}
39-
"""
49+
{additional_environment}"""
4050

4151
_NF_CONFIG_CONTENT: str = """
4252
docker.enabled = true
@@ -84,6 +94,7 @@ def __init__(
8494
command: str,
8595
test_environment: Dict[str, str],
8696
user_id: Optional[int] = None,
97+
group_id: Optional[int] = None,
8798
):
8899

89100
# Memory must have a Mi or Gi suffix.
@@ -105,6 +116,7 @@ def __init__(
105116
self._command: str = command
106117
self._test_environment = copy.deepcopy(test_environment)
107118
self._user_id: Optional[int] = user_id
119+
self._group_id: Optional[int] = group_id
108120

109121
def get_test_path(self) -> str:
110122
"""Returns the path to the root directory for a given test."""
@@ -122,7 +134,7 @@ def create(self) -> str:
122134
full path to the test (project) directory.
123135
"""
124136

125-
print("# Creating test environment...")
137+
print("# Compose: Creating test environment...")
126138

127139
# First, delete
128140
test_path: str = self.get_test_path()
@@ -132,7 +144,7 @@ def create(self) -> str:
132144
# Do we have the docker-compose version the user's installed?
133145
if not Compose._COMPOSE_VERSION:
134146
Compose._COMPOSE_VERSION = _get_docker_compose_version()
135-
print(f"# docker-compose ({Compose._COMPOSE_VERSION})")
147+
print(f"# Compose: docker-compose ({Compose._COMPOSE_VERSION})")
136148

137149
# Make the test directory
138150
# (where the test is launched from)
@@ -143,25 +155,31 @@ def create(self) -> str:
143155
if not os.path.exists(inst_path):
144156
os.makedirs(inst_path)
145157

146-
# Run as a specific user ID?
158+
# Run as a specific user/group ID?
147159
if self._user_id is not None:
148160
user_id = self._user_id
149161
else:
150162
user_id = os.getuid()
163+
if self._group_id is not None:
164+
group_id = self._group_id
165+
else:
166+
group_id = os.getgid()
151167

152168
# Write the Docker compose content to a file in the test directory
153169
additional_environment: str = ""
154170
if self._test_environment:
155171
for e_name, e_value in self._test_environment.items():
156172
additional_environment += f" - {e_name}='{e_value}'\n"
157173
variables: Dict[str, Any] = {
174+
"command": self._command,
158175
"test_path": project_path,
159176
"job": self._job,
160177
"test": self._test,
161178
"image": self._image,
162179
"memory_limit": self._memory,
163180
"cpus": self._cores,
164181
"uid": user_id,
182+
"gid": group_id,
165183
"project_directory": self._project_directory,
166184
"working_directory": self._working_directory,
167185
"instance_directory": INSTANCE_DIRECTORY,
@@ -172,14 +190,6 @@ def create(self) -> str:
172190
with open(compose_path, "wt", encoding="UTF-8") as compose_file:
173191
compose_file.write(compose_content)
174192

175-
# Now write the command to the instance directory, as `command`.
176-
command_path: str = f"{inst_path}/command"
177-
with open(command_path, "wt", encoding="UTF-8") as command_file:
178-
command_file.write("#!/bin/sh\numask 0002\n")
179-
command_file.write(self._command + "\n")
180-
# And set read/write/execute permission...
181-
os.chmod(command_path, 0o775)
182-
183193
# nextflow config?
184194
if self._image_type == "nextflow":
185195
# Write a nextflow config to the project path
@@ -189,7 +199,7 @@ def create(self) -> str:
189199
with open(nf_cfg_path, "wt", encoding="UTF-8") as nf_cfg_file:
190200
nf_cfg_file.write(_NF_CONFIG_CONTENT)
191201

192-
print("# Created")
202+
print("# Compose: Created")
193203

194204
return project_path
195205

@@ -204,8 +214,8 @@ def run(
204214

205215
execution_directory: str = self.get_test_path()
206216

207-
print('# Executing the test ("docker-compose up")...')
208-
print(f'# Execution directory is "{execution_directory}"')
217+
print('# Compose: Executing the test ("docker-compose up")...')
218+
print(f'# Compose: Execution directory is "{execution_directory}"')
209219

210220
cwd = os.getcwd()
211221
os.chdir(execution_directory)
@@ -234,16 +244,16 @@ def run(
234244
finally:
235245
os.chdir(cwd)
236246

237-
print(f"# Executed (exit code {test.returncode})")
247+
print(f"# Compose: Executed (exit code {test.returncode})")
238248

239249
return test.returncode, test.stdout.decode("utf-8"), test.stderr.decode("utf-8")
240250

241251
def delete(self) -> None:
242252
"""Deletes a test directory created by 'create()'."""
243-
print("# Deleting the test...")
253+
print("# Compose: Deleting the test...")
244254

245255
test_path: str = self.get_test_path()
246256
if os.path.exists(test_path):
247257
shutil.rmtree(test_path)
248258

249-
print("# Deleted")
259+
print("# Compose: Deleted")

0 commit comments

Comments
 (0)