Skip to content

Commit 2e26056

Browse files
committed
Add support to download hook target data for stack-level hooks
Stack level hooks will not be provided with invocation payload information, unlike resource level hooks. Instead, Hooks Service will pass in an S3 presigned URL that points to a file that contains the stack-level invocation payload. The base hook handler (before it reaches the customer's handler code), will use that URL to download the data and set it on the target model that is passed to the customer's handler.
1 parent dd20afb commit 2e26056

File tree

4 files changed

+27
-20
lines changed

4 files changed

+27
-20
lines changed

src/main/java/software/amazon/cloudformation/HookAbstractWrapper.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.amazonaws.AmazonServiceException;
1818
import com.amazonaws.retry.RetryUtils;
1919
import com.fasterxml.jackson.core.type.TypeReference;
20+
import com.google.common.annotations.VisibleForTesting;
2021
import java.io.ByteArrayOutputStream;
2122
import java.io.IOException;
2223
import java.io.InputStream;
@@ -27,8 +28,6 @@
2728
import java.util.Collections;
2829
import java.util.Date;
2930
import java.util.Map;
30-
31-
import com.google.common.annotations.VisibleForTesting;
3231
import org.apache.commons.io.FileUtils;
3332
import org.apache.commons.io.IOUtils;
3433
import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -389,8 +388,7 @@ public Map<String, Object> retrieveHookInvocationPayloadFromS3(final String s3Pr
389388

390389
try {
391390
URL presignedUrl = new URL(s3PresignedUrl);
392-
SdkHttpRequest httpRequest = SdkHttpRequest.builder().method(SdkHttpMethod.GET).uri(presignedUrl.toURI())
393-
.build();
391+
SdkHttpRequest httpRequest = SdkHttpRequest.builder().method(SdkHttpMethod.GET).uri(presignedUrl.toURI()).build();
394392

395393
HttpExecuteRequest executeRequest = HttpExecuteRequest.builder().request(httpRequest).build();
396394

src/main/java/software/amazon/cloudformation/proxy/hook/targetmodel/ChangedResource.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
package software.amazon.cloudformation.proxy.hook.targetmodel;
1616

1717
import com.fasterxml.jackson.annotation.JsonProperty;
18-
import lombok.*;
18+
import lombok.AllArgsConstructor;
19+
import lombok.Builder;
20+
import lombok.Data;
21+
import lombok.NoArgsConstructor;
1922

2023
@Data
2124
@Builder

src/main/java/software/amazon/cloudformation/proxy/hook/targetmodel/StackHookTargetModel.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@
1919
import com.fasterxml.jackson.annotation.JsonProperty;
2020
import com.fasterxml.jackson.core.type.TypeReference;
2121
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
22+
import lombok.EqualsAndHashCode;
23+
import lombok.Getter;
24+
import lombok.NoArgsConstructor;
25+
import lombok.ToString;
26+
2227
import java.util.List;
23-
import lombok.*;
2428

2529
@EqualsAndHashCode(callSuper = false)
2630
@Getter
@@ -33,13 +37,13 @@ public class StackHookTargetModel extends HookTargetModel {
3337
};
3438

3539
@JsonProperty("Template")
36-
private String template;
40+
private Object template;
3741

3842
@JsonProperty("PreviousTemplate")
39-
private String previousTemplate;
43+
private Object previousTemplate;
4044

4145
@JsonProperty("ResolvedTemplate")
42-
private String resolvedTemplate;
46+
private Object resolvedTemplate;
4347

4448
@JsonProperty("ChangedResources")
4549
private List<ChangedResource> changedResources;

src/test/java/software/amazon/cloudformation/HookLambdaWrapperTest.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.amazonaws.services.lambda.runtime.Context;
2424
import com.amazonaws.services.lambda.runtime.LambdaLogger;
2525
import com.fasterxml.jackson.core.type.TypeReference;
26+
import com.google.common.collect.ImmutableList;
27+
import com.google.common.collect.ImmutableMap;
2628
import java.io.ByteArrayOutputStream;
2729
import java.io.File;
2830
import java.io.FileInputStream;
@@ -33,9 +35,6 @@
3335
import java.util.Collections;
3436
import java.util.List;
3537
import java.util.Map;
36-
37-
import com.google.common.collect.ImmutableList;
38-
import com.google.common.collect.ImmutableMap;
3938
import org.junit.jupiter.api.Assertions;
4039
import org.junit.jupiter.api.BeforeEach;
4140
import org.junit.jupiter.api.Test;
@@ -408,16 +407,19 @@ public void testIsHookInvocationPayloadRemote() {
408407
Assertions.assertThrows(TerminalException.class, () -> wrapper.isHookInvocationPayloadRemote(requestData));
409408
});
410409

411-
Assertions.assertThrows(TerminalException.class, () -> wrapper.isHookInvocationPayloadRemote(null));
410+
Assertions.assertThrows(TerminalException.class, () -> wrapper.isHookInvocationPayloadRemote(null));
412411

413-
HookRequestData bothFieldsPopulated = HookRequestData.builder().targetModel(ImmutableMap.of("foo", "bar")).payload("http://s3PresignedUrl").build();
414-
HookRequestData onlyTargetModelPopulated = HookRequestData.builder().targetModel(ImmutableMap.of("foo", "bar")).payload(null).build();
415-
HookRequestData onlyPayloadPopulated = HookRequestData.builder().targetModel(Collections.emptyMap()).payload("http://s3PresignedUrl").build();
412+
HookRequestData bothFieldsPopulated = HookRequestData.builder().targetModel(ImmutableMap.of("foo", "bar"))
413+
.payload("http://s3PresignedUrl").build();
414+
HookRequestData onlyTargetModelPopulated = HookRequestData.builder().targetModel(ImmutableMap.of("foo", "bar"))
415+
.payload(null).build();
416+
HookRequestData onlyPayloadPopulated = HookRequestData.builder().targetModel(Collections.emptyMap())
417+
.payload("http://s3PresignedUrl").build();
416418

417-
Assertions.assertFalse(wrapper.isHookInvocationPayloadRemote(bothFieldsPopulated));
418-
Assertions.assertFalse(wrapper.isHookInvocationPayloadRemote(onlyTargetModelPopulated));
419-
Assertions.assertTrue(wrapper.isHookInvocationPayloadRemote(onlyPayloadPopulated));
420-
}
419+
Assertions.assertFalse(wrapper.isHookInvocationPayloadRemote(bothFieldsPopulated));
420+
Assertions.assertFalse(wrapper.isHookInvocationPayloadRemote(onlyTargetModelPopulated));
421+
Assertions.assertTrue(wrapper.isHookInvocationPayloadRemote(onlyPayloadPopulated));
422+
}
421423

422424
private final String expectedStringWhenStrictDeserializingWithExtraneousFields = "Unrecognized field \"targetName\" (class software.amazon.cloudformation.proxy.hook.HookInvocationRequest), not marked as ignorable (10 known properties: \"requestContext\", \"stackId\", \"clientRequestToken\", \"hookModel\", \"hookTypeName\", \"requestData\", \"actionInvocationPoint\", \"awsAccountId\", \"changeSetId\", \"hookTypeVersion\"])\n"
423425
+ " at [Source: (String)\"{\n" + " \"clientRequestToken\": \"123456\",\n" + " \"awsAccountId\": \"123456789012\",\n"

0 commit comments

Comments
 (0)