first steps undertaken to fix spulec/moto#1684 and spulec/moto#1685

This commit is contained in:
Stephan Huber 2018-06-13 16:14:18 +02:00
parent e118a678a6
commit 3a355f126c
2 changed files with 82 additions and 15 deletions

View File

@ -4,12 +4,12 @@ import hashlib
from copy import copy from copy import copy
from random import random from random import random
from botocore.exceptions import ParamValidationError
from moto.core import BaseBackend, BaseModel from moto.core import BaseBackend, BaseModel
from moto.ec2 import ec2_backends from moto.ec2 import ec2_backends
from moto.ecr.exceptions import ImageNotFoundException, RepositoryNotFoundException from moto.ecr.exceptions import ImageNotFoundException, RepositoryNotFoundException
from botocore.exceptions import ParamValidationError
DEFAULT_REGISTRY_ID = '012345678910' DEFAULT_REGISTRY_ID = '012345678910'
@ -97,13 +97,13 @@ class Repository(BaseObject):
class Image(BaseObject): class Image(BaseObject):
def __init__(self, tag, manifest, repository, registry_id=DEFAULT_REGISTRY_ID): def __init__(self, tag, manifest, repository, digest=None, registry_id=DEFAULT_REGISTRY_ID):
self.image_tag = tag self.image_tag = tag
self.image_manifest = manifest self.image_manifest = manifest
self.image_size_in_bytes = 50 * 1024 * 1024 self.image_size_in_bytes = 50 * 1024 * 1024
self.repository = repository self.repository = repository
self.registry_id = registry_id self.registry_id = registry_id
self.image_digest = None self.image_digest = digest
self.image_pushed_at = None self.image_pushed_at = None
def _create_digest(self): def _create_digest(self):
@ -115,6 +115,9 @@ class Image(BaseObject):
self._create_digest() self._create_digest()
return self.image_digest return self.image_digest
def get_image_manifest(self):
return self.image_manifest
@property @property
def response_object(self): def response_object(self):
response_object = self.gen_response_object() response_object = self.gen_response_object()
@ -124,14 +127,14 @@ class Image(BaseObject):
response_object['imageManifest'] = self.image_manifest response_object['imageManifest'] = self.image_manifest
response_object['repositoryName'] = self.repository response_object['repositoryName'] = self.repository
response_object['registryId'] = self.registry_id response_object['registryId'] = self.registry_id
return response_object return {k: v for k, v in response_object.items() if v is not None and v != [None]}
@property @property
def response_list_object(self): def response_list_object(self):
response_object = self.gen_response_object() response_object = self.gen_response_object()
response_object['imageTag'] = self.image_tag response_object['imageTag'] = self.image_tag
response_object['imageDigest'] = "i don't know" response_object['imageDigest'] = "i don't know"
return response_object return {k: v for k, v in response_object.items() if v is not None and v != [None]}
@property @property
def response_describe_object(self): def response_describe_object(self):
@ -143,7 +146,7 @@ class Image(BaseObject):
response_object['registryId'] = self.registry_id response_object['registryId'] = self.registry_id
response_object['imageSizeInBytes'] = self.image_size_in_bytes response_object['imageSizeInBytes'] = self.image_size_in_bytes
response_object['imagePushedAt'] = '2017-05-09' response_object['imagePushedAt'] = '2017-05-09'
return response_object return {k: v for k, v in response_object.items() if v is not None and v != [None]}
@property @property
def response_batch_get_image(self): def response_batch_get_image(self):
@ -154,7 +157,7 @@ class Image(BaseObject):
response_object['imageManifest'] = self.image_manifest response_object['imageManifest'] = self.image_manifest
response_object['repositoryName'] = self.repository response_object['repositoryName'] = self.repository
response_object['registryId'] = self.registry_id response_object['registryId'] = self.registry_id
return response_object return {k: v for k, v in response_object.items() if v is not None and v != [None]}
class ECRBackend(BaseBackend): class ECRBackend(BaseBackend):
@ -252,8 +255,14 @@ class ECRBackend(BaseBackend):
else: else:
raise Exception("{0} is not a repository".format(repository_name)) raise Exception("{0} is not a repository".format(repository_name))
image = Image(image_tag, image_manifest, repository_name) existing_image = list(filter(lambda x: x.response_object['imageManifest'] == image_manifest, repository.images))
repository.images.append(image) if not existing_image:
image = Image(image_tag, image_manifest, repository_name)
repository.images.append(image)
else:
image = Image(image_tag, image_manifest, repository_name, existing_image[0].get_image_digest())
repository.images.append(image)
return image return image
def batch_get_image(self, repository_name, registry_id=None, image_ids=None, accepted_media_types=None): def batch_get_image(self, repository_name, registry_id=None, image_ids=None, accepted_media_types=None):

View File

