Skip to content

Commit e264a2f

Browse files
authored
fix(ecr): autoDeleteImages fails when repository is renamed (#26742)
This PR fixes the bug that ECRAutoDeleteImages fails on repo rename. The customResource depends on the role, and when the repository name changes, the role is updated to match the new repository instead of the old one, before customResource runs and the old repository is deleted. It was difficult to delete the old repo before the role update ran, so I changed the resource of the role to a wildcard. Closes #26711. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 8dc5190 commit e264a2f

File tree

7 files changed

+102
-67
lines changed

7 files changed

+102
-67
lines changed

packages/@aws-cdk-testing/framework-integ/test/aws-ecr/test/integ.repository-auto-delete-images.js.snapshot/aws-ecr-integ-stack.assets.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
}
1515
}
1616
},
17-
"32b456cdb8ff646c98c4580ff6d88bd51e84e33af74af927bb882158a53a0d21": {
17+
"adb4722adf5406a51ec51892647c61e7ac61ba38b845cd1163397018822e542e": {
1818
"source": {
1919
"path": "aws-ecr-integ-stack.template.json",
2020
"packaging": "file"
2121
},
2222
"destinations": {
2323
"current_account-current_region": {
2424
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
25-
"objectKey": "32b456cdb8ff646c98c4580ff6d88bd51e84e33af74af927bb882158a53a0d21.json",
25+
"objectKey": "adb4722adf5406a51ec51892647c61e7ac61ba38b845cd1163397018822e542e.json",
2626
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
2727
}
2828
}

packages/@aws-cdk-testing/framework-integ/test/aws-ecr/test/integ.repository-auto-delete-images.js.snapshot/aws-ecr-integ-stack.template.json

+23-4
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,31 @@
6969
],
7070
"Resource": [
7171
{
72-
"Fn::GetAtt": [
73-
"Repo02AC86CF",
74-
"Arn"
72+
"Fn::Join": [
73+
"",
74+
[
75+
"arn:",
76+
{
77+
"Ref": "AWS::Partition"
78+
},
79+
":ecr:",
80+
{
81+
"Ref": "AWS::Region"
82+
},
83+
":",
84+
{
85+
"Ref": "AWS::AccountId"
86+
},
87+
":repository/*"
88+
]
7589
]
7690
}
77-
]
91+
],
92+
"Condition": {
93+
"StringEquals": {
94+
"ecr:ResourceTag/aws-cdk:auto-delete-images": "true"
95+
}
96+
}
7897
}
7998
]
8099
}

