Issue #3541
Updated by bmbouter about 5 years ago
h3. General Problem: Some plugins have validation requirements for the membership of content units in a repository. The validation required depends on the plugin and the content type. Currently add/remove is done with a POST to v3/repositories/1234/versions/. This does not involve the plugins at all, so there is no opportunity for plugins to create these validations. h3. Example Problem with Docker: ManifestLists cannot be added unless the Manifests they refer to are also in the repository. L1 is ManifestList, and it refers to (contains) 2 Manifests, M1, M2. The repository is considered corrupt if it contains L1, but not M1 and M2. M1 and M2 could be in the repository without L1. h2. Solutions: h3. Add a plugin opportunity to Validate Allow a plugin to define a <code>validate_repo_version</code> <pre> class DockerManifestList(Content): ... @staticmethod def validate_repo_version(qs_content, repo_version): """ Validates a repository version's DockerManifestList units. This method specifically ensures that the repo has all the right DockerManifests that correspond with this DockerManifestList Args: qs_content (django.Queryset): A Queryset of the detail instances for this content type repo_version (RepositoryVersion): The Repository version to validate Raises: django.core.exceptions.ValidationError: if the repository is invalid """ # check all of the validation related DockerManifestList content if has_a_validation_problem: raise ValidationException('Repo foo has ManifestList Y but is missing Manifest Z') </pre> h3. Add a plugin add_content and remove_content <pre> class ModuleMD(Content): ... @staticmethod def add_content(qa_add_content, repo_version): """ Handles any extra work needed for ModuleMD content being added to a RepositoryVersion. Args: qs_content (django.Queryset): A Queryset of the detail instances for this content type repo_version (RepositoryVersion): The Repository version the content is being added to """ # check on if I need to also add some other content also @staticmethod def remove_content(qa_add_content, repo_version): """ Handles any extra work needed for ModuleMD content being removed from a RepositoryVersion. Args: qs_content (django.Queryset): A Queryset of the detail instances for this content type repo_version (RepositoryVersion): The Repository version the content is being removed from """ # check if I should also remove corresponding RPMs # qa_rpms_to_remove = ... if qa_rpms_to _remove repo_version.remove_content(qa_rpms_to_remove, call_plugin_hook=False) repo_version.remove(qa_rpms_to_remove) </pre> It's possible we'll have a recursive call RepositoryVersion.remove_content -> ModuleMD.remove_content -> RepositoryVersion.remove_content so the 'if' statement will prevent it by not causing an additional call to ModuleMD.remove_content if there are 0 items to remove. The "existing add_content and remove_content": calls will receive an additional parameter <code>call_plugin_hook</code which defaults to True. If True, the plugin callback will occur, otherwise it won't.