Skip to content

Commit

Permalink
Provide a factory for resource options
Browse files Browse the repository at this point in the history
The options accept resources by the "[[<plugin>:]<type>:]name" pattern.

Fixes pulp#158
  • Loading branch information
mdellweg committed May 12, 2021
1 parent 4acacaf commit 8e760e1
Show file tree
Hide file tree
Showing 16 changed files with 254 additions and 239 deletions.
1 change: 1 addition & 0 deletions CHANGES/158.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Change resource options to accept plugin and type along with the name.
65 changes: 64 additions & 1 deletion pulpcore/cli/common/generic.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import gettext
import json
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, TypeVar, Union

import click

from pulpcore.cli.common.context import (
DEFAULT_LIMIT,
EntityDefinition,
EntityFieldDefinition,
PluginRequirement,
PulpContentContext,
PulpContext,
Expand All @@ -21,6 +22,7 @@
)

_ = gettext.gettext

_F = TypeVar("_F")


Expand Down Expand Up @@ -202,6 +204,67 @@ def pulp_option(*args: Any, **kwargs: Any) -> Callable[[_F], _F]:
return click.option(*args, **kwargs)


def resource_option(*args: Any, **kwargs: Any) -> Callable[[_F], _F]:
default_plugin: Optional[str] = kwargs.pop("default_plugin", None)
default_type: Optional[str] = kwargs.pop("default_type", None)
lookup_key: str = kwargs.pop("lookup_key", "name")
context_table: Dict[str, Type[PulpEntityContext]] = kwargs.pop("context_table")

def _option_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> EntityFieldDefinition:
# Pass None and "" verbatim
if value:
split_value = value.split(":", maxsplit=2)
while len(split_value) < 3:
split_value.insert(0, "")
plugin, resource_type, identifier = split_value

if resource_type == "":
if default_type is None:
raise click.ClickException(
_(
"A resource type must be specified with the {option_name} option."
).format(option_name=param.name)
)
resource_type = default_type
if plugin == "":
if default_plugin is None:
raise click.ClickException(
_("A plugin must be specified with the {option_name} option.").format(
option_name=param.name
)
)
plugin = default_plugin

context_class = context_table.get(plugin + ":" + resource_type)
if context_class is None:
raise click.ClickException(
_(
"The type '{plugin}:{resource_type}' "
"is not valid for the {option_name} option."
).format(plugin=plugin, resource_type=resource_type, option_name=param.name)
)
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
return context_class(pulp_ctx, entity={lookup_key: identifier})
return value

def _multi_option_callback(
ctx: click.Context, param: click.Parameter, value: Iterable[Optional[str]]
) -> Iterable[EntityFieldDefinition]:
if value:
return (_option_callback(ctx, param, item) for item in value)
return tuple()

if "cls" not in kwargs:
kwargs["cls"] = PulpOption
if kwargs.get("multiple"):
kwargs["callback"] = _multi_option_callback
else:
kwargs["callback"] = _option_callback
return click.option(*args, **kwargs)


