Example #1
0
func (p *AWSProvider) BuildCreateTar(app string, src io.Reader, manifest, description string, cache bool) (*structs.Build, error) {
	a, err := p.AppGet(app)
	if err != nil {
		return nil, err
	}

	b := structs.NewBuild(app)
	b.Description = description

	err = p.BuildSave(b)
	if err != nil {
		return nil, err
	}

	// TODO: save the tarball in s3?

	args := p.buildArgs(a, b, "-")

	env, err := p.buildEnv(a, b, manifest, cache)
	if err != nil {
		return b, err
	}

	err = p.buildRun(a, b, args, env, src)

	p.EventSend(&structs.Event{
		Action: "build:create",
		Data: map[string]string{
			"app": b.App,
			"id":  b.Id,
		},
	}, err)

	return b, err
}
Example #2
0
func (p *AWSProvider) BuildCreateRepo(app, url, manifest, description string, cache bool) (*structs.Build, error) {
	a, err := p.AppGet(app)
	if err != nil {
		return nil, err
	}

	b := structs.NewBuild(app)
	b.Description = description

	err = p.BuildSave(b)
	if err != nil {
		return nil, err
	}

	args := p.buildArgs(a, b, url)

	env, err := p.buildEnv(a, b, manifest, cache)
	if err != nil {
		return b, err
	}

	err = p.buildRun(a, b, args, env, nil)

	// build create is now complete or failed
	p.EventSend(&structs.Event{
		Action: "build:create",
		Data: map[string]string{
			"app": b.App,
			"id":  b.Id,
		},
	}, err)

	return b, err
}
Example #3
0
func (p *AWSProvider) BuildCreate(app, method, url string, opts structs.BuildOptions) (*structs.Build, error) {
	log := Logger.At("BuildCreate").Namespace("app=%q method=%q url=%q", app, method, url).Start()

	_, err := p.AppGet(app)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	b := structs.NewBuild(app)

	b.Description = opts.Description
	b.Started = time.Now()

	if p.IsTest() {
		b.Id = "B123"
		b.Started = time.Unix(1473028693, 0).UTC()
		b.Ended = time.Unix(1473028892, 0).UTC()
	}

	if err := p.BuildSave(b); err != nil {
		log.Error(err)
		return nil, err
	}

	if err := p.runBuild(b, method, url, opts); err != nil {
		log.Error(err)
		return nil, err
	}

	p.EventSend(&structs.Event{
		Action: "build:create",
		Data: map[string]string{
			"app": b.App,
			"id":  b.Id,
		},
	}, nil)

	// AWS currently has a limit of 1000 images in ECR
	// This is a "hopefully temporary" and brute force means
	// to prevent hitting limits during deployment
	bs, err := p.BuildList(app, 150)
	if err != nil {
		fmt.Printf("Error listing builds for cleanup: %s\n", err.Error())
	} else {
		if len(bs) >= 50 {
			go func() {
				for _, b := range bs[50:] {
					_, err := p.BuildDelete(app, b.Id)
					if err != nil {
						fmt.Printf("Error cleaning up build %s: %s\n", b.Id, err.Error())
					}
					time.Sleep(1 * time.Second)
				}
			}()
		}
	}

	log.Success()
	return b, nil
}
Example #4
0
// BuildImport imports a build artifact
func (p *AWSProvider) BuildImport(app string, r io.Reader) (*structs.Build, error) {
	log := Logger.At("BuildImport").Namespace("app=%s", app).Start()

	var sourceBuild structs.Build

	// set up the new build
	targetBuild := structs.NewBuild(app)
	targetBuild.Started = time.Now()
	targetBuild.Status = "complete"

	if p.IsTest() {
		targetBuild.Id = "B12345"
	}

	repo, err := p.appRepository(app)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	if err := p.dockerLogin(); err != nil {
		log.Error(err)
		return nil, err
	}

	gz, err := gzip.NewReader(r)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	tr := tar.NewReader(gz)

	for {
		header, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Error(err)
			return nil, err
		}
		if header.Typeflag != tar.TypeReg {
			continue
		}

		if header.Name == "build.json" {
			var buf bytes.Buffer

			io.Copy(&buf, tr)

			if err := json.Unmarshal(buf.Bytes(), &sourceBuild); err != nil {
				log.Error(err)
				return nil, err
			}
		}

		if strings.HasSuffix(header.Name, ".tar") {
			log.Step("load").Logf("tar=%q", header.Name)

			cmd := exec.Command("docker", "load")

			pr, pw := io.Pipe()
			tee := io.TeeReader(tr, pw)
			outb := &bytes.Buffer{}

			cmd.Stdin = pr
			cmd.Stdout = outb

			if err := cmd.Start(); err != nil {
				log.Error(err)
				return nil, err
			}

			log.Step("manifest").Logf("tar=%q", header.Name)
			manifest, err := extractImageManifest(tee)
			if err != nil {
				log.Error(err)
				return nil, err
			}

			if err := pw.Close(); err != nil {
				log.Error(err)
				return nil, err
			}

			if err := cmd.Wait(); err != nil {
				return nil, log.Errorf("%s: %s\n", lastline(outb.Bytes()), err.Error())
			}

			if len(manifest) != 1 || len(manifest[0].RepoTags) != 1 {
				log.Errorf("invalid image manifest")
				return nil, fmt.Errorf("invalid image manifest")
			}

			image := manifest[0].RepoTags[0]
			ps := strings.Split(header.Name, ".")[0]
			target := fmt.Sprintf("%s:%s.%s", repo.URI, ps, targetBuild.Id)

			log.Step("tag").Logf("from=%q to=%q", image, target)
			if out, err := exec.Command("docker", "tag", image, target).CombinedOutput(); err != nil {
				return nil, log.Error(fmt.Errorf("%s: %s\n", lastline(out), err.Error()))
			}

			log.Step("push").Logf("to=%q", target)
			if out, err := exec.Command("docker", "push", target).CombinedOutput(); err != nil {
				return nil, log.Error(fmt.Errorf("%s: %s\n", lastline(out), err.Error()))
			}
		}
	}

	env, err := p.EnvironmentGet(app)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	release := structs.NewRelease(app)

	if p.IsTest() {
		release.Id = "R23456"
	}

	targetBuild.Description = sourceBuild.Description
	targetBuild.Ended = time.Now()
	targetBuild.Logs = sourceBuild.Logs
	targetBuild.Manifest = sourceBuild.Manifest
	targetBuild.Release = release.Id

	if err := p.BuildSave(targetBuild); err != nil {
		log.Error(err)
		return nil, err
	}

	release.Env = env.Raw()
	release.Build = targetBuild.Id
	release.Manifest = targetBuild.Manifest

	if err := p.ReleaseSave(release); err != nil {
		log.Error(err)
		return nil, err
	}

	log.Successf("build=%q release=%q", targetBuild.Id, release.Id)

	return targetBuild, nil
}