From 3e2adbcc3af002ad41d2d2ac6c871a76d52f1085 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Fri, 25 Mar 2022 14:11:54 -0100 Subject: [PATCH] ECR - Fix bug in batch_delete where images could not be deleted (#4969) --- moto/ecr/models.py | 30 ++++++++++++++-------------- tests/test_ecr/test_ecr_boto3.py | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/moto/ecr/models.py b/moto/ecr/models.py index a303f1c19..3d83fea77 100644 --- a/moto/ecr/models.py +++ b/moto/ecr/models.py @@ -631,24 +631,24 @@ class ECRBackend(BaseBackend): else: repository.images.remove(image) - if not image_found: - failure_response = { - "imageId": {}, - "failureCode": "ImageNotFound", - "failureReason": "Requested image not found", - } + if not image_found: + failure_response = { + "imageId": {}, + "failureCode": "ImageNotFound", + "failureReason": "Requested image not found", + } - if "imageDigest" in image_id: - failure_response["imageId"]["imageDigest"] = image_id.get( - "imageDigest", "null" - ) + if "imageDigest" in image_id: + failure_response["imageId"]["imageDigest"] = image_id.get( + "imageDigest", "null" + ) - if "imageTag" in image_id: - failure_response["imageId"]["imageTag"] = image_id.get( - "imageTag", "null" - ) + if "imageTag" in image_id: + failure_response["imageId"]["imageTag"] = image_id.get( + "imageTag", "null" + ) - response["failures"].append(failure_response) + response["failures"].append(failure_response) return response diff --git a/tests/test_ecr/test_ecr_boto3.py b/tests/test_ecr/test_ecr_boto3.py index 3f405129a..aaa49d6d6 100644 --- a/tests/test_ecr/test_ecr_boto3.py +++ b/tests/test_ecr/test_ecr_boto3.py @@ -1249,6 +1249,40 @@ def test_batch_delete_image_with_mismatched_digest_and_tag(): ) +@mock_ecr +def test_delete_batch_image_with_multiple_images(): + client = boto3.client("ecr", region_name="us-east-1") + repo_name = "test-repo" + client.create_repository(repositoryName=repo_name) + + # Populate mock repo with images + for i in range(10): + client.put_image( + repositoryName=repo_name, imageManifest=f"manifest{i}", imageTag=f"tag{i}" + ) + + # Pull down image digests for each image in the mock repo + repo_images = client.describe_images(repositoryName=repo_name)["imageDetails"] + image_digests = [{"imageDigest": image["imageDigest"]} for image in repo_images] + + # Pick a couple of images to delete + images_to_delete = image_digests[5:7] + + # Delete the images + response = client.batch_delete_image( + repositoryName=repo_name, imageIds=images_to_delete + ) + response["imageIds"].should.have.length_of(2) + response["failures"].should.equal([]) + + # Verify other images still exist + repo_images = client.describe_images(repositoryName=repo_name)["imageDetails"] + image_tags = [img["imageTags"][0] for img in repo_images] + image_tags.should.equal( + ["tag0", "tag1", "tag2", "tag3", "tag4", "tag7", "tag8", "tag9"] + ) + + @mock_ecr def test_list_tags_for_resource(): # given