pactown 0.1.4__py3-none-any.whl → 0.1.47__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pactown/__init__.py +178 -4
- pactown/cli.py +539 -37
- pactown/config.py +12 -11
- pactown/deploy/__init__.py +17 -3
- pactown/deploy/base.py +35 -33
- pactown/deploy/compose.py +59 -58
- pactown/deploy/docker.py +40 -41
- pactown/deploy/kubernetes.py +43 -42
- pactown/deploy/podman.py +55 -56
- pactown/deploy/quadlet.py +1021 -0
- pactown/deploy/quadlet_api.py +533 -0
- pactown/deploy/quadlet_shell.py +557 -0
- pactown/events.py +1066 -0
- pactown/fast_start.py +514 -0
- pactown/generator.py +31 -30
- pactown/llm.py +450 -0
- pactown/markpact_blocks.py +50 -0
- pactown/network.py +59 -38
- pactown/orchestrator.py +90 -93
- pactown/parallel.py +40 -40
- pactown/platform.py +146 -0
- pactown/registry/__init__.py +1 -1
- pactown/registry/client.py +45 -46
- pactown/registry/models.py +25 -25
- pactown/registry/server.py +24 -24
- pactown/resolver.py +30 -30
- pactown/runner_api.py +458 -0
- pactown/sandbox_manager.py +480 -79
- pactown/security.py +682 -0
- pactown/service_runner.py +1201 -0
- pactown/user_isolation.py +458 -0
- {pactown-0.1.4.dist-info → pactown-0.1.47.dist-info}/METADATA +65 -9
- pactown-0.1.47.dist-info/RECORD +36 -0
- pactown-0.1.47.dist-info/entry_points.txt +5 -0
- pactown-0.1.4.dist-info/RECORD +0 -24
- pactown-0.1.4.dist-info/entry_points.txt +0 -3
- {pactown-0.1.4.dist-info → pactown-0.1.47.dist-info}/WHEEL +0 -0
- {pactown-0.1.4.dist-info → pactown-0.1.47.dist-info}/licenses/LICENSE +0 -0
pactown/deploy/docker.py
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import subprocess
|
|
6
5
|
import json
|
|
6
|
+
import subprocess
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Any, Optional
|
|
9
9
|
|
|
10
10
|
from .base import (
|
|
11
11
|
DeploymentBackend,
|
|
12
|
-
DeploymentConfig,
|
|
13
12
|
DeploymentResult,
|
|
14
13
|
RuntimeType,
|
|
15
14
|
)
|
|
@@ -17,11 +16,11 @@ from .base import (
|
|
|
17
16
|
|
|
18
17
|
class DockerBackend(DeploymentBackend):
|
|
19
18
|
"""Docker container runtime backend."""
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
@property
|
|
22
21
|
def runtime_type(self) -> RuntimeType:
|
|
23
22
|
return RuntimeType.DOCKER
|
|
24
|
-
|
|
23
|
+
|
|
25
24
|
def is_available(self) -> bool:
|
|
26
25
|
"""Check if Docker is available."""
|
|
27
26
|
try:
|
|
@@ -34,7 +33,7 @@ class DockerBackend(DeploymentBackend):
|
|
|
34
33
|
return result.returncode == 0
|
|
35
34
|
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
36
35
|
return False
|
|
37
|
-
|
|
36
|
+
|
|
38
37
|
def build_image(
|
|
39
38
|
self,
|
|
40
39
|
service_name: str,
|
|
@@ -48,18 +47,18 @@ class DockerBackend(DeploymentBackend):
|
|
|
48
47
|
image_name = f"{image_name}:{tag}"
|
|
49
48
|
else:
|
|
50
49
|
image_name = f"{image_name}:latest"
|
|
51
|
-
|
|
50
|
+
|
|
52
51
|
cmd = [
|
|
53
52
|
"docker", "build",
|
|
54
53
|
"-t", image_name,
|
|
55
54
|
"-f", str(dockerfile_path),
|
|
56
55
|
str(context_path),
|
|
57
56
|
]
|
|
58
|
-
|
|
57
|
+
|
|
59
58
|
# Add labels
|
|
60
59
|
for key, value in self.config.labels.items():
|
|
61
60
|
cmd.extend(["--label", f"{key}={value}"])
|
|
62
|
-
|
|
61
|
+
|
|
63
62
|
try:
|
|
64
63
|
result = subprocess.run(
|
|
65
64
|
cmd,
|
|
@@ -67,7 +66,7 @@ class DockerBackend(DeploymentBackend):
|
|
|
67
66
|
text=True,
|
|
68
67
|
timeout=300,
|
|
69
68
|
)
|
|
70
|
-
|
|
69
|
+
|
|
71
70
|
if result.returncode == 0:
|
|
72
71
|
return DeploymentResult(
|
|
73
72
|
success=True,
|
|
@@ -89,7 +88,7 @@ class DockerBackend(DeploymentBackend):
|
|
|
89
88
|
runtime=self.runtime_type,
|
|
90
89
|
error="Build timed out",
|
|
91
90
|
)
|
|
92
|
-
|
|
91
|
+
|
|
93
92
|
def push_image(
|
|
94
93
|
self,
|
|
95
94
|
image_name: str,
|
|
@@ -104,7 +103,7 @@ class DockerBackend(DeploymentBackend):
|
|
|
104
103
|
["docker", "tag", image_name, target],
|
|
105
104
|
capture_output=True,
|
|
106
105
|
)
|
|
107
|
-
|
|
106
|
+
|
|
108
107
|
try:
|
|
109
108
|
result = subprocess.run(
|
|
110
109
|
["docker", "push", target],
|
|
@@ -112,7 +111,7 @@ class DockerBackend(DeploymentBackend):
|
|
|
112
111
|
text=True,
|
|
113
112
|
timeout=300,
|
|
114
113
|
)
|
|
115
|
-
|
|
114
|
+
|
|
116
115
|
return DeploymentResult(
|
|
117
116
|
success=result.returncode == 0,
|
|
118
117
|
service_name=image_name.split("/")[-1].split(":")[0],
|
|
@@ -127,7 +126,7 @@ class DockerBackend(DeploymentBackend):
|
|
|
127
126
|
runtime=self.runtime_type,
|
|
128
127
|
error="Push timed out",
|
|
129
128
|
)
|
|
130
|
-
|
|
129
|
+
|
|
131
130
|
def deploy(
|
|
132
131
|
self,
|
|
133
132
|
service_name: str,
|
|
@@ -138,13 +137,13 @@ class DockerBackend(DeploymentBackend):
|
|
|
138
137
|
) -> DeploymentResult:
|
|
139
138
|
"""Deploy a container."""
|
|
140
139
|
container_name = f"{self.config.namespace}-{service_name}"
|
|
141
|
-
|
|
140
|
+
|
|
142
141
|
# Stop existing container if running
|
|
143
142
|
subprocess.run(
|
|
144
143
|
["docker", "rm", "-f", container_name],
|
|
145
144
|
capture_output=True,
|
|
146
145
|
)
|
|
147
|
-
|
|
146
|
+
|
|
148
147
|
cmd = [
|
|
149
148
|
"docker", "run",
|
|
150
149
|
"-d",
|
|
@@ -152,37 +151,37 @@ class DockerBackend(DeploymentBackend):
|
|
|
152
151
|
"--network", self.config.network_name,
|
|
153
152
|
"--restart", "unless-stopped",
|
|
154
153
|
]
|
|
155
|
-
|
|
154
|
+
|
|
156
155
|
# Port mapping
|
|
157
156
|
if self.config.expose_ports:
|
|
158
157
|
cmd.extend(["-p", f"{port}:{port}"])
|
|
159
|
-
|
|
158
|
+
|
|
160
159
|
# Environment variables
|
|
161
160
|
for key, value in env.items():
|
|
162
161
|
cmd.extend(["-e", f"{key}={value}"])
|
|
163
|
-
|
|
162
|
+
|
|
164
163
|
# Resource limits
|
|
165
164
|
if self.config.memory_limit:
|
|
166
165
|
cmd.extend(["--memory", self.config.memory_limit])
|
|
167
166
|
if self.config.cpu_limit:
|
|
168
167
|
cmd.extend(["--cpus", self.config.cpu_limit])
|
|
169
|
-
|
|
168
|
+
|
|
170
169
|
# Security options
|
|
171
170
|
if self.config.read_only_fs:
|
|
172
171
|
cmd.append("--read-only")
|
|
173
172
|
cmd.extend(["--tmpfs", "/tmp"])
|
|
174
|
-
|
|
173
|
+
|
|
175
174
|
if self.config.no_new_privileges:
|
|
176
175
|
cmd.append("--security-opt=no-new-privileges:true")
|
|
177
|
-
|
|
176
|
+
|
|
178
177
|
if self.config.drop_capabilities:
|
|
179
178
|
for cap in self.config.drop_capabilities:
|
|
180
179
|
cmd.extend(["--cap-drop", cap])
|
|
181
|
-
|
|
180
|
+
|
|
182
181
|
if self.config.add_capabilities:
|
|
183
182
|
for cap in self.config.add_capabilities:
|
|
184
183
|
cmd.extend(["--cap-add", cap])
|
|
185
|
-
|
|
184
|
+
|
|
186
185
|
# Health check
|
|
187
186
|
if health_check:
|
|
188
187
|
cmd.extend([
|
|
@@ -191,31 +190,31 @@ class DockerBackend(DeploymentBackend):
|
|
|
191
190
|
"--health-timeout", self.config.health_check_timeout,
|
|
192
191
|
"--health-retries", str(self.config.health_check_retries),
|
|
193
192
|
])
|
|
194
|
-
|
|
193
|
+
|
|
195
194
|
# Labels
|
|
196
195
|
for key, value in self.config.labels.items():
|
|
197
196
|
cmd.extend(["--label", f"{key}={value}"])
|
|
198
|
-
|
|
197
|
+
|
|
199
198
|
cmd.append(image_name)
|
|
200
|
-
|
|
199
|
+
|
|
201
200
|
try:
|
|
202
201
|
# Ensure network exists
|
|
203
202
|
subprocess.run(
|
|
204
203
|
["docker", "network", "create", self.config.network_name],
|
|
205
204
|
capture_output=True,
|
|
206
205
|
)
|
|
207
|
-
|
|
206
|
+
|
|
208
207
|
result = subprocess.run(
|
|
209
208
|
cmd,
|
|
210
209
|
capture_output=True,
|
|
211
210
|
text=True,
|
|
212
211
|
timeout=60,
|
|
213
212
|
)
|
|
214
|
-
|
|
213
|
+
|
|
215
214
|
if result.returncode == 0:
|
|
216
215
|
container_id = result.stdout.strip()[:12]
|
|
217
216
|
endpoint = f"http://{container_name}:{port}" if self.config.use_internal_dns else f"http://localhost:{port}"
|
|
218
|
-
|
|
217
|
+
|
|
219
218
|
return DeploymentResult(
|
|
220
219
|
success=True,
|
|
221
220
|
service_name=service_name,
|
|
@@ -238,54 +237,54 @@ class DockerBackend(DeploymentBackend):
|
|
|
238
237
|
runtime=self.runtime_type,
|
|
239
238
|
error="Deploy timed out",
|
|
240
239
|
)
|
|
241
|
-
|
|
240
|
+
|
|
242
241
|
def stop(self, service_name: str) -> DeploymentResult:
|
|
243
242
|
"""Stop a container."""
|
|
244
243
|
container_name = f"{self.config.namespace}-{service_name}"
|
|
245
|
-
|
|
244
|
+
|
|
246
245
|
result = subprocess.run(
|
|
247
246
|
["docker", "stop", container_name],
|
|
248
247
|
capture_output=True,
|
|
249
248
|
text=True,
|
|
250
249
|
)
|
|
251
|
-
|
|
250
|
+
|
|
252
251
|
subprocess.run(
|
|
253
252
|
["docker", "rm", container_name],
|
|
254
253
|
capture_output=True,
|
|
255
254
|
)
|
|
256
|
-
|
|
255
|
+
|
|
257
256
|
return DeploymentResult(
|
|
258
257
|
success=result.returncode == 0,
|
|
259
258
|
service_name=service_name,
|
|
260
259
|
runtime=self.runtime_type,
|
|
261
260
|
error=result.stderr if result.returncode != 0 else None,
|
|
262
261
|
)
|
|
263
|
-
|
|
262
|
+
|
|
264
263
|
def logs(self, service_name: str, tail: int = 100) -> str:
|
|
265
264
|
"""Get container logs."""
|
|
266
265
|
container_name = f"{self.config.namespace}-{service_name}"
|
|
267
|
-
|
|
266
|
+
|
|
268
267
|
result = subprocess.run(
|
|
269
268
|
["docker", "logs", "--tail", str(tail), container_name],
|
|
270
269
|
capture_output=True,
|
|
271
270
|
text=True,
|
|
272
271
|
)
|
|
273
|
-
|
|
272
|
+
|
|
274
273
|
return result.stdout + result.stderr
|
|
275
|
-
|
|
274
|
+
|
|
276
275
|
def status(self, service_name: str) -> dict[str, Any]:
|
|
277
276
|
"""Get container status."""
|
|
278
277
|
container_name = f"{self.config.namespace}-{service_name}"
|
|
279
|
-
|
|
278
|
+
|
|
280
279
|
result = subprocess.run(
|
|
281
280
|
["docker", "inspect", container_name],
|
|
282
281
|
capture_output=True,
|
|
283
282
|
text=True,
|
|
284
283
|
)
|
|
285
|
-
|
|
284
|
+
|
|
286
285
|
if result.returncode != 0:
|
|
287
286
|
return {"running": False, "error": "Container not found"}
|
|
288
|
-
|
|
287
|
+
|
|
289
288
|
try:
|
|
290
289
|
data = json.loads(result.stdout)[0]
|
|
291
290
|
return {
|
pactown/deploy/kubernetes.py
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import subprocess
|
|
6
5
|
import json
|
|
7
|
-
import
|
|
6
|
+
import subprocess
|
|
8
7
|
from pathlib import Path
|
|
9
|
-
from typing import
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
import yaml
|
|
10
11
|
|
|
11
12
|
from .base import (
|
|
12
13
|
DeploymentBackend,
|
|
@@ -19,7 +20,7 @@ from .base import (
|
|
|
19
20
|
class KubernetesBackend(DeploymentBackend):
|
|
20
21
|
"""
|
|
21
22
|
Kubernetes deployment backend for production environments.
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
Generates and applies Kubernetes manifests for:
|
|
24
25
|
- Deployments with rolling updates
|
|
25
26
|
- Services for internal/external access
|
|
@@ -28,22 +29,22 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
28
29
|
- HorizontalPodAutoscaler for scaling
|
|
29
30
|
- NetworkPolicies for security
|
|
30
31
|
"""
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
def __init__(self, config: DeploymentConfig, kubeconfig: Optional[str] = None):
|
|
33
34
|
super().__init__(config)
|
|
34
35
|
self.kubeconfig = kubeconfig
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
@property
|
|
37
38
|
def runtime_type(self) -> RuntimeType:
|
|
38
39
|
return RuntimeType.KUBERNETES
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
def _kubectl(self, *args: str, input_data: Optional[str] = None) -> subprocess.CompletedProcess:
|
|
41
42
|
"""Run kubectl command."""
|
|
42
43
|
cmd = ["kubectl"]
|
|
43
44
|
if self.kubeconfig:
|
|
44
45
|
cmd.extend(["--kubeconfig", self.kubeconfig])
|
|
45
46
|
cmd.extend(args)
|
|
46
|
-
|
|
47
|
+
|
|
47
48
|
return subprocess.run(
|
|
48
49
|
cmd,
|
|
49
50
|
capture_output=True,
|
|
@@ -51,7 +52,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
51
52
|
input=input_data,
|
|
52
53
|
timeout=60,
|
|
53
54
|
)
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
def is_available(self) -> bool:
|
|
56
57
|
"""Check if kubectl is available and cluster is reachable."""
|
|
57
58
|
try:
|
|
@@ -59,7 +60,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
59
60
|
return result.returncode == 0
|
|
60
61
|
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
61
62
|
return False
|
|
62
|
-
|
|
63
|
+
|
|
63
64
|
def build_image(
|
|
64
65
|
self,
|
|
65
66
|
service_name: str,
|
|
@@ -74,7 +75,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
74
75
|
image_name = f"{image_name}:{tag}"
|
|
75
76
|
else:
|
|
76
77
|
image_name = f"{image_name}:latest"
|
|
77
|
-
|
|
78
|
+
|
|
78
79
|
# Try podman first, then docker
|
|
79
80
|
for runtime in ["podman", "docker"]:
|
|
80
81
|
try:
|
|
@@ -93,14 +94,14 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
93
94
|
)
|
|
94
95
|
except FileNotFoundError:
|
|
95
96
|
continue
|
|
96
|
-
|
|
97
|
+
|
|
97
98
|
return DeploymentResult(
|
|
98
99
|
success=False,
|
|
99
100
|
service_name=service_name,
|
|
100
101
|
runtime=self.runtime_type,
|
|
101
102
|
error="No container runtime (docker/podman) available",
|
|
102
103
|
)
|
|
103
|
-
|
|
104
|
+
|
|
104
105
|
def push_image(
|
|
105
106
|
self,
|
|
106
107
|
image_name: str,
|
|
@@ -124,14 +125,14 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
124
125
|
)
|
|
125
126
|
except FileNotFoundError:
|
|
126
127
|
continue
|
|
127
|
-
|
|
128
|
+
|
|
128
129
|
return DeploymentResult(
|
|
129
130
|
success=False,
|
|
130
131
|
service_name=image_name,
|
|
131
132
|
runtime=self.runtime_type,
|
|
132
133
|
error="Failed to push image",
|
|
133
134
|
)
|
|
134
|
-
|
|
135
|
+
|
|
135
136
|
def deploy(
|
|
136
137
|
self,
|
|
137
138
|
service_name: str,
|
|
@@ -148,12 +149,12 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
148
149
|
env=env,
|
|
149
150
|
health_check=health_check,
|
|
150
151
|
)
|
|
151
|
-
|
|
152
|
+
|
|
152
153
|
# Apply all manifests
|
|
153
154
|
for manifest in manifests:
|
|
154
155
|
manifest_yaml = yaml.dump(manifest, default_flow_style=False)
|
|
155
156
|
result = self._kubectl("apply", "-f", "-", input_data=manifest_yaml)
|
|
156
|
-
|
|
157
|
+
|
|
157
158
|
if result.returncode != 0:
|
|
158
159
|
return DeploymentResult(
|
|
159
160
|
success=False,
|
|
@@ -161,16 +162,16 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
161
162
|
runtime=self.runtime_type,
|
|
162
163
|
error=result.stderr,
|
|
163
164
|
)
|
|
164
|
-
|
|
165
|
+
|
|
165
166
|
# Get service endpoint
|
|
166
167
|
result = self._kubectl(
|
|
167
168
|
"get", "service", service_name,
|
|
168
169
|
"-n", self.config.namespace,
|
|
169
170
|
"-o", "jsonpath={.status.loadBalancer.ingress[0].ip}",
|
|
170
171
|
)
|
|
171
|
-
|
|
172
|
+
|
|
172
173
|
endpoint = f"http://{result.stdout}:{port}" if result.stdout else f"http://{service_name}.{self.config.namespace}.svc.cluster.local:{port}"
|
|
173
|
-
|
|
174
|
+
|
|
174
175
|
return DeploymentResult(
|
|
175
176
|
success=True,
|
|
176
177
|
service_name=service_name,
|
|
@@ -178,7 +179,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
178
179
|
image_name=image_name,
|
|
179
180
|
endpoint=endpoint,
|
|
180
181
|
)
|
|
181
|
-
|
|
182
|
+
|
|
182
183
|
def stop(self, service_name: str) -> DeploymentResult:
|
|
183
184
|
"""Delete Kubernetes resources."""
|
|
184
185
|
result = self._kubectl(
|
|
@@ -186,14 +187,14 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
186
187
|
"-l", f"app={service_name}",
|
|
187
188
|
"-n", self.config.namespace,
|
|
188
189
|
)
|
|
189
|
-
|
|
190
|
+
|
|
190
191
|
return DeploymentResult(
|
|
191
192
|
success=result.returncode == 0,
|
|
192
193
|
service_name=service_name,
|
|
193
194
|
runtime=self.runtime_type,
|
|
194
195
|
error=result.stderr if result.returncode != 0 else None,
|
|
195
196
|
)
|
|
196
|
-
|
|
197
|
+
|
|
197
198
|
def logs(self, service_name: str, tail: int = 100) -> str:
|
|
198
199
|
"""Get pod logs."""
|
|
199
200
|
result = self._kubectl(
|
|
@@ -203,7 +204,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
203
204
|
"--tail", str(tail),
|
|
204
205
|
)
|
|
205
206
|
return result.stdout + result.stderr
|
|
206
|
-
|
|
207
|
+
|
|
207
208
|
def status(self, service_name: str) -> dict[str, Any]:
|
|
208
209
|
"""Get deployment status."""
|
|
209
210
|
result = self._kubectl(
|
|
@@ -211,10 +212,10 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
211
212
|
"-n", self.config.namespace,
|
|
212
213
|
"-o", "json",
|
|
213
214
|
)
|
|
214
|
-
|
|
215
|
+
|
|
215
216
|
if result.returncode != 0:
|
|
216
217
|
return {"running": False, "error": "Deployment not found"}
|
|
217
|
-
|
|
218
|
+
|
|
218
219
|
try:
|
|
219
220
|
data = json.loads(result.stdout)
|
|
220
221
|
status = data.get("status", {})
|
|
@@ -227,7 +228,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
227
228
|
}
|
|
228
229
|
except json.JSONDecodeError:
|
|
229
230
|
return {"running": False, "error": "Failed to parse status"}
|
|
230
|
-
|
|
231
|
+
|
|
231
232
|
def generate_manifests(
|
|
232
233
|
self,
|
|
233
234
|
service_name: str,
|
|
@@ -243,9 +244,9 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
243
244
|
"managed-by": "pactown",
|
|
244
245
|
**self.config.labels,
|
|
245
246
|
}
|
|
246
|
-
|
|
247
|
+
|
|
247
248
|
manifests = []
|
|
248
|
-
|
|
249
|
+
|
|
249
250
|
# Namespace
|
|
250
251
|
manifests.append({
|
|
251
252
|
"apiVersion": "v1",
|
|
@@ -255,7 +256,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
255
256
|
"labels": {"managed-by": "pactown"},
|
|
256
257
|
},
|
|
257
258
|
})
|
|
258
|
-
|
|
259
|
+
|
|
259
260
|
# ConfigMap for environment variables
|
|
260
261
|
if env:
|
|
261
262
|
manifests.append({
|
|
@@ -268,7 +269,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
268
269
|
},
|
|
269
270
|
"data": env,
|
|
270
271
|
})
|
|
271
|
-
|
|
272
|
+
|
|
272
273
|
# Deployment
|
|
273
274
|
container_spec = {
|
|
274
275
|
"name": service_name,
|
|
@@ -294,12 +295,12 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
294
295
|
},
|
|
295
296
|
},
|
|
296
297
|
}
|
|
297
|
-
|
|
298
|
+
|
|
298
299
|
if env:
|
|
299
300
|
container_spec["envFrom"] = [
|
|
300
301
|
{"configMapRef": {"name": f"{service_name}-config"}}
|
|
301
302
|
]
|
|
302
|
-
|
|
303
|
+
|
|
303
304
|
if health_check:
|
|
304
305
|
container_spec["livenessProbe"] = {
|
|
305
306
|
"httpGet": {"path": health_check, "port": port},
|
|
@@ -315,7 +316,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
315
316
|
"timeoutSeconds": 3,
|
|
316
317
|
"failureThreshold": 3,
|
|
317
318
|
}
|
|
318
|
-
|
|
319
|
+
|
|
319
320
|
deployment = {
|
|
320
321
|
"apiVersion": "apps/v1",
|
|
321
322
|
"kind": "Deployment",
|
|
@@ -350,7 +351,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
350
351
|
},
|
|
351
352
|
}
|
|
352
353
|
manifests.append(deployment)
|
|
353
|
-
|
|
354
|
+
|
|
354
355
|
# Service
|
|
355
356
|
service = {
|
|
356
357
|
"apiVersion": "v1",
|
|
@@ -367,7 +368,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
367
368
|
},
|
|
368
369
|
}
|
|
369
370
|
manifests.append(service)
|
|
370
|
-
|
|
371
|
+
|
|
371
372
|
# NetworkPolicy for security
|
|
372
373
|
network_policy = {
|
|
373
374
|
"apiVersion": "networking.k8s.io/v1",
|
|
@@ -389,9 +390,9 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
389
390
|
},
|
|
390
391
|
}
|
|
391
392
|
manifests.append(network_policy)
|
|
392
|
-
|
|
393
|
+
|
|
393
394
|
return manifests
|
|
394
|
-
|
|
395
|
+
|
|
395
396
|
def generate_hpa(
|
|
396
397
|
self,
|
|
397
398
|
service_name: str,
|
|
@@ -427,7 +428,7 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
427
428
|
}],
|
|
428
429
|
},
|
|
429
430
|
}
|
|
430
|
-
|
|
431
|
+
|
|
431
432
|
def save_manifests(
|
|
432
433
|
self,
|
|
433
434
|
service_name: str,
|
|
@@ -437,13 +438,13 @@ class KubernetesBackend(DeploymentBackend):
|
|
|
437
438
|
"""Save manifests to files."""
|
|
438
439
|
output_dir = Path(output_dir)
|
|
439
440
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
440
|
-
|
|
441
|
+
|
|
441
442
|
output_file = output_dir / f"{service_name}.yaml"
|
|
442
|
-
|
|
443
|
+
|
|
443
444
|
with open(output_file, "w") as f:
|
|
444
445
|
for i, manifest in enumerate(manifests):
|
|
445
446
|
if i > 0:
|
|
446
447
|
f.write("---\n")
|
|
447
448
|
yaml.dump(manifest, f, default_flow_style=False)
|
|
448
|
-
|
|
449
|
+
|
|
449
450
|
return output_file
|