Example #1
0
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)
}
Example #2
0
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")
}
Example #3
0
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)
}
Example #4
0
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
}