@ -197,6 +197,54 @@ def test_put_image():
response['image']['repositoryName'].should.equal('test_repository') response['image']['repositoryName'].should.equal('test_repository')
response['image']['registryId'].should.equal('012345678910') response['image']['registryId'].should.equal('012345678910')
@mock_ecr
def test_put_image_with_multiple_tags():
client = boto3.client('ecr', region_name='us-east-1')
_ = client.create_repository(
repositoryName='test_repository'
)
manifest = _create_image_manifest()
response = client.put_image(
repositoryName='test_repository',
imageManifest=json.dumps(manifest),
imageTag='v1'
)
response['image']['imageId']['imageTag'].should.equal('v1')
response['image']['imageId']['imageDigest'].should.contain("sha")
response['image']['repositoryName'].should.equal('test_repository')
response['image']['registryId'].should.equal('012345678910')
response1 = client.put_image(
repositoryName='test_repository',
imageManifest=json.dumps(manifest),
imageTag='latest'
)
response1['image']['imageId']['imageTag'].should.equal('latest')
response1['image']['imageId']['imageDigest'].should.contain("sha")
response1['image']['repositoryName'].should.equal('test_repository')
response1['image']['registryId'].should.equal('012345678910')
response2 = client.describe_images(repositoryName='test_repository')
type(response2['imageDetails']).should.be(list)
len(response2['imageDetails']).should.be(1)
response['imageDetails'][0]['imageDigest'].should.contain("sha")
# response['imageDetails'][0]['registryId'].should.equal("012345678910")
# response['imageDetails'][1]['registryId'].should.equal("012345678910")
# response['imageDetails'][2]['registryId'].should.equal("012345678910")
# response['imageDetails'][3]['registryId'].should.equal("012345678910")
#
# response['imageDetails'][0]['repositoryName'].should.equal("test_repository")
# response['imageDetails'][1]['repositoryName'].should.equal("test_repository")
# response['imageDetails'][2]['repositoryName'].should.equal("test_repository")
# response['imageDetails'][3]['repositoryName'].should.equal("test_repository")
#
# response['imageDetails'][0].should_not.have.key('imageTags')
# len(response['imageDetails'][1]['imageTags']).should.be(1)
@mock_ecr @mock_ecr
def test_list_images(): def test_list_images():
@ -259,6 +307,11 @@ def test_describe_images():
repositoryName='test_repository' repositoryName='test_repository'
) )
_ = client.put_image(
repositoryName='test_repository',
imageManifest=json.dumps(_create_image_manifest())
)
_ = client.put_image( _ = client.put_image(
repositoryName='test_repository', repositoryName='test_repository',
imageManifest=json.dumps(_create_image_manifest()), imageManifest=json.dumps(_create_image_manifest()),
@ -279,32 +332,37 @@ def test_describe_images():
response = client.describe_images(repositoryName='test_repository') response = client.describe_images(repositoryName='test_repository')
type(response['imageDetails']).should.be(list) type(response['imageDetails']).should.be(list)
len(response['imageDetails']).should.be(3) len(response['imageDetails']).should.be(4)
response['imageDetails'][0]['imageDigest'].should.contain("sha") response['imageDetails'][0]['imageDigest'].should.contain("sha")
response['imageDetails'][1]['imageDigest'].should.contain("sha") response['imageDetails'][1]['imageDigest'].should.contain("sha")
response['imageDetails'][2]['imageDigest'].should.contain("sha") response['imageDetails'][2]['imageDigest'].should.contain("sha")
response['imageDetails'][3]['imageDigest'].should.contain("sha")
response['imageDetails'][0]['registryId'].should.equal("012345678910") response['imageDetails'][0]['registryId'].should.equal("012345678910")
response['imageDetails'][1]['registryId'].should.equal("012345678910") response['imageDetails'][1]['registryId'].should.equal("012345678910")
response['imageDetails'][2]['registryId'].should.equal("012345678910") response['imageDetails'][2]['registryId'].should.equal("012345678910")
response['imageDetails'][3]['registryId'].should.equal("012345678910")
response['imageDetails'][0]['repositoryName'].should.equal("test_repository") response['imageDetails'][0]['repositoryName'].should.equal("test_repository")
response['imageDetails'][1]['repositoryName'].should.equal("test_repository") response['imageDetails'][1]['repositoryName'].should.equal("test_repository")
response['imageDetails'][2]['repositoryName'].should.equal("test_repository") response['imageDetails'][2]['repositoryName'].should.equal("test_repository")
response['imageDetails'][3]['repositoryName'].should.equal("test_repository")
len(response['imageDetails'][0]['imageTags']).should.be(1) response['imageDetails'][0].should_not.have.key('imageTags')
len(response['imageDetails'][1]['imageTags']).should.be(1) len(response['imageDetails'][1]['imageTags']).should.be(1)
len(response['imageDetails'][2]['imageTags']).should.be(1) len(response['imageDetails'][2]['imageTags']).should.be(1)
len(response['imageDetails'][3]['imageTags']).should.be(1)
image_tags = ['latest', 'v1', 'v2'] image_tags = ['latest', 'v1', 'v2']
set([response['imageDetails'][0]['imageTags'][0], set([response['imageDetails'][1]['imageTags'][0],
response['imageDetails'][1]['imageTags'][0], response['imageDetails'][2]['imageTags'][0],
response['imageDetails'][2]['imageTags'][0]]).should.equal(set(image_tags)) response['imageDetails'][3]['imageTags'][0]]).should.equal(set(image_tags))
response['imageDetails'][0]['imageSizeInBytes'].should.equal(52428800) response['imageDetails'][0]['imageSizeInBytes'].should.equal(52428800)
response['imageDetails'][1]['imageSizeInBytes'].should.equal(52428800) response['imageDetails'][1]['imageSizeInBytes'].should.equal(52428800)
response['imageDetails'][2]['imageSizeInBytes'].should.equal(52428800) response['imageDetails'][2]['imageSizeInBytes'].should.equal(52428800)
response['imageDetails'][3]['imageSizeInBytes'].should.equal(52428800)
@mock_ecr @mock_ecr