Skip to content

Commit

Permalink
Add rpm package content support
Browse files Browse the repository at this point in the history
Adds 'rpm package content', as well as the 'pulp rpm
repository content' command group.

fixes pulp#284
  • Loading branch information
Tjev committed Sep 27, 2021
1 parent 49bb141 commit d21d6fb
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES/284.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added rpm package content commands support.
2 changes: 2 additions & 0 deletions pulpcore/cli/rpm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from pulpcore.cli.common import main
from pulpcore.cli.common.context import PluginRequirement, PulpContext, pass_pulp_context
from pulpcore.cli.rpm.content import content
from pulpcore.cli.rpm.distribution import distribution
from pulpcore.cli.rpm.publication import publication
from pulpcore.cli.rpm.remote import remote
Expand All @@ -20,3 +21,4 @@ def rpm(pulp_ctx: PulpContext) -> None:
rpm.add_command(remote)
rpm.add_command(publication)
rpm.add_command(distribution)
rpm.add_command(content)
123 changes: 123 additions & 0 deletions pulpcore/cli/rpm/content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import gettext
from typing import IO, Optional, Union

import click

from pulpcore.cli.common.context import (
PulpContext,
PulpEntityContext,
pass_entity_context,
pass_pulp_context,
)
from pulpcore.cli.common.generic import (
chunk_size_option,
create_command,
href_option,
list_command,
show_command,
)
from pulpcore.cli.core.context import PulpArtifactContext
from pulpcore.cli.rpm.context import PulpRpmPackageContext

_ = gettext.gettext


def _relative_path_callback(ctx: click.Context, param: click.Parameter, value: str) -> str:
if value is not None:
entity_ctx = ctx.find_object(PulpEntityContext)
assert entity_ctx is not None
entity_ctx.entity = {"relative_path": value}
return value


def _sha256_callback(ctx: click.Context, param: click.Parameter, value: str) -> str:
if value is not None:
entity_ctx = ctx.find_object(PulpEntityContext)
assert entity_ctx is not None
entity_ctx.entity = {"sha256": value}
return value


def _sha256_artifact_callback(
ctx: click.Context, param: click.Parameter, value: Optional[str]
) -> Optional[Union[str, PulpEntityContext]]:
# Pass None and "" verbatim
if value:
pulp_ctx = ctx.find_object(PulpContext)
assert pulp_ctx is not None
return PulpArtifactContext(pulp_ctx, entity={"sha256": value})
return value


@click.group()
@click.option(
"-t",
"--type",
"content_type",
type=click.Choice(["package"], case_sensitive=False),
default="package",
)
@pass_pulp_context
@click.pass_context
def content(ctx: click.Context, pulp_ctx: PulpContext, content_type: str) -> None:
if content_type == "package":
ctx.obj = PulpRpmPackageContext(pulp_ctx)
else:
raise NotImplementedError()


list_options = [
click.option("--arch"),
click.option("--arch-in", "arch__in"),
click.option("--epoch"),
click.option("--epoch-in", "epoch__in"),
click.option("--fields"),
click.option("--name"),
click.option("--name-in", "name__in"),
click.option("--package-href"),
click.option("--release"),
click.option("--release-in", "release__in"),
click.option("--repository-version"),
click.option("--version"),
click.option("--version-in", "version__in"),
]
lookup_options = [
href_option,
click.option("--relative-path", callback=_relative_path_callback, expose_value=False),
click.option("--sha256", callback=_sha256_callback, expose_value=False),
]
create_options = [
click.option("--relative-path", required=True),
click.option(
"--sha256",
"artifact",
required=True,
help=_("Digest of the artifact to use"),
callback=_sha256_artifact_callback,
),
]


content.add_command(list_command(decorators=list_options))
content.add_command(show_command(decorators=lookup_options))
content.add_command(create_command(decorators=create_options))


@content.command()
@click.option("--relative-path", required=True)
@click.option("--file", type=click.File("rb"), required=True)
@chunk_size_option
@pass_entity_context
@pass_pulp_context
def upload(
pulp_ctx: PulpContext,
entity_ctx: PulpRpmPackageContext,
relative_path: str,
file: IO[bytes],
chunk_size: int,
) -> None:
"""Create an rpm package content unit by uploading a file"""
artifact_href = PulpArtifactContext(pulp_ctx).upload(file, chunk_size)
content = {"relative_path": relative_path, "artifact": artifact_href}
result = entity_ctx.create(body=content)
pulp_ctx.output_result(result)
11 changes: 11 additions & 0 deletions pulpcore/cli/rpm/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pulpcore.cli.common.context import (
EntityDefinition,
PluginRequirement,
PulpContentContext,
PulpEntityContext,
PulpRemoteContext,
PulpRepositoryContext,
Expand All @@ -24,6 +25,15 @@ class PulpRpmDistributionContext(PulpEntityContext):
NULLABLES = {"publication"}


class PulpRpmPackageContext(PulpContentContext):
ENTITY = "rpm package"
ENTITIES = "rpm packages"
HREF = "rpm_package_href"
LIST_ID = "content_rpm_packages_list"
READ_ID = "content_rpm_packages_read"
CREATE_ID = "content_rpm_packages_create"


class PulpRpmPublicationContext(PulpEntityContext):
ENTITY = "publication"
HREF = "rpm_rpm_publication_href"
Expand Down Expand Up @@ -68,6 +78,7 @@ class PulpRpmRepositoryContext(PulpRepositoryContext):
UPDATE_ID = "repositories_rpm_rpm_partial_update"
DELETE_ID = "repositories_rpm_rpm_delete"
SYNC_ID = "repositories_rpm_rpm_sync"
MODIFY_ID = "repositories_rpm_rpm_modify"
VERSION_CONTEXT = PulpRpmRepositoryVersionContext
CAPABILITIES = {"pulpexport": [PluginRequirement("rpm", "3.3.0")]}

Expand Down
59 changes: 58 additions & 1 deletion pulpcore/cli/rpm/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any, Dict, Iterable, Optional

import click
import schema as s

from pulpcore.cli.common.context import (
EntityFieldDefinition,
Expand All @@ -15,13 +16,15 @@
)
from pulpcore.cli.common.generic import (
create_command,
create_content_json_callback,
destroy_command,
href_option,
label_command,
label_select_option,
list_command,
name_option,
pulp_option,
repository_content_command,
repository_href_option,
repository_option,
resource_option,
Expand All @@ -32,7 +35,11 @@
)
from pulpcore.cli.core.generic import task_command
from pulpcore.cli.rpm.common import CHECKSUM_CHOICES
from pulpcore.cli.rpm.context import PulpRpmRemoteContext, PulpRpmRepositoryContext
from pulpcore.cli.rpm.context import (
PulpRpmPackageContext,
PulpRpmRemoteContext,
PulpRpmRepositoryContext,
)

_ = gettext.gettext

Expand All @@ -50,6 +57,17 @@
)


