Fix for hard merge
This commit is contained in:
parent
a8b340feb6
commit
9679ec91ec
6 changed files with 54 additions and 29 deletions
|
@ -10,7 +10,7 @@ from endpoints.api import (resource, nickname, require_repo_read, require_repo_w
|
||||||
parse_args, query_param, truthy_bool, disallow_for_app_repositories)
|
parse_args, query_param, truthy_bool, disallow_for_app_repositories)
|
||||||
from endpoints.api.tag_models_interface import Repository
|
from endpoints.api.tag_models_interface import Repository
|
||||||
from endpoints.api.tag_models_pre_oci import pre_oci_model as model
|
from endpoints.api.tag_models_pre_oci import pre_oci_model as model
|
||||||
from endpoints.exception import NotFound
|
from endpoints.exception import NotFound, InvalidRequest
|
||||||
from endpoints.v2.manifest import _generate_and_store_manifest
|
from endpoints.v2.manifest import _generate_and_store_manifest
|
||||||
from util.names import TAG_ERROR, TAG_REGEX
|
from util.names import TAG_ERROR, TAG_REGEX
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class ListRepositoryTags(RepositoryParamResource):
|
||||||
class RepositoryTag(RepositoryParamResource):
|
class RepositoryTag(RepositoryParamResource):
|
||||||
""" Resource for managing repository tags. """
|
""" Resource for managing repository tags. """
|
||||||
schemas = {
|
schemas = {
|
||||||
'MoveTag': {
|
'ChangeTag': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'description': 'Makes changes to a specific tag',
|
'description': 'Makes changes to a specific tag',
|
||||||
'properties': {
|
'properties': {
|
||||||
|
@ -61,7 +61,7 @@ class RepositoryTag(RepositoryParamResource):
|
||||||
'type': ['string', 'null'],
|
'type': ['string', 'null'],
|
||||||
'description': '(If specified) Image identifier to which the tag should point',
|
'description': '(If specified) Image identifier to which the tag should point',
|
||||||
},
|
},
|
||||||
'image': {
|
'expiration': {
|
||||||
'type': ['number', 'null'],
|
'type': ['number', 'null'],
|
||||||
'description': '(If specified) The expiration for the image',
|
'description': '(If specified) The expiration for the image',
|
||||||
},
|
},
|
||||||
|
@ -71,8 +71,8 @@ class RepositoryTag(RepositoryParamResource):
|
||||||
|
|
||||||
@require_repo_write
|
@require_repo_write
|
||||||
@disallow_for_app_repositories
|
@disallow_for_app_repositories
|
||||||
@nickname('changeTagImage')
|
@nickname('changeTag')
|
||||||
@validate_json_request('MoveTag')
|
@validate_json_request('ChangeTag')
|
||||||
def put(self, namespace, repository, tag):
|
def put(self, namespace, repository, tag):
|
||||||
""" Change which image a tag points to or create a new tag."""
|
""" Change which image a tag points to or create a new tag."""
|
||||||
|
|
||||||
|
@ -106,12 +106,16 @@ class RepositoryTag(RepositoryParamResource):
|
||||||
'namespace': namespace,
|
'namespace': namespace,
|
||||||
'expiration_date': expiration_date,
|
'expiration_date': expiration_date,
|
||||||
'old_expiration_date': existing_end_ts
|
'old_expiration_date': existing_end_ts
|
||||||
}, repo=repo)
|
}, repo_name=repository)
|
||||||
else:
|
else:
|
||||||
abort(400, 'Could not update tag expiration; Tag has probably changed')
|
raise InvalidRequest('Could not update tag expiration; Tag has probably changed')
|
||||||
|
|
||||||
if 'image' in request.get_json():
|
if 'image' in request.get_json():
|
||||||
image_id = request.get_json()['image']
|
image_id = request.get_json()['image']
|
||||||
|
image = model.get_repository_image(namespace, repository, image_id)
|
||||||
|
if image is None:
|
||||||
|
raise NotFound()
|
||||||
|
|
||||||
original_image_id = model.get_repo_tag_image(repo, tag)
|
original_image_id = model.get_repo_tag_image(repo, tag)
|
||||||
model.create_or_update_tag(namespace, repository, tag, image_id)
|
model.create_or_update_tag(namespace, repository, tag, image_id)
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Repository(namedtuple('Repository', ['namespace_name', 'repository_name'])
|
||||||
class Image(
|
class Image(
|
||||||
namedtuple('Image', [
|
namedtuple('Image', [
|
||||||
'docker_image_id', 'created', 'comment', 'command', 'storage_image_size',
|
'docker_image_id', 'created', 'comment', 'command', 'storage_image_size',
|
||||||
'storage_uploading', 'ancestor_length', 'ancestor_id_list'
|
'storage_uploading', 'ancestor_id_list'
|
||||||
])):
|
])):
|
||||||
"""
|
"""
|
||||||
Image
|
Image
|
||||||
|
@ -71,7 +71,6 @@ class Image(
|
||||||
:type command: string
|
:type command: string
|
||||||
:type storage_image_size: int
|
:type storage_image_size: int
|
||||||
:type storage_uploading: boolean
|
:type storage_uploading: boolean
|
||||||
:type ancestor_length: int
|
|
||||||
:type ancestor_id_list: [int]
|
:type ancestor_id_list: [int]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -91,7 +90,7 @@ class Image(
|
||||||
'command': json.loads(command) if command else None,
|
'command': json.loads(command) if command else None,
|
||||||
'size': self.storage_image_size,
|
'size': self.storage_image_size,
|
||||||
'uploading': self.storage_uploading,
|
'uploading': self.storage_uploading,
|
||||||
'sort_index': self.ancestor_length,
|
'sort_index': len(self.ancestor_id_list),
|
||||||
}
|
}
|
||||||
|
|
||||||
if include_ancestors:
|
if include_ancestors:
|
||||||
|
@ -116,9 +115,9 @@ class TagDataInterface(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_repo(self, namespace_name, repository_name, docker_image_id):
|
def get_repo(self, namespace_name, repository_name):
|
||||||
"""
|
"""
|
||||||
Returns a repository associated with the given namespace, repository, and docker_image_id
|
Returns a repository associated with the given namespace and repository name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -157,6 +156,13 @@ class TagDataInterface(object):
|
||||||
Returns the repository associated with the namespace_name and repository_name
|
Returns the repository associated with the namespace_name and repository_name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_repository_image(self, namespace_name, repository_name, docker_image_id):
|
||||||
|
"""
|
||||||
|
Returns the repository image associated with the namespace_name, repository_name, and docker
|
||||||
|
image ID.
|
||||||
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def restore_tag_to_manifest(self, repository_name, tag_name, manifest_digest):
|
def restore_tag_to_manifest(self, repository_name, tag_name, manifest_digest):
|
||||||
"""
|
"""
|
||||||
|
@ -170,3 +176,11 @@ class TagDataInterface(object):
|
||||||
Returns the existing repo tag image if it exists or else returns None
|
Returns the existing repo tag image if it exists or else returns None
|
||||||
Side effects include adding the tag with associated name to the image with the associated id in the named repo.
|
Side effects include adding the tag with associated name to the image with the associated id in the named repo.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def change_repository_tag_expiration(self, namespace_name, repository_name, tag_name,
|
||||||
|
expiration_date):
|
||||||
|
""" Sets the expiration date of the tag under the matching repository to that given. If the
|
||||||
|
expiration date is None, then the tag will not expire. Returns a tuple of the previous
|
||||||
|
expiration timestamp in seconds (if any), and whether the operation succeeded.
|
||||||
|
"""
|
||||||
|
|
|
@ -27,12 +27,12 @@ class PreOCIModel(TagDataInterface):
|
||||||
|
|
||||||
return RepositoryTagHistory(tags=repository_tag_history, more=more)
|
return RepositoryTagHistory(tags=repository_tag_history, more=more)
|
||||||
|
|
||||||
def get_repo(self, namespace_name, repository_name, docker_image_id):
|
def get_repo(self, namespace_name, repository_name):
|
||||||
image = model.image.get_repo_image(namespace_name, repository_name, docker_image_id)
|
repo = model.repository.get_repository(namespace_name, repository_name)
|
||||||
if image is None:
|
if repo is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return Repository(image.repository.namespace_user, image.repository.name)
|
return Repository(repo.namespace_user, repo.name)
|
||||||
|
|
||||||
def get_repo_tag_image(self, repository, tag_name):
|
def get_repo_tag_image(self, repository, tag_name):
|
||||||
repo = model.repository.get_repository(str(repository.namespace_name), str(repository.repository_name))
|
repo = model.repository.get_repository(str(repository.namespace_name), str(repository.repository_name))
|
||||||
|
@ -73,6 +73,13 @@ class PreOCIModel(TagDataInterface):
|
||||||
new_tags.append(convert_tag(tag))
|
new_tags.append(convert_tag(tag))
|
||||||
return new_tags
|
return new_tags
|
||||||
|
|
||||||
|
def get_repository_image(self, namespace_name, repository_name, docker_image_id):
|
||||||
|
image = model.image.get_repo_image(namespace_name, repository_name, docker_image_id)
|
||||||
|
if image is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return convert_image(image)
|
||||||
|
|
||||||
def get_repository(self, namespace_name, repository_name):
|
def get_repository(self, namespace_name, repository_name):
|
||||||
repo = model.repository.get_repository(namespace_name, repository_name)
|
repo = model.repository.get_repository(namespace_name, repository_name)
|
||||||
if repo is None:
|
if repo is None:
|
||||||
|
@ -102,13 +109,17 @@ class PreOCIModel(TagDataInterface):
|
||||||
|
|
||||||
return convert_image(image)
|
return convert_image(image)
|
||||||
|
|
||||||
|
def change_repository_tag_expiration(self, namespace_name, repository_name, tag_name,
|
||||||
|
expiration_date):
|
||||||
|
return model.tag.change_repository_tag_expiration(namespace_name, repository_name, tag_name,
|
||||||
|
expiration_date)
|
||||||
|
|
||||||
|
|
||||||
def convert_image(database_image):
|
def convert_image(database_image):
|
||||||
return Image(docker_image_id=database_image.docker_image_id, created=database_image.created,
|
return Image(docker_image_id=database_image.docker_image_id, created=database_image.created,
|
||||||
comment=database_image.comment, command=database_image.command,
|
comment=database_image.comment, command=database_image.command,
|
||||||
storage_image_size=database_image.storage.image_size,
|
storage_image_size=database_image.storage.image_size,
|
||||||
storage_uploading=database_image.storage.uploading,
|
storage_uploading=database_image.storage.uploading,
|
||||||
ancestor_length=len(database_image.ancestors),
|
|
||||||
ancestor_id_list=database_image.ancestor_id_list())
|
ancestor_id_list=database_image.ancestor_id_list())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -106,20 +106,18 @@ def test_list_repository_tag_history(expected, namespace_name, repository_name,
|
||||||
specific_tag) == expected
|
specific_tag) == expected
|
||||||
|
|
||||||
|
|
||||||
def get_repo_image_mock(monkeypatch, return_value):
|
def get_repo_mock(monkeypatch, return_value):
|
||||||
def return_return_value(namespace_name, repository_name, image_id):
|
def return_return_value(namespace_name, repository_name):
|
||||||
return return_value
|
return return_value
|
||||||
|
|
||||||
monkeypatch.setattr(model.image, 'get_repo_image', return_return_value)
|
monkeypatch.setattr(model.repository, 'get_repository', return_return_value)
|
||||||
|
|
||||||
|
|
||||||
def test_get_repo_not_exists(get_monkeypatch):
|
def test_get_repo_not_exists(get_monkeypatch):
|
||||||
namespace_name = 'namespace_name'
|
namespace_name = 'namespace_name'
|
||||||
repository_name = 'repository_name'
|
repository_name = 'repository_name'
|
||||||
image_id = 'image_id'
|
get_repo_mock(get_monkeypatch, None)
|
||||||
get_repo_image_mock(get_monkeypatch, None)
|
repo = pre_oci_model.get_repo(namespace_name, repository_name)
|
||||||
|
|
||||||
repo = pre_oci_model.get_repo(namespace_name, repository_name, image_id)
|
|
||||||
|
|
||||||
assert repo is None
|
assert repo is None
|
||||||
|
|
||||||
|
@ -127,14 +125,13 @@ def test_get_repo_not_exists(get_monkeypatch):
|
||||||
def test_get_repo_exists(get_monkeypatch):
|
def test_get_repo_exists(get_monkeypatch):
|
||||||
namespace_name = 'namespace_name'
|
namespace_name = 'namespace_name'
|
||||||
repository_name = 'repository_name'
|
repository_name = 'repository_name'
|
||||||
image_id = 'image_id'
|
|
||||||
mock = Mock()
|
mock = Mock()
|
||||||
mock.namespace_user = namespace_name
|
mock.namespace_user = namespace_name
|
||||||
mock.name = repository_name
|
mock.name = repository_name
|
||||||
mock.repository = mock
|
mock.repository = mock
|
||||||
get_repo_image_mock(get_monkeypatch, mock)
|
get_repo_mock(get_monkeypatch, mock)
|
||||||
|
|
||||||
repo = pre_oci_model.get_repo(namespace_name, repository_name, image_id)
|
repo = pre_oci_model.get_repo(namespace_name, repository_name)
|
||||||
|
|
||||||
assert repo is not None
|
assert repo is not None
|
||||||
assert repo.repository_name == repository_name
|
assert repo.repository_name == repository_name
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from app import app
|
from app import app
|
||||||
from endpoints.v2.models_pre_oci import pre_oci_model as model
|
from endpoints.v2.models_pre_oci import data_model as model
|
||||||
from util.timedeltastring import convert_to_timedelta
|
from util.timedeltastring import convert_to_timedelta
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
|
@ -17,7 +17,6 @@ from endpoints.v2.models_interface import Label
|
||||||
from endpoints.v2.models_pre_oci import data_model as model
|
from endpoints.v2.models_pre_oci import data_model as model
|
||||||
from endpoints.v2.errors import (BlobUnknown, ManifestInvalid, ManifestUnknown, TagInvalid,
|
from endpoints.v2.errors import (BlobUnknown, ManifestInvalid, ManifestUnknown, TagInvalid,
|
||||||
NameInvalid, TagExpired)
|
NameInvalid, TagExpired)
|
||||||
>>>>>>> Change error message when trying to pull a deleted or expired tag
|
|
||||||
from endpoints.v2.labelhandlers import handle_label
|
from endpoints.v2.labelhandlers import handle_label
|
||||||
from image.docker import ManifestException
|
from image.docker import ManifestException
|
||||||
from image.docker.schema1 import DockerSchema1Manifest, DockerSchema1ManifestBuilder
|
from image.docker.schema1 import DockerSchema1Manifest, DockerSchema1ManifestBuilder
|
||||||
|
|
Reference in a new issue