Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typed Repositories #354

Merged
merged 4 commits into from Nov 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 23 additions & 18 deletions .travis/test_bindings.py
@@ -1,10 +1,15 @@
from pulpcore.client.pulpcore import (ApiClient as CoreApiClient, ArtifactsApi, Configuration,
Repository, RepositoriesApi, RepositoriesVersionsApi,
TasksApi, Upload, UploadCommit, UploadsApi)
from pulpcore.client.pulp_file import (ApiClient as FileApiClient, ContentFilesApi,
DistributionsFileApi, FileFileDistribution,
PublicationsFileApi, RemotesFileApi, FileFileRemote,
RepositorySyncURL, FileFilePublication)
from pulpcore.client.pulpcore import (
ApiClient as CoreApiClient, ArtifactsApi, Configuration,
TasksApi, Upload, UploadCommit, UploadsApi
)
from pulpcore.client.pulp_file import (
ApiClient as FileApiClient, ContentFilesApi,
DistributionsFileApi, FileFileDistribution,
PublicationsFileApi, RemotesFileApi, FileFileRemote,
RepositorySyncURL, FileFilePublication,
FileFileRepository, RepositoriesFileApi,
RepositoriesFileVersionsApi,
)
from pprint import pprint
from time import sleep
import hashlib
Expand Down Expand Up @@ -32,7 +37,7 @@ def monitor_task(task_href):
task = tasks.read(task_href)
pprint(task)
if task.state == 'completed':
print("The task was successfful.")
print("The task was successful.")
return task.created_resources
else:
print("The task did not finish successfully.")
Expand Down Expand Up @@ -94,12 +99,12 @@ def upload_file_in_chunks(file_path):

# Create api clients for all resource types
artifacts = ArtifactsApi(core_client)
repositories = RepositoriesApi(core_client)
repoversions = RepositoriesVersionsApi(core_client)
filerepoversions = RepositoriesFileVersionsApi(file_client)
filecontent = ContentFilesApi(file_client)
filedistributions = DistributionsFileApi(core_client)
filedistributions = DistributionsFileApi(file_client)
filepublications = PublicationsFileApi(file_client)
fileremotes = RemotesFileApi(file_client)
filerepositories = RepositoriesFileApi(file_client)
tasks = TasksApi(core_client)
uploads = UploadsApi(core_client)

Expand All @@ -121,20 +126,20 @@ def upload_file_in_chunks(file_path):
pprint(file_remote)

# Create a Repository
repository_data = Repository(name='foo25')
repository = repositories.create(repository_data)
repository_data = FileFileRepository(name='foo25')
repository = filerepositories.create(repository_data)
pprint(repository)

# Sync a Repository
repository_sync_data = RepositorySyncURL(repository=repository.pulp_href)
sync_response = fileremotes.sync(file_remote.pulp_href, repository_sync_data)
repository_sync_data = RepositorySyncURL(remote=file_remote.pulp_href)
sync_response = filerepositories.sync(repository.pulp_href, repository_sync_data)

pprint(sync_response)

# Monitor the sync task
created_resources = monitor_task(sync_response.task)

repository_version_1 = repoversions.read(created_resources[0])
repository_version_1 = filerepoversions.read(created_resources[0])
dralley marked this conversation as resolved.
Show resolved Hide resolved
pprint(repository_version_1)

# Create an artifact from a local file
Expand All @@ -148,12 +153,12 @@ def upload_file_in_chunks(file_path):

# Add the new FileContent to a repository version
repo_version_data = {'add_content_units': [created_resources[0]]}
repo_version_response = repoversions.create(repository.pulp_href, repo_version_data)
repo_version_response = filerepositories.modify(repository.pulp_href, repo_version_data)

# Monitor the repo version creation task
created_resources = monitor_task(repo_version_response.task)

repository_version_2 = repoversions.read(created_resources[0])
repository_version_2 = filerepoversions.read(created_resources[0])
pprint(repository_version_2)

# Create a publication from the latest version of the repository
Expand Down
16 changes: 8 additions & 8 deletions .travis/test_bindings.rb
Expand Up @@ -20,8 +20,8 @@


@artifacts_api = PulpcoreClient::ArtifactsApi.new
@repositories_api = PulpcoreClient::RepositoriesApi.new
@repoversions_api = PulpcoreClient::RepositoriesVersionsApi.new
@filerepositories_api = PulpFileClient::RepositoriesFileApi.new
@repoversions_api = PulpFileClient::RepositoriesFileVersionsApi.new
@filecontent_api = PulpFileClient::ContentFilesApi.new
@filedistributions_api = PulpFileClient::DistributionsFileApi.new
@filepublications_api = PulpFileClient::PublicationsFileApi.new
Expand Down Expand Up @@ -108,12 +108,12 @@ def upload_file_in_chunks(file_path)
file_remote = @fileremotes_api.create(remote_data)

