diff --git a/CHANGES/4.feature b/CHANGES/4.feature new file mode 100644 index 0000000..43aedc1 --- /dev/null +++ b/CHANGES/4.feature @@ -0,0 +1 @@ +Added --component and --architecture flags to the remote command. diff --git a/pulpcore/cli/deb/context.py b/pulpcore/cli/deb/context.py index ba99e63..d22a0e0 100644 --- a/pulpcore/cli/deb/context.py +++ b/pulpcore/cli/deb/context.py @@ -75,12 +75,27 @@ class PulpAptRemoteContext(PulpEntityContext): CREATE_ID = "remotes_deb_apt_create" UPDATE_ID = "remotes_deb_apt_partial_update" DELETE_ID = "remotes_deb_apt_delete" + NULLABLES = {"architectures", "components"} + + @staticmethod + def tuple_to_whitespace_separated_string(field_name: str, body: EntityDefinition) -> None: + """ + Safely turns a tuple contained in body[field_name] into a whitespace separated string. + If body[field_name] contains None or (), then field_name is dropped from body. + If we end up with an empty string, we use None instead. + All conversions happen in place. + If body[field_name] does not contain a tuple, the behaviour is undefined. + """ + field = body.pop(field_name, None) + if field is not None and field != (): + string_field = " ".join(field).strip() + body[field_name] = string_field if string_field else None def preprocess_body(self, body: EntityDefinition) -> EntityDefinition: body = super().preprocess_body(body) - distributions = body.pop("distributions", None) - if isinstance(distributions, tuple) and distributions: - body["distributions"] = " ".join(distributions) + self.tuple_to_whitespace_separated_string("distributions", body) + self.tuple_to_whitespace_separated_string("components", body) + self.tuple_to_whitespace_separated_string("architectures", body) return body diff --git a/pulpcore/cli/deb/remote.py b/pulpcore/cli/deb/remote.py index c841bab..2a59733 100644 --- a/pulpcore/cli/deb/remote.py +++ b/pulpcore/cli/deb/remote.py @@ -43,6 +43,24 @@ def remote(ctx: click.Context, pulp_ctx: PulpContext, remote_type: str) -> None: click.option( "--policy", type=click.Choice(["immediate", "on_demand", "streamed"], case_sensitive=False) ), + click.option( + "--component", + "components", + multiple=True, + help=_( + "Component to sync; can be specified multiple times. " + "Will sync all available if specified once with the empty string." + ), + ), + click.option( + "--architecture", + "architectures", + multiple=True, + help=_( + "Architecture to sync; can be specified multiple times. " + "Will sync all available if specified once with the empty string." + ), + ), ] distribution_help = _("Distribution to sync; can be specified multiple times.") diff --git a/tests/scripts/config.source b/tests/scripts/config.source index 0231eaf..a868ffe 100644 --- a/tests/scripts/config.source +++ b/tests/scripts/config.source @@ -46,4 +46,27 @@ expect_fail () { fi } +# Expects the provided test to pass +# Supresses all output, which is redirected to ASSERTION_OUTPUT and ASSERTION_ERROUTPUT so as not +# to overwrite the latest OUTPUT and ERROUTPUT, that way we can test several assertions in a row. +# Reports verbosely on failure +assert () { + if { + test "$@" + } 1>log.out 2>log.err + then + echo "SUCCESS [$@]" >&3 + ASSERTION_OUTPUT="$(cat log.out)" + ASSERTION_ERROUTPUT="$(cat log.err)" + else + echo "FAILURE [$@]" >&3 + echo "=== STDOUT ===" >&3 + cat log.out >&3 + echo "=== STDERR ===" >&3 + cat log.err >&3 + echo "==============" >&3 + false + fi +} + set -eu diff --git a/tests/scripts/pulp_deb/test_deb_remote.sh b/tests/scripts/pulp_deb/test_deb_remote.sh new file mode 100755 index 0000000..f0bb6dd --- /dev/null +++ b/tests/scripts/pulp_deb/test_deb_remote.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# shellcheck source=tests/scripts/config.source +. "$(dirname "$(dirname "$(realpath "$0")")")/config.source" + +ENTITIES_NAME="test_deb_remote" + +cleanup() { + pulp deb remote destroy --name "${ENTITIES_NAME}" || true +} +trap cleanup EXIT + +# Fail to create some remotes: +expect_fail pulp deb remote create --name "foo" --url "foo" --distribution "" +expect_fail pulp deb remote create --name "foo" --url "foo" +expect_fail pulp deb remote create --name "foo" --url "" --distribution "foo" +expect_fail pulp deb remote create --name "foo" --distribution "foo" +expect_fail pulp deb remote create --name "" --url "foo" --distribution "foo" +expect_fail pulp deb remote create --url "foo" --distribution "foo" + +# Create and trivially update a remote: +expect_succ pulp deb remote create --name "${ENTITIES_NAME}" \ + --url "foo" \ + --distribution "foo" \ + --component "foo" \ + --architecture "foo" + +assert "$(echo "$OUTPUT" | jq -r .url)" == "foo" +assert "$(echo "$OUTPUT" | jq -r .distributions)" == "foo" +assert "$(echo "$OUTPUT" | jq -r .components)" == "foo" +assert "$(echo "$OUTPUT" | jq -r .architectures)" == "foo" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" + +# Try some possible modifications of the remote's distribution: +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --distribution "bar" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .distributions)" == "bar" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --distribution "bar" --distribution "baz" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .distributions)" == "bar baz" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --distribution "bar" --distribution "" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .distributions)" == "bar" +expect_fail pulp deb remote update --name "${ENTITIES_NAME}" --distribution "" +assert "${ERROUTPUT}" == 'Error: {"distributions":["This field may not be null."]}' + +# Try some possible modifications of the remote's components: +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --component "bar" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .components)" == "bar" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --component "bar" --component "baz" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .components)" == "bar baz" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --component "bar" --component "" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .components)" == "bar" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --component "" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .components)" == "null" + +# Try some possible modifications of the remote's architectures: +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --architecture "bar" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .architectures)" == "bar" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --architecture "bar" --architecture "baz" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .architectures)" == "bar baz" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --architecture "bar" --architecture "" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .architectures)" == "bar" +expect_succ pulp deb remote update --name "${ENTITIES_NAME}" --architecture "" +expect_succ pulp deb remote show --name "${ENTITIES_NAME}" +assert "$(echo "$OUTPUT" | jq -r .architectures)" == "null" + +# Now destroy the remote +expect_succ pulp deb remote destroy --name "${ENTITIES_NAME}" diff --git a/tests/scripts/pulp_deb/test_deb_sync_publish.sh b/tests/scripts/pulp_deb/test_deb_sync_publish.sh index 93e85bb..b64bb1b 100755 --- a/tests/scripts/pulp_deb/test_deb_sync_publish.sh +++ b/tests/scripts/pulp_deb/test_deb_sync_publish.sh @@ -1,12 +1,14 @@ -#!/bin/sh +#!/bin/bash # shellcheck source=tests/scripts/config.source . "$(dirname "$(dirname "$(realpath "$0")")")/config.source" +ENTITIES_NAME="test_deb_sync_publish" + cleanup() { - pulp deb remote destroy --name "cli_test_deb_remote" || true - pulp deb repository destroy --name "cli_test_deb_repository" || true - pulp deb distribution destroy --name "cli_test_deb_distro" || true + pulp deb remote destroy --name "${ENTITIES_NAME}_remote" || true + pulp deb repository destroy --name "${ENTITIES_NAME}_repo" || true + pulp deb distribution destroy --name "${ENTITIES_NAME}_distro" || true } trap cleanup EXIT @@ -17,21 +19,32 @@ else curl_opt="" fi -expect_succ pulp deb remote create --name "cli_test_deb_remote" --url "$DEB_REMOTE_URL" --distribution "$DEB_DISTRIBUTION" -expect_succ pulp deb repository create --name "cli_test_deb_repository" +expect_succ pulp deb remote create \ + --name "${ENTITIES_NAME}_remote" \ + --url "$DEB_REMOTE_URL" \ + --distribution "$DEB_DISTRIBUTION" + +expect_succ pulp deb repository create \ + --name "${ENTITIES_NAME}_repo" + +expect_succ pulp deb repository sync \ + --name "${ENTITIES_NAME}_repo" \ + --remote "${ENTITIES_NAME}_remote" + +expect_succ pulp deb publication create \ + --repository "${ENTITIES_NAME}_repo" \ + --simple "True" -expect_succ pulp deb repository sync --name "cli_test_deb_repository" --remote "cli_test_deb_remote" -expect_succ pulp deb publication create --repository "cli_test_deb_repository" --simple "True" PUBLICATION_HREF=$(echo "$OUTPUT" | jq -r .pulp_href) -expect_succ pulp deb distribution create --name "cli_test_deb_distro" \ +expect_succ pulp deb distribution create --name "${ENTITIES_NAME}_distro" \ --base-path "cli_test_deb_distro" \ --publication "$PUBLICATION_HREF" -expect_succ curl "$curl_opt" --head --fail "$PULP_BASE_URL/pulp/content/cli_test_deb_distro/dists/default/Release" - -expect_succ pulp deb distribution destroy --name "cli_test_deb_distro" -expect_succ pulp deb publication destroy --href "$PUBLICATION_HREF" +expect_succ curl "$curl_opt" --head \ + --fail "$PULP_BASE_URL/pulp/content/cli_test_deb_distro/dists/default/Release" -expect_succ pulp deb repository destroy --name "cli_test_deb_repository" -expect_succ pulp deb remote destroy --name "cli_test_deb_remote" +expect_succ pulp deb distribution destroy --name "${ENTITIES_NAME}_distro" +expect_succ pulp deb publication destroy --href "${PUBLICATION_HREF}" +expect_succ pulp deb repository destroy --name "${ENTITIES_NAME}_repo" +expect_succ pulp deb remote destroy --name "${ENTITIES_NAME}_remote"