konduktor-nightly 0.1.0.dev20251023104627__py3-none-any.whl → 0.1.0.dev20251024104753__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.

Potentially problematic release.


This version of konduktor-nightly might be problematic. Click here for more details.

konduktor/__init__.py CHANGED
@@ -11,7 +11,7 @@ from konduktor.task import Task
11
11
  __all__ = ['launch', 'Resources', 'Task', 'Serving']
12
12
 
13
13
  # Replaced with the current commit when building the wheels.
14
- _KONDUKTOR_COMMIT_SHA = '77ea1a3b26250e8ce18a507a4ab0d2538e351cb5'
14
+ _KONDUKTOR_COMMIT_SHA = '431cdb62b9ab33df94d918db9d957bc4c54c2096'
15
15
  os.makedirs(os.path.expanduser('~/.konduktor'), exist_ok=True)
16
16
 
17
17
 
@@ -45,5 +45,5 @@ def _get_git_commit():
45
45
 
46
46
 
47
47
  __commit__ = _get_git_commit()
48
- __version__ = '1.0.0.dev0.1.0.dev20251023104627'
48
+ __version__ = '1.0.0.dev0.1.0.dev20251024104753'
49
49
  __root_dir__ = os.path.dirname(os.path.abspath(__file__))
@@ -5,15 +5,12 @@ import json
5
5
  import tempfile
6
6
  import time
7
7
  import typing
8
- from datetime import datetime, timezone
8
+ from datetime import datetime, timedelta, timezone
9
9
  from typing import Any, Dict, Optional, Tuple
10
10
 
11
11
  import click
12
12
  import colorama
13
13
 
14
- if typing.TYPE_CHECKING:
15
- from datetime import timedelta
16
-
17
14
  import konduktor
18
15
  from konduktor import kube_client, logging
19
16
  from konduktor.backends import constants as backend_constants
@@ -428,7 +425,9 @@ def _parse_timestamp_filter(timestamp_str: str) -> datetime:
428
425
  seconds=abs(local_offset)
429
426
  )
430
427
  else:
431
- dt = dt.replace(tzinfo=timezone.utc)
428
+ # Handle date-only format (local midnight --> UTC)
429
+ local_tz = datetime.now().astimezone().tzinfo
430
+ return dt.replace(tzinfo=local_tz).astimezone(timezone.utc)
432
431
  return dt
433
432
  except ValueError:
434
433
  continue
