Skip to content

Commit 6f18348

Browse files
authoredAug 22, 2023
add EmptyOnDelete to support force delete on repository resource deletion (#51)
1 parent ac66e5b commit 6f18348

File tree

5 files changed

+60
-9
lines changed

5 files changed

+60
-9
lines changed
 

‎aws-ecr-repository/aws-ecr-repository.json

+10
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,16 @@
9595
"description": "If you use the KMS encryption type, specify the CMK to use for encryption. The alias, key ID, or full ARN of the CMK can be specified. The key must exist in the same Region as the repository. If no key is specified, the default AWS managed CMK for Amazon ECR will be used.",
9696
"minLength": 1,
9797
"maxLength": 2048
98+
},
99+
"EmptyOnDelete" : {
100+
"type": "boolean",
101+
"description": "If true, deleting the repository force deletes the contents of the repository. Without a force delete, you can only delete empty repositories."
98102
}
99103
},
100104
"properties": {
105+
"EmptyOnDelete" : {
106+
"$ref": "#/definitions/EmptyOnDelete"
107+
},
101108
"LifecyclePolicy": {
102109
"$ref": "#/definitions/LifecyclePolicy"
103110
},
@@ -156,6 +163,9 @@
156163
"/properties/Arn",
157164
"/properties/RepositoryUri"
158165
],
166+
"writeOnlyProperties": [
167+
"/properties/EmptyOnDelete"
168+
],
159169
"primaryIdentifier": [
160170
"/properties/RepositoryName"
161171
],

‎aws-ecr-repository/contract-tests-artifacts/inputs_1.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"CreateInputs": {
3-
"RepositoryName": "my-testing-inputs-repository-test",
3+
"RepositoryName": "contract-test-inputs-repository",
44
"Tags": [
55
{
66
"Key": "Env",
@@ -30,7 +30,8 @@
3030
},
3131
"LifecyclePolicy": {
3232
"LifecyclePolicyText": "{\"rules\":[{\"rulePriority\":1,\"description\":\"Keep only one untagged image, expire all others\",\"selection\":{\"tagStatus\":\"untagged\",\"countType\":\"imageCountMoreThan\",\"countNumber\":1},\"action\":{\"type\":\"expire\"}}]}"
33-
}
33+
},
34+
"EmptyOnDelete": false
3435
},
3536

