func ReleaseList(rw http.ResponseWriter, r *http.Request) *httperr.Error { app := mux.Vars(r)["app"] releases, err := provider.ReleaseList(app) if awsError(err) == "ValidationError" { return httperr.Errorf(404, "no such app: %s", app) } if err != nil { return httperr.Server(err) } return RenderJson(rw, releases) }
func SystemReleaseList(rw http.ResponseWriter, r *http.Request) *httperr.Error { rack, err := provider.SystemGet() if awsError(err) == "ValidationError" { return httperr.Errorf(404, "no such stack: %s", rack) } if err != nil { return httperr.Server(err) } releases, err := provider.ReleaseList(rack.Name) if err != nil { return httperr.Server(err) } return RenderJson(rw, releases) }
// FIXME: Port to provider interface func (a *App) LatestRelease() (*Release, error) { releases, err := provider.ReleaseList(a.Name) if err != nil { return nil, err } if len(releases) == 0 { return nil, nil } r := releases[0] return &Release{ Id: r.Id, App: r.App, Build: r.Build, Env: r.Env, Manifest: r.Manifest, Created: r.Created, }, nil }
func TestReleaseList(t *testing.T) { aws := StubAwsProvider( describeStacksCycle, releasesQueryCycle, ) 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) }() r, err := provider.ReleaseList("httpd") assert.Nil(t, err) assert.EqualValues(t, structs.Releases{ structs.Release{ Id: "RVFETUHHKKD", App: "httpd", Build: "BHINCLZYYVN", Env: "foo=bar", Manifest: "web:\n image: httpd\n ports:\n - 80:80\n", Created: time.Unix(1459780542, 627770380).UTC(), }, structs.Release{ Id: "RFVZFLKVTYO", App: "httpd", Build: "BNOARQMVHUO", Env: "foo=bar", Manifest: "web:\n image: httpd\n ports:\n - 80:80\n", Created: time.Unix(1459709199, 166694813).UTC(), }, }, r) }
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 }