diff --git a/CHANGES/+api-version.feature b/CHANGES/+api-version.feature new file mode 100644 index 000000000..0d00b1ea1 --- /dev/null +++ b/CHANGES/+api-version.feature @@ -0,0 +1,3 @@ +Added the abililty to specify which REST API version you want to talk to. + +Use `--api-version=` on the command line, or `api_version=` in your config profile. diff --git a/pulp-glue/src/pulp_glue/common/context.py b/pulp-glue/src/pulp_glue/common/context.py index be6f74e9c..ea14d9ad6 100644 --- a/pulp-glue/src/pulp_glue/common/context.py +++ b/pulp-glue/src/pulp_glue/common/context.py @@ -287,7 +287,7 @@ class PulpContext: It is an abstraction layer for api access and output handling. Parameters: - api_root: The base url (excluding "api/v3/") to the servers api. + api_root: The base url (excluding "api/{version}/") to the servers api. api_kwargs: Extra arguments to pass to the wrapped `OpenAPI` object. background_tasks: Whether to wait for tasks. If `True`, all tasks triggered will immediately raise `PulpNoWait`. @@ -297,6 +297,7 @@ class PulpContext: Where possible, instead of failing, the requested result will be faked. This implies `dry_run=True` on the `api_kwargs`. verify_ssl: A boolean or a path to the CA bundle. + api-version: Version of the Pulp API to talk to (e.g., "v3") """ def echo(self, message: str, nl: bool = True, err: bool = False) -> None: @@ -328,8 +329,10 @@ def __init__( verify_ssl: bool | str | None = None, verify: bool | str | None = None, # Deprecated chunk_size: int | None = None, + api_version: str | None = "v3", ) -> None: self._api: OpenAPI | None = None + self._api_version = api_version self._api_root: str = api_root self._api_kwargs = api_kwargs self.verify_ssl = verify_ssl @@ -435,6 +438,7 @@ def from_config(cls, config: dict[str, t.Any]) -> "t.Self": api_root=config.get("api_root", "/pulp/"), domain=config.get("domain", "default"), verify_ssl=config.get("verify_ssl", True), + api_version=config.get("api_version", "v3"), api_kwargs=api_kwargs, ) @@ -453,8 +457,8 @@ def domain_enabled(self) -> bool: @property def api_path(self) -> str: if self.domain_enabled: - return self._api_root + self.pulp_domain + "/api/v3/" - return self._api_root + "api/v3/" + return f"{self._api_root}{self.pulp_domain}/api/{self._api_version}/" + return f"{self._api_root}api/{self._api_version}/" @property def api(self) -> OpenAPI: @@ -481,7 +485,7 @@ def api(self) -> OpenAPI: ) try: self._api = OpenAPI( - doc_path=f"{self._api_root}api/v3/docs/api.json", + doc_path=f"{self._api_root}api/{self._api_version}/docs/api.json", verify_ssl=self.verify_ssl, patch_api_hook=_patch_api_hook, **self._api_kwargs, @@ -535,6 +539,7 @@ def call( if "pulp_domain" in self.api.param_spec(operation_id, "path", required=True): parameters["pulp_domain"] = self.pulp_domain parameters = preprocess_payload(parameters) + if body is not None: body = preprocess_payload(body) try: diff --git a/pulp-glue/src/pulp_glue/common/openapi.py b/pulp-glue/src/pulp_glue/common/openapi.py index 77cad6c80..2a910dc14 100644 --- a/pulp-glue/src/pulp_glue/common/openapi.py +++ b/pulp-glue/src/pulp_glue/common/openapi.py @@ -728,7 +728,6 @@ def call( rel_url = path for name, value in rendered_parameters["path"].items(): rel_url = path.replace("{" + name + "}", value) - query_params = rendered_parameters["query"] url = urljoin(self._base_url, rel_url) diff --git a/pulp-glue/src/pulp_glue/rpm/context.py b/pulp-glue/src/pulp_glue/rpm/context.py index 32c3ee67a..2161445d2 100644 --- a/pulp-glue/src/pulp_glue/rpm/context.py +++ b/pulp-glue/src/pulp_glue/rpm/context.py @@ -24,7 +24,7 @@ @api_spec_quirk(PluginRequirement("rpm", specifier=">=3.3.0")) def patch_rpm_copy_scheme(api_spec: t.Any) -> t.Any: path, operation = next( - ((k, v["post"]) for k, v in api_spec["paths"].items() if k.endswith("/api/v3/rpm/copy/")) + ((k, v["post"]) for k, v in api_spec["paths"].items() if k.endswith("/rpm/copy/")) ) api_spec["components"]["schemas"]["RpmCopy"] = { "type": "object", diff --git a/src/pulp_cli/__init__.py b/src/pulp_cli/__init__.py index d5fc022a4..e1401b529 100644 --- a/src/pulp_cli/__init__.py +++ b/src/pulp_cli/__init__.py @@ -225,6 +225,7 @@ def main( dry_run: bool, timeout: int, cid: str, + api_version: str, ) -> None: if verbose: logging.basicConfig(level=logging.DEBUG + 4 - verbose, format="%(message)s") @@ -252,6 +253,7 @@ def main( oauth2_client_id=client_id, oauth2_client_secret=client_secret, chunk_size=chunk_size, + api_version=api_version, ) diff --git a/src/pulp_cli/config.py b/src/pulp_cli/config.py index a465e7847..576d4086f 100644 --- a/src/pulp_cli/config.py +++ b/src/pulp_cli/config.py @@ -37,6 +37,7 @@ str(Path(click.utils.get_app_dir("pulp"), "cli.toml")), ] FORMAT_CHOICES = list(REGISTERED_OUTPUT_FORMATTERS.keys()) +VERSIONS = ["v3", "v4"] REQUIRED_SETTINGS = { "base_url", "api_root", @@ -57,6 +58,7 @@ "key", "chunk_size", "plugins", + "api_version", } SETTINGS = REQUIRED_SETTINGS | OPTIONAL_SETTINGS @@ -137,6 +139,12 @@ def headers_callback( count=True, help=_("Increase verbosity; explain api calls as they are made"), ), + click.option( + "--api-version", + type=click.Choice(VERSIONS, case_sensitive=True), + default="v3", + help=_("API version to talk to (e.g., 'v3')"), + ), ] diff --git a/src/pulp_cli/generic.py b/src/pulp_cli/generic.py index 402e7155d..e438f7352 100644 --- a/src/pulp_cli/generic.py +++ b/src/pulp_cli/generic.py @@ -143,6 +143,7 @@ class PulpCLIContext(PulpContext): Parameters: api_root: The base url (excluding "api/v3/") to the server's api. + api_version: The version of Pulp's API to talk to (e.g. "v3"). api_kwargs: Extra arguments to pass to the wrapped `OpenAPI` object. background_tasks: Whether to wait for tasks. If `True`, all tasks triggered will immediately raise `PulpNoWait`. @@ -166,6 +167,7 @@ def __init__( oauth2_client_id: str | None = None, oauth2_client_secret: str | None = None, chunk_size: int | None = None, + api_version: str | None = "v3", ) -> None: self.username = username self.password = password @@ -184,6 +186,7 @@ def __init__( timeout=timeout, domain=domain, chunk_size=chunk_size, + api_version=api_version, ) self.format = format diff --git a/src/pulpcore/cli/core/task.py b/src/pulpcore/cli/core/task.py index 88c172ea2..4ab8bea0f 100644 --- a/src/pulpcore/cli/core/task.py +++ b/src/pulpcore/cli/core/task.py @@ -192,7 +192,9 @@ def profile_artifact_urls( pulp_ctx.output_result(urls) if download: task_name: str = task_ctx.entity["name"] - uuid_match = re.match(r".*/api/v3/tasks/(?P.*)/", task_ctx.entity["pulp_href"]) + uuid_match = re.match( + r".*/api/(?Pv\d+)/tasks/(?P.*)/", task_ctx.entity["pulp_href"] + ) assert uuid_match is not None uuid = uuid_match.group("uuid") profile_artifact_dir = Path(f"task_profile-{task_name}-{uuid}") diff --git a/tests/scripts/pulp_file/test_acs.sh b/tests/scripts/pulp_file/test_acs.sh index 00d0ebc61..433268af7 100755 --- a/tests/scripts/pulp_file/test_acs.sh +++ b/tests/scripts/pulp_file/test_acs.sh @@ -39,7 +39,7 @@ test "$(echo "$OUTPUT" | jq ".paths | length")" -eq 2 # test refresh expect_succ pulp --background file acs refresh --acs $acs -task_group=$(echo "$ERROUTPUT" | grep -E -o "/.*/api/v3/task-groups/[-[:xdigit:]]*/") +task_group=$(echo "$ERROUTPUT" | grep -E -o "/.*/api/v[[:xdigit:]]+/task-groups/[-[:xdigit:]]*/") expect_succ pulp task-group show --href "$task_group" --wait group_task_uuid="${task_group%/}" diff --git a/tests/scripts/pulp_file/test_sync.sh b/tests/scripts/pulp_file/test_sync.sh index 75538414f..bd2e0f50f 100755 --- a/tests/scripts/pulp_file/test_sync.sh +++ b/tests/scripts/pulp_file/test_sync.sh @@ -52,9 +52,9 @@ expect_succ pulp file repository version destroy --version 1 --repository "cli_t # Test autopublish expect_succ pulp file repository create --name "$autopublish_repo" --remote "cli_test_file_sync_remote" --autopublish expect_succ pulp file repository sync --repository "$autopublish_repo" -task=$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v3/tasks/[-[:xdigit:]]*/") +task=$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v[[:xdigit:]]+/tasks/[-[:xdigit:]]*/") created_resources=$(pulp show --href "$task" | jq -r ".created_resources") -echo "$created_resources" | grep -q -E "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v3/publications/file/file/" +echo "$created_resources" | grep -q -E "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v[[:xdigit:]]+/publications/file/file/" # Test retained versions expect_succ pulp file repository create --name "$one_version_repo" --remote "cli_test_file_sync_remote" --retain-repo-versions 1 diff --git a/tests/scripts/pulp_rpm/test_acs.sh b/tests/scripts/pulp_rpm/test_acs.sh index 36623f894..26f1f46d6 100755 --- a/tests/scripts/pulp_rpm/test_acs.sh +++ b/tests/scripts/pulp_rpm/test_acs.sh @@ -41,7 +41,7 @@ test "$(echo "$OUTPUT" | jq ".paths | length")" -eq 2 # test refresh expect_succ pulp rpm acs refresh --acs $acs -task_group=$(echo "$ERROUTPUT" | grep -E -o "/.*/api/v3/task-groups/[-[:xdigit:]]*/") +task_group=$(echo "$ERROUTPUT" | grep -E -o "/.*/api/v[[:xdigit:]]+/task-groups/[-[:xdigit:]]*/") expect_succ pulp task-group show --href "$task_group" test "$(echo "$OUTPUT" | jq ".tasks | length")" -eq 2 diff --git a/tests/scripts/pulpcore/test_task.sh b/tests/scripts/pulpcore/test_task.sh index 4b5d74769..def7aeb8f 100755 --- a/tests/scripts/pulpcore/test_task.sh +++ b/tests/scripts/pulpcore/test_task.sh @@ -32,7 +32,7 @@ repository_href="$(echo "$OUTPUT" | jq -r '.pulp_href')" if pulp debug has-plugin --name "core" --specifier ">=3.21.0" then expect_succ pulp --background file repository sync --name "cli_test_core_task_repository" --remote "cli_test_core_task_large_remote" - task="$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v3/tasks/[-[:xdigit:]]*/")" + task="$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v[[:xdigit:]]+/tasks/[-[:xdigit:]]*/")" if expect_succ pulp task cancel --href "$task" then expect_succ pulp task list --name $sync_task --state canceled @@ -50,9 +50,9 @@ fi expect_fail pulp --dry-run task cancel --all -# Test waiting for a task +## Test waiting for a task expect_succ pulp --header X-Task-Diagnostics:memory --background file repository sync --name "cli_test_core_task_repository" -task=$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v3/tasks/[-[:xdigit:]]*/") +task=$(echo "$ERROUTPUT" | grep -E -o "${PULP_API_ROOT}([-_a-zA-Z0-9]+/)?api/v[[:xdigit:]]+/tasks/[-[:xdigit:]]*/") task_uuid="${task%/}" task_uuid="${task_uuid##*/}" expect_succ pulp task show --wait --uuid "$task_uuid" diff --git a/tests/scripts/test_debug_api.sh b/tests/scripts/test_debug_api.sh index c392f9bab..92edb9ffd 100755 --- a/tests/scripts/test_debug_api.sh +++ b/tests/scripts/test_debug_api.sh @@ -5,7 +5,7 @@ set -eu . "$(dirname "$(realpath "$0")")"/config.source expect_succ pulp -v status -echo "${ERROUTPUT}" | grep -q "^status_read : get https\?://\w.*/api/v3/status/$" +echo "${ERROUTPUT}" | grep -q "^status_read : get https\?://\w.*/api/v[[:xdigit:]]\+/status/$" expect_succ pulp -vv --header "test-header:Value with space" status echo "${ERROUTPUT}" | grep -q "^ test-header: Value with space$"