diff --git a/pulp_rpm/app/schema/__init__.py b/pulp_rpm/app/schema/__init__.py new file mode 100644 index 000000000..1cd42a19f --- /dev/null +++ b/pulp_rpm/app/schema/__init__.py @@ -0,0 +1,7 @@ +import json +import os + +location = os.path.dirname(os.path.realpath(__file__)) + +with open(os.path.join(location, "copy_criteria.json")) as copy_json: + COPY_CRITERIA_SCHEMA = json.load(copy_json) diff --git a/pulp_rpm/app/schema/copy_criteria.json b/pulp_rpm/app/schema/copy_criteria.json new file mode 100644 index 000000000..4e301cfa0 --- /dev/null +++ b/pulp_rpm/app/schema/copy_criteria.json @@ -0,0 +1,205 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CopyCriteria", + "description": "Criteria for copying content between repos", + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + + "package": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "name": { + "type": "string" + }, + "epoch": { + "type": "string" + }, + "version": { + "type": "string" + }, + "release": { + "type": "string" + }, + "arch": { + "type": "string" + }, + "pkgId": { + "type": "string" + }, + "checksum_type": { + "type": "string" + } + } + } + }, + + "advisory": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "id": { + "type": "string" + }, + "updated_date": { + "type": "string" + } + } + } + }, + + "packagecategory": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + + "packagegroup": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + + "packageenvironment": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + + "packagelangpacks": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "digest": { + "type": "string" + } + } + } + }, + + "repo_metadata_file": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "data_type": { + "type": "string" + }, + "checksum_type": { + "type": "string" + }, + "checksum": { + "type": "string" + } + } + } + }, + + "modulemd": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "name": { + "type": "string" + }, + "stream": { + "type": "string" + }, + "version": { + "type": "string" + }, + "context": { + "type": "string" + }, + "arch": { + "type": "string" + } + } + } + }, + + "modulemd_defaults": { + "type": "array", + "items": { + "type": "object", + "minProperties": 1, + "additionalProperties": false, + "properties": { + "pulp_href": { + "type": "string" + }, + "module": { + "type": "string" + }, + "stream": { + "type": "string" + } + } + } + } + } +} diff --git a/pulp_rpm/app/serializers.py b/pulp_rpm/app/serializers.py index 314e6c31d..3a6db6bea 100644 --- a/pulp_rpm/app/serializers.py +++ b/pulp_rpm/app/serializers.py @@ -3,6 +3,7 @@ from gettext import gettext as _ from django.db import IntegrityError +from jsonschema import Draft7Validator from rest_framework import serializers from rest_framework.exceptions import NotAcceptable @@ -64,6 +65,7 @@ UpdateReference ) from pulp_rpm.app.shared_utils import _prepare_package +from pulp_rpm.app.schema import COPY_CRITERIA_SCHEMA class PackageSerializer(SingleArtifactContentUploadSerializer, ContentChecksumSerializer): @@ -585,19 +587,6 @@ class RpmRepositorySyncURLSerializer(RepositorySyncURLSerializer): ) ) -# SCHEMA = '''{ -# "$schema": "http://json-schema.org/draft-07/schema#", -# "title": "CopyPlan", -# "type": "object", -# "properties": { -# "type": "object", -# "minItems": 1, -# "additionalProperties": false -# } -# }, -# "additionalProperties": false -# }''' - class CopySerializer(serializers.Serializer): """ @@ -625,6 +614,7 @@ class CopySerializer(serializers.Serializer): criteria = serializers.JSONField( help_text=_('A JSON document describing what content you want to be copied'), + required=False, ) dependency_solving = serializers.BooleanField( @@ -643,21 +633,20 @@ def validate(self, data): """ super().validate(data) - # schema = json.loads(SCHEMA) - # validator = Draft7Validator(schema) - if hasattr(self, 'initial_data'): validate_unknown_fields(self.initial_data, self.fields) - # criteria = data.get('criteria') + criteria = data.get('criteria') + if criteria: + validator = Draft7Validator(COPY_CRITERIA_SCHEMA) - # err = [] - # for error in sorted(validator.iter_errors(criteria), key=str): - # err.append(error.message) - # if err: - # raise serializers.ValidationError( - # _("Provided copy criteria is invalid:'{}'".format(err)) - # ) + err = [] + for error in sorted(validator.iter_errors(criteria), key=str): + err.append(error.message) + if err: + raise serializers.ValidationError( + _("Provided copy criteria is invalid:'{}'".format(err)) + ) return data diff --git a/pulp_rpm/app/viewsets.py b/pulp_rpm/app/viewsets.py index 50a6cb730..8a54c1ea6 100644 --- a/pulp_rpm/app/viewsets.py +++ b/pulp_rpm/app/viewsets.py @@ -255,7 +255,7 @@ def create(self, request): source_repo = serializer.validated_data['source_repo'] # source_repo_version = serializer.validated_data['source_repo_version'] dest_repo = serializer.validated_data['dest_repo'] - criteria = serializer.validated_data['criteria'] + criteria = serializer.validated_data.get('criteria', None) dependency_solving = serializer.validated_data['dependency_solving'] source_repos = [source_repo] diff --git a/pulp_rpm/tests/functional/api/test_copy.py b/pulp_rpm/tests/functional/api/test_copy.py index b5a534a26..def518ddd 100644 --- a/pulp_rpm/tests/functional/api/test_copy.py +++ b/pulp_rpm/tests/functional/api/test_copy.py @@ -2,6 +2,8 @@ """Tests that sync rpm plugin repositories.""" import unittest +from requests.exceptions import HTTPError + from pulp_smash import api, config from pulp_smash.pulp3.utils import ( delete_orphans, @@ -81,7 +83,7 @@ def test_copy_all(self): """Test copying all the content from one repo to another.""" criteria = {} results = RPM_FIXTURE_SUMMARY - self._do_test(criteria, results) + self._do_test(None, results) # def test_copy_by_href(self): # criteria = {} @@ -97,3 +99,17 @@ def test_copy_by_advisory_id(self): RPM_ADVISORY_CONTENT_NAME: 1 } self._do_test(criteria, results) + + def test_invalid_criteria(self): + """Test invalid criteria.""" + with self.assertRaises(HTTPError): + criteria = { + 'meta': 'morphosis' + } + self._do_test(criteria, {}) + + with self.assertRaises(HTTPError): + criteria = { + 'advisory': [{'bad': 'field'}] + } + self._do_test(criteria, {}) diff --git a/pulp_rpm/tests/functional/utils.py b/pulp_rpm/tests/functional/utils.py index bd7a77166..b6d550fe4 100644 --- a/pulp_rpm/tests/functional/utils.py +++ b/pulp_rpm/tests/functional/utils.py @@ -122,8 +122,12 @@ def rpm_copy(cfg, source_repo, dest_repo, criteria, recursive=True): 'source_repo': source_repo['pulp_href'], 'dest_repo': dest_repo['pulp_href'], 'criteria': criteria, - 'dependency_solving': True, + 'dependency_solving': recursive, } + + if criteria: + data['criteria'] = criteria + return client.post(RPM_COPY_PATH, data) diff --git a/setup.py b/setup.py index 47e15492f..386a96743 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,7 @@ requirements = [ 'createrepo_c~=0.13', + 'jsonschema', 'libcomps~=0.1.11', 'productmd', 'pulpcore>=3.2',