konduktor/cli.py CHANGED
@@ -161,7 +161,9 @@ def _make_task_with_overrides(
161
161
  if workdir is not None:
162
162
  task.workdir = workdir
163
163
 
164
- task.set_resources_override(override_params)
164
+ # perform overrides from CLI
165
+ if override_params:
166
+ task.set_resources_override(override_params)
165
167
  if task.serving:
166
168
  task.set_serving_override(serving_override_params)
167
169
 
@@ -653,28 +655,23 @@ def status(
653
655
  all_users: bool, limit: Optional[int], after: Optional[str], before: Optional[str]
654
656
  ):
655
657
  # NOTE(dev): Keep the docstring consistent between the Python API and CLI.
656
- """Shows list of all the jobs with optional filtering and pagination
657
-
658
- Args:
659
- all_users (bool): whether to show all jobs for all users
660
- limit (Optional[int]): maximum number of jobs to display
661
- after (Optional[str]): show jobs created after this timestamp
662
- before (Optional[str]): show jobs created before this timestamp
658
+ """Shows list of all the jobs with optional filtering and pagination.
663
659
 
660
+ \b
664
661
  Examples:
665
- konduktor status --limit 10
666
- konduktor status --before "08/06/25 03:53PM"
667
- konduktor status --all-users --limit 10 --after "08/06/25 03:53PM"
668
-
669
- Note:
670
- When using --before or --after timestamps, passing in "08/06/25" is
671
- equivalent to passing in "08/06/25 00:00".
672
- When using --before or --after timestamps, passing in "03:53PM" is
673
- equivalent to passing in "03:53:00PM".
674
- Timestamps shown in "konduktor startus" are truncated and are in the
675
- local timezone. ex. "03:53:55PM" --> "03:53PM"
676
- and would show up in --after "03:53PM" but not in --before "03:53PM"
677
- despite status showing as "03:53PM".
662
+ konduktor status --limit 10
663
+ konduktor status --before "08/06/25 03:53PM"
664
+ konduktor status --all-users --limit 10 --after "08/06/25 03:53PM"
665
+
666
+ \b
667
+ Notes:
668
+ When using --before or --after timestamps, "08/06/25"
669
+ is equivalent to "08/06/25 00:00".
670
+ • "03:53PM" is equivalent to "03:53:00PM".
671
+ Timestamps shown in "konduktor status" are truncated
672
+ and are in the local timezone.
673
+ Example: "03:53:55PM" "03:53PM" would show up in
674
+ --after "03:53PM" but not in --before "03:53PM".
678
675
  """
679
676
  context = kubernetes_utils.get_current_kube_config_context_name()
680
677
  namespace = kubernetes_utils.get_kube_config_context_namespace(context)
@@ -802,6 +799,13 @@ def logs(
802
799
  # pylint: disable=bad-docstring-quotes
803
800
  help='Skip confirmation prompt.',
804
801
  )
802
+ @click.option(
803
+ '--skip-image-check',
804
+ '-s',
805
+ is_flag=True,
806
+ default=False,
807
+ help='Skip Docker image validation checks for faster startup.',
808
+ )
805
809
  def launch(
806
810
  entrypoint: Tuple[str, ...],
807
811
  dryrun: bool,
@@ -820,6 +824,7 @@ def launch(
820
824
  env: List[Tuple[str, str]],
821
825
  disk_size: Optional[int],
822
826
  yes: bool,
827
+ skip_image_check: bool,
823
828
  ):
824
829
  """Launch a task.
825
830
 
@@ -829,6 +834,9 @@ def launch(
829
834
  # NOTE(dev): Keep the docstring consistent between the Python API and CLI.
830
835
  env = _merge_env_vars(env_file, env)
831
836
 
837
+ if skip_image_check:
838
+ os.environ['KONDUKTOR_SKIP_IMAGE_CHECK'] = '1'
839
+
832
840
  task = _make_task_with_overrides(
833
841
  entrypoint=entrypoint,
834
842
  name=name,
@@ -1694,6 +1702,13 @@ def serve():
1694
1702
  # pylint: disable=bad-docstring-quotes
1695
1703
  help='Skip confirmation prompt.',
1696
1704
  )
1705
+ @click.option(
1706
+ '--skip-image-check',
1707
+ '-s',
1708
+ is_flag=True,
1709
+ default=False,
1710
+ help='Skip Docker image validation checks for faster startup.',
1711
+ )
1697
1712
  def serve_launch(
1698
1713
  entrypoint: Tuple[str, ...],
1699
1714
  dryrun: bool,
@@ -1716,6 +1731,7 @@ def serve_launch(
1716
1731
  ports: Optional[int],
1717
1732
  probe: Optional[str],
1718
1733
  yes: bool,
1734
+ skip_image_check: bool = False,
1719
1735
  ):
1720
1736
  """Launch a deployment to serve.
1721
1737
 
@@ -1725,6 +1741,9 @@ def serve_launch(
1725
1741
  # NOTE(dev): Keep the docstring consistent between the Python API and CLI.
1726
1742
  env = _merge_env_vars(env_file, env)
1727
1743
 
1744
+ if skip_image_check:
1745
+ os.environ['KONDUKTOR_SKIP_IMAGE_CHECK'] = '1'
1746
+
1728
1747
  task = _make_task_with_overrides(
1729
1748
  entrypoint=entrypoint,
1730
1749
  name=name,
@@ -1739,6 +1758,7 @@ def serve_launch(
1739
1758
  image_id=image_id,
1740
1759
  env=env,
1741
1760
  disk_size=disk_size,
1761
+ # serving stuff
1742
1762
  min_replicas=min_replicas,
1743
1763
  max_replicas=max_replicas,
1744
1764
  ports=ports,
konduktor/resource.py CHANGED
@@ -59,6 +59,8 @@ class Resources:
59
59
  # Internal use only.
60
60
  # pylint: disable=invalid-name
61
61
  _cluster_config_overrides: Optional[Dict[str, Any]] = None,
62
+ # used to prevent double validation of image (would happen from overrides)
63
+ _validate_image: bool = True,
62
64
  ):
63
65
  """Initialize a Resources object.
64
66
 
@@ -124,7 +126,8 @@ class Resources:
124
126
  if isinstance(image_id, str):
125
127
  self._image_id = image_id.strip()
126
128
  # Validate Docker image format and existence
127
- validator.validate_and_warn_image(self._image_id, 'task')
129
+ if _validate_image:
130
+ validator.validate_and_warn_image(self._image_id, 'task')
128
131
 
129
132
  self._labels = labels
130
133
  self._cluster_config_overrides = _cluster_config_overrides
@@ -435,15 +438,19 @@ class Resources:
435
438
 
436
439
  def copy(self, **override) -> 'Resources':
437
440
  """Returns a copy of the given Resources."""
441
+ # used to prevent double validation of image (would happen from overrides)
442
+ new_image_id = override.pop('image_id', self.image_id)
438
443
  resources = Resources(
439
444
  cloud=override.pop('cloud', self.cloud),
440
445
  cpus=override.pop('cpus', self._cpus),
441
446
  memory=override.pop('memory', self.memory),
442
447
  accelerators=override.pop('accelerators', self.accelerators),
443
448
  disk_size=override.pop('disk_size', self.disk_size),
444
- image_id=override.pop('image_id', self.image_id),
449
+ image_id=new_image_id,
445
450
  labels=override.pop('labels', self.labels),
446
451
  job_config=override.pop('job_config', self.job_config),
452
+ # used to prevent double validation of image (would happen from overrides)
453
+ _validate_image=(new_image_id != self.image_id),
447
454
  )
448
455
  assert len(override) == 0
449
456
  return resources
konduktor/task.py CHANGED
@@ -29,7 +29,7 @@ import konduktor
29
29
  from konduktor import constants, logging
30
30
  from konduktor.data import data_utils
31
31
  from konduktor.data import storage as storage_lib
32
- from konduktor.utils import common_utils, exceptions, schemas, ux_utils, validator
32
+ from konduktor.utils import common_utils, exceptions, schemas, ux_utils
33
33
 
34
34
  logger = logging.get_logger(__name__)
35
35
 
@@ -388,10 +388,6 @@ class Task:
388
388
  )
389
389
  resources_config['_cluster_config_overrides'] = cluster_config_override
390
390
 
391
- # Validate Docker image if specified in resources
392
- if 'image_id' in resources_config and resources_config['image_id']:
393
- validator.validate_and_warn_image(resources_config['image_id'], 'task')
394
-
395
391
  task.set_resources(konduktor.Resources.from_yaml_config(resources_config))
396
392
 
397
393
  # Parse serving field.
@@ -37,6 +37,11 @@ SCHEMA_URLS = {
37
37
  logger = logging.get_logger(__name__)
38
38
 
39
39
 
40
+ def _skip_image_checks() -> bool:
41
+ val = os.getenv('KONDUKTOR_SKIP_IMAGE_CHECK', '')
42
+ return val.lower() in ('1', 'true', 'yes', 'y')
43
+
44
+
40
45
  def case_insensitive_enum(validator, enums, instance, schema):
41
46
  del validator, schema # Unused.
42
47
  if instance.lower() not in [enum.lower() for enum in enums]:
@@ -419,6 +424,13 @@ def validate_and_warn_image(image_id: str, context: str = 'task') -> None:
419
424
  if not image_id:
420
425
  return
421
426
 
427
+ if _skip_image_checks():
428
+ logger.info(
429
+ 'Skipping Docker image validation for %s',
430
+ image_id,
431
+ )
432
+ return
433
+
422
434
  status, message = validate_docker_image(image_id)
423
435
 
424
436
  if status == 'invalid':
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: konduktor-nightly
3
- Version: 0.1.0.dev20251023104627
3
+ Version: 0.1.0.dev20251024104753
4
4
  Summary: GPU Cluster Health Management
5
5
  Author: Andrew Aikawa
6
6
  Author-email: asai@berkeley.edu
@@ -1,4 +1,4 @@
1
- konduktor/__init__.py,sha256=euAoDTHdzANHMdyIr3iKaAQpvyi4s5M_i560sLnWwcU,1574
1
+ konduktor/__init__.py,sha256=FjWMNSOYV6pEAda12-HGCn8TZYDK0aAYzyFGQLTOB74,1574
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
@@ -10,10 +10,10 @@ konduktor/backends/constants.py,sha256=nt9G9AmFCOMwO4GuKgRQSzJJuKapOmaROp4_Y0tMF
10
10
  konduktor/backends/deployment.py,sha256=VXz0GMvFzqq8kd1-pXaNaTsEtSyMmVO2OSd-_-T9nIE,6171
11
11
  konduktor/backends/deployment_utils.py,sha256=rfVpiM0KlXma8SxA029TczrpbY-gRG3T0pj2eeARkE8,49257
12
12
  konduktor/backends/jobset.py,sha256=drt8Gc0iYQx18JWXBU6XfhUvC2xCKd8szSJ2JC4O20Q,8640
13
- konduktor/backends/jobset_utils.py,sha256=If4pv5peB_yXrJJwjkySgVzbjcxDEDWfkOQxUkwSlOk,26386
13
+ konduktor/backends/jobset_utils.py,sha256=veY0O1Yn5YK9e3uZhBdeoATvKFjyARU9FYUzX5Ypyrc,26496
14
14
  konduktor/backends/pod_utils.py,sha256=KP_PAgsdNHFgt4Od-5gAtpifAKIL7DMBg7NJ44uqikg,14885
15
15
  konduktor/check.py,sha256=JennyWoaqSKhdyfUldd266KwVXTPJpcYQa4EED4a_BA,7569
16
- konduktor/cli.py,sha256=HOL_O7BpYCl7uF5mKkMvXLjFNMTeAh2hYkraaJ6zi3w,57674
16
+ konduktor/cli.py,sha256=vb9SD8eJYjddiInVVQMq8K2BwqVDFoaMSTuaPhGp50I,57907
17
17
  konduktor/config.py,sha256=9upqgCCYvcu6fKw7tovEYC1MWTkAAir0_WHPdayylbI,15536
18
18
  konduktor/constants.py,sha256=T3AeXXxuQHINW_bAWyztvDeS8r4g8kXBGIwIq13cys0,1814
19
19
  konduktor/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -75,9 +75,9 @@ konduktor/manifests/controller_deployment.yaml,sha256=6p3oSLkEVONZsvKZGqVop0Dhn4
75
75
  konduktor/manifests/dashboard_deployment.yaml,sha256=xJLd4FbPMAosI0fIv5_8y7dV9bw0Vsf81l-w4MB_aU8,2837
76
76
  konduktor/manifests/dmesg_daemonset.yaml,sha256=pSWt7YOeTYjS0l0iki1fvHOs7MhY-sH-RQfVW6JJyno,1391
77
77
  konduktor/manifests/pod_cleanup_controller.yaml,sha256=hziL1Ka1kCAEL9R7Tjvpb80iw1vcq9_3gwHCu75Bi0A,3939
78
- konduktor/resource.py,sha256=kfdhnUR_9kDLSm2sUAkv1sLQXyAkI08p3wIzCz1p7-M,20791
78
+ konduktor/resource.py,sha256=JqEE3LZiBBd5vqAiHDk-nlLve_VUQHhgdo6BIgx2Xfk,21215
79
79
  konduktor/serving.py,sha256=4s8cQhsVjf-HByZF65pbMxuqaV319hUSQE9pC8gP4Sg,5405
80
- konduktor/task.py,sha256=LcTblvTNCSFNBHNUIOGN-i43whR8B6ccBm3HZTDoCMs,38050
80
+ konduktor/task.py,sha256=FIWm_rC_63GPBoe-Hi8a_eJ0H8Szw747SwXYPrNtOWE,37820
81
81
  konduktor/templates/deployment.yaml.j2,sha256=ByA33oaBgWnSx_QZ6yKeaMcCjktphcwF8R5KiOlM4pE,4859
82
82
  konduktor/templates/jobset.yaml.j2,sha256=NQcVeRNsTLLmTnJRnkL1vr45mSeth-b11YShXn_RoSg,1323
83
83
  konduktor/templates/pod.yaml.j2,sha256=p9yE-AQkCF2Tgjd1QQiOLtzgI6Gbpps-MZYJZ9fQWIs,19159
@@ -99,9 +99,9 @@ konduktor/utils/rich_utils.py,sha256=ycADW6Ij3wX3uT8ou7T8qxX519RxlkJivsLvUahQaJo
99
99
  konduktor/utils/schemas.py,sha256=cr39nEAgjluhXoUYnvIwCwLBH8rLds37MBsF1uQv1rw,19067
100
100
  konduktor/utils/subprocess_utils.py,sha256=WoFkoFhGecPR8-rF8WJxbIe-YtV94LXz9UG64SDhCY4,9448
101
101
  konduktor/utils/ux_utils.py,sha256=LSH4b5lckD157qDF4keThxtkGdxNrAfGKmH1ewhZkm4,8646
102
- konduktor/utils/validator.py,sha256=gCB5v9Up9bCWD_92fS5ChfRRXj_m56Ky9uzd_77wXGI,16927
103
- konduktor_nightly-0.1.0.dev20251023104627.dist-info/LICENSE,sha256=MuuqTZbHvmqXR_aNKAXzggdV45ANd3wQ5YI7tnpZhm0,6586
104
- konduktor_nightly-0.1.0.dev20251023104627.dist-info/METADATA,sha256=mZ4Eqs59fnE0eMgtnmnOHv4N0p6hTnp_Hk8aAWd4kS4,4247
105
- konduktor_nightly-0.1.0.dev20251023104627.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
106
- konduktor_nightly-0.1.0.dev20251023104627.dist-info/entry_points.txt,sha256=k3nG5wDFIJhNqsZWrHk4d0irIB2Ns9s47cjRWYsTCT8,48
107
- konduktor_nightly-0.1.0.dev20251023104627.dist-info/RECORD,,
102
+ konduktor/utils/validator.py,sha256=UcLvZCk9Cpbbhw8r_ZJtTpMSTfY1NKqcyciKsPzRPZM,17222
103
+ konduktor_nightly-0.1.0.dev20251024104753.dist-info/LICENSE,sha256=MuuqTZbHvmqXR_aNKAXzggdV45ANd3wQ5YI7tnpZhm0,6586
104
+ konduktor_nightly-0.1.0.dev20251024104753.dist-info/METADATA,sha256=mXfjZjQzu3XmB8hxuhoM4rt_7ynOqileNOekKbwgY8M,4247
105
+ konduktor_nightly-0.1.0.dev20251024104753.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
106
+ konduktor_nightly-0.1.0.dev20251024104753.dist-info/entry_points.txt,sha256=k3nG5wDFIJhNqsZWrHk4d0irIB2Ns9s47cjRWYsTCT8,48
107
+ konduktor_nightly-0.1.0.dev20251024104753.dist-info/RECORD,,