Skip to content

Commit d4ac54a

Browse files
authored
Implement dependecies validation (#366)
*Implement dependencies validation Signed-off-by: Piotr Pawłowski <ppawl@google.com> --------- Signed-off-by: Piotr Pawłowski <ppawl@google.com>
1 parent 49f1ece commit d4ac54a

File tree

7 files changed

+96
-5
lines changed

7 files changed

+96
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Following tools must be installed:
9090
# sudo may be required
9191
apt-get -y install make
9292
```
93-
In addition, below dependencies will be installed with `make install` command:
93+
In addition, below dependencies can be installed either using provided links or using `make install` command, if xpk is downloaded via `git clone` command:
9494
- kueuectl (install from [here](https://kueue.sigs.k8s.io/docs/reference/kubectl-kueue/installation/))
9595
- kjob (installation instructions [here](https://github.com/kubernetes-sigs/kjob/blob/main/docs/installation.md))
9696

pytype-conf.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ exclude =
2525
# Keep going past errors to analyze as many files as possible.
2626
keep_going = True
2727

28-
jobs = 5
28+
jobs = auto
2929

3030
# Platform (e.g., "linux", "win32") that the target code runs on.
3131
platform = linux

src/xpk/commands/version.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
from ..utils.console import xpk_print
1919

2020

21+
def get_xpk_version() -> str:
22+
return __version__
23+
24+
2125
def version(args) -> None: # pylint: disable=unused-argument
2226
"""Get version of xpk."""
2327
xpk_version, git_hash = __version__.split('+')

src/xpk/core/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ def run_command_for_value(
246246
int: return_code, default is 0
247247
str: return_val, default is '0'
248248
"""
249-
if global_args.dry_run:
249+
if global_args is not None and global_args.dry_run:
250250
xpk_print(
251251
f'Task: `{task}` is implemented by the following command'
252252
' not running since it is a dry run.'

src/xpk/core/config.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@
3434
CLUSTER_NAME_KEY = 'cluster-name'
3535
PROJECT_KEY = 'project-id'
3636
ZONE_KEY = 'zone'
37+
CONFIGS_KEY = 'configs'
38+
DEPENDENCIES_KEY = 'deps-verified-version'
39+
XPK_CONFIG_FILE = os.path.expanduser('~/.config/xpk/config.yaml')
40+
3741
DEFAULT_KEYS = [
3842
CFG_BUCKET_KEY,
3943
CLUSTER_NAME_KEY,
4044
PROJECT_KEY,
4145
ZONE_KEY,
46+
DEPENDENCIES_KEY,
4247
]
4348
VERTEX_TENSORBOARD_FEATURE_FLAG = XPK_CURRENT_VERSION >= '0.4.0'
4449
GCS_FUSE_ANNOTATION = 'gke-gcsfuse/volumes: "true"'
@@ -92,7 +97,7 @@ def get(self, key: str) -> str | None:
9297
return None
9398

9499
vals: dict[str, str] = config_yaml[CONFIGS_KEY]
95-
return vals[key]
100+
return vals.get(key)
96101

97102
def get_all(
98103
self,

src/xpk/main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@
3636

3737
from .parser.core import set_parser
3838
from .utils.console import xpk_print
39-
39+
from .utils.validation import validate_dependencies
4040
################### Compatibility Check ###################
4141
# Check that the user runs the below version or greater.
4242

43+
4344
major_version_supported = 3
4445
minor_version_supported = 10
4546

@@ -60,6 +61,7 @@
6061
set_parser(parser=parser)
6162

6263
xpk_print('Starting xpk', flush=True)
64+
validate_dependencies()
6365
main_args = parser.parse_args()
6466
main_args.enable_ray_cluster = False
6567
main_args.func(main_args)

src/xpk/utils/validation.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""
2+
Copyright 2025 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
https://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
16+
17+
from ..core.commands import run_command_for_value
18+
from .console import xpk_exit, xpk_print
19+
from ..commands.config import xpk_cfg
20+
from ..core.config import DEPENDENCIES_KEY
21+
from ..commands.version import get_xpk_version
22+
23+
24+
validation_commands = {
25+
'kubectl': {
26+
'command': 'kubectl --help',
27+
'message': (
28+
'`kubectl` not installed. Please follow'
29+
' https://github.com/AI-Hypercomputer/xpk?tab=readme-ov-file#prerequisites'
30+
' to install xpk prerequisites.'
31+
),
32+
},
33+
'kjob': {
34+
'command': 'kubectl kjob --help',
35+
'message': (
36+
'`kjobctl` not installed. Please follow'
37+
' https://github.com/AI-Hypercomputer/xpk?tab=readme-ov-file#prerequisites'
38+
' to install xpk prerequisites.'
39+
),
40+
},
41+
'gcloud': {
42+
'command': 'gcloud version',
43+
'message': (
44+
'`gcloud not installed. Please follow'
45+
' https://github.com/AI-Hypercomputer/xpk?tab=readme-ov-file#prerequisites'
46+
' to install xpk prerequisites.'
47+
),
48+
},
49+
'docker': {
50+
'command': 'docker version',
51+
'message': (
52+
'`docker` not installed. Please follow'
53+
' https://github.com/AI-Hypercomputer/xpk?tab=readme-ov-file#prerequisites'
54+
' to install xpk prerequisites.'
55+
),
56+
},
57+
'kueuectl': {
58+
'command': 'kubectl kueue --help',
59+
'message': (
60+
'`kueuectl` not installed. Please follow'
61+
' https://github.com/AI-Hypercomputer/xpk?tab=readme-ov-file#prerequisites'
62+
' to install xpk prerequisites.'
63+
),
64+
},
65+
}
66+
67+
68+
def validate_dependencies():
69+
deps_version = xpk_cfg.get(DEPENDENCIES_KEY)
70+
xpk_version = get_xpk_version()
71+
if deps_version is None or deps_version != xpk_version:
72+
for name, check in validation_commands.items():
73+
cmd, message = check['command'], check['message']
74+
code, _ = run_command_for_value(
75+
cmd, f'Validate {name} installation.', None
76+
)
77+
if code != 0:
78+
xpk_print(message)
79+
xpk_exit(code)
80+
xpk_cfg.set(DEPENDENCIES_KEY, get_xpk_version())

0 commit comments

Comments
 (0)