packages/@aws-cdk-testing/framework-integ/test/aws-ecr/test/integ.repository-auto-delete-images.js.snapshot/manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"validateOnSynth": false,
1818
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
1919
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
20-
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/32b456cdb8ff646c98c4580ff6d88bd51e84e33af74af927bb882158a53a0d21.json",
20+
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/adb4722adf5406a51ec51892647c61e7ac61ba38b845cd1163397018822e542e.json",
2121
"requiresBootstrapStackVersion": 6,
2222
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
2323
"additionalDependencies": [

packages/@aws-cdk-testing/framework-integ/test/aws-ecr/test/integ.repository-auto-delete-images.js.snapshot/tree.json

+32-32
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
}
2929
},
3030
"constructInfo": {
31-
"fqn": "aws-cdk-lib.aws_ecr.CfnRepository",
32-
"version": "0.0.0"
31+
"fqn": "constructs.Construct",
32+
"version": "10.2.69"
3333
}
3434
},
3535
"AutoDeleteImagesCustomResource": {
@@ -40,20 +40,20 @@
4040
"id": "Default",
4141
"path": "aws-ecr-integ-stack/Repo/AutoDeleteImagesCustomResource/Default",
4242
"constructInfo": {
43-
"fqn": "aws-cdk-lib.CfnResource",
44-
"version": "0.0.0"
43+
"fqn": "constructs.Construct",
44+
"version": "10.2.69"
4545
}
4646
}
4747
},
4848
"constructInfo": {
49-
"fqn": "aws-cdk-lib.CustomResource",
50-
"version": "0.0.0"
49+
"fqn": "constructs.Construct",
50+
"version": "10.2.69"
5151
}
5252
}
5353
},
5454
"constructInfo": {
55-
"fqn": "aws-cdk-lib.aws_ecr.Repository",
56-
"version": "0.0.0"
55+
"fqn": "constructs.Construct",
56+
"version": "10.2.69"
5757
}
5858
},
5959
"Custom::ECRAutoDeleteImagesCustomResourceProvider": {
@@ -64,60 +64,60 @@
6464
"id": "Staging",
6565
"path": "aws-ecr-integ-stack/Custom::ECRAutoDeleteImagesCustomResourceProvider/Staging",
6666
"constructInfo": {
67-
"fqn": "aws-cdk-lib.AssetStaging",
68-
"version": "0.0.0"
67+
"fqn": "constructs.Construct",
68+
"version": "10.2.69"
6969
}
7070
},
7171
"Role": {
7272
"id": "Role",
7373
"path": "aws-ecr-integ-stack/Custom::ECRAutoDeleteImagesCustomResourceProvider/Role",
7474
"constructInfo": {
75-
"fqn": "aws-cdk-lib.CfnResource",
76-
"version": "0.0.0"
75+
"fqn": "constructs.Construct",
76+
"version": "10.2.69"
7777
}
7878
},
7979
"Handler": {
8080
"id": "Handler",
8181
"path": "aws-ecr-integ-stack/Custom::ECRAutoDeleteImagesCustomResourceProvider/Handler",
8282
"constructInfo": {
83-
"fqn": "aws-cdk-lib.CfnResource",
84-
"version": "0.0.0"
83+
"fqn": "constructs.Construct",
84+
"version": "10.2.69"
8585
}
8686
}
8787
},
8888
"constructInfo": {
89-
"fqn": "aws-cdk-lib.CustomResourceProvider",
90-
"version": "0.0.0"
89+
"fqn": "constructs.Construct",
90+
"version": "10.2.69"
9191
}
9292
},
9393
"RepositoryURI": {
9494
"id": "RepositoryURI",
9595
"path": "aws-ecr-integ-stack/RepositoryURI",
9696
"constructInfo": {
97-
"fqn": "aws-cdk-lib.CfnOutput",
98-
"version": "0.0.0"
97+
"fqn": "constructs.Construct",
98+
"version": "10.2.69"
9999
}
100100
},
101101
"BootstrapVersion": {
102102
"id": "BootstrapVersion",
103103
"path": "aws-ecr-integ-stack/BootstrapVersion",
104104
"constructInfo": {
105-
"fqn": "aws-cdk-lib.CfnParameter",
106-
"version": "0.0.0"
105+
"fqn": "constructs.Construct",
106+
"version": "10.2.69"
107107
}
108108
},
109109
"CheckBootstrapVersion": {
110110
"id": "CheckBootstrapVersion",
111111
"path": "aws-ecr-integ-stack/CheckBootstrapVersion",
112112
"constructInfo": {
113-
"fqn": "aws-cdk-lib.CfnRule",
114-
"version": "0.0.0"
113+
"fqn": "constructs.Construct",
114+
"version": "10.2.69"
115115
}
116116
}
117117
},
118118
"constructInfo": {
119-
"fqn": "aws-cdk-lib.Stack",
120-
"version": "0.0.0"
119+
"fqn": "constructs.Construct",
120+
"version": "10.2.69"
121121
}
122122
},
123123
"cdk-integ-auto-delete-images": {
@@ -144,22 +144,22 @@
144144
"id": "BootstrapVersion",
145145
"path": "cdk-integ-auto-delete-images/DefaultTest/DeployAssert/BootstrapVersion",
146146
"constructInfo": {
147-
"fqn": "aws-cdk-lib.CfnParameter",
148-
"version": "0.0.0"
147+
"fqn": "constructs.Construct",
148+
"version": "10.2.69"
149149
}
150150
},
151151
"CheckBootstrapVersion": {
152152
"id": "CheckBootstrapVersion",
153153
"path": "cdk-integ-auto-delete-images/DefaultTest/DeployAssert/CheckBootstrapVersion",
154154
"constructInfo": {
155-
"fqn": "aws-cdk-lib.CfnRule",
156-
"version": "0.0.0"
155+
"fqn": "constructs.Construct",
156+
"version": "10.2.69"
157157
}
158158
}
159159
},
160160
"constructInfo": {
161-
"fqn": "aws-cdk-lib.Stack",
162-
"version": "0.0.0"
161+
"fqn": "constructs.Construct",
162+
"version": "10.2.69"
163163
}
164164
}
165165
},
@@ -184,8 +184,8 @@
184184
}
185185
},
186186
"constructInfo": {
187-
"fqn": "aws-cdk-lib.App",
188-
"version": "0.0.0"
187+
"fqn": "constructs.Construct",
188+
"version": "10.2.69"
189189
}
190190
}
191191
}

