Skip to content

Commit ffc8689

Browse files
committed
rename builder to handler and add few more docker operations
1 parent 055c6a8 commit ffc8689

File tree

2 files changed

+123
-79
lines changed

2 files changed

+123
-79
lines changed

src/gaiaflow/managers/minikube_manager.py

Lines changed: 121 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -95,20 +95,20 @@ def run_cmd(self, args: list[str], **kwargs):
9595
return subprocess.run(full_cmd, **kwargs)
9696

9797

98-
class BaseDockerBuilder:
99-
"""Abstract docker builder with optional hooks."""
98+
class BaseDockerHandler:
99+
"""Abstract docker handler with optional hooks."""
100100

101101
@classmethod
102-
def get_docker_builder(cls, mode: str, **kwargs):
103-
builder_cls = BUILDER_REGISTRY.get(mode)
104-
if not builder_cls:
102+
def get_docker_handler(cls, mode: str, **kwargs):
103+
handler_cls = HANDLER_REGISTRY.get(mode)
104+
if not handler_cls:
105105
raise ValueError(f"Unknown Docker build mode: {mode}")
106-
return builder_cls(**kwargs)
106+
return handler_cls(**kwargs)
107107

108108
def pre_build(self, image_name: str, dockerfile_path: Path, project_path: Path):
109109
"""Override this if you want a different or no pre_build"""
110110
log_info(f"Updating Dockerfile at {dockerfile_path}")
111-
DockerHelper._add_copy_statements_to_dockerfile(
111+
BaseDockerHandler._add_copy_statements_to_dockerfile(
112112
str(dockerfile_path), find_python_packages(project_path)
113113
)
114114
runner_src = Path(__file__).parent.parent.resolve() / "core" / "runner.py"
@@ -121,58 +121,150 @@ def build(self, image_name: str, dockerfile_path: Path, project_path: Path):
121121
def post_build(self, image_name: str, dockerfile_path: Path, project_path: Path):
122122
pass
123123

124-
class LocalDockerBuilder(BaseDockerBuilder):
124+
def list_images(self):
125+
raise NotImplementedError
126+
127+
def remove_image(self, image_name: str):
128+
raise NotImplementedError
129+
130+
def prune_images(self):
131+
raise NotImplementedError
132+
133+
def _update_dockerfile(self, dockerfile_path: Path):
134+
BaseDockerHandler._add_copy_statements_to_dockerfile(
135+
str(dockerfile_path), find_python_packages(self.project_path)
136+
)
137+
138+
@staticmethod
139+
def _add_copy_statements_to_dockerfile(
140+
dockerfile_path: str, local_packages: list[str]
141+
):
142+
with open(dockerfile_path, "r") as f:
143+
lines = f.readlines()
144+
145+
env_index = next(
146+
(i for i, line in enumerate(lines) if line.strip().startswith("ENV")),
147+
None,
148+
)
149+
150+
if env_index is None:
151+
raise ValueError("No ENV found in Dockerfile.")
152+
153+
entrypoint_index = next(
154+
(
155+
i
156+
for i, line in enumerate(lines)
157+
if line.strip().startswith("ENTRYPOINT")
158+
),
159+
None,
160+
)
161+
162+
if entrypoint_index is None:
163+
raise ValueError("No ENTRYPOINT found in Dockerfile.")
164+
165+
copy_lines = [f"COPY {pkg} ./{pkg}\n" for pkg in local_packages]
166+
copy_lines.append("COPY runner.py ./runner.py\n")
167+
168+
updated_lines = (
169+
lines[: env_index + 1]
170+
+ copy_lines #
171+
+ lines[entrypoint_index:]
172+
)
173+
with open(dockerfile_path, "w") as f:
174+
f.writelines(updated_lines)
175+
176+
print("Dockerfile updated with COPY statements.")
177+
178+
class LocalDockerHandler(BaseDockerHandler):
125179
def build(self, image_name: str, dockerfile_path: Path, project_path: Path):
126180
log_info(f"Building Docker image [{image_name}] locally")
127181
run(
128182
["docker", "build", "-t", image_name, "-f", str(dockerfile_path), str(project_path)],
129183
"Error building Docker image locally",
130184
)
131185

132-
class MinikubeDockerBuilder(BaseDockerBuilder):
186+
def list_images(self):
187+
run(["docker", "image", "ls"], "Error listing Docker images locally")
188+
189+
def remove_image(self, image_name: str):
190+
run(["docker", "rmi", "-f", image_name], f"Error removing Docker image {image_name} "
191+
"locally")
192+
193+
def prune_images(self):
194+
run(["docker", "image", "prune", "-f"], "Error pruning Docker images "
195+
"locally")
196+
197+
class MinikubeDockerHandler(BaseDockerHandler):
133198
def __init__(self, minikube_helper: MinikubeHelper):
134199
self.minikube_helper = minikube_helper
200+
self.env = self._get_minikube_env()
135201

136202
def build(self, image_name: str, dockerfile_path: Path, project_path: Path):
137203
log_info(f"Building Docker image [{image_name}] in Minikube context")
138-
result = self.minikube_helper.run_cmd(
139-
["docker-env", "--shell", "bash"], stdout=subprocess.PIPE, check=True
140-
)
141-
env = DockerHelper._parse_minikube_env(result.stdout.decode())
142204
run(
143205
["docker", "build", "-t", image_name, "-f", str(dockerfile_path), str(project_path)],
144206
"Error building Docker image inside Minikube",
145-
env=env,
207+
env=self.env,
208+
)
209+
210+
def list_images(self):
211+
run(["docker", "image", "ls"],"Error listing Docker images inside Minikube", env=self.env)
212+
213+
def remove_image(self, image_name: str):
214+
run(["docker", "rmi", "-f", image_name], f"Error removing Docker image {image_name} "
215+
"inside Minikube", env=self.env)
216+
217+
def prune_images(self):
218+
run(["docker", "image", "prune", "-f"], "Error pruning Docker images "
219+
"inside Minikube", env=self.env)
220+
221+
def _get_minikube_env(self):
222+
result = self.minikube_helper.run_cmd(
223+
["docker-env", "--shell", "bash"], stdout=subprocess.PIPE, check=True
146224
)
225+
return MinikubeDockerHandler._parse_minikube_env(result.stdout.decode())
147226

148-
class LocalUserCustomImageDockerBuilder(LocalDockerBuilder):
227+
@staticmethod
228+
def _parse_minikube_env(output: str) -> dict:
229+
env = os.environ.copy()
230+
for line in output.splitlines():
231+
if line.startswith("export "):
232+
try:
233+
key, value = line.replace("export ", "").split("=", 1)
234+
env[key.strip()] = value.strip('"')
235+
except ValueError:
236+
continue
237+
return env
238+
239+
class LocalUserCustomImageDockerHandler(LocalDockerHandler):
149240
def pre_build(self, image_name: str, dockerfile_path: Path, project_path: Path):
150241
pass
242+
151243
def build(self, image_name: str, dockerfile_path: Path, project_path: Path):
152244
log_info("Building user provided dockerfile")
153245
super().build(image_name, dockerfile_path, project_path)
154246

155-
class MinikubeUserCustomImageDockerBuilder(MinikubeDockerBuilder):
247+
class MinikubeUserCustomImageDockerHandler(MinikubeDockerHandler):
156248
def pre_build(self, image_name: str, dockerfile_path: Path, project_path: Path):
157249
pass
158250

159251
def build(self, image_name: str, dockerfile_path: Path, project_path: Path):
160252
log_info("Building user provided dockerfile")
161253
super().build(image_name, dockerfile_path, project_path)
162254

163-
BUILDER_REGISTRY = {
164-
"local": LocalDockerBuilder,
165-
"minikube": MinikubeDockerBuilder,
166-
"local-user": LocalUserCustomImageDockerBuilder,
167-
"minikube-user": MinikubeUserCustomImageDockerBuilder
255+
HANDLER_REGISTRY = {
256+
"local": LocalDockerHandler,
257+
"minikube": MinikubeDockerHandler,
258+
"local-user": LocalUserCustomImageDockerHandler,
259+
"minikube-user": MinikubeUserCustomImageDockerHandler
168260
}
169261

170262
class DockerHelper:
171263
def __init__(
172264
self,
173265
image_name: str,
174266
project_path: Path,
175-
builder: BaseDockerBuilder
267+
builder: BaseDockerHandler
176268
):
177269
self.image_name = image_name
178270
self.project_path = project_path
@@ -194,62 +286,14 @@ def build_image(self, dockerfile_path: Path):
194286

195287
self.builder.post_build(self.image_name, dockerfile_path, self.project_path)
196288

197-
def _update_dockerfile(self, dockerfile_path: Path):
198-
DockerHelper._add_copy_statements_to_dockerfile(
199-
str(dockerfile_path), find_python_packages(self.project_path)
200-
)
201-
202-
@staticmethod
203-
def _parse_minikube_env(output: str) -> dict:
204-
env = os.environ.copy()
205-
for line in output.splitlines():
206-
if line.startswith("export "):
207-
try:
208-
key, value = line.replace("export ", "").split("=", 1)
209-
env[key.strip()] = value.strip('"')
210-
except ValueError:
211-
continue
212-
return env
213-
214-
@staticmethod
215-
def _add_copy_statements_to_dockerfile(
216-
dockerfile_path: str, local_packages: list[str]
217-
):
218-
with open(dockerfile_path, "r") as f:
219-
lines = f.readlines()
220-
221-
env_index = next(
222-
(i for i, line in enumerate(lines) if line.strip().startswith("ENV")),
223-
None,
224-
)
225-
226-
if env_index is None:
227-
raise ValueError("No ENV found in Dockerfile.")
228-
229-
entrypoint_index = next(
230-
(
231-
i
232-
for i, line in enumerate(lines)
233-
if line.strip().startswith("ENTRYPOINT")
234-
),
235-
None,
236-
)
237-
238-
if entrypoint_index is None:
239-
raise ValueError("No ENTRYPOINT found in Dockerfile.")
240-
241-
copy_lines = [f"COPY {pkg} ./{pkg}\n" for pkg in local_packages]
242-
copy_lines.append("COPY runner.py ./runner.py\n")
289+
def list_images(self):
290+
self.builder.list_images()
243291

244-
updated_lines = (
245-
lines[: env_index + 1]
246-
+ copy_lines #
247-
+ lines[entrypoint_index:]
248-
)
249-
with open(dockerfile_path, "w") as f:
250-
f.writelines(updated_lines)
292+
def remove_image(self, image_name: str):
293+
self.builder.remove_image(image_name)
251294

252-
print("Dockerfile updated with COPY statements.")
295+
def prune_images(self):
296+
self.builder.prune_images()
253297

254298

255299
class KubeConfigHelper:
@@ -348,7 +392,7 @@ def __init__(
348392
self.image_name = image_name
349393

350394
self.minikube_helper = MinikubeHelper()
351-
builder = BaseDockerBuilder.get_docker_builder(docker_build_mode,
395+
builder = BaseDockerHandler.get_docker_builder(docker_build_mode,
352396
minikube_helper=self.minikube_helper)
353397
self.docker_helper = DockerHelper(
354398
image_name=image_name,

src/gaiaflow/managers/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ def log_error(message: str):
5050
)
5151

5252

53-
def run(command: list, error_message: str, env=None):
53+
def run(command: list, error_message: str, **kwargs):
5454
try:
55-
subprocess.call(command, env=env)
55+
subprocess.call(command, **kwargs)
5656
except Exception:
5757
log_error(error_message)
5858
raise

0 commit comments

Comments
 (0)