Skip to content

Commit

Permalink
Add repository content commands for ansible
Browse files Browse the repository at this point in the history
fixes: pulp#363
  • Loading branch information
gerrod3 committed Sep 3, 2021
1 parent e9ec154 commit 34fba9a
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGES/363.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added content management commands for Ansible repositories
113 changes: 110 additions & 3 deletions pulpcore/cli/ansible/repository.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import gettext
from typing import Any

import click
import schema as s

from pulpcore.cli.ansible.context import (
PulpAnsibleCollectionRemoteContext,
PulpAnsibleCollectionVersionContext,
PulpAnsibleRepositoryContext,
PulpAnsibleRoleContext,
PulpAnsibleRoleRemoteContext,
)
from pulpcore.cli.common.context import (
Expand All @@ -17,13 +21,16 @@
pass_repository_context,
)
from pulpcore.cli.common.generic import (
GroupOption,
create_command,
create_content_json_callback,
destroy_command,
href_option,
label_command,
label_select_option,
list_command,
name_option,
repository_content_command,
resource_option,
retained_versions_option,
show_command,
Expand All @@ -49,6 +56,31 @@
)


CONTENT_LIST_SCHEMA = s.Schema(
[{"name": s.And(str, len), "namespace": s.And(str, len), "version": s.And(str, len)}]
)


def _content_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any:
print(value)
if value:
ctx.obj.entity = value # The context is set by the type parameter on the content commands
return value


def _content_type_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any:
# This is eagerly ran
pulp_ctx = ctx.find_object(PulpContext)
assert pulp_ctx is not None
if value == "collection-version":
ctx.obj = PulpAnsibleCollectionVersionContext(pulp_ctx)
elif value == "role":
ctx.obj = PulpAnsibleRoleContext(pulp_ctx)
else:
raise NotImplementedError()
return value


