io.linguarobot.aws.cdk.maven.Stacks Maven / Gradle / Ivy
package io.linguarobot.aws.cdk.maven;
import com.google.common.collect.ImmutableSet;
import software.amazon.awssdk.services.cloudformation.CloudFormationClient;
import software.amazon.awssdk.services.cloudformation.model.Capability;
import software.amazon.awssdk.services.cloudformation.model.CloudFormationException;
import software.amazon.awssdk.services.cloudformation.model.CreateStackRequest;
import software.amazon.awssdk.services.cloudformation.model.CreateStackResponse;
import software.amazon.awssdk.services.cloudformation.model.DeleteStackRequest;
import software.amazon.awssdk.services.cloudformation.model.DescribeStackEventsRequest;
import software.amazon.awssdk.services.cloudformation.model.DescribeStackEventsResponse;
import software.amazon.awssdk.services.cloudformation.model.DescribeStacksRequest;
import software.amazon.awssdk.services.cloudformation.model.Output;
import software.amazon.awssdk.services.cloudformation.model.Parameter;
import software.amazon.awssdk.services.cloudformation.model.Stack;
import software.amazon.awssdk.services.cloudformation.model.StackEvent;
import software.amazon.awssdk.services.cloudformation.model.StackStatus;
import software.amazon.awssdk.services.cloudformation.model.UpdateStackRequest;
import software.amazon.awssdk.services.cloudformation.model.UpdateStackResponse;
import javax.annotation.Nullable;
import java.time.Duration;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Stacks {
private static final ScheduledExecutorService SCHEDULER = new ScheduledThreadPoolExecutor(0);
private static final Set IN_PROGRESS_STATUSES = ImmutableSet.builder()
.add(StackStatus.CREATE_IN_PROGRESS)
.add(StackStatus.DELETE_IN_PROGRESS)
.add(StackStatus.REVIEW_IN_PROGRESS)
.add(StackStatus.ROLLBACK_IN_PROGRESS)
.add(StackStatus.UPDATE_COMPLETE_CLEANUP_IN_PROGRESS)
.add(StackStatus.UPDATE_IN_PROGRESS)
.add(StackStatus.UPDATE_ROLLBACK_IN_PROGRESS)
.add(StackStatus.IMPORT_IN_PROGRESS)
.add(StackStatus.IMPORT_ROLLBACK_IN_PROGRESS)
.build();
private static final Set FAILED_STATUSES = ImmutableSet.builder()
.add(StackStatus.CREATE_FAILED)
.add(StackStatus.DELETE_FAILED)
.add(StackStatus.ROLLBACK_FAILED)
.add(StackStatus.UPDATE_ROLLBACK_FAILED)
.add(StackStatus.IMPORT_ROLLBACK_FAILED)
.build();
private static final Capability[] CAPABILITIES =
new Capability[]{Capability.CAPABILITY_IAM, Capability.CAPABILITY_NAMED_IAM, Capability.CAPABILITY_AUTO_EXPAND};
public static Optional findStack(CloudFormationClient client, String stackName) {
Objects.requireNonNull(client, "CloudFormation client can't be null");
Objects.requireNonNull(stackName, "stack name can't be null");
try {
return Optional.of(getStack(client, stackName));
} catch (CloudFormationException e) {
// Assuming that the exception is thrown only if the stack doesn't exist
return Optional.empty();
}
}
public static Stack createStack(CloudFormationClient client, String stackName, TemplateRef template) {
return createStack(client, stackName, template, Collections.emptyMap());
}
public static Stack createStack(CloudFormationClient client,
String stackName,
TemplateRef template,
Map parameters) {
Objects.requireNonNull(client, "CloudFormation client can't be null");
Objects.requireNonNull(stackName, "stack name can't be null");
Objects.requireNonNull(template, "template reference can't be null");
CreateStackRequest request = CreateStackRequest.builder()
.stackName(stackName)
.templateBody(template.getBody())
.templateURL(template.getUrl())
.parameters(parameters != null ? buildParameters(parameters) : Collections.emptyList())
.capabilities(CAPABILITIES)
.build();
CreateStackResponse response = client.createStack(request);
return getStack(client, response.stackId());
}
public static Stack updateStack(CloudFormationClient client,
String stackName,
TemplateRef template,
Map parameters) {
Objects.requireNonNull(client, "CloudFormation client can't be null");
Objects.requireNonNull(stackName, "stack name can't be null");
Objects.requireNonNull(template, "template reference can't be null");
UpdateStackRequest request = UpdateStackRequest.builder()
.stackName(stackName)
.templateBody(template.getBody())
.templateURL(template.getUrl())
.parameters(parameters != null ? buildParameters(parameters) : Collections.emptyList())
.capabilities(CAPABILITIES)
.build();
UpdateStackResponse response = client.updateStack(request);
return getStack(client, response.stackId());
}
private static List buildParameters(Map parameters) {
return parameters.entrySet().stream()
.map(parameter -> Parameter.builder()
.parameterKey(parameter.getKey())
.parameterValue(parameter.getValue().get())
.usePreviousValue(!parameter.getValue().isUpdated())
.build())
.collect(Collectors.toList());
}
public static Stack deleteStack(CloudFormationClient client, String stackName) {
Objects.requireNonNull(client, "CloudFormation client can't be null");
Objects.requireNonNull(stackName, "stack name can't be null");
DeleteStackRequest request = DeleteStackRequest.builder()
.stackName(stackName)
.build();
client.deleteStack(request);
return getStack(client, stackName);
}
public static Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy