util/awsservice/cloudformation.go (66 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
package awsservice
import (
"context"
"log"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudformation"
"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
"github.com/google/uuid"
)
const instanceIdKey = "InstanceId"
func CreateStackName(stackPrefix string) string {
// Create stack name
// Only adding the first 5 char for readability
// Chance of conflict is 1 in 35^5 or about 1 in 52.5 million
generatedUuid, err := uuid.NewUUID()
if err != nil {
log.Fatalf("Failed to create uuid error %v", err)
}
return stackPrefix + generatedUuid.String()[0:5]
}
func StartStack(ctx context.Context, stackName string, client *cloudformation.Client, templateText string, timeOutInMinutes int32, parameters []types.Parameter) {
log.Printf("Template text : %s", templateText)
// Create cf stack config
createStackInput := cloudformation.CreateStackInput{
StackName: aws.String(stackName),
TemplateBody: aws.String(templateText),
TimeoutInMinutes: aws.Int32(timeOutInMinutes),
Parameters: parameters,
}
// Start cf stack
_, err := client.CreateStack(ctx, &createStackInput)
if err != nil {
log.Fatalf("Failed to create stack %v", err)
}
}
func DeleteStack(ctx context.Context, stackName string, client *cloudformation.Client) {
r := recover()
deleteStackInput := cloudformation.DeleteStackInput{
StackName: aws.String(stackName),
}
_, err := client.DeleteStack(ctx, &deleteStackInput)
if err != nil {
log.Fatalf("Could not delete stack %s", stackName)
}
if r != nil {
log.Fatalf("Delete stack %s is called on panic thus delete stack then continue panic", stackName)
}
}
func FindStackInstanceId(ctx context.Context, stackName string, client *cloudformation.Client, timeOutMinutes int) string {
for i := 0; i <= timeOutMinutes; i++ {
cfStackInput := cloudformation.DescribeStacksInput{
StackName: aws.String(stackName),
}
stacks, err := client.DescribeStacks(ctx, &cfStackInput)
if err != nil || len(stacks.Stacks) != 1 || stacks.Stacks[0].StackStatus != types.StackStatusCreateComplete {
log.Printf("Stack %s not ready in minute %d continue to next minute", stackName, i)
} else {
for output := range stacks.Stacks[0].Outputs {
if *stacks.Stacks[0].Outputs[output].OutputKey == instanceIdKey {
log.Printf("Found instance id %s from stack %s", *stacks.Stacks[0].Outputs[output].OutputValue, stackName)
return *stacks.Stacks[0].Outputs[output].OutputValue
}
}
}
log.Printf("Sleep for one minute to wait for stack to start")
time.Sleep(time.Minute)
}
log.Fatalf("Stack not created within timeout %s", stackName)
return ""
}