From 5dabdac6fd4395096d53c6a68c846be127787e44 Mon Sep 17 00:00:00 2001 From: Terje Kvernes Date: Thu, 6 Jun 2024 16:41:42 +0200 Subject: [PATCH] Support multiple destinations in host_copy. (#259) * Support multiple destinations in host_copy. - Also reduces output noise. - Also handles the situation where a destination already has the role in question. - Requires Role to be hashable. --- mreg_cli/api/models.py | 4 ++++ mreg_cli/commands/policy.py | 24 +++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/mreg_cli/api/models.py b/mreg_cli/api/models.py index 1c3eb6d6..a2e99228 100644 --- a/mreg_cli/api/models.py +++ b/mreg_cli/api/models.py @@ -1121,6 +1121,10 @@ class Role(HostPolicy, WithHistory): history_resource: ClassVar[HistoryResource] = HistoryResource.HostPolicy_Role + def __hash__(self) -> int: + """Hash the role by ID and name.""" + return hash(str(self.id) + self.name) + @classmethod def endpoint(cls) -> Endpoint: """Return the endpoint for the class.""" diff --git a/mreg_cli/commands/policy.py b/mreg_cli/commands/policy.py index d263b3d6..e38fe2a4 100644 --- a/mreg_cli/commands/policy.py +++ b/mreg_cli/commands/policy.py @@ -317,7 +317,7 @@ def host_add(args: argparse.Namespace) -> None: short_desc="Copy roles between hosts", flags=[ Flag("source", description="Source host", metavar="SOURCE"), - Flag("destination", description="Destination host", metavar="DESTINATION"), + Flag("destination", description="Destination host", nargs="+", metavar="DESTINATION"), ], ) def host_copy(args: argparse.Namespace) -> None: @@ -326,16 +326,22 @@ def host_copy(args: argparse.Namespace) -> None: :param args: argparse.Namespace (source, destination) """ source_name: str = args.source - destination_name: str = args.destination - source = Host.get_by_any_means_or_raise(source_name) - destination = Host.get_by_any_means_or_raise(destination_name) + source_roles = set(source.roles()) - for role in source.roles(): - role.add_host(destination.name.hostname) - OutputManager().add_line( - f"Copied role {role.name} from {source_name} to {destination_name}" - ) + for destination_name in args.destination: + destination = Host.get_by_any_means_or_raise(destination_name) + destination_roles = set(destination.roles()) + OutputManager().add_line(f"Copying roles from from {source_name} to {destination_name}") + + # Check if role already exists in destination + for role in source_roles & destination_roles: + OutputManager().add_line(f" + {role.name} (existing membership)") + + # Check what roles need to be added + for role in source_roles - destination_roles: + role.add_host(destination.name.hostname) + OutputManager().add_line(f" + {role.name}") @command_registry.register_command(