limit_option = pulp_option(
"--limit",
default=DEFAULT_LIMIT,
Expand Down
61 changes: 16 additions & 45 deletions pulpcore/cli/container/distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
create_command,
destroy_command,
href_option,
label_command,
label_select_option,
list_command,
name_option,
resource_option,
show_command,
)
from pulpcore.cli.container.context import (
Expand All @@ -29,28 +32,15 @@
_ = gettext.gettext


def _repository_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Union[None, str, PulpEntityContext]:
# Pass None and "" verbatim
if value:
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
entity_ctx = ctx.find_object(PulpEntityContext)
if entity_ctx.meta.get("repository_type") == "container":
return PulpContainerRepositoryContext(pulp_ctx, entity={"name": value})
elif entity_ctx.meta.get("repository_type") == "push":
return PulpContainerPushRepositoryContext(pulp_ctx, entity={"name": value})
else:
raise NotImplementedError()
return value


def _repository_type_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[str]:
entity_ctx = ctx.find_object(PulpEntityContext)
entity_ctx.meta["repository_type"] = value
return value
repository_option = resource_option(
"--repository",
default_plugin="container",
default_type="container",
context_table={
"container:container": PulpContainerRepositoryContext,
"container:push": PulpContainerPushRepositoryContext,
},
)


@click.group()
Expand All @@ -70,49 +60,30 @@ def distribution(ctx: click.Context, pulp_ctx: PulpContext, distribution_type: s
raise NotImplementedError()


filter_options = [base_path_option, base_path_contains_option]
filter_options = [label_select_option, base_path_option, base_path_contains_option]
lookup_options = [href_option, name_option]
create_options = [
click.option("--name", required=True),
click.option("--base-path", required=True),
click.option("--repository", callback=_repository_callback),
repository_option,
click.option(
"--version", type=int, help=_("a repository version number, leave blank for latest")
),
click.option(
"-t",
"--repository-type",
"repository_type",
type=click.Choice(["container", "push"], case_sensitive=False),
default="container",
is_eager=True,
expose_value=False,
callback=_repository_type_callback,
),
]

distribution.add_command(list_command(decorators=filter_options))
distribution.add_command(show_command(decorators=lookup_options))
distribution.add_command(create_command(decorators=create_options))
distribution.add_command(destroy_command(decorators=lookup_options))
distribution.add_command(label_command())


@distribution.command()
@href_option
@name_option
@click.option("--base-path")
@click.option("--repository", callback=_repository_callback)
@repository_option
@click.option("--version", type=int, help=_("a repository version number, leave blank for latest"))
@click.option(
"-t",
"--repository-type",
"repository_type",
type=click.Choice(["container", "push"], case_sensitive=False),
default="container",
is_eager=True,
expose_value=False,
callback=_repository_type_callback,
)
@pass_entity_context
@pass_pulp_context
def update(
Expand Down
44 changes: 24 additions & 20 deletions pulpcore/cli/container/repository.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import gettext
from typing import Optional, Union
from typing import Any, Dict

import click

from pulpcore.cli.common.context import (
EntityFieldDefinition,
PluginRequirement,
PulpContext,
PulpEntityContext,
PulpRepositoryContext,
Expand All @@ -18,6 +20,10 @@
label_select_option,
list_command,
name_option,
pulp_option,
repository_href_option,
repository_option,
resource_option,
show_command,
update_command,
version_command,
Expand All @@ -27,18 +33,17 @@
PulpContainerRemoteContext,
PulpContainerRepositoryContext,
)
from pulpcore.cli.core.generic import task_command

_ = gettext.gettext


def _remote_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[Union[str, PulpEntityContext]]:
# Pass None and "" verbatim
if value:
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
return PulpContainerRemoteContext(pulp_ctx, entity={"name": value})
return value
remote_option = resource_option(
"--remote",
default_plugin="container",
default_type="container",
context_table={"container:container": PulpContainerRemoteContext},
)


@click.group()
Expand All @@ -61,41 +66,40 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non


lookup_options = [href_option, name_option]
create_options = [
click.option("--name", required=True),
click.option("--description"),
click.option("--remote", callback=_remote_callback),
]
nested_lookup_options = [repository_href_option, repository_option]
update_options = [
click.option("--description"),
click.option("--remote", callback=_remote_callback),
remote_option,
pulp_option("--retained-versions", needs_plugins=[PluginRequirement("core", "3.13.0.dev")]),
]
create_options = update_options + [click.option("--name", required=True)]

repository.add_command(list_command(decorators=[label_select_option]))
repository.add_command(show_command(decorators=lookup_options))
repository.add_command(create_command(decorators=create_options))
repository.add_command(update_command(decorators=lookup_options + update_options))
repository.add_command(destroy_command(decorators=lookup_options))
repository.add_command(version_command())
repository.add_command(label_command())
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.command()
@name_option
@href_option
@click.option("--remote", callback=_remote_callback)
@remote_option
@pass_repository_context
def sync(
repository_ctx: PulpRepositoryContext,
remote: Optional[Union[str, PulpEntityContext]],
remote: EntityFieldDefinition,
) -> None:
if repository_ctx.SYNC_ID is None:
raise click.ClickException(_("Repository type does not support sync."))

repository = repository_ctx.entity
repository_href = repository_ctx.pulp_href

body = {}
body: Dict[str, Any] = {}

if isinstance(remote, PulpEntityContext):
body["remote"] = remote.pulp_href
Expand Down
24 changes: 10 additions & 14 deletions pulpcore/cli/file/distribution.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import gettext
from typing import Optional, Union

import click

from pulpcore.cli.common.context import PulpContext, PulpEntityContext, pass_pulp_context
from pulpcore.cli.common.context import PulpContext, pass_pulp_context
from pulpcore.cli.common.generic import (
base_path_contains_option,
base_path_option,
Expand All @@ -14,6 +13,7 @@
label_select_option,
list_command,
name_option,
resource_option,
show_command,
update_command,
)
Expand All @@ -22,14 +22,12 @@
_ = gettext.gettext


def _repository_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Union[str, PulpEntityContext, None]:
# Pass None and "" verbatim
if value:
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
return PulpFileRepositoryContext(pulp_ctx, entity={"name": value})
return value
repository_option = resource_option(
"--repository",
default_plugin="file",
default_type="file",
context_table={"file:file": PulpFileRepositoryContext},
)


@click.group()
Expand All @@ -54,11 +52,9 @@ def distribution(ctx: click.Context, pulp_ctx: PulpContext, distribution_type: s
update_options = [
click.option("--base-path"),
click.option("--publication"),
click.option("--repository", callback=_repository_callback),
]
create_options = update_options + [
click.option("--name", required=True),
repository_option,
]
create_options = update_options + [click.option("--name", required=True)]

distribution.add_command(list_command(decorators=filter_options))
distribution.add_command(show_command(decorators=lookup_options))
Expand Down
20 changes: 9 additions & 11 deletions pulpcore/cli/file/publication.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
import gettext
from typing import Optional, Union

import click

from pulpcore.cli.common.context import PulpContext, PulpEntityContext, pass_pulp_context
from pulpcore.cli.common.context import PulpContext, pass_pulp_context
from pulpcore.cli.common.generic import (
create_command,
destroy_command,
href_option,
list_command,
resource_option,
show_command,
)
from pulpcore.cli.file.context import PulpFilePublicationContext, PulpFileRepositoryContext

_ = gettext.gettext


def _repository_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[Union[str, PulpEntityContext]]:
# Pass None and "" verbatim
if value:
pulp_ctx: PulpContext = ctx.find_object(PulpContext)
return PulpFileRepositoryContext(pulp_ctx, entity={"name": value})
return value
repository_option = resource_option(
"--repository",
default_plugin="file",
default_type="file",
context_table={"file:file": PulpFileRepositoryContext},
)


@click.group()
Expand All @@ -45,7 +43,7 @@ def publication(ctx: click.Context, pulp_ctx: PulpContext, publication_type: str

lookup_options = [href_option]
create_options = [
click.option("--repository", required=True, callback=_repository_callback),
repository_option,
click.option(
"--version", type=int, help=_("a repository version number, leave blank for latest")
),
Expand Down
Loading

0 comments on commit 8e760e1

Please sign in to comment.