# Create a Repository
repository_data = PulpcoreClient::Repository.new({name: 'foo38'})
repository = @repositories_api.create(repository_data)
repository_data = PulpFileClient::FileFileRepository.new({name: 'foo38'})
file_repository = @filerepositories_api.create(repository_data)

# Sync a Repository
repository_sync_data = PulpFileClient::RepositorySyncURL.new({repository: repository.pulp_href})
sync_response = @fileremotes_api.sync(file_remote.pulp_href, repository_sync_data)
repository_sync_data = PulpFileClient::RepositorySyncURL.new({remote: file_remote.pulp_href})
sync_response = @filerepositories_api.sync(file_repository.pulp_href, repository_sync_data)

# Monitor the sync task
created_resources = monitor_task(sync_response.task)
Expand All @@ -131,15 +131,15 @@ def upload_file_in_chunks(file_path)

# Add the new FileContent to a repository version
repo_version_data = {add_content_units: [created_resources[0]]}
repo_version_response = @repoversions_api.create(repository.pulp_href, repo_version_data)
repo_version_response = @filerepositories_api.modify(file_repository.pulp_href, repo_version_data)

# Monitor the repo version creation task
created_resources = monitor_task(repo_version_response.task)

repository_version_2 = @repoversions_api.read(created_resources[0])

# Create a publication from the latest version of the repository
publish_data = PulpFileClient::FileFilePublication.new({repository: repository.pulp_href})
publish_data = PulpFileClient::FileFilePublication.new({repository: file_repository.pulp_href})
publish_response = @filepublications_api.create(publish_data)

# Monitor the publish task
Expand Down
3 changes: 3 additions & 0 deletions CHANGES/5625.removal
@@ -0,0 +1,3 @@
The /pulp/api/v3/repositories/ endpoint has been removed and Repositories have made a "typed" object. They now live at /pulp/api/v3/repositories/<plugin>/<type>, e.g. /repositories/file/file/.

The convention for sync is that it will now be performed by POSTing to {repo_href}/sync/ remote={remote_href} instead of by POSTING to {remote_href}/sync/ repository={repo_href}. The latter convention will break due to the aforementioned change.
5 changes: 5 additions & 0 deletions CHANGES/plugin_api/5625.removal
@@ -0,0 +1,5 @@
models.RepositoryVersion.create() is no longer available, it has been replaced by {repository instance}.new_version().

The convention for sync is that it will now be performed by POSTing to {repo_href}/sync/ remote={remote_href} instead of by POSTING to {remote_href}/sync/ repository={repo_href}. The latter will break due to becoming a typed resource, so plugins will need to adjust their code for the former convention.

Make repositories "typed". Plugin writers need to subclass the Repository model, viewset, and serializer, as well as the RepositoryVersion viewset (just the viewset). They should also remove the /sync/ endpoint from their remote viewset and place it on the repository viewset.
2 changes: 1 addition & 1 deletion docs/plugins/plugin-writer/concepts/tasks/add-remove.rst
Expand Up @@ -18,7 +18,7 @@ working directory setup, and database cleanup after encountering failures.

.. code-block:: python

with RepositoryVersion.create(repository) as new_version:
with repository.new_version() as new_version:

# add content manually
new_version.add_content(content)
Expand Down
16 changes: 8 additions & 8 deletions docs/workflows/exposing-content.rst
Expand Up @@ -43,8 +43,8 @@ will serve the latest RepositoryVersion associated with that Repository.

First lets make a Repository named ``foo`` and save its URL as ``REPO_HREF``::

http POST http://localhost:24817/pulp/api/v3/repositories/ name=foo
export REPO_HREF=$(http :24817/pulp/api/v3/repositories/ | jq -r '.results[] | select(.name == "foo") | .pulp_href')
http POST http://localhost:24817/pulp/api/v3/repositories/file/file/ name=foo
export REPO_HREF=$(http :24817/pulp/api/v3/repositories/file/file/ | jq -r '.results[] | select(.name == "foo") | .pulp_href')

Then lets make a :term:`Distribution` that will distribute ``foo`` at base_url ``mypath``::

Expand Down Expand Up @@ -73,15 +73,15 @@ First create a :term:`RepositoryVersion` with some `pulp_ansible <https://github
pulp_ansible>`_ content in it::

