Skip to content

Commit 26f2a63

Browse files
committed
17728 FIX omd update: Don't query target version indefinitely
Squashes: I514337e4c2cc09626d8d862acedb097924a5c0b3 Ic3af0ad543cb723e22571f7b4c4136abe1e82758 I23de56808974a9096d11011f8b51c5249efba789 CMK-22005 Change-Id: I6e80fde744240f4f7fea32326b14f4f3df650224
1 parent 2908053 commit 26f2a63

File tree

4 files changed

+56
-69
lines changed

4 files changed

+56
-69
lines changed

.werks/17728.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[//]: # (werk v2)
2+
# omd update: Don't query target version indefinitely
3+
4+
key | value
5+
---------- | ---
6+
date | 2025-03-23T10:12:21+00:00
7+
version | 2.4.0b3
8+
class | fix
9+
edition | cre
10+
component | omd
11+
level | 1
12+
compatible | yes
13+
14+
Previously, the command `omd -V {version} update` did not work correctly, if `{version}` matched the version of the site.
15+
This a user error, since the site cannot be updated if it already has the target version.
16+
In this case, `omd` would open the TUI and ask the user to pick a different version.
17+
This infinite loop would only stop once the user selected 'Abort'.
18+
19+
With this Werk, `omd` will immediately exit with an appropriate error message.

omd/packages/omd/omdlib/global_options.py

+7-21
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,12 @@
33
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
44
# conditions defined in the file COPYING, which is part of this source code package.
55

6-
import os
7-
from typing import NamedTuple, Self
6+
from dataclasses import dataclass
87

98

10-
class GlobalOptions(NamedTuple):
11-
verbose: bool
12-
force: bool
13-
interactive: bool
14-
orig_working_directory: str
15-
16-
@classmethod
17-
def default(cls) -> Self:
18-
try:
19-
orig_working_directory = os.getcwd()
20-
except FileNotFoundError:
21-
orig_working_directory = "/"
22-
23-
return cls(
24-
verbose=False,
25-
force=False,
26-
interactive=False,
27-
orig_working_directory=orig_working_directory,
28-
)
9+
@dataclass(frozen=True)
10+
class GlobalOptions:
11+
version: str | None = None
12+
verbose: bool = False
13+
force: bool = False
14+
interactive: bool = False

omd/packages/omd/omdlib/main.py

+30-20
Original file line numberDiff line numberDiff line change
@@ -2559,22 +2559,18 @@ def main_diff(
25592559
# one file is specified, we directly show the unified diff.
25602560
# This behaviour can also be forced by the OMD option -v.
25612561

2562+
verbose = global_opts.verbose
25622563
if len(args) == 0:
25632564
args = ["."]
25642565
elif len(args) == 1 and os.path.isfile(args[0]):
2565-
global_opts = GlobalOptions(
2566-
verbose=True,
2567-
force=global_opts.force,
2568-
interactive=global_opts.interactive,
2569-
orig_working_directory=global_opts.orig_working_directory,
2570-
)
2566+
verbose = True
25712567

25722568
for arg in args:
2573-
diff_list(global_opts, options, site, from_skelroot, arg)
2569+
diff_list(verbose, options, site, from_skelroot, arg)
25742570

25752571

25762572
def diff_list(
2577-
global_opts: GlobalOptions,
2573+
verbose: bool,
25782574
options: CommandOptions,
25792575
site: SiteContext,
25802576
from_skelroot: str,
@@ -2617,18 +2613,18 @@ def diff_list(
26172613
bail_out("Sorry, 'omd diff' only works for files in the site's directory.")
26182614

26192615
if not os.path.isdir(abs_path):
2620-
print_diff(rel_path, global_opts, options, site, from_skelroot, site.dir, old_perms)
2616+
print_diff(rel_path, verbose, options, site, from_skelroot, site.dir, old_perms)
26212617
else:
26222618
if not rel_path:
26232619
rel_path = "."
26242620

26252621
for file_path in walk_skel(from_skelroot, depth_first=False, relbase=rel_path):
2626-
print_diff(file_path, global_opts, options, site, from_skelroot, site.dir, old_perms)
2622+
print_diff(file_path, verbose, options, site, from_skelroot, site.dir, old_perms)
26272623

26282624

26292625
def print_diff(
26302626
rel_path: str,
2631-
global_opts: GlobalOptions,
2627+
verbose: bool,
26322628
options: CommandOptions,
26332629
site: SiteContext,
26342630
source_path: str,
@@ -2657,7 +2653,7 @@ def print_diff(
26572653
def print_status(color: str, f: str, status: str, long_out: str) -> None:
26582654
if "bare" in options:
26592655
sys.stdout.write(f"{status} {f}\n")
2660-
elif not global_opts.verbose:
2656+
elif not verbose:
26612657
sys.stdout.write(color + f" {long_out} {f}\n")
26622658
else:
26632659
arrow = tty.magenta + "->" + tty.normal
@@ -2717,6 +2713,8 @@ def main_update( # pylint: disable=too-many-branches
27172713
from_version = version_from_site_dir(Path(site.dir))
27182714
if from_version is None:
27192715
bail_out("Failed to determine site version")
2716+
if from_version == global_opts.version:
2717+
bail_out(f"Site already has version {global_opts.version}.")
27202718

27212719
# Target version: the version of the OMD binary
27222720
to_version = omdlib.__version__
@@ -3304,6 +3302,7 @@ def main_backup(
33043302
global_opts: GlobalOptions,
33053303
args: Arguments,
33063304
options: CommandOptions,
3305+
orig_working_directory: str,
33073306
) -> None:
33083307
if len(args) == 0:
33093308
bail_out(
@@ -3317,7 +3316,7 @@ def main_backup(
33173316
_try_backup_site_to_tarfile(sys.stdout.buffer, "w|", options, site, global_opts)
33183317
else:
33193318
if not (dest_path := Path(dest)).is_absolute():
3320-
dest_path = global_opts.orig_working_directory / dest_path
3319+
dest_path = orig_working_directory / dest_path
33213320
with dest_path.open(mode="wb") as fh:
33223321
_try_backup_site_to_tarfile(fh, "w:", options, site, global_opts)
33233322

@@ -4408,15 +4407,13 @@ class Command(NamedTuple):
44084407
def handle_global_option(
44094408
global_opts: GlobalOptions, main_args: Arguments, opt: str, orig: str
44104409
) -> tuple[GlobalOptions, Arguments]:
4410+
version = global_opts.version
44114411
verbose = global_opts.verbose
44124412
force = global_opts.force
44134413
interactive = global_opts.interactive
44144414

44154415
if opt in ["V", "version"]:
4416-
# Switch to other version of bin/omd
44174416
version, main_args = _opt_arg(main_args, opt)
4418-
if version != omdlib.__version__:
4419-
exec_other_omd(version)
44204417
elif opt in ["f", "force"]:
44214418
force = True
44224419
interactive = False
@@ -4429,10 +4426,10 @@ def handle_global_option(
44294426
bail_out("Invalid global option %s.\n" "Call omd help for available options." % orig)
44304427

44314428
new_global_opts = GlobalOptions(
4429+
version=version,
44324430
verbose=verbose,
44334431
force=force,
44344432
interactive=interactive,
4435-
orig_working_directory=global_opts.orig_working_directory,
44364433
)
44374434

44384435
return new_global_opts, main_args
@@ -4611,6 +4608,7 @@ def _run_command(
46114608
global_opts: GlobalOptions,
46124609
args: Arguments,
46134610
command_options: CommandOptions,
4611+
orig_working_directory: str,
46144612
) -> None:
46154613
try:
46164614
match command.command:
@@ -4678,7 +4676,9 @@ def _run_command(
46784676
main_umount(object(), site, object(), object(), command_options)
46794677
case "backup":
46804678
assert command.needs_site == 1 and isinstance(site, SiteContext)
4681-
main_backup(object(), site, global_opts, args, command_options)
4679+
main_backup(
4680+
object(), site, global_opts, args, command_options, orig_working_directory
4681+
)
46824682
case "restore":
46834683
main_restore(version_info, object(), global_opts, args, command_options)
46844684
case "cleanup":
@@ -4703,7 +4703,12 @@ def main() -> None: # pylint: disable=too-many-branches
47034703
version_info = VersionInfo(omdlib.__version__)
47044704
version_info.load()
47054705

4706-
global_opts = GlobalOptions.default()
4706+
try:
4707+
orig_working_directory = os.getcwd()
4708+
except FileNotFoundError:
4709+
orig_working_directory = "/"
4710+
4711+
global_opts = GlobalOptions()
47074712
while len(main_args) >= 1 and main_args[0].startswith("-"):
47084713
opt = main_args[0]
47094714
main_args = main_args[1:]
@@ -4712,6 +4717,9 @@ def main() -> None: # pylint: disable=too-many-branches
47124717
else:
47134718
for c in opt[1:]:
47144719
global_opts, main_args = handle_global_option(global_opts, main_args, c, opt)
4720+
if global_opts.version is not None and global_opts.version != omdlib.__version__:
4721+
# Switch to other version of bin/omd
4722+
exec_other_omd(global_opts.version)
47154723

47164724
if len(main_args) < 1:
47174725
main_help()
@@ -4762,7 +4770,9 @@ def main() -> None: # pylint: disable=too-many-branches
47624770
if answer in ["", "no"]:
47634771
bail_out(tty.normal + "Aborted.")
47644772

4765-
_run_command(command, version_info, site, global_opts, args, command_options)
4773+
_run_command(
4774+
command, version_info, site, global_opts, args, command_options, orig_working_directory
4775+
)
47664776

47674777

47684778
def _get_command(command_arg: str) -> Command:

tests/unit/omdlib/test_global_options.py

-28
This file was deleted.

0 commit comments

Comments
 (0)