From 5cd7fff04128ca16becf761b7196fd30a0824a30 Mon Sep 17 00:00:00 2001 From: Matthias Dellweg Date: Fri, 16 Jul 2021 16:29:51 +0200 Subject: [PATCH] Add validation to file content json parameters fixes #255 --- CHANGES/255.bugfix | 1 + mypy.ini | 3 +++ pulpcore/cli/file/repository.py | 30 ++++++++++++++++++++++-------- setup.py | 1 + 4 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 CHANGES/255.bugfix diff --git a/CHANGES/255.bugfix b/CHANGES/255.bugfix new file mode 100644 index 000000000..c264e8d12 --- /dev/null +++ b/CHANGES/255.bugfix @@ -0,0 +1 @@ +Added validation to some json input parameters. diff --git a/mypy.ini b/mypy.ini index 44204b26e..f927ec968 100644 --- a/mypy.ini +++ b/mypy.ini @@ -13,3 +13,6 @@ ignore_missing_imports = True [mypy-click_shell.*] ignore_missing_imports = True + +[mypy-schema.*] +ignore_missing_imports = True diff --git a/pulpcore/cli/file/repository.py b/pulpcore/cli/file/repository.py index 3ba9b78dd..58635723d 100644 --- a/pulpcore/cli/file/repository.py +++ b/pulpcore/cli/file/repository.py @@ -2,6 +2,7 @@ from typing import Any, Dict, List, Optional import click +import schema as s from pulpcore.cli.common.context import ( EntityFieldDefinition, @@ -59,6 +60,19 @@ def _content_callback(ctx: click.Context, param: click.Parameter, value: Any) -> return value +CONTENT_LIST_SCHEMA = s.Schema([{"sha256": str, "relative_path": str}]) + + +def _content_list_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: + result = load_json_callback(ctx, param, value) + if result is None: + return None + try: + return CONTENT_LIST_SCHEMA.validate(result) + except s.SchemaError as e: + raise click.ClickException("Validation of '{}' failed: {}".format(param.name, str(e))) + + @click.group() @click.option( "-t", @@ -104,19 +118,19 @@ def repository(ctx: click.Context, pulp_ctx: PulpContext, repo_type: str) -> Non modify_options = [ click.option( "--add-content", - callback=content_json_callback, + callback=_content_list_callback, help=_( """JSON string with a list of objects to add to the repository. - Each object should consist of the following keys: "sha256", "relative_path".. + Each object must contain the following keys: "sha256", "relative_path". 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, + callback=_content_list_callback, help=_( """JSON string with a list of objects to remove from the repository. - Each object should consist of the following keys: "sha256", "relative_path".. + Each object must contain the following keys: "sha256", "relative_path". The argument prefixed with the '@' can be the path to a JSON file with a list of objects.""" ), ), @@ -247,22 +261,22 @@ def remove( @click.option( "--add-content", default="[]", - callback=load_json_callback, + callback=_content_list_callback, expose_value=True, help=_( """JSON string with a list of objects to add to the repository. - Each object should consist of the following keys: "sha256", "relative_path".. + Each object must contain the following keys: "sha256", "relative_path". The argument prefixed with the '@' can be the path to a JSON file with a list of objects.""" ), ) @click.option( "--remove-content", default="[]", - callback=load_json_callback, + callback=_content_list_callback, expose_value=True, help=_( """JSON string with a list of objects to remove from the repository. - Each object should consist of the following keys: "sha256", "relative_path".. + Each object must contain the following keys: "sha256", "relative_path". The argument prefixed with the '@' can be the path to a JSON file with a list of objects.""" ), ) diff --git a/setup.py b/setup.py index 23ea55ac1..e37cb84d0 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ "click>=7.1.2,<9.0.0", "packaging", "PyYAML~=5.3", + "schema==0.7.4", "requests~=2.24", "toml==0.10.2", ],