func BuildList(rw http.ResponseWriter, r *http.Request) *httperr.Error { app := mux.Vars(r)["app"] builds, err := provider.BuildList(app) if awsError(err) == "ValidationError" { return httperr.Errorf(404, "no such app: %s", app) } if err != nil { return httperr.Server(err) } return RenderJson(rw, builds) }
func TestBuildList(t *testing.T) { aws := StubAwsProvider( describeStacksCycle, buildsQueryCycle, build1GetObjectCycle, build2GetObjectCycle, ) defer aws.Close() defer func() { //TODO: remove: as we arent updating all tests we need to set current provider back to a //clean default one (I miss rspec before) provider.CurrentProvider = new(provider.TestProviderRunner) }() b, err := provider.BuildList("httpd") assert.Nil(t, err) assert.EqualValues(t, structs.Builds{ structs.Build{ Id: "BHINCLZYYVN", App: "httpd", Logs: "RUNNING: docker pull httpd", Manifest: "web:\n image: httpd\n ports:\n - 80:80\n", Release: "RVFETUHHKKD", Status: "complete", Started: time.Unix(1459780456, 178278576).UTC(), Ended: time.Unix(1459780542, 440881687).UTC(), }, structs.Build{ Id: "BNOARQMVHUO", App: "httpd", Logs: "RUNNING: docker pull httpd", Manifest: "web:\n image: httpd\n ports:\n - 80:80\n", Release: "RFVZFLKVTYO", Status: "complete", Started: time.Unix(1459709087, 472025215).UTC(), Ended: time.Unix(1459709198, 984281955).UTC(), }, }, b) }
func (a *App) Cleanup() error { err := cleanupBucket(a.Outputs["Settings"]) if err != nil { return err } // FIXME: BuildList and ReleaseList only lists and cleans up the last 20 builds/releases // FIXME: Should the delete calls happen in a goroutine? builds, err := provider.BuildList(a.Name) if err != nil { return err } for _, build := range builds { provider.BuildDelete(a.Name, build.Id) } releases, err := provider.ReleaseList(a.Name) if err != nil { return err } for _, release := range releases { provider.ReleaseDelete(a.Name, release.Id) } // monitor and stack deletion state for up to 10 minutes // retry once if DELETE_FAILED to automate around transient errors // send delete success event only when stack is gone shouldRetry := true for i := 0; i < 60; i++ { res, err := CloudFormation().DescribeStacks(&cloudformation.DescribeStacksInput{ StackName: aws.String(a.StackName()), }) // return when stack is not found indicating successful delete if ae, ok := err.(awserr.Error); ok { if ae.Code() == "ValidationError" { helpers.TrackEvent("kernel-app-delete-success", nil) // Last ditch effort to remove the empty bucket CF leaves behind. _, err := S3().DeleteBucket(&s3.DeleteBucketInput{Bucket: aws.String(a.Outputs["Settings"])}) if err != nil { fmt.Printf("error: %s\n", err) } return nil } } if err == nil && len(res.Stacks) == 1 && shouldRetry { // if delete failed, issue one more delete stack and return s := res.Stacks[0] if *s.StackStatus == "DELETE_FAILED" { helpers.TrackEvent("kernel-app-delete-retry", nil) _, err := CloudFormation().DeleteStack(&cloudformation.DeleteStackInput{StackName: aws.String(a.StackName())}) if err != nil { helpers.TrackEvent("kernel-app-delete-retry-error", nil) } else { shouldRetry = false } } } time.Sleep(10 * time.Second) } return nil }