konduktor-nightly 0.1.0.dev20250616105058__py3-none-any.whl → 0.1.0.dev20250617053930__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.
- konduktor/__init__.py +2 -2
- konduktor/backends/jobset_utils.py +7 -4
- konduktor/utils/validator.py +54 -0
- {konduktor_nightly-0.1.0.dev20250616105058.dist-info → konduktor_nightly-0.1.0.dev20250617053930.dist-info}/METADATA +1 -1
- {konduktor_nightly-0.1.0.dev20250616105058.dist-info → konduktor_nightly-0.1.0.dev20250617053930.dist-info}/RECORD +8 -8
- {konduktor_nightly-0.1.0.dev20250616105058.dist-info → konduktor_nightly-0.1.0.dev20250617053930.dist-info}/LICENSE +0 -0
- {konduktor_nightly-0.1.0.dev20250616105058.dist-info → konduktor_nightly-0.1.0.dev20250617053930.dist-info}/WHEEL +0 -0
- {konduktor_nightly-0.1.0.dev20250616105058.dist-info → konduktor_nightly-0.1.0.dev20250617053930.dist-info}/entry_points.txt +0 -0
konduktor/__init__.py
CHANGED
@@ -14,7 +14,7 @@ __all__ = [
|
|
14
14
|
]
|
15
15
|
|
16
16
|
# Replaced with the current commit when building the wheels.
|
17
|
-
_KONDUKTOR_COMMIT_SHA = '
|
17
|
+
_KONDUKTOR_COMMIT_SHA = 'babfa5dcf2f304f8895837754d26a46dc1ad8c0a'
|
18
18
|
os.makedirs(os.path.expanduser('~/.konduktor'), exist_ok=True)
|
19
19
|
|
20
20
|
|
@@ -48,5 +48,5 @@ def _get_git_commit():
|
|
48
48
|
|
49
49
|
|
50
50
|
__commit__ = _get_git_commit()
|
51
|
-
__version__ = '1.0.0.dev0.1.0.
|
51
|
+
__version__ = '1.0.0.dev0.1.0.dev20250617053930'
|
52
52
|
__root_dir__ = os.path.dirname(os.path.abspath(__file__))
|
@@ -24,6 +24,7 @@ from konduktor.utils import (
|
|
24
24
|
kubernetes_utils,
|
25
25
|
log_utils,
|
26
26
|
ux_utils,
|
27
|
+
validator,
|
27
28
|
)
|
28
29
|
|
29
30
|
if typing.TYPE_CHECKING:
|
@@ -270,9 +271,9 @@ def create_pod_spec(task: 'konduktor.Task') -> Dict[str, Any]:
|
|
270
271
|
env_map.values()
|
271
272
|
)
|
272
273
|
|
273
|
-
#
|
274
|
-
# https://github.com/
|
275
|
-
|
274
|
+
# validate pod spec using json schema
|
275
|
+
# schema: https://github.com/instrumenta/kubernetes-json-schema/blob/master/v1.9.8-standalone-strict/podspec.json
|
276
|
+
validator.validate_pod_spec(pod_config['kubernetes']['pod_config']['spec'])
|
276
277
|
|
277
278
|
return pod_config
|
278
279
|
|
@@ -310,7 +311,9 @@ def create_jobset(
|
|
310
311
|
temp.name,
|
311
312
|
)
|
312
313
|
jobset_spec = common_utils.read_yaml(temp.name)
|
313
|
-
jobset_spec['jobset']['metadata']['labels'].update(
|
314
|
+
jobset_spec['jobset']['metadata']['labels'].update(
|
315
|
+
**(task.resources.labels or {})
|
316
|
+
)
|
314
317
|
assert task.resources.labels is not None
|
315
318
|
maxRunDurationSeconds = task.resources.labels.get('maxRunDurationSeconds', None)
|
316
319
|
if not maxRunDurationSeconds:
|
konduktor/utils/validator.py
CHANGED
@@ -5,7 +5,18 @@ allow for case-insensitive enum matching since this is currently not supported
|
|
5
5
|
by the JSON Schema specification.
|
6
6
|
"""
|
7
7
|
|
8
|
+
import json
|
9
|
+
import time
|
10
|
+
from pathlib import Path
|
11
|
+
|
8
12
|
import jsonschema
|
13
|
+
import requests
|
14
|
+
from colorama import Fore, Style
|
15
|
+
|
16
|
+
SCHEMA_VERSION = 'v1.32.0-standalone-strict'
|
17
|
+
SCHEMA_URL = f'https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{SCHEMA_VERSION}/podspec.json'
|
18
|
+
SCHEMA_CACHE_PATH = Path.home() / '.konduktor/schemas/podspec.json'
|
19
|
+
CACHE_MAX_AGE_SECONDS = 86400 # 24 hours
|
9
20
|
|
10
21
|
|
11
22
|
def case_insensitive_enum(validator, enums, instance, schema):
|
@@ -18,3 +29,46 @@ SchemaValidator = jsonschema.validators.extend(
|
|
18
29
|
jsonschema.Draft7Validator,
|
19
30
|
validators={'case_insensitive_enum': case_insensitive_enum},
|
20
31
|
)
|
32
|
+
|
33
|
+
|
34
|
+
def get_cached_schema() -> dict:
|
35
|
+
# Check if schema file exists and is fresh
|
36
|
+
if SCHEMA_CACHE_PATH.exists():
|
37
|
+
age = time.time() - SCHEMA_CACHE_PATH.stat().st_mtime
|
38
|
+
# if old
|
39
|
+
if age < CACHE_MAX_AGE_SECONDS:
|
40
|
+
with open(SCHEMA_CACHE_PATH, 'r') as f:
|
41
|
+
return json.load(f)
|
42
|
+
|
43
|
+
# Download schema
|
44
|
+
resp = requests.get(SCHEMA_URL)
|
45
|
+
resp.raise_for_status()
|
46
|
+
|
47
|
+
SCHEMA_CACHE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
48
|
+
with open(SCHEMA_CACHE_PATH, 'w') as f:
|
49
|
+
f.write(resp.text)
|
50
|
+
|
51
|
+
return resp.json()
|
52
|
+
|
53
|
+
|
54
|
+
def validate_pod_spec(pod_spec: dict) -> None:
|
55
|
+
schema = get_cached_schema()
|
56
|
+
|
57
|
+
validator = jsonschema.Draft7Validator(schema)
|
58
|
+
errors = sorted(validator.iter_errors(pod_spec), key=lambda e: e.path)
|
59
|
+
|
60
|
+
if not errors:
|
61
|
+
return
|
62
|
+
|
63
|
+
formatted = [
|
64
|
+
f'{Fore.RED}- {error.message}'
|
65
|
+
+ (f" at path: {' → '.join(str(p) for p in error.path)}" if error.path else '')
|
66
|
+
+ Style.RESET_ALL
|
67
|
+
for error in errors
|
68
|
+
]
|
69
|
+
|
70
|
+
raise ValueError(
|
71
|
+
f'\n{Fore.RED}Invalid k8s pod spec/config: \
|
72
|
+
{Style.RESET_ALL}\n'
|
73
|
+
+ '\n'.join(formatted)
|
74
|
+
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
konduktor/__init__.py,sha256=
|
1
|
+
konduktor/__init__.py,sha256=7FZjW6utVolfaEo49Xw64Oq9gm_yIVLqOBxipiKL0W4,1540
|
2
2
|
konduktor/adaptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
konduktor/adaptors/aws.py,sha256=s47Ra-GaqCQibzVfmD0pmwEWHif1EGO5opMbwkLxTCU,8244
|
4
4
|
konduktor/adaptors/common.py,sha256=ZIqzjx77PIHUwpjfAQ1uX8B2aX78YMuGj4Bppd-MdyM,4183
|
@@ -7,7 +7,7 @@ konduktor/authentication.py,sha256=_mVy3eqoKohicHostFiGwG1-2ybxP-l7ouofQ0LRlCY,4
|
|
7
7
|
konduktor/backends/__init__.py,sha256=1Q6sqqdeMYarpTX_U-QVywJYf7idiUTRsyP-E4BQSOw,129
|
8
8
|
konduktor/backends/backend.py,sha256=qh0bp94lzoTYZkzyQv2-CVrB5l91FkG2vclXg24UFC0,2910
|
9
9
|
konduktor/backends/jobset.py,sha256=UdhwAuZODLMbLY51Y2zOBsh6wg4Pb84oHVvUKzx3Z2w,8434
|
10
|
-
konduktor/backends/jobset_utils.py,sha256=
|
10
|
+
konduktor/backends/jobset_utils.py,sha256=mOjK3oFgmNacpg956r0qtR7cdZ0PPzXYVVuIr3QqKuI,22170
|
11
11
|
konduktor/check.py,sha256=JennyWoaqSKhdyfUldd266KwVXTPJpcYQa4EED4a_BA,7569
|
12
12
|
konduktor/cli.py,sha256=i5vXN_p21Tj7etX_QIkq1HCJ3I2Pn_OpKdddBMqRR-g,33877
|
13
13
|
konduktor/config.py,sha256=J50JxC6MsXMnlrJPXdDUMr38C89xvOO7mR8KJ6fyils,15520
|
@@ -90,9 +90,9 @@ konduktor/utils/rich_utils.py,sha256=ycADW6Ij3wX3uT8ou7T8qxX519RxlkJivsLvUahQaJo
|
|
90
90
|
konduktor/utils/schemas.py,sha256=VGPERAso2G4sVAznsJ80qT2Q-I_EFxXw6Rfcw-vkYgQ,16535
|
91
91
|
konduktor/utils/subprocess_utils.py,sha256=WoFkoFhGecPR8-rF8WJxbIe-YtV94LXz9UG64SDhCY4,9448
|
92
92
|
konduktor/utils/ux_utils.py,sha256=czCwiS1bDqgeKtzAJctczpLwFZzAse7WuozdvzEFYJ4,7437
|
93
|
-
konduktor/utils/validator.py,sha256=
|
94
|
-
konduktor_nightly-0.1.0.
|
95
|
-
konduktor_nightly-0.1.0.
|
96
|
-
konduktor_nightly-0.1.0.
|
97
|
-
konduktor_nightly-0.1.0.
|
98
|
-
konduktor_nightly-0.1.0.
|
93
|
+
konduktor/utils/validator.py,sha256=MSQ2EO7Bod8IVkNa2UsKLjg0qvDRvf7q3z-tOwSUkwo,2227
|
94
|
+
konduktor_nightly-0.1.0.dev20250617053930.dist-info/LICENSE,sha256=MuuqTZbHvmqXR_aNKAXzggdV45ANd3wQ5YI7tnpZhm0,6586
|
95
|
+
konduktor_nightly-0.1.0.dev20250617053930.dist-info/METADATA,sha256=gsj-UQMYSFgug5J9pZNL4vUbaYgyr8my5bioB65DfxE,4289
|
96
|
+
konduktor_nightly-0.1.0.dev20250617053930.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
97
|
+
konduktor_nightly-0.1.0.dev20250617053930.dist-info/entry_points.txt,sha256=k3nG5wDFIJhNqsZWrHk4d0irIB2Ns9s47cjRWYsTCT8,48
|
98
|
+
konduktor_nightly-0.1.0.dev20250617053930.dist-info/RECORD,,
|
File without changes
|
File without changes
|