diff --git a/CHANGES/532.feature b/CHANGES/532.feature new file mode 100644 index 000000000..1f6636c55 --- /dev/null +++ b/CHANGES/532.feature @@ -0,0 +1 @@ +Added `--repository` option to ansible collection signature upload and `--gpgkey` to ansible repository. diff --git a/pulpcore/cli/ansible/content.py b/pulpcore/cli/ansible/content.py index 00e58a9b8..47a65319b 100644 --- a/pulpcore/cli/ansible/content.py +++ b/pulpcore/cli/ansible/content.py @@ -1,15 +1,17 @@ -from typing import IO, Any, Union +from typing import IO, Any, Optional, Union import click from pulpcore.cli.ansible.context import ( PulpAnsibleCollectionVersionContext, PulpAnsibleCollectionVersionSignatureContext, + PulpAnsibleRepositoryContext, PulpAnsibleRoleContext, ) from pulpcore.cli.common.context import ( PulpContext, PulpEntityContext, + PulpRepositoryContext, pass_entity_context, pass_pulp_context, ) @@ -20,6 +22,7 @@ parse_size_callback, pulp_group, pulp_option, + resource_option, show_command, ) from pulpcore.cli.common.i18n import get_translation @@ -29,6 +32,12 @@ _ = translation.gettext +collection_context = (PulpAnsibleCollectionVersionContext,) +role_context = (PulpAnsibleRoleContext,) +content_context = (PulpAnsibleRoleContext, PulpAnsibleCollectionVersionContext) +signature_context = (PulpAnsibleCollectionVersionSignatureContext,) + + def _content_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: if value: entity_ctx = ctx.find_object(PulpEntityContext) @@ -37,6 +46,21 @@ def _content_callback(ctx: click.Context, param: click.Parameter, value: Any) -> return value +repository_option = resource_option( + "--repository", + default_plugin="ansible", + default_type="ansible", + context_table={ + "ansible:ansible": PulpAnsibleRepositoryContext, + }, + href_pattern=PulpRepositoryContext.HREF_PATTERN, + allowed_with_contexts=signature_context, + help=_( + "Repository to upload into in the form '[[:]:]' or by href." + ), +) + + @pulp_group() @click.option( "-t", @@ -58,10 +82,6 @@ def content(ctx: click.Context, pulp_ctx: PulpContext, content_type: str) -> Non raise NotImplementedError() -collection_context = (PulpAnsibleCollectionVersionContext,) -role_context = (PulpAnsibleRoleContext,) -content_context = (PulpAnsibleRoleContext, PulpAnsibleCollectionVersionContext) -signature_context = (PulpAnsibleCollectionVersionSignatureContext,) list_options = [ pulp_option("--name", help=_("Name of {entity}"), allowed_with_contexts=content_context), pulp_option( @@ -161,6 +181,7 @@ def content(ctx: click.Context, pulp_ctx: PulpContext, content_type: str) -> Non @content.command() @click.option("--file", type=click.File("rb"), required=True) +@repository_option @pulp_option( "--chunk-size", help=_("Chunk size to break up {entity} into. Defaults to 1MB"), @@ -201,7 +222,6 @@ def upload( file: IO[bytes], **kwargs: Any, ) -> None: - if isinstance(content_ctx, PulpAnsibleRoleContext): chunk_size = kwargs.pop("chunk_size") artifact_href = PulpArtifactContext(pulp_ctx).upload(file, chunk_size) @@ -210,7 +230,10 @@ def upload( result = content_ctx.create(body=body) pulp_ctx.output_result(result) elif isinstance(content_ctx, PulpAnsibleCollectionVersionSignatureContext): - body = {"signed_collection": kwargs.get("collection")} + body = {"signed_collection": kwargs["collection"]} + repository: Optional[PulpRepositoryContext] = kwargs["repository"] + if repository: + body["repository"] = repository.pulp_href uploads = {"file": file.read()} pulp_ctx.output_result(content_ctx.create(body=body, uploads=uploads)) elif isinstance(content_ctx, PulpAnsibleCollectionVersionContext): diff --git a/pulpcore/cli/ansible/context.py b/pulpcore/cli/ansible/context.py index e0054e508..1c79357db 100644 --- a/pulpcore/cli/ansible/context.py +++ b/pulpcore/cli/ansible/context.py @@ -87,6 +87,7 @@ class PulpAnsibleRepositoryContext(PulpRepositoryContext): ID_PREFIX = "repositories_ansible_ansible" VERSION_CONTEXT = PulpAnsibleRepositoryVersionContext CAPABILITIES = {"pulpexport": [PluginRequirement("ansible")]} + NULLABLES = PulpRepositoryContext.NULLABLES | {"gpgkey"} registered_repository_contexts["ansible:ansible"] = PulpAnsibleRepositoryContext diff --git a/pulpcore/cli/ansible/repository.py b/pulpcore/cli/ansible/repository.py index 29f54894d..b2edd29e5 100644 --- a/pulpcore/cli/ansible/repository.py +++ b/pulpcore/cli/ansible/repository.py @@ -12,6 +12,7 @@ ) from pulpcore.cli.common.context import ( EntityFieldDefinition, + PluginRequirement, PulpContext, PulpEntityContext, PulpRemoteContext, @@ -28,9 +29,11 @@ label_command, label_select_option, list_command, + load_file_or_string_callback, load_json_callback, name_option, pulp_group, + pulp_option, repository_content_command, resource_option, retained_versions_option, @@ -100,6 +103,15 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non create_options = [ click.option("--name", required=True), click.option("--description"), + pulp_option( + "--gpgkey", + callback=load_file_or_string_callback, + needs_plugins=[ + PluginRequirement( + "ansible", min="0.15.0.dev", feature="gpgkeys on ansible repositories" + ) + ], + ), remote_option, retained_versions_option, ] diff --git a/tests/scripts/pulp_ansible/test_content.sh b/tests/scripts/pulp_ansible/test_content.sh index 4641bdbcf..88e51c47e 100755 --- a/tests/scripts/pulp_ansible/test_content.sh +++ b/tests/scripts/pulp_ansible/test_content.sh @@ -7,10 +7,20 @@ pulp debug has-plugin --name "ansible" || exit 3 cleanup() { pulp ansible repository destroy --name "cli_test_ansible_repository" || true - pulp orphan cleanup || true + pulp ansible repository destroy --name "cli_test_ansible_repository_verify" || true } trap cleanup EXIT +pulp orphan cleanup --protection-time 0 + +if pulp debug has-plugin --name "ansible" --min-version "0.15.0.dev" +then + gpg --output pulp_pubkey.key --armor --export "Pulp QE" + expect_succ pulp ansible repository create --name "cli_test_ansible_repository_verify" --gpgkey @pulp_pubkey.key +else + expect_succ pulp ansible repository create --name "cli_test_ansible_repository_verify" +fi + # Test ansible collection-version upload wget "https://galaxy.ansible.com/download/ansible-posix-1.3.0.tar.gz" sha256=$(sha256sum ansible-posix-1.3.0.tar.gz | cut -d' ' -f1) @@ -42,7 +52,7 @@ then tar --extract --file="ansible-posix-1.3.0.tar.gz" "MANIFEST.json" collection_path="$(realpath 'MANIFEST.json')" signature_path="$("$(dirname "$(dirname "$(dirname "$(realpath "$0")")")")"/assets/sign_detached.sh "$collection_path" | jq -r .signature)" - expect_succ pulp ansible content --type "signature" upload --file "$signature_path" --collection "$content_href" + expect_succ pulp ansible content --type "signature" upload --file "$signature_path" --collection "$content_href" --repository "cli_test_ansible_repository_verify" expect_succ pulp ansible content --type "signature" list --collection "$content_href" --pubkey-fingerprint "6EDF301256480B9B801EBA3D05A5E6DA269D9D98" test "$(echo "$OUTPUT" | jq -r length)" -eq "1" content3_href="$(echo "$OUTPUT" | jq -r .[0].pulp_href)"