packages/@aws-cdk/app-staging-synthesizer-alpha/test/integ.synth-default-resources.js.snapshot/StagingStack-default-resourcesmax-ACCOUNT-REGION.template.json

+23-10
Original file line numberDiff line numberDiff line change
@@ -636,18 +636,31 @@
636636
],
637637
"Resource": [
638638
{
639-
"Fn::GetAtt": [
640-
"defaultresourcesmaxecrasset13112F7F9",
641-
"Arn"
642-
]
643-
},
644-
{
645-
"Fn::GetAtt": [
646-
"defaultresourcesmaxecrasset2904B88A7",
647-
"Arn"
639+
"Fn::Join": [
640+
"",
641+
[
642+
"arn:",
643+
{
644+
"Ref": "AWS::Partition"
645+
},
646+
":ecr:",
647+
{
648+
"Ref": "AWS::Region"
649+
},
650+
":",
651+
{
652+
"Ref": "AWS::AccountId"
653+
},
654+
":repository/*"
655+
]
648656
]
649657
}
650-
]
658+
],
659+
"Condition": {
660+
"StringEquals": {
661+
"ecr:ResourceTag/aws-cdk:auto-delete-images": "true"
662+
}
663+
}
651664
}
652665
]
653666
}

packages/aws-cdk-lib/aws-ecr/lib/repository.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import {
2020
CustomResource,
2121
CustomResourceProvider,
2222
CustomResourceProviderRuntime,
23+
Aws,
2324
} from '../../core';
2425

2526
const AUTO_DELETE_IMAGES_RESOURCE_TYPE = 'Custom::ECRAutoDeleteImages';
2627
const AUTO_DELETE_IMAGES_TAG = 'aws-cdk:auto-delete-images';
27-
const REPO_ARN_SYMBOL = Symbol.for('@aws-cdk/aws-ecr.RepoArns');
2828

2929
/**
3030
* Represents an ECR repository.
@@ -867,12 +867,8 @@ export class Repository extends RepositoryBase {
867867
});
868868

869869
if (firstTime) {
870-
const repoArns = [this._resource.attrArn];
871-
(provider as any)[REPO_ARN_SYMBOL] = repoArns;
872-
873870
// Use a iam policy to allow the custom resource to list & delete
874871
// images in the repository and the ability to get all repositories to find the arn needed on delete.
875-
// We lazily produce a list of repositories associated with this custom resource provider.
876872
provider.addToRolePolicy({
877873
Effect: 'Allow',
878874
Action: [
@@ -881,10 +877,13 @@ export class Repository extends RepositoryBase {
881877
'ecr:ListImages',
882878
'ecr:ListTagsForResource',
883879
],
884-
Resource: Lazy.list({ produce: () => repoArns }),
880+
Resource: [`arn:${Aws.PARTITION}:ecr:${Stack.of(this).region}:${Stack.of(this).account}:repository/*`],
881+
Condition: {
882+
StringEquals: {
883+
['ecr:ResourceTag/' + AUTO_DELETE_IMAGES_TAG]: 'true',
884+
},
885+
},
885886
});
886-
} else {
887-
(provider as any)[REPO_ARN_SYMBOL].push(this._resource.attrArn);
888887
}
889888

890889
const customResource = new CustomResource(this, 'AutoDeleteImagesCustomResource', {

packages/aws-cdk-lib/aws-ecr/test/repository.test.ts

+14-10
Original file line numberDiff line numberDiff line change
@@ -1006,18 +1006,22 @@ describe('repository', () => {
10061006
],
10071007
Resource: [
10081008
{
1009-
'Fn::GetAtt': [
1010-
'Repo1DBD717D9',
1011-
'Arn',
1012-
],
1013-
},
1014-
{
1015-
'Fn::GetAtt': [
1016-
'Repo2730A8200',
1017-
'Arn',
1018-
],
1009+
'Fn::Join': ['', [
1010+
'arn:',
1011+
{ Ref: 'AWS::Partition' },
1012+
':ecr:',
1013+
{ Ref: 'AWS::Region' },
1014+
':',
1015+
{ Ref: 'AWS::AccountId' },
1016+
':repository/*',
1017+
]],
10191018
},
10201019
],
1020+
Condition: {
1021+
StringEquals: {
1022+
'ecr:ResourceTag/aws-cdk:auto-delete-images': 'true',
1023+
},
1024+
},
10211025
},
10221026
],
10231027
},

0 commit comments

Comments
 (0)