-
Notifications
You must be signed in to change notification settings - Fork 45
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
Add Pull-through caching #1299
Add Pull-through caching #1299
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Added support for pull-through caching. Users can now configure a dedicated distribution and remote | ||
linked to an external registry without the need to create and mirror repositories in advance. Pulp | ||
downloads missing content automatically if requested and acts as a caching proxy. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Generated by Django 4.2.8 on 2023-12-12 21:15 | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import pulpcore.app.models.access_policy | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('core', '0116_alter_remoteartifact_md5_alter_remoteartifact_sha1_and_more'), | ||
('container', '0036_containerpushrepository_pending_blobs_manifests'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='ContainerPullThroughRemote', | ||
fields=[ | ||
('remote_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.remote')), | ||
], | ||
options={ | ||
'permissions': [('manage_roles_containerpullthroughremote', 'Can manage role assignments on pull-through container remote')], | ||
'default_related_name': '%(app_label)s_%(model_name)s', | ||
}, | ||
bases=('core.remote', pulpcore.app.models.access_policy.AutoAddObjPermsMixin), | ||
), | ||
migrations.AddField( | ||
model_name='containerrepository', | ||
name='pending_blobs', | ||
field=models.ManyToManyField(to='container.blob'), | ||
), | ||
migrations.AddField( | ||
model_name='containerrepository', | ||
name='pending_manifests', | ||
field=models.ManyToManyField(to='container.manifest'), | ||
), | ||
migrations.CreateModel( | ||
name='ContainerPullThroughDistribution', | ||
fields=[ | ||
('distribution_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.distribution')), | ||
('private', models.BooleanField(default=False, help_text='Restrict pull access to explicitly authorized users. Related distributions inherit this value. Defaults to unrestricted pull access.')), | ||
('description', models.TextField(null=True)), | ||
('namespace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='container_pull_through_distributions', to='container.containernamespace')), | ||
], | ||
options={ | ||
'permissions': [('manage_roles_containerpullthroughdistribution', 'Can manage role assignments on pull-through cache distribution')], | ||
'default_related_name': '%(app_label)s_%(model_name)s', | ||
}, | ||
bases=('core.distribution', pulpcore.app.models.access_policy.AutoAddObjPermsMixin), | ||
), | ||
migrations.AddField( | ||
model_name='containerdistribution', | ||
name='pull_through_distribution', | ||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='distributions', to='container.containerpullthroughdistribution'), | ||
), | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -413,6 +413,25 @@ class Meta: | |
] | ||
|
||
|
||
class ContainerPullThroughRemote(Remote, AutoAddObjPermsMixin): | ||
""" | ||
A remote for pull-through caching, omitting the requirement for the upstream name. | ||
|
||
This remote is used for instantiating new regular container remotes with the upstream name. | ||
ipanova marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Configuring credentials and everything related to container workflows can be therefore done | ||
from within a single instance of this remote. | ||
""" | ||
|
||
class Meta: | ||
default_related_name = "%(app_label)s_%(model_name)s" | ||
permissions = [ | ||
( | ||
"manage_roles_containerpullthroughremote", | ||
"Can manage role assignments on pull-through container remote", | ||
), | ||
] | ||
|
||
|
||
class ManifestSigningService(SigningService): | ||
""" | ||
Signing service used for creating container signatures. | ||
|
@@ -486,6 +505,8 @@ class ContainerRepository( | |
manifest_signing_service = models.ForeignKey( | ||
ManifestSigningService, on_delete=models.SET_NULL, null=True | ||
) | ||
pending_blobs = models.ManyToManyField(Blob) | ||
pending_manifests = models.ManyToManyField(Manifest) | ||
|
||
class Meta: | ||
default_related_name = "%(app_label)s_%(model_name)s" | ||
|
@@ -509,6 +530,15 @@ def finalize_new_version(self, new_version): | |
""" | ||
remove_duplicates(new_version) | ||
validate_repo_version(new_version) | ||
self.remove_pending_content(new_version) | ||
|
||
def remove_pending_content(self, repository_version): | ||
"""Remove pending blobs and manifests when committing the content to the repository.""" | ||
added_content = repository_version.added( | ||
base_version=repository_version.base_version | ||
).values_list("pk") | ||
self.pending_blobs.remove(*Blob.objects.filter(pk__in=added_content)) | ||
self.pending_manifests.remove(*Manifest.objects.filter(pk__in=added_content)) | ||
|
||
|
||
class ContainerPushRepository(Repository, AutoAddObjPermsMixin): | ||
|
@@ -565,6 +595,39 @@ def remove_pending_content(self, repository_version): | |
self.pending_manifests.remove(*Manifest.objects.filter(pk__in=added_content)) | ||
|
||
|
||
class ContainerPullThroughDistribution(Distribution, AutoAddObjPermsMixin): | ||
""" | ||
A distribution for pull-through caching, referencing normal distributions. | ||
""" | ||
|
||
TYPE = "pull-through" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about private flag? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. I did not consider this. |
||
|
||
namespace = models.ForeignKey( | ||
ContainerNamespace, | ||
on_delete=models.CASCADE, | ||
related_name="container_pull_through_distributions", | ||
null=True, | ||
) | ||
private = models.BooleanField( | ||
default=False, | ||
help_text=_( | ||
"Restrict pull access to explicitly authorized users. " | ||
"Related distributions inherit this value. " | ||
"Defaults to unrestricted pull access." | ||
), | ||
) | ||
description = models.TextField(null=True) | ||
|
||
class Meta: | ||
default_related_name = "%(app_label)s_%(model_name)s" | ||
permissions = [ | ||
( | ||
"manage_roles_containerpullthroughdistribution", | ||
"Can manage role assignments on pull-through cache distribution", | ||
), | ||
] | ||
|
||
|
||
class ContainerDistribution(Distribution, AutoAddObjPermsMixin): | ||
""" | ||
A container distribution defines how a repository version is distributed by Pulp's webserver. | ||
|
@@ -595,6 +658,13 @@ class ContainerDistribution(Distribution, AutoAddObjPermsMixin): | |
) | ||
description = models.TextField(null=True) | ||
|
||
pull_through_distribution = models.ForeignKey( | ||
ContainerPullThroughDistribution, | ||
related_name="distributions", | ||
on_delete=models.CASCADE, | ||
null=True, | ||
) | ||
Comment on lines
+661
to
+666
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be interesting to use this link in permissions... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you imagine having permissions assigned to these objects? Users who are in charge of pull-through cache distributions should be able to preview the created subdistributions. Are you suggesting adjusting default roles and viewsets in a manner that will disallow the users from seeing specific distributions (possible) or getting to pull-through cache distributions from reverse relation (not possible from API)? I would leave the permissions untouched as we have between Tasks and TaskGroups. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that the owner of the pull-through distribution should also own all the auto-created stuff related to it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to focus on delivering an MVP first to see if we get any feedback for this feature. |
||
|
||
def get_repository_version(self): | ||
""" | ||
Returns the repository version that is supposed to be served by this ContainerDistribution. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Distributions are public by default.