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 // Log all CREATE_FAILED to display and MixPanel if !isDeleting && *event.ResourceStatus == "CREATE_FAILED" { msg := fmt.Sprintf("Failed %s: %s", *event.ResourceType, *event.ResourceStatusReason) fmt.Println(msg) sendMixpanelEvent("convox-install-error", msg) } 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": 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_SKIPPED": id := *event.PhysicalResourceId if strings.HasPrefix(id, "arn:") { id = *event.LogicalResourceId } fmt.Printf("Skipped %s: %s\n", name, id) case "DELETE_FAILED": id := *event.PhysicalResourceId if strings.HasPrefix(id, "arn:") { id = *event.LogicalResourceId } fmt.Printf("Failed to delete %s: %s\n", name, id) case "ROLLBACK_IN_PROGRESS", "ROLLBACK_COMPLETE": 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 }