3637
"PatchInputs": [

‎aws-ecr-repository/docs/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ To declare this entity in your AWS CloudFormation template, use the following sy
1212
{
1313
"Type" : "AWS::ECR::Repository",
1414
"Properties" : {
15+
"<a href="#emptyondelete" title="EmptyOnDelete">EmptyOnDelete</a>" : <i>Boolean</i>,
1516
"<a href="#lifecyclepolicy" title="LifecyclePolicy">LifecyclePolicy</a>" : <i><a href="lifecyclepolicy.md">LifecyclePolicy</a></i>,
1617
"<a href="#repositoryname" title="RepositoryName">RepositoryName</a>" : <i>String</i>,
1718
"<a href="#repositorypolicytext" title="RepositoryPolicyText">RepositoryPolicyText</a>" : <i>Map, String</i>,
@@ -28,6 +29,7 @@ To declare this entity in your AWS CloudFormation template, use the following sy
2829
<pre>
2930
Type: AWS::ECR::Repository
3031
Properties:
32+
<a href="#emptyondelete" title="EmptyOnDelete">EmptyOnDelete</a>: <i>Boolean</i>
3133
<a href="#lifecyclepolicy" title="LifecyclePolicy">LifecyclePolicy</a>: <i><a href="lifecyclepolicy.md">LifecyclePolicy</a></i>
3234
<a href="#repositoryname" title="RepositoryName">RepositoryName</a>: <i>String</i>
3335
<a href="#repositorypolicytext" title="RepositoryPolicyText">RepositoryPolicyText</a>: <i>Map, String</i>
@@ -40,6 +42,16 @@ Properties:
4042

4143
## Properties
4244

45+
#### EmptyOnDelete
46+
47+
If true, deleting the repository force deletes the contents of the repository. Without a force delete, you can only delete empty repositories.
48+
49+
_Required_: No
50+
51+
_Type_: Boolean
52+
53+
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
54+
4355
#### LifecyclePolicy
4456

4557
The LifecyclePolicy property type specifies a lifecycle policy. For information about lifecycle policy syntax, see https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html

‎aws-ecr-repository/src/main/java/software/amazon/ecr/repository/Translator.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class Translator {
3232
public static final ObjectMapper MAPPER = new ObjectMapper();
3333

3434
static CreateRepositoryRequest createRepositoryRequest(final ResourceModel model,
35-
final Map<String, String> tags) {
35+
final Map<String, String> tags) {
3636

3737
CreateRepositoryRequest.Builder createRepositoryRequest = CreateRepositoryRequest.builder()
3838
.repositoryName(model.getRepositoryName())
@@ -98,9 +98,14 @@ static DeleteRepositoryPolicyRequest deleteRepositoryPolicyRequest(final Resourc
9898
}
9999

100100
static DeleteRepositoryRequest deleteRepositoryRequest(final ResourceModel model) {
101-
return DeleteRepositoryRequest.builder()
102-
.repositoryName(model.getRepositoryName())
103-
.build();
101+
DeleteRepositoryRequest.Builder requestBuilder = DeleteRepositoryRequest.builder()
102+
.repositoryName(model.getRepositoryName());
103+
104+
if (model.getEmptyOnDelete() != null) {
105+
requestBuilder.force(model.getEmptyOnDelete());
106+
}
107+
108+
return requestBuilder.build();
104109
}
105110

106111
static TagResourceRequest tagResourceRequest(final List<Tag> tags, final String arn) {
@@ -161,7 +166,7 @@ static GetLifecyclePolicyRequest getLifecyclePolicyRequest(final String reposito
161166
}
162167

163168
static PutImageTagMutabilityRequest putImageTagMutabilityRequest(final ResourceModel model,
164-
final String registryId) {
169+
final String registryId) {
165170
return PutImageTagMutabilityRequest.builder()
166171
.registryId(registryId)
167172
.repositoryName(model.getRepositoryName())
@@ -170,7 +175,7 @@ static PutImageTagMutabilityRequest putImageTagMutabilityRequest(final ResourceM
170175
}
171176

172177
static PutImageScanningConfigurationRequest putImageScanningConfigurationRequest(final ResourceModel model,
173-
final String registryId) {
178+
final String registryId) {
174179
ImageScanningConfiguration sdkImageScanningConfiguration = ImageScanningConfiguration.builder()
175180
.scanOnPush(model.getImageScanningConfiguration().getScanOnPush()).build();
176181

‎aws-ecr-repository/src/test/java/software/amazon/ecr/repository/DeleteHandlerTest.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void setup() {
4949
@Test
5050
void handleRequest_SimpleSuccess() {
5151
final ProgressEvent<ResourceModel, CallbackContext> response
52-
= handler.handleRequest(proxy, request, new CallbackContext(), proxyEcrClient, logger);
52+
= handler.handleRequest(proxy, request, new CallbackContext(), proxyEcrClient, logger);
5353

5454
assertThat(response).isNotNull();
5555
assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
@@ -70,4 +70,27 @@ void handleRequest_RepoNotFound() {
7070
assertThatThrownBy(() -> handler.handleRequest(proxy, request, context, proxyEcrClient, logger))
7171
.isInstanceOf(ResourceNotFoundException.class);
7272
}
73+
74+
@Test
75+
void handleRequest_SuccessWithForceDelete() {
76+
model = ResourceModel.builder()
77+
.repositoryName("repo")
78+
.emptyOnDelete(true)
79+
.build();
80+
81+
request = ResourceHandlerRequest.<ResourceModel>builder()
82+
.desiredResourceState(model)
83+
.build();
84+
85+
final ProgressEvent<ResourceModel, CallbackContext> response
86+
= handler.handleRequest(proxy, request, new CallbackContext(), proxyEcrClient, logger);
87+
88+
assertThat(response).isNotNull();
89+
assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS);
90+
assertThat(response.getCallbackContext()).isNull();
91+
assertThat(response.getCallbackDelaySeconds()).isZero();
92+
assertThat(response.getResourceModels()).isNull();
93+
assertThat(response.getMessage()).isNull();
94+
assertThat(response.getErrorCode()).isNull();
95+
}
7396
}

0 commit comments

Comments
 (0)