@click.group()
@click.option(
"-t",
Expand Down Expand Up @@ -78,6 +110,73 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non
remote_option,
retained_versions_option,
]
content_options = [
click.option(
"--name",
help=_("Name of {entity}"),
group=["namespace", "version"],
expose_value=False,
cls=GroupOption,
callback=_content_callback,
),
click.option(
"--namespace",
help=_("Namespace of {entity}"),
group=["name", "version"],
expose_value=False,
cls=GroupOption,
),
click.option(
"--version",
help=_("Version of {entity}"),
group=["namespace", "name"],
expose_value=False,
cls=GroupOption,
),
click.option(
"-t",
"--type",
"type",
type=click.Choice(["collection-version", "role"]),
default="collection-version",
expose_value=False,
callback=_content_type_callback,
is_eager=True,
),
href_option,
]
content_json_callback = create_content_json_callback(schema=CONTENT_LIST_SCHEMA)
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 must contain the following keys: "name", "namespace", "version".
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 must contain the following keys: "name", "namespace", "version".
The argument prefixed with the '@' can be the path to a JSON file with a list of objects."""
),
),
click.option(
"-t",
"--type",
"type",
type=click.Choice(["collection-version", "role"]),
default="collection-version",
expose_value=False,
callback=_content_type_callback,
is_eager=True,
),
]


repository.add_command(show_command(decorators=lookup_options))
repository.add_command(list_command(decorators=[label_select_option]))
Expand All @@ -86,6 +185,17 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non
repository.add_command(create_command(decorators=create_options))
repository.add_command(update_command(decorators=lookup_options + update_options))
repository.add_command(label_command())
repository.add_command(
repository_content_command(
contexts={
"collection-version": PulpAnsibleCollectionVersionContext,
"role": PulpAnsibleRoleContext,
},
add_decorators=content_options,
remove_decorators=content_options,
modify_decorators=modify_options,
)
)


@repository.command()
Expand Down Expand Up @@ -116,6 +226,3 @@ def sync(
href=repository_href,
body=body,
)


# TODO Finish 'add' and 'remove' commands when role and collection contexts are implemented
17 changes: 12 additions & 5 deletions pulpcore/cli/common/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ 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) + "."
kwargs.get("help", "") + " Option is grouped with " + ", ".join(self.group) + "."
).strip()
super().__init__(*args, **kwargs)

Expand All @@ -107,7 +107,9 @@ def handle_parse_result(
) -> Any:
assert self.name is not None
all_options = self.group + [self.name]
if all(x in opts for x in all_options):
options_present = [x for x in all_options if x in opts]
num_options = len(options_present)
if not num_options and not self.required or num_options == len(all_options):
self.prompt = None
else:
raise click.UsageError(
Expand All @@ -116,7 +118,7 @@ def handle_parse_result(
)
value = opts.get(self.name)
if self.callback is not None:
value = self.callback(ctx, self, {o: opts[o] for o in all_options})
value = self.callback(ctx, self, {o: opts[o] for o in options_present})
if self.expose_value:
ctx.params[self.name] = value
return value, args
Expand Down Expand Up @@ -212,11 +214,12 @@ def load_json_callback(


def create_content_json_callback(
content_ctx: Type[PulpContentContext], schema: s.Schema = None
content_ctx: Optional[Type[PulpContentContext]] = None, schema: s.Schema = None
) -> Any:
def _callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[List[PulpContentContext]]:
ctx_class = content_ctx
new_value = load_json_callback(ctx, param, value)
if new_value is not None:
if schema is not None:
Expand All @@ -228,7 +231,11 @@ def _callback(
)
pulp_ctx = ctx.find_object(PulpContext)
assert pulp_ctx is not None
return [content_ctx(pulp_ctx, entity=unit) for unit in new_value]
if ctx_class is None:
context = ctx.find_object(PulpContentContext)
assert context is not None
ctx_class = type(context)
return [ctx_class(pulp_ctx, entity=unit) for unit in new_value]
return new_value

return _callback
Expand Down
17 changes: 17 additions & 0 deletions tests/scripts/pulp_ansible/test_content.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
pulp debug has-plugin --name "ansible" || exit 3

cleanup() {
pulp ansible repository destroy --name "cli_test_ansible_repository" || true
pulp orphans delete || true
}
trap cleanup EXIT
Expand Down Expand Up @@ -33,3 +34,19 @@ expect_succ pulp ansible content --type "role" list --name "kubernetes-modules"
test "$(echo "$OUTPUT" | jq -r length)" -eq "1"
content2_href="$(echo "$OUTPUT" | jq -r .[0].pulp_href)"
expect_succ pulp ansible content --type "role" show --href "$content2_href"

# New content commands
expect_succ pulp ansible repository create --name "cli_test_ansible_repository"
expect_succ pulp ansible repository content add --repository "cli_test_ansible_repository" --name "posix" --namespace "ansible" --version "1.3.0"
expect_succ pulp ansible repository content list --repository "cli_test_ansible_repository" --version 1
test "$(echo "$OUTPUT" | jq -r length)" -eq "1"
expect_succ pulp ansible repository content add --repository "cli_test_ansible_repository" --type "role" --name "kubernetes-modules" --namespace "ansible" --version "0.0.1"
expect_succ pulp ansible repository content list --repository "cli_test_ansible_repository" --version 2 --type "role"
test "$(echo "$OUTPUT" | jq -r length)" -eq "1"
expect_succ pulp ansible repository content list --repository "cli_test_ansible_repository" --version 2 --type "all"
test "$(echo "$OUTPUT" | jq -r length)" -eq "2"

expect_succ pulp ansible repository content remove --repository "cli_test_ansible_repository" --href "$content_href"
expect_succ pulp ansible repository content remove --repository "cli_test_ansible_repository" --href "$content2_href"
expect_succ pulp ansible repository content list --repository "cli_test_ansible_repository"
test "$(echo "$OUTPUT" | jq -r length)" -eq "0"

0 comments on commit 34fba9a

Please sign in to comment.