From 4740fbdedbb505a9c354f1b96f33cb0656bc737e Mon Sep 17 00:00:00 2001 From: Matthias Dellweg <mdellweg@redhat.com> Date: Thu, 3 Feb 2022 12:48:53 +0100 Subject: [PATCH] Add needs_capability to EntityContext This also makes use of it for tagging and untagging in container repositories as well as for all roles related subcommands. fixes #465 --- .ci/scripts/validate_commit_message.py | 12 +++++++++++- CHANGES/465.devel | 1 + pulpcore/cli/common/context.py | 15 +++++++++++++++ pulpcore/cli/container/context.py | 24 ++++++++++++++++++++++-- pulpcore/cli/container/repository.py | 23 +++++------------------ pulpcore/cli/core/content_guard.py | 4 +--- pulpcore/cli/core/context.py | 3 +++ 7 files changed, 58 insertions(+), 24 deletions(-) create mode 100644 CHANGES/465.devel diff --git a/.ci/scripts/validate_commit_message.py b/.ci/scripts/validate_commit_message.py index 627adc9aa..660a085e8 100644 --- a/.ci/scripts/validate_commit_message.py +++ b/.ci/scripts/validate_commit_message.py @@ -8,7 +8,17 @@ KEYWORDS = ["fixes", "closes"] NO_ISSUE = "[noissue]" -CHANGELOG_EXTS = [".feature", ".bugfix", ".doc", ".removal", ".misc", ".deprecation"] +# TODO (On a rainy afternoon) Fetch the extensions from pyproject.toml +CHANGELOG_EXTS = [ + ".feature", + ".bugfix", + ".doc", + ".removal", + ".misc", + ".deprecation", + ".translation", + ".devel", +] sha = sys.argv[1] project = "pulp-cli" diff --git a/CHANGES/465.devel b/CHANGES/465.devel new file mode 100644 index 000000000..1ee97edbf --- /dev/null +++ b/CHANGES/465.devel @@ -0,0 +1 @@ +Added `needs_capability` to `EntityContext` so context member function can require capabilities. diff --git a/pulpcore/cli/common/context.py b/pulpcore/cli/common/context.py index ecd719547..a47c0cc35 100644 --- a/pulpcore/cli/common/context.py +++ b/pulpcore/cli/common/context.py @@ -551,12 +551,15 @@ def show_label(self, href: str, key: str) -> Any: raise click.ClickException(_("Could not find label with key '{key}'.").format(key=key)) def my_permissions(self) -> Any: + self.needs_capability("roles") return self.call("my_permissions", parameters={self.HREF: self.pulp_href}) def list_roles(self) -> Any: + self.needs_capability("roles") return self.call("list_roles", parameters={self.HREF: self.pulp_href}) def add_role(self, role: str, users: List[str], groups: List[str]) -> Any: + self.needs_capability("roles") return self.call( "add_role", parameters={self.HREF: self.pulp_href}, @@ -564,6 +567,7 @@ def add_role(self, role: str, users: List[str], groups: List[str]) -> Any: ) def remove_role(self, role: str, users: List[str], groups: List[str]) -> Any: + self.needs_capability("roles") return self.call( "remove_role", parameters={self.HREF: self.pulp_href}, @@ -575,6 +579,17 @@ def capable(self, capability: str) -> bool: (self.pulp_ctx.has_plugin(pr) for pr in self.CAPABILITIES[capability]) ) + def needs_capability(self, capability: str) -> None: + if capability in self.CAPABILITIES: + for pr in self.CAPABILITIES[capability]: + self.pulp_ctx.needs_plugin(pr) + else: + raise click.ClickException( + _("Capability '{capability}' needed on '{entity}' for this command.").format( + capability=capability, entity=self.ENTITY + ) + ) + class PulpRemoteContext(PulpEntityContext): """ diff --git a/pulpcore/cli/container/context.py b/pulpcore/cli/container/context.py index ba4c07f67..1691837c7 100644 --- a/pulpcore/cli/container/context.py +++ b/pulpcore/cli/container/context.py @@ -1,3 +1,5 @@ +from typing import Any + from pulpcore.cli.common.context import ( EntityDefinition, PluginRequirement, @@ -76,7 +78,25 @@ class PulpContainerPushRepositoryVersionContext(PulpRepositoryVersionContext): ID_PREFIX = "repositories_container_container_push_versions" -class PulpContainerRepositoryContext(PulpRepositoryContext): +class PulpContainerBaseRepositoryContext(PulpRepositoryContext): + def tag(self, tag: str, digest: str) -> Any: + self.needs_capability("tag") + return self.call( + "tag", + parameters={self.HREF: self.pulp_href}, + body={"tag": tag, "digest": digest}, + ) + + def untag(self, tag: str) -> Any: + self.needs_capability("tag") + return self.call( + "untag", + parameters={self.HREF: self.pulp_href}, + body={"tag": tag}, + ) + + +class PulpContainerRepositoryContext(PulpContainerBaseRepositoryContext): HREF = "container_container_repository_href" ID_PREFIX = "repositories_container_container" VERSION_CONTEXT = PulpContainerRepositoryVersionContext @@ -87,7 +107,7 @@ class PulpContainerRepositoryContext(PulpRepositoryContext): } -class PulpContainerPushRepositoryContext(PulpRepositoryContext): +class PulpContainerPushRepositoryContext(PulpContainerBaseRepositoryContext): HREF = "container_container_push_repository_href" ID_PREFIX = "repositories_container_container_push" VERSION_CONTEXT = PulpContainerPushRepositoryVersionContext diff --git a/pulpcore/cli/container/repository.py b/pulpcore/cli/container/repository.py index 4b2e89f64..498359024 100644 --- a/pulpcore/cli/container/repository.py +++ b/pulpcore/cli/container/repository.py @@ -30,6 +30,7 @@ ) from pulpcore.cli.common.i18n import get_translation from pulpcore.cli.container.context import ( + PulpContainerBaseRepositoryContext, PulpContainerPushRepositoryContext, PulpContainerRemoteContext, PulpContainerRepositoryContext, @@ -142,24 +143,17 @@ def sync( @click.option("--digest", help=_("SHA256 digest of the Manifest file"), required=True) @pass_repository_context def add_tag( - repository_ctx: PulpRepositoryContext, + repository_ctx: PulpContainerBaseRepositoryContext, digest: str, tag: str, ) -> None: - if not repository_ctx.capable("tag"): - raise click.ClickException(_("pulp_container 2.3.0 is required to tag images")) - digest = digest.strip() if not digest.startswith("sha256:"): digest = f"sha256:{digest}" if len(digest) != 71: # len("sha256:") + 64 raise click.ClickException("Improper SHA256, please provide a valid 64 digit digest.") - repository_ctx.call( - "tag", - parameters={repository_ctx.HREF: repository_ctx.pulp_href}, - body={"tag": tag, "digest": digest}, - ) + repository_ctx.tag(tag, digest) @repository.command(name="untag") @@ -167,12 +161,5 @@ def add_tag( @href_option @click.option("--tag", help=_("Name of tag to remove"), required=True, callback=_tag_callback) @pass_repository_context -def remove_tag(repository_ctx: PulpRepositoryContext, tag: str) -> None: - if not repository_ctx.capable("tag"): - raise click.ClickException(_("pulp_container 2.3.0 is required to untag images")) - - repository_ctx.call( - "untag", - parameters={repository_ctx.HREF: repository_ctx.pulp_href}, - body={"tag": tag}, - ) +def remove_tag(repository_ctx: PulpContainerBaseRepositoryContext, tag: str) -> None: + repository_ctx.untag(tag) diff --git a/pulpcore/cli/core/content_guard.py b/pulpcore/cli/core/content_guard.py index f3f590292..df05b09a4 100644 --- a/pulpcore/cli/core/content_guard.py +++ b/pulpcore/cli/core/content_guard.py @@ -52,9 +52,7 @@ def rbac(ctx: click.Context, pulp_ctx: PulpContext) -> None: rbac.add_command(show_command(decorators=lookup_options)) rbac.add_command(update_command(decorators=lookup_options)) rbac.add_command(destroy_command(decorators=lookup_options)) -rbac.add_command( - role_command(decorators=lookup_options, needs_plugins=[PluginRequirement("core", min="3.17")]) -) +rbac.add_command(role_command(decorators=lookup_options)) @rbac.command() diff --git a/pulpcore/cli/core/context.py b/pulpcore/cli/core/context.py index 0ae5325b7..a3497f475 100644 --- a/pulpcore/cli/core/context.py +++ b/pulpcore/cli/core/context.py @@ -117,6 +117,7 @@ class PulpGroupContext(PulpEntityContext): # Handled by a workaround # HREF = "group_href" ID_PREFIX = "groups" + CAPABILITIES = {"roles": [PluginRequirement("core", "3.17.0")]} @property def HREF(self) -> str: # type:ignore @@ -245,6 +246,7 @@ class PulpRbacContentGuardContext(PulpContentGuardContext): HREF = "r_b_a_c_content_guard_href" ID_PREFIX = "contentguards_core_rbac" DOWNLOAD_ROLE: ClassVar[str] = "core.rbaccontentguard_downloader" + CAPABILITIES = {"roles": [PluginRequirement("core", "3.17.0")]} def assign(self, href: str, users: Optional[List[str]], groups: Optional[List[str]]) -> Any: if self.pulp_ctx.has_plugin(PluginRequirement("core", min="3.17.0.dev")): @@ -285,6 +287,7 @@ class PulpTaskContext(PulpEntityContext): ENTITIES = _("tasks") HREF = "task_href" ID_PREFIX = "tasks" + CAPABILITIES = {"roles": [PluginRequirement("core", "3.17.0")]} resource_context: Optional[PulpEntityContext] = None