func displayProgress(stack string, CloudFormation *cloudformation.CloudFormation, isDeleting bool) error { res, err := CloudFormation.DescribeStackEvents(&cloudformation.DescribeStackEventsInput{ StackName: aws.String(stack), }) if err != nil { return err } for _, event := range res.StackEvents { if events[*event.EventID] == true { continue } events[*event.EventID] = true name := friendlyName(*event.ResourceType) if name == "" { continue } switch *event.ResourceStatus { case "CREATE_IN_PROGRESS": case "CREATE_COMPLETE": if !isDeleting { id := *event.PhysicalResourceID if strings.HasPrefix(id, "arn:") { id = *event.LogicalResourceID } fmt.Printf("Created %s: %s\n", name, id) } case "CREATE_FAILED": return fmt.Errorf("stack creation failed") case "DELETE_IN_PROGRESS": case "DELETE_COMPLETE": id := *event.PhysicalResourceID if strings.HasPrefix(id, "arn:") { id = *event.LogicalResourceID } fmt.Printf("Deleted %s: %s\n", name, id) case "DELETE_FAILED": return fmt.Errorf("stack deletion failed") case "UPDATE_IN_PROGRESS", "UPDATE_COMPLETE", "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS", "UPDATE_FAILED", "UPDATE_ROLLBACK_IN_PROGRESS", "UPDATE_ROLLBACK_COMPLETE", "UPDATE_ROLLBACK_FAILED": default: return fmt.Errorf("Unhandled status: %s\n", *event.ResourceStatus) } } return nil }
func waitForCompletion(stack string, CloudFormation *cloudformation.CloudFormation, isDeleting bool) (string, error) { for { dres, err := CloudFormation.DescribeStacks(&cloudformation.DescribeStacksInput{ StackName: aws.String(stack), }) if err != nil { stdcli.Error(err) } err = displayProgress(stack, CloudFormation, isDeleting) if err != nil { stdcli.Error(err) } if len(dres.Stacks) != 1 { stdcli.Error(fmt.Errorf("could not read stack status")) } switch *dres.Stacks[0].StackStatus { case "CREATE_COMPLETE": // Dump .env if DEVELOPMENT development := os.Getenv("DEVELOPMENT") if development == "Yes" { fmt.Printf("Development .env:\n") // convert Port5432TcpAddr to PORT_5432_TCP_ADDR re := regexp.MustCompile("([a-z])([A-Z0-9])") // lower case letter followed by upper case or number, i.e. Port5432 re2 := regexp.MustCompile("([0-9])([A-Z])") // number followed by upper case letter, i.e. 5432Tcp for _, o := range dres.Stacks[0].Outputs { k := re.ReplaceAllString(*o.OutputKey, "${1}_${2}") k = re2.ReplaceAllString(k, "${1}_${2}") k = strings.ToUpper(k) fmt.Printf("%v=%v\n", k, *o.OutputValue) } } for _, o := range dres.Stacks[0].Outputs { if *o.OutputKey == "Dashboard" { return *o.OutputValue, nil } } return "", fmt.Errorf("could not install stack, contact [email protected] for assistance") case "CREATE_FAILED": return "", fmt.Errorf("stack creation failed, contact [email protected] for assistance") case "ROLLBACK_COMPLETE": return "", fmt.Errorf("stack creation failed, contact [email protected] for assistance") case "DELETE_COMPLETE": return "", nil case "DELETE_FAILED": return "", fmt.Errorf("stack deletion failed, contact [email protected] for assistance") } time.Sleep(2 * time.Second) } }