diff --git a/javav2/example_code/autoscale/pom.xml b/javav2/example_code/autoscale/pom.xml
index 4697cbbe0a1..cb8abe17bdf 100644
--- a/javav2/example_code/autoscale/pom.xml
+++ b/javav2/example_code/autoscale/pom.xml
@@ -8,9 +8,9 @@
1.0-SNAPSHOT
UTF-8
- 21
- 21
- 21
+ 17
+ 17
+ 17
@@ -26,14 +26,7 @@
software.amazon.awssdk
bom
- 2.31.8
- pom
- import
-
-
- org.apache.logging.log4j
- log4j-bom
- 2.23.1
+ 2.29.45
pom
import
@@ -50,14 +43,9 @@
software.amazon.awssdk
secretsmanager
-
- com.google.code.gson
- gson
- 2.10.1
-
software.amazon.awssdk
- autoscaling
+ cloudformation
software.amazon.awssdk
@@ -65,32 +53,28 @@
software.amazon.awssdk
- auth
+ netty-nio-client
- software.amazon.awssdk
- sso
+ com.google.code.gson
+ gson
+ 2.10.1
software.amazon.awssdk
- ssooidc
-
-
- org.apache.logging.log4j
- log4j-core
+ autoscaling
- org.slf4j
- slf4j-api
- 2.0.13
+ software.amazon.awssdk
+ auth
- org.apache.logging.log4j
- log4j-slf4j2-impl
+ software.amazon.awssdk
+ sso
- org.apache.logging.log4j
- log4j-1.2-api
+ software.amazon.awssdk
+ ssooidc
\ No newline at end of file
diff --git a/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/AutoScalingScenario.java b/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/AutoScalingScenario.java
index 14b7ca01af3..0e86bd18fea 100644
--- a/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/AutoScalingScenario.java
+++ b/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/AutoScalingScenario.java
@@ -29,8 +29,21 @@
import software.amazon.awssdk.services.autoscaling.model.TerminateInstanceInAutoScalingGroupRequest;
import software.amazon.awssdk.services.autoscaling.model.DescribeAutoScalingInstancesRequest;
import software.amazon.awssdk.services.ec2.Ec2Client;
+import software.amazon.awssdk.services.ec2.model.CreateLaunchTemplateVersionRequest;
+import software.amazon.awssdk.services.ec2.model.CreateLaunchTemplateVersionResponse;
+import software.amazon.awssdk.services.ec2.model.DescribeSubnetsRequest;
+import software.amazon.awssdk.services.ec2.model.DescribeSubnetsResponse;
+import software.amazon.awssdk.services.ec2.model.DescribeVpcsRequest;
+import software.amazon.awssdk.services.ec2.model.DescribeVpcsResponse;
+import software.amazon.awssdk.services.ec2.model.Ec2Exception;
+import software.amazon.awssdk.services.ec2.model.Filter;
+import software.amazon.awssdk.services.ec2.model.ModifyLaunchTemplateRequest;
+import software.amazon.awssdk.services.ec2.model.RequestLaunchTemplateData;
+import software.amazon.awssdk.services.ec2.model.ResponseLaunchTemplateData;
+import software.amazon.awssdk.services.ec2.model.Vpc;
import java.util.List;
+import java.util.Map;
// snippet-end:[autoscale.java2.create_scaling_scenario.import]
// snippet-start:[autoscale.java2.create_scaling_scenario.main]
@@ -65,41 +78,34 @@
public class AutoScalingScenario {
public static final String DASHES = new String(new char[80]).replace("\0", "-");
-
+ private static final String ROLES_STACK = "MyCdkAutoScaleStack";
public static void main(String[] args) throws InterruptedException {
- final String usage = """
-
- Usage:
-
-
- Where:
- groupName - The name of the Auto Scaling group.
- launchTemplateName - The name of the launch template.\s
- vpcZoneId - A subnet Id for a virtual private cloud (VPC) where instances in the Auto Scaling group can be created.
- """;
-
- //if (args.length != 3) {
- // System.out.println(usage);
- // System.exit(1);
- // }
-
- String groupName = "Scott250" ; //rgs[0];
- String launchTemplateName = "MyTemplate5" ;//args[1];
- String vpcZoneId = "subnet-0ddc451b8a8a1aa44" ; //args[2];
-
+ // The name of the Auto Scaling group.
+ String groupName = "MyAutoScalingGroup2";
AutoScalingClient autoScalingClient = AutoScalingClient.builder()
- .region(Region.US_EAST_1)
+ .region(Region.US_WEST_2)
.build();
- Ec2Client ec2 = Ec2Client.create();
+ Ec2Client ec2 = Ec2Client.builder()
+ .region(Region.US_WEST_2)
+ .build();
System.out.println(DASHES);
System.out.println("Welcome to the Amazon EC2 Auto Scaling example scenario.");
System.out.println(DASHES);
System.out.println(DASHES);
+ System.out.println("First, we will create a launch template using a CloudFormation script");
+ CloudFormationHelper.deployCloudFormationStack(ROLES_STACK);
+ Map stackOutputs = CloudFormationHelper.getStackOutputsAsync(ROLES_STACK).join();
+ String launchTemplateName = stackOutputs.get("LaunchTemplateNameOutput");
+ String vpcZoneId = getVPC(ec2);
+ updateTemlate(ec2, launchTemplateName );
+ System.out.println("The VPC zone id created by the CloudFormation stack is"+vpcZoneId);
+
System.out.println("1. Create an Auto Scaling group named " + groupName);
- createAutoScalingGroup(autoScalingClient, groupName, launchTemplateName, vpcZoneId);
+ createAutoScalingGroup(autoScalingClient, ec2, groupName, launchTemplateName, vpcZoneId);
+
System.out.println(
"Wait 1 min for the resources, including the instance. Otherwise, an empty instance Id is returned");
Thread.sleep(60000);
@@ -170,7 +176,8 @@ public static void main(String[] args) throws InterruptedException {
System.out.println(DASHES);
System.out.println(DASHES);
- System.out.println("13. Delete the Auto Scaling group");
+ System.out.println("13. Delete the Auto Scaling group and cloud formation resources");
+ CloudFormationHelper.destroyCloudFormationStack(ROLES_STACK);
deleteAutoScalingGroup(autoScalingClient, groupName);
System.out.println(DASHES);
@@ -181,6 +188,56 @@ public static void main(String[] args) throws InterruptedException {
autoScalingClient.close();
}
+ public static String getVPC(Ec2Client ec2) {
+ try {
+ DescribeVpcsRequest request = DescribeVpcsRequest.builder()
+ .filters(f -> f.name("isDefault").values("true"))
+ .build();
+
+ DescribeVpcsResponse response = ec2.describeVpcs(request);
+
+ if (!response.vpcs().isEmpty()) {
+ Vpc defaultVpc = response.vpcs().get(0);
+ System.out.println("Default VPC ID: " + defaultVpc.vpcId());
+ return defaultVpc.vpcId();
+ } else {
+ System.out.println("No default VPC found.");
+ return null; // Return null if no default VPC is found
+ }
+
+ } catch (Ec2Exception e) {
+ System.err.println("EC2 error: " + e.awsErrorDetails().errorMessage());
+ return null; // Return null in case of an error
+ }
+ }
+
+
+ public static void updateTemlate(Ec2Client ec2, String launchTemplateName ) {
+ // Step 1: Create new launch template version
+ String newAmiId = "ami-0025f0db847eb6254";
+ RequestLaunchTemplateData launchTemplateData = RequestLaunchTemplateData.builder()
+ .imageId(newAmiId)
+ .build();
+
+ CreateLaunchTemplateVersionRequest createVersionRequest = CreateLaunchTemplateVersionRequest.builder()
+ .launchTemplateName(launchTemplateName)
+ .versionDescription("Updated with valid AMI")
+ .sourceVersion("1")
+ .launchTemplateData(launchTemplateData)
+ .build();
+
+ CreateLaunchTemplateVersionResponse createResponse = ec2.createLaunchTemplateVersion(createVersionRequest);
+ int newVersionNumber = createResponse.launchTemplateVersion().versionNumber().intValue();
+
+ // Step 2: Modify default version
+ ModifyLaunchTemplateRequest modifyRequest = ModifyLaunchTemplateRequest.builder()
+ .launchTemplateName(launchTemplateName)
+ .defaultVersion(String.valueOf(newVersionNumber))
+ .build();
+
+ ec2.modifyLaunchTemplate(modifyRequest);
+ System.out.println("Updated launch template to version " + newVersionNumber + " with AMI " + newAmiId);
+ }
// snippet-start:[autoscale.java2.describe_scaling_activites.main]
@@ -224,42 +281,61 @@ public static void setDesiredCapacity(AutoScalingClient autoScalingClient, Strin
}
// snippet-end:[autoscale.java2.set_capacity.main]
- // snippet-start:[autoscale.java2.create_autoscalinggroup.main]
+ // snippet-start:[autoscale.java2.create_scaling_group.main]
public static void createAutoScalingGroup(AutoScalingClient autoScalingClient,
- String groupName,
- String launchTemplateName,
- String vpcZoneId) {
+ Ec2Client ec2Client,
+ String groupName,
+ String launchTemplateName,
+ String vpcId) {
try {
- AutoScalingWaiter waiter = autoScalingClient.waiter();
+ // Step 1: Get one subnet ID in the given VPC
+ DescribeSubnetsRequest subnetRequest = DescribeSubnetsRequest.builder()
+ .filters(Filter.builder().name("vpc-id").values(vpcId).build())
+ .build();
+
+ DescribeSubnetsResponse subnetResponse = ec2Client.describeSubnets(subnetRequest);
+
+ if (subnetResponse.subnets().isEmpty()) {
+ throw new RuntimeException("No subnets found in VPC: " + vpcId);
+ }
+
+ String subnetId = subnetResponse.subnets().get(0).subnetId(); // Use first subnet
+ System.out.println("Using subnet: " + subnetId);
+
+ // Step 2: Create launch template reference
LaunchTemplateSpecification templateSpecification = LaunchTemplateSpecification.builder()
.launchTemplateName(launchTemplateName)
.build();
+ // Step 3: Create Auto Scaling group
CreateAutoScalingGroupRequest request = CreateAutoScalingGroupRequest.builder()
.autoScalingGroupName(groupName)
- .availabilityZones("us-east-1a")
.launchTemplate(templateSpecification)
- .maxSize(1)
.minSize(1)
- .vpcZoneIdentifier(vpcZoneId)
+ .maxSize(1)
+ .vpcZoneIdentifier(subnetId) // Correct: subnet ID, not VPC ID
.build();
autoScalingClient.createAutoScalingGroup(request);
+
+ // Step 4: Wait until group is created
+ AutoScalingWaiter waiter = autoScalingClient.waiter();
DescribeAutoScalingGroupsRequest groupsRequest = DescribeAutoScalingGroupsRequest.builder()
.autoScalingGroupNames(groupName)
.build();
- WaiterResponse waiterResponse = waiter
- .waitUntilGroupExists(groupsRequest);
+ WaiterResponse waiterResponse =
+ waiter.waitUntilGroupExists(groupsRequest);
+
waiterResponse.matched().response().ifPresent(System.out::println);
System.out.println("Auto Scaling Group created");
- } catch (AutoScalingException e) {
- System.err.println(e.awsErrorDetails().errorMessage());
+ } catch (Ec2Exception | AutoScalingException e) {
+ System.err.println("Error: " + e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
- // snippet-end:[autoscale.java2.create_autoscalinggroup.main]
+ // snippet-end:[autoscale.java2.create_scaling_group.main]
// snippet-start:[autoscale.java2.describe_autoscalinggroup.main]
public static void describeAutoScalingInstance(AutoScalingClient autoScalingClient, String id) {
@@ -437,7 +513,7 @@ public static void terminateInstanceInAutoScalingGroup(AutoScalingClient autoSca
}
// snippet-end:[autoscale.java2.terminate_instance.main]
- // snippet-start:[autoscale.java2.del_group.main]
+ // snippet-start:[autoscale.java2.del_scaling_group.main]
public static void deleteAutoScalingGroup(AutoScalingClient autoScalingClient, String groupName) {
try {
DeleteAutoScalingGroupRequest deleteAutoScalingGroupRequest = DeleteAutoScalingGroupRequest.builder()
@@ -453,6 +529,6 @@ public static void deleteAutoScalingGroup(AutoScalingClient autoScalingClient, S
System.exit(1);
}
}
- // snippet-end:[autoscale.java2.del_group.main]
+ // snippet-end:[autoscale.java2.del_scaling_group.main]
}
// snippet-end:[autoscale.java2.create_scaling_scenario.main]
diff --git a/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/CloudFormationHelper.java b/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/CloudFormationHelper.java
new file mode 100644
index 00000000000..07783c260d1
--- /dev/null
+++ b/javav2/example_code/autoscale/src/main/java/com/example/autoscaling/scenario/CloudFormationHelper.java
@@ -0,0 +1,161 @@
+package com.example.autoscaling.scenario;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.retry.RetryMode;
+import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
+import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.cloudformation.CloudFormationAsyncClient;
+import software.amazon.awssdk.services.cloudformation.model.Capability;
+import software.amazon.awssdk.services.cloudformation.model.CloudFormationException;
+import software.amazon.awssdk.services.cloudformation.model.DescribeStacksRequest;
+import software.amazon.awssdk.services.cloudformation.model.DescribeStacksResponse;
+import software.amazon.awssdk.services.cloudformation.model.Output;
+import software.amazon.awssdk.services.cloudformation.model.Stack;
+import software.amazon.awssdk.services.cloudformation.waiters.CloudFormationAsyncWaiter;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+public class CloudFormationHelper {
+ private static final String CFN_TEMPLATE = "launchtemplate.yaml";
+ private static final Logger logger = LoggerFactory.getLogger(CloudFormationHelper.class);
+
+ private static CloudFormationAsyncClient cloudFormationClient;
+
+ private static CloudFormationAsyncClient getCloudFormationClient() {
+ if (cloudFormationClient == null) {
+ SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder()
+ .maxConcurrency(100)
+ .connectionTimeout(Duration.ofSeconds(60))
+ .readTimeout(Duration.ofSeconds(60))
+ .writeTimeout(Duration.ofSeconds(60))
+ .build();
+
+ ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder()
+ .apiCallTimeout(Duration.ofMinutes(2))
+ .apiCallAttemptTimeout(Duration.ofSeconds(90))
+ .retryStrategy(RetryMode.STANDARD)
+ .build();
+
+ cloudFormationClient = CloudFormationAsyncClient.builder()
+ .httpClient(httpClient)
+ .overrideConfiguration(overrideConfig)
+ .region(Region.US_WEST_2)
+ .build();
+ }
+ return cloudFormationClient;
+ }
+
+ public static void deployCloudFormationStack(String stackName) {
+ String templateBody;
+ boolean doesExist = describeStack(stackName);
+ if (!doesExist) {
+ try {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ Path filePath = Paths.get(classLoader.getResource(CFN_TEMPLATE).toURI());
+ templateBody = Files.readString(filePath);
+ } catch (IOException | URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+
+ getCloudFormationClient().createStack(b -> b.stackName(stackName)
+ .templateBody(templateBody)
+ .capabilities(Capability.CAPABILITY_IAM))
+ .whenComplete((csr, t) -> {
+ if (csr != null) {
+ System.out.println("Stack creation requested, ARN is " + csr.stackId());
+ try (CloudFormationAsyncWaiter waiter = getCloudFormationClient().waiter()) {
+ waiter.waitUntilStackCreateComplete(request -> request.stackName(stackName))
+ .whenComplete((dsr, th) -> {
+ if (th != null) {
+ System.out.println("Error waiting for stack creation: " + th.getMessage());
+ } else {
+ dsr.matched().response().orElseThrow(() -> new RuntimeException("Failed to deploy"));
+ System.out.println("Stack created successfully");
+ }
+ }).join();
+ }
+ } else {
+ System.out.format("Error creating stack: " + t.getMessage(), t);
+ throw new RuntimeException(t.getCause().getMessage(), t);
+ }
+ }).join();
+ } else {
+ logger.info("{} stack already exists", CFN_TEMPLATE);
+ }
+ }
+
+ // Check to see if the Stack exists before deploying it
+ public static Boolean describeStack(String stackName) {
+ try {
+ CompletableFuture> future = getCloudFormationClient().describeStacks();
+ DescribeStacksResponse stacksResponse = (DescribeStacksResponse) future.join();
+ List stacks = stacksResponse.stacks();
+ for (Stack myStack : stacks) {
+ if (myStack.stackName().compareTo(stackName) == 0) {
+ return true;
+ }
+ }
+ } catch (CloudFormationException e) {
+ System.err.println(e.getMessage());
+ }
+ return false;
+ }
+
+ public static void destroyCloudFormationStack(String stackName) {
+ getCloudFormationClient().deleteStack(b -> b.stackName(stackName))
+ .whenComplete((dsr, t) -> {
+ if (dsr != null) {
+ System.out.println("Delete stack requested ....");
+ try (CloudFormationAsyncWaiter waiter = getCloudFormationClient().waiter()) {
+ waiter.waitUntilStackDeleteComplete(request -> request.stackName(stackName))
+ .whenComplete((waiterResponse, throwable) ->
+ System.out.println("Stack deleted successfully."))
+ .join();
+ }
+ } else {
+ System.out.format("Error deleting stack: " + t.getMessage(), t);
+ throw new RuntimeException(t.getCause().getMessage(), t);
+ }
+ }).join();
+ }
+
+ public static CompletableFuture