Beispiel #1
0
// Build builds the image.
func (b *Builder) Build(ctx context.Context, w io.Writer, opts builder.BuildOptions) (image string, err error) {
	log.Printf("Starting build: id=%s repository=%s branch=%s sha=%s",
		opts.ID,
		opts.Repository,
		opts.Branch,
		opts.Sha,
	)

	// Embed the reporter in the context.Context.
	ctx = reporter.WithReporter(ctx, b.reporter())

	if b.Timeout != 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, b.Timeout)
		defer cancel() // Release resources.
	}

	reporter.AddContext(ctx, "options", opts)
	defer reporter.Monitor(ctx)

	defer func() {
		if err != nil {
			reporter.Report(ctx, err)
		}
	}()

	image, err = b.builder.Build(ctx, w, opts)
	return
}
Beispiel #2
0
// ServeHTTPContext implements the httpx.Handler interface. It will ensure that
// there is a Bearer token present and that it is valid.
func (h *Authentication) ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
	token, ok := extractToken(r)
	if !ok {
		return ErrUnauthorized
	}

	at, err := h.findAccessToken(token)
	if err != nil {
		return err
	}

	// Token is invalid or not found.
	if at == nil {
		return ErrUnauthorized
	}

	user := at.User

	// Embed the associated user into the context.
	ctx = empire.WithUser(ctx, user)

	logger.Info(ctx,
		"authenticated",
		"user", user.Name,
	)

	reporter.AddContext(ctx, "user", user.Name)

	return h.handler.ServeHTTPContext(ctx, w, r)
}
Beispiel #3
0
// ServeHTTPContext implements the httpx.Handler interface. It recovers from
// panics and returns an error for upstream middleware to handle.
func (h *Recovery) ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) (err error) {
	ctx = reporter.WithReporter(ctx, h.Reporter)

	// Add the request to the context.
	reporter.AddRequest(ctx, r)

	// Add the request id
	reporter.AddContext(ctx, "request_id", httpx.RequestID(ctx))

	defer func() {
		if v := recover(); v != nil {
			err = fmt.Errorf("%v", v)

			if v, ok := v.(error); ok {
				err = v
			}

			reporter.Report(ctx, err)

			return
		}
	}()

	err = h.handler.ServeHTTPContext(ctx, w, r)

	return
}
Beispiel #4
0
func findApp(ctx context.Context, e interface {
	AppsFind(empire.AppsQuery) (*empire.App, error)
}) (*empire.App, error) {
	vars := httpx.Vars(ctx)
	name := vars["app"]

	a, err := e.AppsFind(empire.AppsQuery{Name: &name})
	reporter.AddContext(ctx, "app", a.Name)
	return a, err
}
Beispiel #5
0
func Example() {
	ctx := reporter.WithReporter(context.Background(), hb.NewReporter("dcb8affa"))
	req, _ := http.NewRequest("GET", "/api/foo", nil)
	req.Header.Set("Content-Type", "application/json")

	reporter.AddContext(ctx, "request_id", "1234")
	reporter.AddRequest(ctx, req)
	reporter.Report(ctx, errBoom)
	// Output:
}
Beispiel #6
0
// WithRequest adds information about the http.Request to reported errors.
func WithRequest(h httpx.Handler) httpx.Handler {
	return httpx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		ctx = httpx.WithRequest(ctx, r)

		// Add the request to the context.
		reporter.AddRequest(ctx, r)

		// Add the request id
		reporter.AddContext(ctx, "request_id", httpx.RequestID(ctx))

		return h.ServeHTTPContext(ctx, w, r)
	})
}
Beispiel #7
0
// ServeHTTPContext implements the httpx.Handler interface. It will ensure that
// there is a Bearer token present and that it is valid.
func (h *Authentication) ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
	username, password, ok := r.BasicAuth()
	if !ok {
		return ErrUnauthorized
	}

	user, err := h.authenticator.Authenticate(username, password, r.Header.Get(HeaderTwoFactor))
	if err != nil {
		switch err {
		case auth.ErrTwoFactor:
			return ErrTwoFactor
		case auth.ErrForbidden:
			return ErrUnauthorized
		}

		if err, ok := err.(*auth.UnauthorizedError); ok {
			return errUnauthorized(err)
		}

		return &ErrorResource{
			Status:  http.StatusForbidden,
			ID:      "forbidden",
			Message: err.Error(),
		}
	}

	// Embed the associated user into the context.
	ctx = WithUser(ctx, user)

	logger.Info(ctx,
		"authenticated",
		"user", user.Name,
	)

	reporter.AddContext(ctx, "user", user.Name)

	return h.handler.ServeHTTPContext(ctx, w, r)
}
Beispiel #8
0
// Build executes the docker image.
func (b *Builder) Build(ctx context.Context, w io.Writer, opts builder.BuildOptions) (string, error) {
	env := []string{
		fmt.Sprintf("REPOSITORY=%s", opts.Repository),
		fmt.Sprintf("BRANCH=%s", opts.Branch),
		fmt.Sprintf("SHA=%s", opts.Sha),
		fmt.Sprintf("DRY=%s", b.dryRun()),
		fmt.Sprintf("CACHE=%s", b.cache(opts)),
	}

	name := strings.Join([]string{
		strings.Replace(opts.Repository, "/", "-", -1),
		opts.Sha,
		uuid.New(),
	}, "-")

	c, err := b.client.CreateContainer(docker.CreateContainerOptions{
		Name: name,
		Config: &docker.Config{
			Tty:          false,
			AttachStdout: true,
			AttachStderr: true,
			OpenStdin:    true,
			Image:        b.image(),
			Hostname:     hostname,
			Env:          env,
		},
	})
	if err != nil {
		return "", fmt.Errorf("create container: %v", err)
	}
	defer b.client.RemoveContainer(docker.RemoveContainerOptions{
		ID:            c.ID,
		RemoveVolumes: true,
		Force:         true,
	})

	reporter.AddContext(ctx, "container_id", c.ID)

	if err := b.client.StartContainer(c.ID, &docker.HostConfig{
		Privileged:  true,
		VolumesFrom: []string{b.dataVolume()},
	}); err != nil {
		return "", fmt.Errorf("start container: %v", err)
	}

	done := make(chan error, 1)
	go func() {
		err := b.client.AttachToContainer(docker.AttachToContainerOptions{
			Container:    c.ID,
			OutputStream: w,
			ErrorStream:  w,
			Logs:         true,
			Stream:       true,
			Stdout:       true,
			Stderr:       true,
			RawTerminal:  false,
		})
		done <- err
	}()

	var canceled bool
	select {
	case <-ctx.Done():
		// Build was canceled or the build timedout. Stop the container
		// prematurely. We'll SIGTERM and give it 10 seconds to stop,
		// after that we'll SIGKILL.
		if err := b.client.StopContainer(c.ID, 10); err != nil {
			return "", fmt.Errorf("stop: %v", err)
		}

		// Wait for log streaming to finish.
		err := <-done
		if err != nil {
			return "", fmt.Errorf("attach: %v", err)
		}

		canceled = true
	case err := <-done:
		if err != nil {
			return "", fmt.Errorf("attach: %v", err)
		}
	}

	exit, err := b.client.WaitContainer(c.ID)
	if err != nil {
		return "", fmt.Errorf("wait container: %v", err)
	}

	// A non-zero exit status means the build failed.
	if exit != 0 {
		err := fmt.Errorf("container returned a non-zero exit code: %d", exit)
		if canceled {
			err = &builder.BuildCanceledError{
				Err:    err,
				Reason: ctx.Err(),
			}
		}
		return "", err
	}

	image := fmt.Sprintf("%s:%s", opts.Repository, opts.Sha)
	return image, nil
}