Skip to content

Commit

Permalink
Added new content subgroup to repository commands
Browse files Browse the repository at this point in the history
fixes: pulp#171
  • Loading branch information
gerrod3 committed Apr 19, 2021
1 parent d2be887 commit 01bde82
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGES/171.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Repository content commands are now nested under a new content subgroup
11 changes: 11 additions & 0 deletions pulpcore/cli/common/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,16 @@ def modify(
)


class PulpContentContext(PulpEntityContext):
"""
Base class for content specific contexts
"""

ENTITY = "content"
ENTITIES = "content"
LIST_ID = "content_list"


EntityFieldDefinition = Union[None, str, PulpEntityContext]
##############################################################################
# Decorator to access certain contexts
Expand All @@ -566,3 +576,4 @@ def modify(
pass_entity_context = click.make_pass_decorator(PulpEntityContext)
pass_repository_context = click.make_pass_decorator(PulpRepositoryContext)
pass_repository_version_context = click.make_pass_decorator(PulpRepositoryVersionContext)
pass_content_context = click.make_pass_decorator(PulpContentContext)
130 changes: 129 additions & 1 deletion pulpcore/cli/common/generic.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import gettext
import json
from typing import Any, NamedTuple, Optional, Tuple, Union
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union

import click

from pulpcore.cli.common.context import (
DEFAULT_LIMIT,
EntityDefinition,
PulpContentContext,
PulpContext,
PulpEntityContext,
PulpRepositoryContext,
PulpRepositoryVersionContext,
pass_content_context,
pass_entity_context,
pass_pulp_context,
pass_repository_context,
Expand Down Expand Up @@ -47,6 +49,32 @@ def get_help_record(self, ctx: click.Context) -> Tuple[str, str]:
return synopsis, help_text


class GroupOption(PulpOption):
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.group: List[str] = kwargs.pop("group")
assert self.group, "'group' parameter required"
kwargs["help"] = (
kwargs.get("help", "") + "Option is grouped with " + ", ".join(self.group) + "."
).strip()
super().__init__(*args, **kwargs)

def handle_parse_result(self, ctx: click.Context, opts: Dict[str, Any], args: Any) -> Any:
all_options = self.group + [self.name]
if all(x in opts for x in all_options):
self.prompt = None # type: ignore
else:
raise click.UsageError(
"Illegal usage, please specify all "
"options in the group: " + ", ".join(all_options)
)
value = opts.get(self.name)
if self.callback is not None:
value = self.callback(ctx, self, {o: opts[o] for o in all_options}) # type: ignore
if self.expose_value:
ctx.params[self.name] = value
return value, args


##############################################################################
# Option callbacks

Expand Down Expand Up @@ -435,3 +463,103 @@ def label_show(entity_ctx: PulpEntityContext, key: str) -> None:
label_group.add_command(subcmd)

return label_group


def repository_content_command(**kwargs: Any) -> click.Group:
"""A factory that creates a repository content command group."""

name = kwargs.get("name", "content")
content_contexts = kwargs.pop("contexts", {})
content_contexts.update({"all": PulpContentContext})
content_names = list(content_contexts.keys())
commands = {}

@click.group(name)
def content_group() -> None:
pass

@click.command("list")
@click.option("-t", "--type", "type", type=click.Choice(content_names), default="all")
@limit_option
@offset_option
@repository_option
@click.option("--base-version", type=int)
@pass_repository_context
@pass_pulp_context
def content_list(
pulp_ctx: PulpContext,
repo_ctx: PulpRepositoryContext,
base_version: Optional[int],
offset: Optional[int],
limit: Optional[int],
type: Optional[str],
**params: Any,
) -> None:
parameters = {k: v for k, v in params.items() if v is not None}
repo_version = (
f"{repo_ctx.pulp_href}versions/{base_version}/" if base_version else repo_ctx.pulp_href
)
parameters.update({"repository_version": repo_version})
result = content_contexts[type](pulp_ctx).list(
limit=limit, offset=offset, parameters=parameters
)
pulp_ctx.output_result(result)

@click.command("add")
@repository_option
@click.option("--base-version", type=int)
@pass_content_context
@pass_repository_context
def content_add(
repo_ctx: PulpRepositoryContext,
content_ctx: PulpContentContext,
base_version: Optional[int],
) -> None:
bv = f"{repo_ctx.pulp_href}versions/{base_version}" if base_version is not None else None
repo_ctx.modify(repo_ctx.pulp_href, add_content=[content_ctx.pulp_href], base_version=bv)

@click.command("remove")
@click.option("--all", is_flag=True, help=_("Remove all content from repository version"))
@repository_option
@click.option("--base-version", type=int)
@pass_content_context
@pass_repository_context
def content_remove(
repo_ctx: PulpRepositoryContext,
content_ctx: PulpContentContext,
base_version: Optional[int],
all: bool,
) -> None:
remove_content = ["*" if all else content_ctx.pulp_href]
bv = f"{repo_ctx.pulp_href}versions/{base_version}" if base_version is not None else None
repo_ctx.modify(repo_ctx.pulp_href, remove_content=remove_content, base_version=bv)

@click.command("modify")
@repository_option
@click.option("--base-version", type=int)
@pass_repository_context
def content_modify(
repo_ctx: PulpRepositoryContext,
base_version: Optional[int],
add_content: List[PulpContentContext],
remove_content: List[PulpContentContext],
) -> None:
bv = f"{repo_ctx.pulp_href}versions/{base_version}" if base_version is not None else None
repo_ctx.modify(
repo_ctx.pulp_href,
add_content=[unit.pulp_href for unit in add_content],
remove_content=[unit.pulp_href for unit in remove_content],
base_version=bv,
)

commands[content_list] = kwargs.pop("list_decorators", [])
commands[content_add] = kwargs.pop("add_decorators", [])
commands[content_remove] = kwargs.pop("remove_decorators", [])
commands[content_modify] = kwargs.pop("modify_decorators", [])

for command, options in commands.items():
for option in options:
command = option(command)
content_group.add_command(command)

return content_group
4 changes: 3 additions & 1 deletion pulpcore/cli/file/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from pulpcore.cli.common.context import (
EntityDefinition,
PulpContentContext,
PulpEntityContext,
PulpRemoteContext,
PulpRepositoryContext,
Expand All @@ -11,13 +12,14 @@
_ = gettext.gettext


class PulpFileContentContext(PulpEntityContext):
class PulpFileContentContext(PulpContentContext):
ENTITY = "file content"
ENTITIES = "file content"
HREF = "file_file_content_href"
LIST_ID = "content_file_files_list"
READ_ID = "content_file_files_read"
CREATE_ID = "content_file_files_create"
UNIQUE_LOOKUPS = ["sha256", "relative-path"]


class PulpFileDistributionContext(PulpEntityContext):
Expand Down
66 changes: 62 additions & 4 deletions pulpcore/cli/file/repository.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import gettext
from typing import Dict, List, Optional, Union
from typing import Any, Dict, List, Optional, Union

import click

Expand All @@ -11,6 +11,7 @@
pass_repository_context,
)
from pulpcore.cli.common.generic import (
GroupOption,
create_command,
destroy_command,
href_option,
Expand All @@ -19,6 +20,7 @@
list_command,
load_json_callback,
name_option,
repository_content_command,
repository_href_option,
repository_option,
show_command,
Expand All @@ -45,6 +47,21 @@ def _remote_callback(
return value


def _content_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Optional[str]:
if value:
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
ctx.obj = PulpFileContentContext(pulp_ctx, entity=value)
return str(value)


def _content_json_callback(ctx: click.Context, param: click.Parameter, value: str) -> Any:
new_value = load_json_callback(ctx, param, value)
if new_value:
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
return [PulpFileContentContext(pulp_ctx, entity=unit) for unit in new_value]
return value


@click.group()
@click.option(
"-t",
Expand Down Expand Up @@ -73,6 +90,36 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non
click.option("--description"),
click.option("--remote", callback=_remote_callback),
]
file_options = [
click.option("--sha256", cls=GroupOption, expose_value=False, group=["relative_path"]),
click.option(
"--relative-path",
cls=GroupOption,
expose_value=False,
group=["sha256"],
callback=_content_callback,
),
]
modify_options = [
click.option(
"--add-content",
callback=_content_json_callback,
help=_(
"""JSON string with a list of objects to add to the repository.
Each object should consist of the following keys: "sha256", "relative_path"..
The argument prefixed with the '@' can be the path to a JSON file with a list of objects."""
),
),
click.option(
"--remove-content",
callback=_content_json_callback,
help=_(
"""JSON string with a list of objects to remove from the repository.
Each object should consist of the following keys: "sha256", "relative_path"..
The argument prefixed with the '@' can be the path to a JSON file with a list of objects."""
),
),
]

repository.add_command(list_command(decorators=[label_select_option]))
repository.add_command(show_command(decorators=lookup_options))
Expand All @@ -82,6 +129,14 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non
repository.add_command(task_command(decorators=nested_lookup_options))
repository.add_command(version_command(decorators=nested_lookup_options))
repository.add_command(label_command(decorators=nested_lookup_options))
repository.add_command(
repository_content_command(
contexts={"file": PulpFileContentContext},
add_decorators=file_options,
remove_decorators=file_options,
modify_decorators=modify_options,
)
)


@repository.command()
Expand Down Expand Up @@ -112,7 +167,7 @@ def sync(
)


@repository.command()
@repository.command(deprecated=True)
@name_option
@href_option
@click.option("--sha256", required=True)
Expand All @@ -127,6 +182,7 @@ def add(
relative_path: str,
base_version: Optional[int],
) -> None:
"""Please use 'content add' instead."""
repository_href = repository_ctx.pulp_href

base_version_href: Optional[str]
Expand All @@ -146,7 +202,7 @@ def add(
)


@repository.command()
@repository.command(deprecated=True)
@name_option
@href_option
@click.option("--sha256", required=True)
Expand All @@ -161,6 +217,7 @@ def remove(
relative_path: str,
base_version: Optional[int],
) -> None:
"""Please use 'content remove' instead."""
repository_href = repository_ctx.pulp_href

base_version_href: Optional[str]
Expand All @@ -180,7 +237,7 @@ def remove(
)


@repository.command()
@repository.command(deprecated=True)
@name_option
@href_option
@click.option("--base-version", type=int)
Expand Down Expand Up @@ -215,6 +272,7 @@ def modify(
remove_content: List[Dict[str, str]],
base_version: Optional[int],
) -> None:
"""Please use 'content modify' instead."""
repository_href = repository_ctx.pulp_href

base_version_href: Optional[str]
Expand Down
3 changes: 2 additions & 1 deletion pulpcore/cli/python/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

from pulpcore.cli.common.context import (
EntityDefinition,
PulpContentContext,
PulpEntityContext,
PulpRepositoryContext,
PulpRepositoryVersionContext,
)


class PulpPythonContentContext(PulpEntityContext):
class PulpPythonContentContext(PulpContentContext):
ENTITY = "python content"
ENTITIES = "python content"
HREF = "python_python_package_content_href"
Expand Down
Loading

0 comments on commit 01bde82

Please sign in to comment.