def _content_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any:
if value:
pulp_ctx = ctx.find_object(PulpContext)
assert pulp_ctx is not None
ctx.obj = PulpRpmPackageContext(pulp_ctx, pulp_href=value)
return value


CONTENT_LIST_SCHEMA = s.Schema([{"pulp_href": str}])


@click.group()
@click.option(
"-t",
Expand All @@ -67,8 +85,39 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non
raise NotImplementedError()


package_options = [
click.option(
"--package-href",
callback=_content_callback,
expose_value=False,
help=_("Href of the rpm package to use"),
)
]
lookup_options = [href_option, name_option]
nested_lookup_options = [repository_href_option, repository_option]
content_json_callback = create_content_json_callback(
PulpRpmPackageContext, 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: "pulp_href".
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: "pulp_href".
The argument prefixed with the '@' can be the path to a JSON file with a list of objects."""
),
),
]
update_options = [
click.option("--description"),
click.option("--retain-package-versions", type=int),
Expand Down Expand Up @@ -99,6 +148,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={"package": PulpRpmPackageContext},
add_decorators=package_options,
remove_decorators=package_options,
modify_decorators=modify_options,
)
)


@repository.command()
Expand Down
55 changes: 55 additions & 0 deletions tests/scripts/pulp_rpm/test_content.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

# shellcheck source=tests/scripts/config.source
. "$(dirname "$(dirname "$(realpath "$0")")")"/config.source

pulp debug has-plugin --name "rpm" || exit 3

cleanup() {
pulp rpm repository destroy --name "cli_test_rpm_repository" || true
pulp rpm remote destroy --name "cli_test_rpm_remote" || true
}
trap cleanup EXIT

# Test rpm package upload

wget "https://fixtures.pulpproject.org/rpm-modules-static-context/bear-4.1-1.noarch.rpm"
expect_succ pulp rpm content upload --file "bear-4.1-1.noarch.rpm" --relative-path "bear-4.1-1.noarch.rpm"
PACKAGE_HREF=$(echo "$OUTPUT" | jq -r .pulp_href)
expect_succ pulp rpm content show --href "$PACKAGE_HREF"

expect_succ pulp rpm remote create --name "cli_test_rpm_remote" --url "$RPM_REMOTE_URL"
expect_succ pulp rpm remote show --name "cli_test_rpm_remote"
expect_succ pulp rpm repository create --name "cli_test_rpm_repository"
expect_succ pulp rpm repository show --name "cli_test_rpm_repository"

expect_succ pulp rpm repository content modify \
--repository "cli_test_rpm_repository" \
--add-content "[{\"pulp_href\": \"$PACKAGE_HREF\"}]"
expect_succ pulp rpm repository content list --repository "cli_test_rpm_repository"
test "(echo \"$OUTPUT\" | jq -r '.[].pulp_href')" = "$PACKAGE_HREF"

expect_succ pulp rpm repository content modify \
--repository "cli_test_rpm_repository" \
--remove-content "[{\"pulp_href\": \"$PACKAGE_HREF\"}]"
expect_succ pulp rpm repository content list --repository "cli_test_rpm_repository"
test "$(echo "$OUTPUT" | jq -r length)" -eq 0

expect_succ pulp rpm repository content add \
--repository "cli_test_rpm_repository" \
--package-href "$PACKAGE_HREF"
expect_succ pulp rpm repository content list --repository "cli_test_rpm_repository"
test "(echo \"$OUTPUT\" | jq -r '.[].pulp_href')" = "$PACKAGE_HREF"

expect_succ pulp rpm repository content remove \
--repository "cli_test_rpm_repository" \
--package-href "$PACKAGE_HREF"
expect_succ pulp rpm repository content list --repository "cli_test_rpm_repository"
test "$(echo "$OUTPUT" | jq -r length)" -eq 0

expect_succ pulp rpm repository content modify \
--repository "cli_test_rpm_repository" \
--remove-content "[{\"pulp_href\": \"$PACKAGE_HREF\"}]"
expect_succ pulp rpm publication destroy --href "$PUBLICATION_HREF"
expect_succ pulp rpm repository destroy --name "cli_test_rpm_repository"
expect_succ pulp rpm remote destroy --name "cli_test_rpm_remote"

0 comments on commit d21d6fb

Please sign in to comment.