# Create a Repository
http POST :24817/pulp/api/v3/repositories/ name=foo
export REPO_HREF=$(http :24817/pulp/api/v3/repositories/ | jq -r '.results[] | select(.name == "foo") | .pulp_href')
http POST :24817/pulp/api/v3/repositories/file/file/ name=foo
export REPO_HREF=$(http :24817/pulp/api/v3/repositories/file/file/ | jq -r '.results[] | select(.name == "foo") | .pulp_href')

# Create an AnsibleRemote to sync roles from galaxy.ansible.com
http POST :24817/pulp/api/v3/remotes/ansible/ansible/ name=bar url='https://galaxy.ansible.com/api/v1/roles/?namespace__name=elastic'
export REMOTE_HREF=$(http :24817/pulp/api/v3/remotes/ansible/ansible/ | jq -r '.results[] | select(.name == "bar") | .pulp_href')

# Sync the repo with the remote
http POST ':24817'$REMOTE_HREF'sync/' repository=$REPO_HREF
http POST ':24817'$REPO_HREF'sync/' remote=$REMOTE_HREF
sleep 3 # wait for the sync to happen
export REPO_VERSION_HREF=$(http GET ':24817'$REPO_HREF'versions/1/' | jq -r '.pulp_href')

Expand Down Expand Up @@ -113,15 +113,15 @@ First create a :term:`Publication` with some `pulp_file <https://github.com/pulp
content in it::

# Create a Repository
http POST :24817/pulp/api/v3/repositories/ name=foo
export REPO_HREF=$(http :24817/pulp/api/v3/repositories/ | jq -r '.results[] | select(.name == "foo") | .pulp_href')
http POST :24817/pulp/api/v3/repositories/file/file/ name=foo
export REPO_HREF=$(http :24817/pulp/api/v3/repositories/file/file/ | jq -r '.results[] | select(.name == "foo") | .pulp_href')

# Create an FileRemote to sync roles from fedorapeople
http POST :24817/pulp/api/v3/remotes/file/file/ name='bar' url='https://repos.fedorapeople.org/pulp/pulp/demo_repos/test_file_repo/PULP_MANIFEST'
export REMOTE_HREF=$(http :24817/pulp/api/v3/remotes/file/file/ | jq -r '.results[] | select(.name == "bar") | .pulp_href')

# Sync the repo with the remote
http POST ':24817'$REMOTE_HREF'sync/' repository=$REPO_HREF
http POST ':24817'$REPO_HREF'sync/' remote=$REMOTE_HREF
sleep 3 # wait for the sync to happen

# Create a Publication
Expand Down
7 changes: 4 additions & 3 deletions pulpcore/app/apps.py
@@ -1,3 +1,4 @@
from collections import defaultdict
from importlib import import_module

from django import apps
Expand Down Expand Up @@ -65,7 +66,7 @@ def __init__(self, app_name, app_module):
# Module containing urlpatterns
self.urls_module = None

# Mapping of model names to viewsets (viewsets unrelated to models are excluded)
# Mapping of model names to viewset lists (viewsets unrelated to models are excluded)
self.named_viewsets = None
# Mapping of serializer names to serializers
self.named_serializers = None
Expand Down Expand Up @@ -99,7 +100,7 @@ def import_serializers(self):
def import_viewsets(self):
# circular import avoidance
from pulpcore.app.viewsets import NamedModelViewSet
self.named_viewsets = {}
self.named_viewsets = defaultdict(list)
if module_has_submodule(self.module, VIEWSETS_MODULE_NAME):
# import the viewsets module and track any interesting viewsets
viewsets_module_name = '{name}.{module}'.format(
Expand All @@ -112,7 +113,7 @@ def import_viewsets(self):
# gets registered in the named_viewsets registry.
if (obj is not NamedModelViewSet and issubclass(obj, NamedModelViewSet)):
model = obj.queryset.model
self.named_viewsets[model] = obj
self.named_viewsets[model].append(obj)
except TypeError:
# obj isn't a class, issubclass exploded but obj can be safely filtered out
continue
Expand Down
18 changes: 18 additions & 0 deletions pulpcore/app/migrations/0013_repository_pulp_type.py
@@ -0,0 +1,18 @@
# Generated by Django 2.2.6 on 2019-10-28 18:42

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0012_auto_20191104_2000'),
]

operations = [
migrations.AddField(
model_name='repository',
name='pulp_type',
field=models.TextField(default=None),
),
]