From 70537a3f3e2333501315ee4740ca13fbd8f25ddb Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Wed, 4 Dec 2019 14:13:05 -0800 Subject: [PATCH] feat: Format Java Code (#199) Formats existing java examples using google-java-format. Adds 'style and formatting' section to CONTRIBUTING.md regarding java code formatting. Fixes #198 --- CONTRIBUTING.md | 10 + .../amazon/awscdk/examples/HelloJavaApp.java | 10 +- .../awscdk/examples/HelloJavaStack.java | 74 ++--- .../amazon/awscdk/examples/SinkQueue.java | 122 ++++---- .../awscdk/examples/SinkQueueProps.java | 97 +++--- .../amazon/awscdk/examples/SinkQueueTest.java | 211 +++++++------ .../amazon/awscdk/examples/LambdaCronApp.java | 10 +- .../awscdk/examples/LambdaCronStack.java | 44 ++- .../awscdk/examples/LambdaCronStackTest.java | 127 ++++---- .../amazon/awscdk/examples/TestUtils.java | 41 +-- .../awscdk/examples/MyWidgetServiceApp.java | 14 +- .../awscdk/examples/MyWidgetServiceStack.java | 83 +++-- .../awscdk/examples/MyWidgetServiceTest.java | 60 ++-- .../amazon/awscdk/examples/TestUtils.java | 41 +-- .../awscdk/examples/ResourceOverridesApp.java | 10 +- .../examples/ResourceOverridesStack.java | 296 +++++++++--------- .../examples/ResourceOverridesStackTest.java | 55 ++-- 17 files changed, 664 insertions(+), 641 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f4e4510249..41b9378b34 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,6 +106,16 @@ Create a directory with a name that is descriptive of the resource type or workf } ``` +## Style and Formatting + +We strive to keep examples consistent in style and formatting. This hopefully makes navigating examples easier for users. Since the examples span different languages, we try to keep example code as idiomatic as possible. + +New guidelines for various languages will be added as we define them. + +### Java +1. Use builders wherever possible. Some classes are unable to have builders generated in JSII but for those that do, prefer them over constructing by hand. +2. Format your code with [google-java-format](https://github.com/google/google-java-format). If you're using visual studio code, [see this comment](https://github.com/redhat-developer/vscode-java/issues/419#issuecomment-360820321) to get a formatter task setup. + ## Finding contributions to work on Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/aws-cdk-examples/labels/help%20wanted) issues is a great place to start. diff --git a/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaApp.java b/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaApp.java index 85c5cbd642..e1c9217166 100644 --- a/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaApp.java +++ b/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaApp.java @@ -3,11 +3,11 @@ import software.amazon.awscdk.core.App; public class HelloJavaApp { - public static void main(final String[] args) { - App app = new App(); + public static void main(final String[] args) { + App app = new App(); - new HelloJavaStack(app, "hello-cdk"); + new HelloJavaStack(app, "hello-cdk"); - app.synth(); - } + app.synth(); + } } diff --git a/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaStack.java b/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaStack.java index b63fab6494..cf425f1fc0 100644 --- a/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaStack.java +++ b/java/hello-world/src/main/java/software/amazon/awscdk/examples/HelloJavaStack.java @@ -1,58 +1,58 @@ package software.amazon.awscdk.examples; -import software.amazon.awscdk.core.Stack; +import java.util.Collections; +import java.util.List; import software.amazon.awscdk.core.Construct; +import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; import software.amazon.awscdk.services.ec2.AmazonLinuxImage; import software.amazon.awscdk.services.ec2.InstanceType; import software.amazon.awscdk.services.ec2.Vpc; import software.amazon.awscdk.services.sns.Topic; -import java.util.Collections; -import java.util.List; - -/** - * Hello, CDK for Java! - */ +/** Hello, CDK for Java! */ class HelloJavaStack extends Stack { - public HelloJavaStack(final Construct parent, final String name) { - super(parent, name); - - Vpc vpc = Vpc.Builder.create(this, "VPC").build(); + public HelloJavaStack(final Construct parent, final String name) { + super(parent, name); - MyAutoScalingGroupProps autoScalingGroupProps = new MyAutoScalingGroupProps(); - autoScalingGroupProps.vpc = vpc; + Vpc vpc = Vpc.Builder.create(this, "VPC").build(); - int topicCount = 5; + MyAutoScalingGroupProps autoScalingGroupProps = new MyAutoScalingGroupProps(); + autoScalingGroupProps.vpc = vpc; - SinkQueue sinkQueue = new SinkQueue(this, "MySinkQueue", SinkQueueProps.builder().withRequiredTopicCount(5).build()); + int topicCount = 5; - for (int i = 0; i < topicCount; ++i) { - sinkQueue.subscribe(new Topic(this, "Topic" + (i+1))); - } + SinkQueue sinkQueue = + new SinkQueue( + this, "MySinkQueue", SinkQueueProps.builder().withRequiredTopicCount(5).build()); - new MyAutoScalingGroup(this, "MyAutoScalingGroup", autoScalingGroupProps); + for (int i = 0; i < topicCount; ++i) { + sinkQueue.subscribe(new Topic(this, "Topic" + (i + 1))); } - static class MyAutoScalingGroupProps { - public Vpc vpc; + new MyAutoScalingGroup(this, "MyAutoScalingGroup", autoScalingGroupProps); + } + + static class MyAutoScalingGroupProps { + public Vpc vpc; + } + + static class MyAutoScalingGroup extends Construct { + MyAutoScalingGroup( + final Construct parent, final String name, final MyAutoScalingGroupProps props) { + super(parent, name); + + AutoScalingGroup.Builder.create(this, "Compute") + .instanceType(new InstanceType("t2.micro")) + .machineImage(new AmazonLinuxImage()) + .vpc(props.vpc) + .build(); } - static class MyAutoScalingGroup extends Construct { - MyAutoScalingGroup(final Construct parent, final String name, final MyAutoScalingGroupProps props) { - super(parent, name); - - AutoScalingGroup.Builder.create(this, "Compute") - .instanceType(new InstanceType("t2.micro")) - .machineImage(new AmazonLinuxImage()) - .vpc(props.vpc) - .build(); - } - - @Override - public List validate() { - System.err.println("Validating MyAutoScalingGroup..."); - return Collections.emptyList(); - } + @Override + public List validate() { + System.err.println("Validating MyAutoScalingGroup..."); + return Collections.emptyList(); } + } } diff --git a/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueue.java b/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueue.java index b7c597e7b4..1e17d10029 100644 --- a/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueue.java +++ b/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueue.java @@ -1,81 +1,83 @@ package software.amazon.awscdk.examples; +import java.util.Arrays; +import java.util.List; import software.amazon.awscdk.core.Construct; import software.amazon.awscdk.services.sns.Topic; import software.amazon.awscdk.services.sns.subscriptions.SqsSubscription; import software.amazon.awscdk.services.sqs.Queue; import software.amazon.awscdk.services.sqs.QueueProps; -import java.util.Arrays; -import java.util.List; - -/** - * A sink queue is a queue aggregates messages published to any number of SNS topics. - */ +/** A sink queue is a queue aggregates messages published to any number of SNS topics. */ public class SinkQueue extends Construct { - private final Queue queue; - private final int expectedTopicCount; + private final Queue queue; + private final int expectedTopicCount; - private int actualTopicCount = 0; + private int actualTopicCount = 0; - /** - * Defines a SinkQueue. - * - * @param parent Parent construct - * @param name Logical name - * @param props Props - */ - public SinkQueue(final Construct parent, final String name, SinkQueueProps props) { - super(parent, name); + /** + * Defines a SinkQueue. + * + * @param parent Parent construct + * @param name Logical name + * @param props Props + */ + public SinkQueue(final Construct parent, final String name, SinkQueueProps props) { + super(parent, name); - // ensure props is non-null - props = props != null ? props : SinkQueueProps.builder().build(); + // ensure props is non-null + props = props != null ? props : SinkQueueProps.builder().build(); - // defaults - QueueProps queueProps = props.getQueueProps(); - this.expectedTopicCount = props.getRequiredTopicCount() != null ? props.getRequiredTopicCount().intValue() : 0; + // defaults + QueueProps queueProps = props.getQueueProps(); + this.expectedTopicCount = + props.getRequiredTopicCount() != null ? props.getRequiredTopicCount().intValue() : 0; - // WORKAROUND: https://github.com/awslabs/aws-cdk/issues/157 - if (queueProps == null) { - queueProps = QueueProps.builder().build(); - } - - this.queue = new Queue(this, "Resource", queueProps); + // WORKAROUND: https://github.com/awslabs/aws-cdk/issues/157 + if (queueProps == null) { + queueProps = QueueProps.builder().build(); } - /** - * Defines a SinkQueue with default props. - * @param parent Parent construct - * @param name Logical name - */ - public SinkQueue(final Construct parent, final String name) { - this(parent, name, null); - } + this.queue = new Queue(this, "Resource", queueProps); + } - /** - * Subscribes this queue to receive messages published to the specified topics. - * - * @param topics The topics to subscribe to - */ - public void subscribe(final Topic... topics) { - for (Topic topic: topics) { - if (expectedTopicCount != 0 && actualTopicCount >= expectedTopicCount) { - throw new RuntimeException("Cannot add more topics to the sink. Maximum topics is configured to " + this.expectedTopicCount); - } - topic.addSubscription(new SqsSubscription(this.queue)); - actualTopicCount++; - } - } + /** + * Defines a SinkQueue with default props. + * + * @param parent Parent construct + * @param name Logical name + */ + public SinkQueue(final Construct parent, final String name) { + this(parent, name, null); + } - @Override - public List validate() { - if (actualTopicCount < expectedTopicCount) { - return Arrays.asList( - "There are not enough subscribers to the sink. Expecting " + - this.expectedTopicCount + - ", actual is " + this.actualTopicCount); - } + /** + * Subscribes this queue to receive messages published to the specified topics. + * + * @param topics The topics to subscribe to + */ + public void subscribe(final Topic... topics) { + for (Topic topic : topics) { + if (expectedTopicCount != 0 && actualTopicCount >= expectedTopicCount) { + throw new RuntimeException( + "Cannot add more topics to the sink. Maximum topics is configured to " + + this.expectedTopicCount); + } + topic.addSubscription(new SqsSubscription(this.queue)); + actualTopicCount++; + } + } - return super.validate(); + @Override + public List validate() { + if (actualTopicCount < expectedTopicCount) { + return Arrays.asList( + "There are not enough subscribers to the sink. Expecting " + + this.expectedTopicCount + + ", actual is " + + this.actualTopicCount); } + + return super.validate(); + } } diff --git a/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueueProps.java b/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueueProps.java index 573ce4ace4..bacc665a15 100644 --- a/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueueProps.java +++ b/java/hello-world/src/main/java/software/amazon/awscdk/examples/SinkQueueProps.java @@ -2,66 +2,61 @@ import software.amazon.awscdk.services.sqs.QueueProps; -/** - * Props for {@link SinkQueue}. - */ +/** Props for {@link SinkQueue}. */ public class SinkQueueProps { + private QueueProps queueProps; + private Number requiredTopicCount; + + /** @return A builder for {@link SinkQueueProps}. */ + public static SinkQueuePropsBuilder builder() { + return new SinkQueuePropsBuilder(); + } + + /** + * The exact number of topics required to subscribe to the queue. You must call {@link + * SinkQueue::subscribe} to subscribe topics to this queue. + * + * @default 0 + */ + public Number getRequiredTopicCount() { + return requiredTopicCount; + } + + /** + * Props for the queue itself + * + * @default See {@link software.amazon.awscdk.sqs.Queue} defaults + */ + public QueueProps getQueueProps() { + return queueProps; + } + + /** Builder for {@link SinkQueue}. */ + public static final class SinkQueuePropsBuilder { private QueueProps queueProps; private Number requiredTopicCount; - /** - * @return A builder for {@link SinkQueueProps}. - */ - public static SinkQueuePropsBuilder builder() { - return new SinkQueuePropsBuilder(); - } + private SinkQueuePropsBuilder() {} - /** - * The exact number of topics required to subscribe to the queue. - * You must call {@link SinkQueue::subscribe} to subscribe topics to this queue. - * @default 0 - */ - public Number getRequiredTopicCount() { - return requiredTopicCount; + public static SinkQueuePropsBuilder aSinkQueueProps() { + return new SinkQueuePropsBuilder(); } - /** - * Props for the queue itself - * @default See {@link software.amazon.awscdk.sqs.Queue} defaults - */ - public QueueProps getQueueProps() { - return queueProps; + public SinkQueuePropsBuilder withQueueProps(QueueProps queueProps) { + this.queueProps = queueProps; + return this; } - /** - * Builder for {@link SinkQueue}. - */ - public static final class SinkQueuePropsBuilder { - private QueueProps queueProps; - private Number requiredTopicCount; - - private SinkQueuePropsBuilder() { - } - - public static SinkQueuePropsBuilder aSinkQueueProps() { - return new SinkQueuePropsBuilder(); - } - - public SinkQueuePropsBuilder withQueueProps(QueueProps queueProps) { - this.queueProps = queueProps; - return this; - } - - public SinkQueuePropsBuilder withRequiredTopicCount(Number requiredTopicCount) { - this.requiredTopicCount = requiredTopicCount; - return this; - } + public SinkQueuePropsBuilder withRequiredTopicCount(Number requiredTopicCount) { + this.requiredTopicCount = requiredTopicCount; + return this; + } - public SinkQueueProps build() { - SinkQueueProps sinkQueueProps = new SinkQueueProps(); - sinkQueueProps.requiredTopicCount = this.requiredTopicCount; - sinkQueueProps.queueProps = this.queueProps; - return sinkQueueProps; - } + public SinkQueueProps build() { + SinkQueueProps sinkQueueProps = new SinkQueueProps(); + sinkQueueProps.requiredTopicCount = this.requiredTopicCount; + sinkQueueProps.queueProps = this.queueProps; + return sinkQueueProps; } + } } diff --git a/java/hello-world/src/test/java/software/amazon/awscdk/examples/SinkQueueTest.java b/java/hello-world/src/test/java/software/amazon/awscdk/examples/SinkQueueTest.java index 08eff3bcdb..90dcf1d723 100644 --- a/java/hello-world/src/test/java/software/amazon/awscdk/examples/SinkQueueTest.java +++ b/java/hello-world/src/test/java/software/amazon/awscdk/examples/SinkQueueTest.java @@ -1,5 +1,13 @@ package software.amazon.awscdk.examples; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.net.URL; +import org.junit.Test; import software.amazon.awscdk.core.App; import software.amazon.awscdk.core.ConstructNode; import software.amazon.awscdk.core.Duration; @@ -8,120 +16,125 @@ import software.amazon.awscdk.cxapi.CloudFormationStackArtifact; import software.amazon.awscdk.services.sns.Topic; import software.amazon.awscdk.services.sqs.QueueProps; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.jsii.JsiiException; -import org.junit.Test; - -import java.io.IOException; -import java.net.URL; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; public class SinkQueueTest { - private static ObjectMapper JSON = new ObjectMapper(); - - /** Defines a queue sink with default props */ - @Test public void testDefaults() throws IOException { - Stack stack = new Stack(); - new SinkQueue(stack, "MySinkQueue"); - assertTemplate(stack, "{\"Resources\":{\"MySinkQueueEFCD79C2\":{\"Type\":\"AWS::SQS::Queue\"}}}"); - } - - /** Defines a sink with custom queue props */ - @Test public void testQueueProps() throws IOException { - Stack stack = new Stack(); - new SinkQueue(stack, "MySinkQueue", SinkQueueProps.builder() - .withQueueProps(QueueProps.builder() - .visibilityTimeout(Duration.seconds(500)) - .build()) - .build()); - assertTemplate(stack, "{\n" + - " \"Resources\" : {\n" + - " \"MySinkQueueEFCD79C2\" : {\n" + - " \"Type\" : \"AWS::SQS::Queue\",\n" + - " \"Properties\" : {\n" + - " \"VisibilityTimeout\" : 500\n" + - " }\n" + - " }\n" + - " }\n" + - "}"); + private static ObjectMapper JSON = new ObjectMapper(); + + /** Defines a queue sink with default props */ + @Test + public void testDefaults() throws IOException { + Stack stack = new Stack(); + new SinkQueue(stack, "MySinkQueue"); + assertTemplate( + stack, "{\"Resources\":{\"MySinkQueueEFCD79C2\":{\"Type\":\"AWS::SQS::Queue\"}}}"); + } + + /** Defines a sink with custom queue props */ + @Test + public void testQueueProps() throws IOException { + Stack stack = new Stack(); + new SinkQueue( + stack, + "MySinkQueue", + SinkQueueProps.builder() + .withQueueProps(QueueProps.builder().visibilityTimeout(Duration.seconds(500)).build()) + .build()); + assertTemplate( + stack, + "{\n" + + " \"Resources\" : {\n" + + " \"MySinkQueueEFCD79C2\" : {\n" + + " \"Type\" : \"AWS::SQS::Queue\",\n" + + " \"Properties\" : {\n" + + " \"VisibilityTimeout\" : 500\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); + } + + /** Calls "subscribe" to add topics to the sink */ + @Test + public void testSubscribeTopics() throws IOException { + Stack stack = new Stack(); + + SinkQueue sink = new SinkQueue(stack, "MySinkQueue"); + + // add three topics in two calls to "subscribe" + sink.subscribe(new Topic(stack, "Topic1"), new Topic(stack, "Topic2")); + sink.subscribe(new Topic(stack, "Topic3")); + + assertTemplate(stack, getClass().getResource("testSubscribeTopics.expected.json")); + } + + /** Verifies that if we exceed the number of allows topics, an exception is thrown */ + @Test + public void failsIfExceedMaxTopic() { + Stack stack = new Stack(); + + SinkQueue sink = + new SinkQueue( + stack, "MySinkQueue", SinkQueueProps.builder().withRequiredTopicCount(3).build()); + + sink.subscribe(new Topic(stack, "Topic1")); + sink.subscribe(new Topic(stack, "Topic2")); + sink.subscribe(new Topic(stack, "Topic3")); + + boolean thrown = false; + try { + sink.subscribe(new Topic(stack, "Topic4")); + } catch (RuntimeException e) { + thrown = true; } + assertTrue(thrown); + } - /** Calls "subscribe" to add topics to the sink */ - @Test public void testSubscribeTopics() throws IOException { - Stack stack = new Stack(); - - SinkQueue sink = new SinkQueue(stack, "MySinkQueue"); + /** Verifies that the sink queue validates that the exact number of subscribers was added */ + @Test(expected = JsiiException.class) + public void failsIfNotEnoughTopics() { + App app = new App(); + Stack stack = new Stack(app, "test"); - // add three topics in two calls to "subscribe" - sink.subscribe(new Topic(stack, "Topic1"), new Topic(stack, "Topic2")); - sink.subscribe(new Topic(stack, "Topic3")); + SinkQueue sink = + new SinkQueue( + stack, "MySinkQueue", SinkQueueProps.builder().withRequiredTopicCount(80).build()); - assertTemplate(stack, getClass().getResource("testSubscribeTopics.expected.json")); + for (int i = 0; i < 77; ++i) { + sink.subscribe(new Topic(stack, "Topic" + i)); } - /** Verifies that if we exceed the number of allows topics, an exception is thrown */ - @Test public void failsIfExceedMaxTopic() { - Stack stack = new Stack(); - - SinkQueue sink = new SinkQueue(stack, "MySinkQueue", SinkQueueProps.builder() - .withRequiredTopicCount(3) - .build()); - - sink.subscribe(new Topic(stack, "Topic1")); - sink.subscribe(new Topic(stack, "Topic2")); - sink.subscribe(new Topic(stack, "Topic3")); - - boolean thrown = false; - try { - sink.subscribe(new Topic(stack, "Topic4")); - } catch (RuntimeException e) { - thrown = true; - } - assertTrue(thrown); - } + getTemplate(stack); + } - /** Verifies that the sink queue validates that the exact number of subscribers was added */ - @Test(expected = JsiiException.class) public void failsIfNotEnoughTopics() { - App app = new App(); - Stack stack = new Stack(app, "test"); + private static void assertTemplate(final Stack stack, final URL expectedResource) + throws IOException { + assertTemplate(stack, JSON.readTree(expectedResource)); + } - SinkQueue sink = new SinkQueue(stack, "MySinkQueue", SinkQueueProps.builder() - .withRequiredTopicCount(80).build()); + private static void assertTemplate(final Stack stack, final String expectedTemplate) + throws IOException { + assertTemplate(stack, JSON.readTree(expectedTemplate)); + } - for (int i = 0; i < 77; ++i) { - sink.subscribe(new Topic(stack, "Topic" + i)); - } + private static void assertTemplate(final Stack stack, final JsonNode expected) + throws IOException { + JsonNode actual = JSON.valueToTree(getTemplate(stack)); - getTemplate(stack); + // print to stderr if non-equal, so it will be easy to grab + if (expected == null || !expected.equals(actual)) { + String prettyActual = JSON.writerWithDefaultPrettyPrinter().writeValueAsString(actual); + System.err.println(prettyActual); } - private static void assertTemplate(final Stack stack, final URL expectedResource) throws IOException { - assertTemplate(stack, JSON.readTree(expectedResource)); - } + assertEquals(expected, actual); + } - private static void assertTemplate(final Stack stack, final String expectedTemplate) throws IOException { - assertTemplate(stack, JSON.readTree(expectedTemplate)); - } - - private static void assertTemplate(final Stack stack, final JsonNode expected) throws IOException { - JsonNode actual = JSON.valueToTree(getTemplate(stack)); - - // print to stderr if non-equal, so it will be easy to grab - if (expected == null || !expected.equals(actual)) { - String prettyActual = JSON.writerWithDefaultPrettyPrinter().writeValueAsString(actual); - System.err.println(prettyActual); - } - - assertEquals(expected, actual); - } - - private static Object getTemplate(Stack stack) { - IConstruct root = stack.getNode().getRoot(); - CloudFormationStackArtifact stackArtifact = ConstructNode.synth(root.getNode()).getStack(stack.getStackName()); - return stackArtifact.getTemplate(); - } + private static Object getTemplate(Stack stack) { + IConstruct root = stack.getNode().getRoot(); + CloudFormationStackArtifact stackArtifact = + ConstructNode.synth(root.getNode()).getStack(stack.getStackName()); + return stackArtifact.getTemplate(); + } } diff --git a/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronApp.java b/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronApp.java index 43cd357956..6346af7ace 100644 --- a/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronApp.java +++ b/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronApp.java @@ -3,11 +3,11 @@ import software.amazon.awscdk.core.App; public class LambdaCronApp { - public static void main(final String[] args) { - App app = new App(); + public static void main(final String[] args) { + App app = new App(); - new LambdaCronStack(app, "cdk-lambda-cron-example"); + new LambdaCronStack(app, "cdk-lambda-cron-example"); - app.synth(); - } + app.synth(); + } } diff --git a/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronStack.java b/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronStack.java index 50fb6ae414..1107e8ecd7 100644 --- a/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronStack.java +++ b/java/lambda-cron/src/main/java/software/amazon/awscdk/examples/LambdaCronStack.java @@ -1,41 +1,37 @@ package software.amazon.awscdk.examples; +import java.util.UUID; import software.amazon.awscdk.core.Construct; import software.amazon.awscdk.core.Duration; import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.services.events.Rule; -import software.amazon.awscdk.services.events.RuleProps; import software.amazon.awscdk.services.events.Schedule; import software.amazon.awscdk.services.events.targets.LambdaFunction; import software.amazon.awscdk.services.lambda.Code; import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.lambda.SingletonFunction; -import java.util.UUID; - -/** - * Lambda Cron CDK example for Java! - */ +/** Lambda Cron CDK example for Java! */ class LambdaCronStack extends Stack { - public LambdaCronStack(final Construct parent, final String name) { - super(parent, name); + public LambdaCronStack(final Construct parent, final String name) { + super(parent, name); - SingletonFunction lambdaFunction = SingletonFunction.Builder.create(this, "cdk-lambda-cron") - .description("Lambda which prints \"I'm running\"") - .code(Code.fromInline( - "def main(event, context):\n" + - " print(\"I'm running!\")\n")) - .handler("index.main") - .timeout(Duration.seconds(300)) - .runtime(Runtime.PYTHON_2_7) - .uuid(UUID.randomUUID().toString()) - .build(); + SingletonFunction lambdaFunction = + SingletonFunction.Builder.create(this, "cdk-lambda-cron") + .description("Lambda which prints \"I'm running\"") + .code(Code.fromInline("def main(event, context):\n" + " print(\"I'm running!\")\n")) + .handler("index.main") + .timeout(Duration.seconds(300)) + .runtime(Runtime.PYTHON_2_7) + .uuid(UUID.randomUUID().toString()) + .build(); - Rule rule = Rule.Builder.create(this, "cdk-lambda-cron-rule") - .description("Run every day at 6PM UTC") - .schedule(Schedule.expression("cron(0 18 ? * MON-FRI *)")) - .build(); + Rule rule = + Rule.Builder.create(this, "cdk-lambda-cron-rule") + .description("Run every day at 6PM UTC") + .schedule(Schedule.expression("cron(0 18 ? * MON-FRI *)")) + .build(); - rule.addTarget(new LambdaFunction(lambdaFunction)); - } + rule.addTarget(new LambdaFunction(lambdaFunction)); + } } diff --git a/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/LambdaCronStackTest.java b/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/LambdaCronStackTest.java index 4ec6ce0326..2210cbf5bc 100644 --- a/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/LambdaCronStackTest.java +++ b/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/LambdaCronStackTest.java @@ -1,82 +1,85 @@ package software.amazon.awscdk.examples; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static software.amazon.awscdk.examples.TestUtils.toCloudFormationJson; + import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import software.amazon.awscdk.core.App; import software.amazon.awscdk.core.Stack; -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; -import static software.amazon.awscdk.examples.TestUtils.toCloudFormationJson; - public class LambdaCronStackTest { - private JsonNode actualStack; - private JsonNode expectedStack; + private JsonNode actualStack; + private JsonNode expectedStack; - @Before - public void setUp() throws IOException { - App app = new App(); - Stack stack = new LambdaCronStack(app, "lambdaResource-cdk-lambda-cron"); - actualStack = toCloudFormationJson(stack).path("Resources"); - expectedStack = TestUtils.fromFileResource(getClass().getResource("testCronLambdaExpected.json")).path("Resources"); - } + @Before + public void setUp() throws IOException { + App app = new App(); + Stack stack = new LambdaCronStack(app, "lambdaResource-cdk-lambda-cron"); + actualStack = toCloudFormationJson(stack).path("Resources"); + expectedStack = + TestUtils.fromFileResource(getClass().getResource("testCronLambdaExpected.json")) + .path("Resources"); + } - @Test - public void testTypes() { - List actual = actualStack.findValues("Type") - .stream().map(JsonNode::textValue).collect(Collectors.toList()); - String[] expected = expectedStack.findValues("Type") - .stream().map(JsonNode::textValue).toArray(String[]::new); - assertThat(actual, containsInAnyOrder(expected)); - } + @Test + public void testTypes() { + List actual = + actualStack.findValues("Type").stream() + .map(JsonNode::textValue) + .collect(Collectors.toList()); + String[] expected = + expectedStack.findValues("Type").stream().map(JsonNode::textValue).toArray(String[]::new); + assertThat(actual, containsInAnyOrder(expected)); + } - @Test - public void testPermission() { - final String type = "AWS::Lambda::Permission"; - JsonNode actual = TestUtils.getJsonNode(actualStack, type); - JsonNode expected = TestUtils.getJsonNode(expectedStack, type); - String[] keys = {"ManagedPolicyArns", "AssumeRolePolicyDocument"}; - for (String key : keys) { - assertThat(actual.get(key), equalTo(expected.get(key))); - } + @Test + public void testPermission() { + final String type = "AWS::Lambda::Permission"; + JsonNode actual = TestUtils.getJsonNode(actualStack, type); + JsonNode expected = TestUtils.getJsonNode(expectedStack, type); + String[] keys = {"ManagedPolicyArns", "AssumeRolePolicyDocument"}; + for (String key : keys) { + assertThat(actual.get(key), equalTo(expected.get(key))); } + } - @Test - public void testRole() { - final String type = "AWS::IAM::Role"; - JsonNode actual = TestUtils.getJsonNode(actualStack, type); - JsonNode expected = TestUtils.getJsonNode(expectedStack, type); - String[] keys = {"ManagedPolicyArns", "AssumeRolePolicyDocument"}; - for (String key : keys) { - assertThat(actual.get(key), equalTo(expected.get(key))); - } + @Test + public void testRole() { + final String type = "AWS::IAM::Role"; + JsonNode actual = TestUtils.getJsonNode(actualStack, type); + JsonNode expected = TestUtils.getJsonNode(expectedStack, type); + String[] keys = {"ManagedPolicyArns", "AssumeRolePolicyDocument"}; + for (String key : keys) { + assertThat(actual.get(key), equalTo(expected.get(key))); } + } - @Test - public void testLambda() { - final String type = "AWS::Lambda::Function"; - JsonNode actual = TestUtils.getJsonNode(actualStack, type); - JsonNode expected = TestUtils.getJsonNode(expectedStack, type); - String[] keys = {"Runtime", "Description", "Timeout", "Handler", "Code", "FunctionName"}; - for (String key : keys) { - assertThat(actual.get(key), equalTo(expected.get(key))); - } + @Test + public void testLambda() { + final String type = "AWS::Lambda::Function"; + JsonNode actual = TestUtils.getJsonNode(actualStack, type); + JsonNode expected = TestUtils.getJsonNode(expectedStack, type); + String[] keys = {"Runtime", "Description", "Timeout", "Handler", "Code", "FunctionName"}; + for (String key : keys) { + assertThat(actual.get(key), equalTo(expected.get(key))); } + } - @Test - public void testRule() { - final String type = "AWS::Events::Rule"; - JsonNode actual = TestUtils.getJsonNode(actualStack, type); - JsonNode expected = TestUtils.getJsonNode(expectedStack, type); - String[] keys = {"ScheduleExpression", "Description", "State"}; - for (String key : keys) { - assertThat(actual.get(key), equalTo(expected.get(key))); - } + @Test + public void testRule() { + final String type = "AWS::Events::Rule"; + JsonNode actual = TestUtils.getJsonNode(actualStack, type); + JsonNode expected = TestUtils.getJsonNode(expectedStack, type); + String[] keys = {"ScheduleExpression", "Description", "State"}; + for (String key : keys) { + assertThat(actual.get(key), equalTo(expected.get(key))); } + } } diff --git a/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/TestUtils.java b/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/TestUtils.java index 1df3a09330..e66f93e36e 100644 --- a/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/TestUtils.java +++ b/java/lambda-cron/src/test/java/software/amazon/awscdk/examples/TestUtils.java @@ -2,33 +2,36 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import software.amazon.awscdk.core.ConstructNode; -import software.amazon.awscdk.core.Stack; - import java.io.IOException; import java.net.URL; import java.util.NoSuchElementException; import java.util.Optional; import java.util.stream.StreamSupport; +import software.amazon.awscdk.core.ConstructNode; +import software.amazon.awscdk.core.Stack; public class TestUtils { - private static ObjectMapper JSON = new ObjectMapper(); + private static ObjectMapper JSON = new ObjectMapper(); - static JsonNode fromFileResource(final URL fileResource) throws IOException { - return JSON.readTree(fileResource); - } + static JsonNode fromFileResource(final URL fileResource) throws IOException { + return JSON.readTree(fileResource); + } - static JsonNode toCloudFormationJson(final Stack stack) throws IOException { - ConstructNode rootNode = stack.getNode().getRoot().getNode(); - JsonNode n = JSON.valueToTree(ConstructNode.synth(rootNode).getStack(stack.getStackName()).getTemplate()); - System.out.println(JSON.writerWithDefaultPrettyPrinter().writeValueAsString(n)); - return n; - } + static JsonNode toCloudFormationJson(final Stack stack) throws IOException { + ConstructNode rootNode = stack.getNode().getRoot().getNode(); + JsonNode n = + JSON.valueToTree( + ConstructNode.synth(rootNode).getStack(stack.getStackName()).getTemplate()); + System.out.println(JSON.writerWithDefaultPrettyPrinter().writeValueAsString(n)); + return n; + } - static JsonNode getJsonNode(JsonNode stackJson, String type) { - Iterable iterable = stackJson::elements; - Optional maybe = StreamSupport.stream(iterable.spliterator(), false) - .filter(jn -> jn.get("Type").textValue().equals(type)).findFirst(); - return maybe.map(jn -> jn.path("Properties")).orElseThrow(NoSuchElementException::new); - } + static JsonNode getJsonNode(JsonNode stackJson, String type) { + Iterable iterable = stackJson::elements; + Optional maybe = + StreamSupport.stream(iterable.spliterator(), false) + .filter(jn -> jn.get("Type").textValue().equals(type)) + .findFirst(); + return maybe.map(jn -> jn.path("Properties")).orElseThrow(NoSuchElementException::new); + } } diff --git a/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceApp.java b/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceApp.java index f349bb7591..8288b1071a 100644 --- a/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceApp.java +++ b/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceApp.java @@ -2,16 +2,12 @@ import software.amazon.awscdk.core.App; - - -import java.util.Arrays; - public class MyWidgetServiceApp { - public static void main(final String argv[]) { - App app = new App(); + public static void main(final String argv[]) { + App app = new App(); - new MyWidgetServiceStack(app, "MyWidgetServiceStack"); + new MyWidgetServiceStack(app, "MyWidgetServiceStack"); - app.synth(); - } + app.synth(); + } } diff --git a/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceStack.java b/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceStack.java index 0e573f81da..c9d06a463f 100644 --- a/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceStack.java +++ b/java/my-widget-service/src/main/java/software/amazon/awscdk/examples/MyWidgetServiceStack.java @@ -4,75 +4,74 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import software.amazon.awscdk.core.Construct; import software.amazon.awscdk.core.Duration; import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.services.apigateway.LambdaIntegration; -import software.amazon.awscdk.services.apigateway.LambdaIntegrationOptions; import software.amazon.awscdk.services.apigateway.Resource; import software.amazon.awscdk.services.apigateway.RestApi; -import software.amazon.awscdk.services.apigateway.RestApiProps; import software.amazon.awscdk.services.iam.IManagedPolicy; import software.amazon.awscdk.services.iam.ManagedPolicy; import software.amazon.awscdk.services.iam.Role; -import software.amazon.awscdk.services.iam.RoleProps; import software.amazon.awscdk.services.iam.ServicePrincipal; import software.amazon.awscdk.services.lambda.Code; import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.FunctionProps; import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.s3.Bucket; public class MyWidgetServiceStack extends Stack { - public MyWidgetServiceStack(final Construct scope, final String id) { - super(scope, id, null); - - Bucket bucket = Bucket.Builder.create(this, "WidgetStore").build(); + public MyWidgetServiceStack(final Construct scope, final String id) { + super(scope, id, null); - RestApi api = RestApi.Builder.create(this, "widgets-api") - .restApiName("Widget Service") - .description("This service serves widgets.") - .build(); + Bucket bucket = Bucket.Builder.create(this, "WidgetStore").build(); - List managedPolicyArray = new ArrayList(); - managedPolicyArray.add((IManagedPolicy) ManagedPolicy.fromAwsManagedPolicyName("AmazonS3FullAccess")); + RestApi api = + RestApi.Builder.create(this, "widgets-api") + .restApiName("Widget Service") + .description("This service serves widgets.") + .build(); - Role restApiRole = Role.Builder.create(this, "RestAPIRole") - .assumedBy(new ServicePrincipal("apigateway.amazonaws.com")) - .managedPolicies(managedPolicyArray) - .build(); + List managedPolicyArray = new ArrayList(); + managedPolicyArray.add( + (IManagedPolicy) ManagedPolicy.fromAwsManagedPolicyName("AmazonS3FullAccess")); - Map environmentVariables = new HashMap(); - environmentVariables.put("BUCKET", bucket.getBucketName()); + Role restApiRole = + Role.Builder.create(this, "RestAPIRole") + .assumedBy(new ServicePrincipal("apigateway.amazonaws.com")) + .managedPolicies(managedPolicyArray) + .build(); - Function lambdaFunction = Function.Builder.create(this, "WidgetHandler") - .code(Code.fromAsset("resources")) - .handler("widgets.main") - .timeout(Duration.seconds(300)) - .runtime(Runtime.NODEJS_10_X) - .environment(environmentVariables) - .build(); + Map environmentVariables = new HashMap(); + environmentVariables.put("BUCKET", bucket.getBucketName()); - bucket.grantReadWrite(lambdaFunction); + Function lambdaFunction = + Function.Builder.create(this, "WidgetHandler") + .code(Code.fromAsset("resources")) + .handler("widgets.main") + .timeout(Duration.seconds(300)) + .runtime(Runtime.NODEJS_10_X) + .environment(environmentVariables) + .build(); - Map lambdaIntegrationMap = new HashMap(); - lambdaIntegrationMap.put("application/json", "{ \"statusCode\": \"200\" }"); + bucket.grantReadWrite(lambdaFunction); - LambdaIntegration getWidgetIntegration = LambdaIntegration.Builder.create(lambdaFunction) - .requestTemplates(lambdaIntegrationMap) - .build(); + Map lambdaIntegrationMap = new HashMap(); + lambdaIntegrationMap.put("application/json", "{ \"statusCode\": \"200\" }"); - api.getRoot().addMethod("GET", getWidgetIntegration); + LambdaIntegration getWidgetIntegration = + LambdaIntegration.Builder.create(lambdaFunction) + .requestTemplates(lambdaIntegrationMap) + .build(); - LambdaIntegration postWidgetIntegration = new LambdaIntegration(lambdaFunction); - LambdaIntegration deleteWidgetIntegration = new LambdaIntegration(lambdaFunction); + api.getRoot().addMethod("GET", getWidgetIntegration); - Resource widget = api.getRoot().addResource("{id}"); + LambdaIntegration postWidgetIntegration = new LambdaIntegration(lambdaFunction); + LambdaIntegration deleteWidgetIntegration = new LambdaIntegration(lambdaFunction); - widget.addMethod("POST", postWidgetIntegration); - widget.addMethod("GET", getWidgetIntegration); - widget.addMethod("DELETE", deleteWidgetIntegration); + Resource widget = api.getRoot().addResource("{id}"); - } + widget.addMethod("POST", postWidgetIntegration); + widget.addMethod("GET", getWidgetIntegration); + widget.addMethod("DELETE", deleteWidgetIntegration); + } } diff --git a/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/MyWidgetServiceTest.java b/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/MyWidgetServiceTest.java index c389347fe3..942993022e 100644 --- a/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/MyWidgetServiceTest.java +++ b/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/MyWidgetServiceTest.java @@ -1,44 +1,40 @@ package software.amazon.awscdk.examples; -import software.amazon.awscdk.core.App; -import software.amazon.awscdk.core.Stack; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertThat; +import static software.amazon.awscdk.examples.TestUtils.toCloudFormationJson; import com.fasterxml.jackson.databind.JsonNode; - +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import software.amazon.awscdk.core.App; import software.amazon.awscdk.core.Stack; -import software.amazon.awscdk.examples.MyWidgetServiceStack; - -import java.io.IOException; -import java.util.List; -import java.util.stream.Collectors; - -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; -import static software.amazon.awscdk.examples.TestUtils.toCloudFormationJson; public class MyWidgetServiceTest { - private JsonNode actualStack; - private JsonNode expectedStack; + private JsonNode actualStack; + private JsonNode expectedStack; + + @Before + public void setUp() throws IOException { + App app = new App(); + Stack stack = new MyWidgetServiceStack(app, "MyWidgetServiceStack"); + actualStack = toCloudFormationJson(stack).path("Resources"); + expectedStack = + TestUtils.fromFileResource(getClass().getResource("testMyWidgetServiceExpected.json")) + .path("Resources"); + } - @Before - public void setUp() throws IOException { - App app = new App(); - Stack stack = new MyWidgetServiceStack(app, "MyWidgetServiceStack"); - actualStack = toCloudFormationJson(stack).path("Resources"); - expectedStack = TestUtils.fromFileResource(getClass().getResource("testMyWidgetServiceExpected.json")).path("Resources"); - } - - @Test - public void testTypes() { - List actual = actualStack.findValues("Type") - .stream().map(JsonNode::textValue).collect(Collectors.toList()); - String[] expected = expectedStack.findValues("Type") - .stream().map(JsonNode::textValue).toArray(String[]::new); - assertThat(actual, containsInAnyOrder(expected)); - } - + @Test + public void testTypes() { + List actual = + actualStack.findValues("Type").stream() + .map(JsonNode::textValue) + .collect(Collectors.toList()); + String[] expected = + expectedStack.findValues("Type").stream().map(JsonNode::textValue).toArray(String[]::new); + assertThat(actual, containsInAnyOrder(expected)); + } } diff --git a/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/TestUtils.java b/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/TestUtils.java index 1df3a09330..e66f93e36e 100644 --- a/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/TestUtils.java +++ b/java/my-widget-service/src/test/java/software/amazon/awscdk/examples/TestUtils.java @@ -2,33 +2,36 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import software.amazon.awscdk.core.ConstructNode; -import software.amazon.awscdk.core.Stack; - import java.io.IOException; import java.net.URL; import java.util.NoSuchElementException; import java.util.Optional; import java.util.stream.StreamSupport; +import software.amazon.awscdk.core.ConstructNode; +import software.amazon.awscdk.core.Stack; public class TestUtils { - private static ObjectMapper JSON = new ObjectMapper(); + private static ObjectMapper JSON = new ObjectMapper(); - static JsonNode fromFileResource(final URL fileResource) throws IOException { - return JSON.readTree(fileResource); - } + static JsonNode fromFileResource(final URL fileResource) throws IOException { + return JSON.readTree(fileResource); + } - static JsonNode toCloudFormationJson(final Stack stack) throws IOException { - ConstructNode rootNode = stack.getNode().getRoot().getNode(); - JsonNode n = JSON.valueToTree(ConstructNode.synth(rootNode).getStack(stack.getStackName()).getTemplate()); - System.out.println(JSON.writerWithDefaultPrettyPrinter().writeValueAsString(n)); - return n; - } + static JsonNode toCloudFormationJson(final Stack stack) throws IOException { + ConstructNode rootNode = stack.getNode().getRoot().getNode(); + JsonNode n = + JSON.valueToTree( + ConstructNode.synth(rootNode).getStack(stack.getStackName()).getTemplate()); + System.out.println(JSON.writerWithDefaultPrettyPrinter().writeValueAsString(n)); + return n; + } - static JsonNode getJsonNode(JsonNode stackJson, String type) { - Iterable iterable = stackJson::elements; - Optional maybe = StreamSupport.stream(iterable.spliterator(), false) - .filter(jn -> jn.get("Type").textValue().equals(type)).findFirst(); - return maybe.map(jn -> jn.path("Properties")).orElseThrow(NoSuchElementException::new); - } + static JsonNode getJsonNode(JsonNode stackJson, String type) { + Iterable iterable = stackJson::elements; + Optional maybe = + StreamSupport.stream(iterable.spliterator(), false) + .filter(jn -> jn.get("Type").textValue().equals(type)) + .findFirst(); + return maybe.map(jn -> jn.path("Properties")).orElseThrow(NoSuchElementException::new); + } } diff --git a/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesApp.java b/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesApp.java index 833f5a5b77..3f7683f7b4 100644 --- a/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesApp.java +++ b/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesApp.java @@ -3,11 +3,11 @@ import software.amazon.awscdk.core.App; public class ResourceOverridesApp { - public static void main(final String[] args) { - App app = new App(); + public static void main(final String[] args) { + App app = new App(); - new ResourceOverridesStack(app, "resource-overrides"); + new ResourceOverridesStack(app, "resource-overrides"); - app.synth(); - } + app.synth(); + } } diff --git a/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesStack.java b/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesStack.java index 5ce67acf53..22706bce0d 100644 --- a/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesStack.java +++ b/java/resource-overrides/src/main/java/software/amazon/awscdk/examples/ResourceOverridesStack.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.util.Collections; import software.amazon.awscdk.core.*; import software.amazon.awscdk.services.autoscaling.AutoScalingGroup; import software.amazon.awscdk.services.autoscaling.CfnLaunchConfiguration; @@ -10,155 +11,166 @@ import software.amazon.awscdk.services.s3.BucketEncryption; import software.amazon.awscdk.services.s3.CfnBucket; -import java.util.Collections; - /** * This is an example of how to override properties of underlying CloudFormation resource of * high-level CDK construct. - *

- * Note: this is just a reference code to show examples of how to use L1 resources. - * Running `cdk deploy` on this app will fail, however you can still run `cdk synth` and explore - * CloudFormation template that gets generated. - *

- * Note: this code shows how to access L1 resources, however you shouldn't do it unless you really need to. - * As you can see below, doing some is quite cumbersome (especially in Java) and not very clean, but still possible. + * + *

Note: this is just a reference code to show examples of how to use L1 resources. Running `cdk + * deploy` on this app will fail, however you can still run `cdk synth` and explore CloudFormation + * template that gets generated. + * + *

Note: this code shows how to access L1 resources, however you shouldn't do it unless you + * really need to. As you can see below, doing some is quite cumbersome (especially in Java) and not + * very clean, but still possible. */ class ResourceOverridesStack extends Stack { - public ResourceOverridesStack(final Construct scope, final String name) { - super(scope, name); - - Bucket otherBucket = Bucket.Builder.create(this, "Other").build(); - - Bucket bucket = Bucket.Builder.create(this, "MyBucket") - .versioned(true) - .encryption(BucketEncryption.KMS_MANAGED) - .build(); - - CfnBucket bucketResource = (CfnBucket) bucket.getNode().getDefaultChild(); - - // - // This is how to access L1 construct - // - accessCfnBucketExample(bucket); - - // - // This is how to modify properties of L1 construct - // - modifyPropertiesExample(bucket); - - // - // This is how to specify resource options such as dependencies, metadata, update policy - // - bucketResource.getNode().addDependency(otherBucket.getNode().getDefaultChild()); - bucketResource.getCfnOptions().setMetadata( - ImmutableMap.of("MetadataKey", "MetadataValue") - ); - bucketResource.getCfnOptions().setUpdatePolicy( - CfnUpdatePolicy.builder() - .autoScalingRollingUpdate(CfnAutoScalingRollingUpdate.builder().pauseTime("390").build()) - .build() - ); - - // - // This is how to specify "raw" overrides at the __resource__ level - // - bucketResource.addOverride("Type", "AWS::S3::Bucketeer"); // even "Type" can be overridden - bucketResource.addOverride("Transform", "Boom"); - bucketResource.addOverride("Properties.CorsConfiguration", - ImmutableMap.builder() - .put("Custom", 123) - .put("Bar", ImmutableList.of("A", "B")) - .build() - ); - - // addPropertyOverride simply allows you to omit the "Properties." prefix - bucketResource.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); - bucketResource.addPropertyOverride("Token", otherBucket.getBucketArn()); - // it's possible to mix L1 and L2 constructs - in this case otherBucket.getBucketName() will create "Ref:" in CloudFormation template - bucketResource.addPropertyOverride("LoggingConfiguration.DestinationBucketName", otherBucket.getBucketName()); - - bucketResource.setAnalyticsConfigurations(Collections.singletonList(ImmutableMap.builder() + public ResourceOverridesStack(final Construct scope, final String name) { + super(scope, name); + + Bucket otherBucket = Bucket.Builder.create(this, "Other").build(); + + Bucket bucket = + Bucket.Builder.create(this, "MyBucket") + .versioned(true) + .encryption(BucketEncryption.KMS_MANAGED) + .build(); + + CfnBucket bucketResource = (CfnBucket) bucket.getNode().getDefaultChild(); + + // + // This is how to access L1 construct + // + accessCfnBucketExample(bucket); + + // + // This is how to modify properties of L1 construct + // + modifyPropertiesExample(bucket); + + // + // This is how to specify resource options such as dependencies, metadata, update policy + // + bucketResource.getNode().addDependency(otherBucket.getNode().getDefaultChild()); + bucketResource.getCfnOptions().setMetadata(ImmutableMap.of("MetadataKey", "MetadataValue")); + bucketResource + .getCfnOptions() + .setUpdatePolicy( + CfnUpdatePolicy.builder() + .autoScalingRollingUpdate( + CfnAutoScalingRollingUpdate.builder().pauseTime("390").build()) + .build()); + + // + // This is how to specify "raw" overrides at the __resource__ level + // + bucketResource.addOverride("Type", "AWS::S3::Bucketeer"); // even "Type" can be overridden + bucketResource.addOverride("Transform", "Boom"); + bucketResource.addOverride( + "Properties.CorsConfiguration", + ImmutableMap.builder().put("Custom", 123).put("Bar", ImmutableList.of("A", "B")).build()); + + // addPropertyOverride simply allows you to omit the "Properties." prefix + bucketResource.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); + bucketResource.addPropertyOverride("Token", otherBucket.getBucketArn()); + // it's possible to mix L1 and L2 constructs - in this case otherBucket.getBucketName() will + // create "Ref:" in CloudFormation template + bucketResource.addPropertyOverride( + "LoggingConfiguration.DestinationBucketName", otherBucket.getBucketName()); + + bucketResource.setAnalyticsConfigurations( + Collections.singletonList( + ImmutableMap.builder() .put("id", "config1") - .put("storageClassAnalysis", ImmutableMap.of( - "dataExport", ImmutableMap.builder() - .put("outputSchemaVersion", "1") - .put("destination", ImmutableMap.builder() - .put("format", "html") - // using L2 construct's method will work as expected - .put("bucketArn", otherBucket.getBucketArn()) - .build() - ) - .build() - ) - ) - .build() - )); - - // - // It is also possible to request a deletion of a value by either assigning - // `null` or use the `addDeletionOverride` method - // - bucketResource.addDeletionOverride("Metadata"); - // same as above - bucketResource.addOverride("Metadata", null); - bucketResource.addPropertyDeletionOverride("CorsConfiguration.Bar"); - - // - // Example of constructs that have more L1 underlying resources and how to access them - // - Vpc vpc = Vpc.Builder.create(this, "VPC") - .maxAzs(1) - .build(); - - AutoScalingGroup asg = AutoScalingGroup.Builder.create(this, "ASG") - .vpc(vpc) - .instanceType(InstanceType.of(InstanceClass.MEMORY4, InstanceSize.XLARGE)) - .machineImage(new AmazonLinuxImage()) - .build(); - - // - // The default child resource is called `Resource`, but secondary resources, such as - // an LaunchConfig, InstanceRole will have a different ID. - // See https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.ConstructNode.html#defaultchild - // You can see all the resources under given construct by running `cdk synth` and looking for `aws:cdk:path` - // - CfnLaunchConfiguration launchConfiguration = (CfnLaunchConfiguration) asg.getNode().findChild("LaunchConfig"); - launchConfiguration.addPropertyOverride("Foo.Bar", "Hello"); - } - - /** - * Example of accessing L1 bucket resource from L2 bucket construct. - *

- * You can read more on L1 vs L2 constructs here: https://aws.amazon.com/blogs/developer/contributing-to-the-aws-cloud-development-kit/ - */ - private void accessCfnBucketExample(Bucket bucket) { - // accessing through finding a child of specific type (not pretty in Java) - CfnBucket bucketResource1 = (CfnBucket) bucket.getNode().getChildren() - .stream() - .filter(child -> ((CfnResource) child).getCfnResourceType().equals("AWS::S3::Bucket")) + .put( + "storageClassAnalysis", + ImmutableMap.of( + "dataExport", + ImmutableMap.builder() + .put("outputSchemaVersion", "1") + .put( + "destination", + ImmutableMap.builder() + .put("format", "html") + // using L2 construct's method will work as expected + .put("bucketArn", otherBucket.getBucketArn()) + .build()) + .build())) + .build())); + + // + // It is also possible to request a deletion of a value by either assigning + // `null` or use the `addDeletionOverride` method + // + bucketResource.addDeletionOverride("Metadata"); + // same as above + bucketResource.addOverride("Metadata", null); + bucketResource.addPropertyDeletionOverride("CorsConfiguration.Bar"); + + // + // Example of constructs that have more L1 underlying resources and how to access them + // + Vpc vpc = Vpc.Builder.create(this, "VPC").maxAzs(1).build(); + + AutoScalingGroup asg = + AutoScalingGroup.Builder.create(this, "ASG") + .vpc(vpc) + .instanceType(InstanceType.of(InstanceClass.MEMORY4, InstanceSize.XLARGE)) + .machineImage(new AmazonLinuxImage()) + .build(); + + // + // The default child resource is called `Resource`, but secondary resources, such as + // an LaunchConfig, InstanceRole will have a different ID. + // See + // https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.ConstructNode.html#defaultchild + // You can see all the resources under given construct by running `cdk synth` and looking for + // `aws:cdk:path` + // + CfnLaunchConfiguration launchConfiguration = + (CfnLaunchConfiguration) asg.getNode().findChild("LaunchConfig"); + launchConfiguration.addPropertyOverride("Foo.Bar", "Hello"); + } + + /** + * Example of accessing L1 bucket resource from L2 bucket construct. + * + *

You can read more on L1 vs L2 constructs here: + * https://aws.amazon.com/blogs/developer/contributing-to-the-aws-cloud-development-kit/ + */ + private void accessCfnBucketExample(Bucket bucket) { + // accessing through finding a child of specific type (not pretty in Java) + CfnBucket bucketResource1 = + (CfnBucket) + bucket.getNode().getChildren().stream() + .filter( + child -> ((CfnResource) child).getCfnResourceType().equals("AWS::S3::Bucket")) .findFirst() .get(); - // accessing through getting a default child - CfnBucket bucketResource2 = (CfnBucket) bucket.getNode().getDefaultChild(); - - assert bucketResource1.equals(bucketResource2); - } - - /** - * Example of how properties of CloudFormation resource can be modified. - * Paths for the properties can be found in CloudFormation documentation. - * For S3 bucket properties see: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html - */ - private void modifyPropertiesExample(Bucket bucket) { - CfnBucket bucketCfnResource = (CfnBucket) bucket.getNode().getDefaultChild(); - - // This is an invalid CF property, but there is no validation at this point, so anything can be set. - // This is just to show that anything can be set at this point, but it's only validated ones the stack - // is being deployed to CloudFormation. - bucketCfnResource.addPropertyOverride("BucketEncryption.ServerSideEncryptionConfiguration.0.EncryptEverythingAndAlways", true); - - // This is a valid CF property - bucketCfnResource.addPropertyDeletionOverride("BucketEncryption.ServerSideEncryptionConfiguration.0.ServerSideEncryptionByDefault"); - } + // accessing through getting a default child + CfnBucket bucketResource2 = (CfnBucket) bucket.getNode().getDefaultChild(); + + assert bucketResource1.equals(bucketResource2); + } + + /** + * Example of how properties of CloudFormation resource can be modified. Paths for the properties + * can be found in CloudFormation documentation. For S3 bucket properties see: + * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html + */ + private void modifyPropertiesExample(Bucket bucket) { + CfnBucket bucketCfnResource = (CfnBucket) bucket.getNode().getDefaultChild(); + + // This is an invalid CF property, but there is no validation at this point, so anything can be + // set. + // This is just to show that anything can be set at this point, but it's only validated ones the + // stack + // is being deployed to CloudFormation. + bucketCfnResource.addPropertyOverride( + "BucketEncryption.ServerSideEncryptionConfiguration.0.EncryptEverythingAndAlways", true); + + // This is a valid CF property + bucketCfnResource.addPropertyDeletionOverride( + "BucketEncryption.ServerSideEncryptionConfiguration.0.ServerSideEncryptionByDefault"); + } } diff --git a/java/resource-overrides/src/test/java/software/amazon/awscdk/examples/ResourceOverridesStackTest.java b/java/resource-overrides/src/test/java/software/amazon/awscdk/examples/ResourceOverridesStackTest.java index d6bbb648ff..ecefd4acc9 100644 --- a/java/resource-overrides/src/test/java/software/amazon/awscdk/examples/ResourceOverridesStackTest.java +++ b/java/resource-overrides/src/test/java/software/amazon/awscdk/examples/ResourceOverridesStackTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; import org.junit.Test; import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; @@ -11,35 +12,29 @@ import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.cxapi.CloudFormationStackArtifact; -import java.io.IOException; - public class ResourceOverridesStackTest { - private static final ObjectMapper JSON = new ObjectMapper(); - - @Test - public void shouldGenerateValidCloudFormationTemplate() throws Exception { - App app = new App(); - Stack stack = new ResourceOverridesStack(app, "resource-overrides"); - - String actual = getStackTemplateJson(stack) - .toPrettyString(); - String expected = readJsonFromResource("testResourceOverrides.expected.json") - .toPrettyString(); - - JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT); - } - - private static JsonNode readJsonFromResource(String resourceName) throws IOException { - return JSON.readTree( - ResourceOverridesStackTest.class.getResource(resourceName) - ); - } - - private static JsonNode getStackTemplateJson(Stack stack) { - IConstruct root = stack.getNode().getRoot(); - CloudFormationStackArtifact stackArtifact = ConstructNode.synth(root.getNode()) - .getStackByName(stack.getStackName()); - - return JSON.valueToTree(stackArtifact.getTemplate()); - } + private static final ObjectMapper JSON = new ObjectMapper(); + + @Test + public void shouldGenerateValidCloudFormationTemplate() throws Exception { + App app = new App(); + Stack stack = new ResourceOverridesStack(app, "resource-overrides"); + + String actual = getStackTemplateJson(stack).toPrettyString(); + String expected = readJsonFromResource("testResourceOverrides.expected.json").toPrettyString(); + + JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT); + } + + private static JsonNode readJsonFromResource(String resourceName) throws IOException { + return JSON.readTree(ResourceOverridesStackTest.class.getResource(resourceName)); + } + + private static JsonNode getStackTemplateJson(Stack stack) { + IConstruct root = stack.getNode().getRoot(); + CloudFormationStackArtifact stackArtifact = + ConstructNode.synth(root.getNode()).getStackByName(stack.getStackName()); + + return JSON.valueToTree(stackArtifact.getTemplate()); + } }