in pkg/cfn/cfn.go [97:161]
func (c Cfn) CreateStack(stackName, template string, zones []*ec2.AvailabilityZone) (*string, error) {
fmt.Println("Creating CloudFormation stack...")
input := &cloudformation.CreateStackInput{
StackName: aws.String(stackName),
TemplateBody: aws.String(template),
Tags: getSimpleEc2Tags(),
}
if zones != nil && len(zones) > 0 {
input.Parameters = []*cloudformation.Parameter{
{
ParameterKey: aws.String("AZ0"),
ParameterValue: zones[0].ZoneName,
},
{
ParameterKey: aws.String("AZ1"),
ParameterValue: zones[1].ZoneName,
},
{
ParameterKey: aws.String("AZ2"),
ParameterValue: zones[2].ZoneName,
},
}
}
output, err := c.Svc.CreateStack(input)
if err != nil {
return nil, err
}
// Keep pinging the stack on creationCheckInterval periodic, until its creation finishes or fails
for {
events, err := c.GetStackEventsByName(stackName)
if err != nil {
return nil, err
}
// Loop over the events and decide further actions
ifEnd := false
for _, event := range events {
/*
If the resource is the stack and status is create complete, move on.
if the status is create failed, no matter what the resource is, throw an error with reason
*/
if *event.LogicalResourceId == stackName &&
*event.ResourceStatus == cloudformation.ResourceStatusCreateComplete {
ifEnd = true
} else if *event.ResourceStatus == cloudformation.ResourceStatusCreateFailed {
return nil, errors.New("Stack creation failed: " + *event.LogicalResourceId + *event.ResourceStatusReason)
}
}
if ifEnd {
break
}
// Sleep to prevent rate exceeded error
time.Sleep(creationCheckInterval)
}
fmt.Println("CloudFormation stack", stackName, "created successfully")
return output.StackId, nil
}