// 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 }
// 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) }
// 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 }
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 }
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: }
// 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) }) }
// 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) }
// 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 }