Allow tags to be marked as hidden. Create a hidden tag on every image during a push to prevent them from getting GCed.
This commit is contained in:
parent
04b06547b8
commit
41108a0856
6 changed files with 63 additions and 14 deletions
|
@ -194,4 +194,7 @@ class DefaultConfig(object):
|
||||||
SYSTEM_SERVICES_PATH = "conf/init/"
|
SYSTEM_SERVICES_PATH = "conf/init/"
|
||||||
|
|
||||||
# Services that should not be shown in the logs view.
|
# Services that should not be shown in the logs view.
|
||||||
SYSTEM_SERVICE_BLACKLIST = []
|
SYSTEM_SERVICE_BLACKLIST = []
|
||||||
|
|
||||||
|
# Temporary tag expiration in seconds, this may actually be longer based on GC policy
|
||||||
|
PUSH_TEMP_TAG_EXPIRATION_S = 60 * 60
|
||||||
|
|
|
@ -469,6 +469,7 @@ class RepositoryTag(BaseModel):
|
||||||
repository = ForeignKeyField(Repository)
|
repository = ForeignKeyField(Repository)
|
||||||
lifetime_start_ts = IntegerField(default=_get_epoch_timestamp)
|
lifetime_start_ts = IntegerField(default=_get_epoch_timestamp)
|
||||||
lifetime_end_ts = IntegerField(null=True, index=True)
|
lifetime_end_ts = IntegerField(null=True, index=True)
|
||||||
|
hidden = BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
database = db
|
database = db
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
"""Allow tags to be marked as hidden.
|
||||||
|
|
||||||
|
Revision ID: 4ef04c61fcf9
|
||||||
|
Revises: 509d2857566f
|
||||||
|
Create Date: 2015-02-18 16:34:16.586129
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '4ef04c61fcf9'
|
||||||
|
down_revision = '509d2857566f'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(tables):
|
||||||
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('repositorytag', sa.Column('hidden', sa.Boolean(), nullable=False, server_default=sa.sql.expression.false()))
|
||||||
|
### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(tables):
|
||||||
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('repositorytag', 'hidden')
|
||||||
|
### end Alembic commands ###
|
|
@ -5,6 +5,7 @@ import json
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from datetime import datetime, timedelta, date
|
from datetime import datetime, timedelta, date
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
from data.database import (User, Repository, Image, AccessToken, Role, RepositoryPermission,
|
from data.database import (User, Repository, Image, AccessToken, Role, RepositoryPermission,
|
||||||
Visibility, RepositoryTag, EmailConfirmation, FederatedLogin,
|
Visibility, RepositoryTag, EmailConfirmation, FederatedLogin,
|
||||||
|
@ -1561,15 +1562,20 @@ def _tag_alive(query):
|
||||||
(RepositoryTag.lifetime_end_ts > int(time.time())))
|
(RepositoryTag.lifetime_end_ts > int(time.time())))
|
||||||
|
|
||||||
|
|
||||||
def list_repository_tags(namespace_name, repository_name):
|
def list_repository_tags(namespace_name, repository_name, include_hidden=False):
|
||||||
return _tag_alive(RepositoryTag
|
query = _tag_alive(RepositoryTag
|
||||||
.select(RepositoryTag, Image)
|
.select(RepositoryTag, Image)
|
||||||
.join(Repository)
|
.join(Repository)
|
||||||
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
||||||
.switch(RepositoryTag)
|
.switch(RepositoryTag)
|
||||||
.join(Image)
|
.join(Image)
|
||||||
.where(Repository.name == repository_name,
|
.where(Repository.name == repository_name,
|
||||||
Namespace.username == namespace_name))
|
Namespace.username == namespace_name))
|
||||||
|
|
||||||
|
if not include_hidden:
|
||||||
|
query = query.where(RepositoryTag.hidden == False)
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
def _garbage_collect_tags(namespace_name, repository_name):
|
def _garbage_collect_tags(namespace_name, repository_name):
|
||||||
|
@ -1786,10 +1792,8 @@ def create_or_update_tag(namespace_name, repository_name, tag_name,
|
||||||
# No tag that needs to be ended
|
# No tag that needs to be ended
|
||||||
pass
|
pass
|
||||||
|
|
||||||
tag = RepositoryTag.create(repository=repo, image=image, name=tag_name,
|
return RepositoryTag.create(repository=repo, image=image, name=tag_name,
|
||||||
lifetime_start_ts=now_ts)
|
lifetime_start_ts=now_ts)
|
||||||
|
|
||||||
return tag
|
|
||||||
|
|
||||||
|
|
||||||
def delete_tag(namespace_name, repository_name, tag_name):
|
def delete_tag(namespace_name, repository_name, tag_name):
|
||||||
|
@ -1812,6 +1816,17 @@ def delete_tag(namespace_name, repository_name, tag_name):
|
||||||
found.save()
|
found.save()
|
||||||
|
|
||||||
|
|
||||||
|
def create_temporary_hidden_tag(repo, image, expiration_s):
|
||||||
|
""" Create a tag with a defined timeline, that will not appear in the UI or CLI. Returns the name
|
||||||
|
of the temporary tag. """
|
||||||
|
now_ts = int(time.time())
|
||||||
|
expire_ts = now_ts + expiration_s
|
||||||
|
tag_name = str(uuid4())
|
||||||
|
RepositoryTag.create(repository=repo, image=image, name=tag_name, lifetime_start_ts=now_ts,
|
||||||
|
lifetime_end_ts=expire_ts, hidden=True)
|
||||||
|
return tag_name
|
||||||
|
|
||||||
|
|
||||||
def purge_all_repository_tags(namespace_name, repository_name):
|
def purge_all_repository_tags(namespace_name, repository_name):
|
||||||
""" Immediately purge all repository tags without respecting the lifeline procedure """
|
""" Immediately purge all repository tags without respecting the lifeline procedure """
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -467,6 +467,10 @@ def put_image_json(namespace, repository, image_id):
|
||||||
repo_image = model.find_create_or_link_image(image_id, repo, username, {},
|
repo_image = model.find_create_or_link_image(image_id, repo, username, {},
|
||||||
store.preferred_locations[0])
|
store.preferred_locations[0])
|
||||||
|
|
||||||
|
# Create a temporary tag to prevent this image from getting garbage collected while the push
|
||||||
|
# is in progress.
|
||||||
|
model.create_temporary_hidden_tag(repo, repo_image, app.config['PUSH_TEMP_TAG_EXPIRATION_S'])
|
||||||
|
|
||||||
uuid = repo_image.storage.uuid
|
uuid = repo_image.storage.uuid
|
||||||
|
|
||||||
if image_id != data['id']:
|
if image_id != data['id']:
|
||||||
|
|
Binary file not shown.
Reference in a new issue