func BuildDelete(rw http.ResponseWriter, r *http.Request) *httperr.Error { vars := mux.Vars(r) app := vars["app"] build := vars["build"] b, err := provider.BuildDelete(app, build) if err != nil { return httperr.Server(err) } return RenderJson(rw, b) }
func TestBuildDeleteActive(t *testing.T) { aws := StubAwsProvider( describeStacksCycle, build1GetItemCycle, build1GetObjectCycle, describeStacksCycle, releasesBuild1QueryCycle, ) 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) }() _, err := provider.BuildDelete("httpd", "BHINCLZYYVN") assert.Equal(t, err.Error(), "cant delete build contained in active release") }
func TestBuildDelete(t *testing.T) { aws := StubAwsProvider( describeStacksCycle, build2GetItemCycle, build2GetObjectCycle, describeStacksCycle, releasesBuild2QueryCycle, releasesBuild2BatchWriteItemCycle, build2DeleteItemCycle, build2BatchDeleteImageCycle, ) 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.BuildDelete("httpd", "BNOARQMVHUO") assert.Nil(t, err) assert.EqualValues(t, &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 }