func()

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
}