func BuildLogs(ws *websocket.Conn) error { vars := mux.Vars(ws.Request()) app := vars["app"] build := vars["build"] _, err := models.GetApp(app) if awsError(err) == "ValidationError" { return fmt.Errorf("no such app: %s", app) } _, err = models.GetBuild(app, build) if err != nil { return err } // proxy to docker container logs // https://docs.docker.com/reference/api/docker_remote_api_v1.19/#get-container-logs client, err := docker.NewClient("unix:///var/run/docker.sock") if err != nil { return err } r, w := io.Pipe() quit := make(chan bool) go scanLines(r, ws) go keepAlive(ws, quit) err = client.Logs(docker.LogsOptions{ Container: fmt.Sprintf("build-%s", build), Follow: true, Stdout: true, Stderr: true, Tail: "all", RawTerminal: false, OutputStream: w, ErrorStream: w, }) quit <- true return err }
func BuildGet(rw http.ResponseWriter, r *http.Request) error { vars := mux.Vars(r) app := vars["app"] build := vars["build"] _, err := models.GetApp(app) if awsError(err) == "ValidationError" { return fmt.Errorf("no such app: %s", app) } b, err := models.GetBuild(app, build) if err != nil && strings.HasPrefix(err.Error(), "no such build") { return RenderNotFound(rw, err.Error()) } if err != nil { return err } return RenderJson(rw, b) }
func BuildCopy(rw http.ResponseWriter, r *http.Request) *httperr.Error { vars := mux.Vars(r) app := vars["app"] build := vars["build"] dest := r.FormValue("app") _, err := models.GetApp(app) if awsError(err) == "ValidationError" { return httperr.Errorf(404, "no such source app: %s", app) } srcBuild, err := models.GetBuild(app, build) if err != nil && strings.HasPrefix(err.Error(), "no such build") { return httperr.Errorf(404, err.Error()) } if err != nil { return httperr.Server(err) } destApp, err := models.GetApp(dest) if awsError(err) == "ValidationError" { return httperr.Errorf(404, "no such destination app: %s", dest) } destBuild, err := srcBuild.CopyTo(*destApp) if err != nil { return httperr.Server(err) } return RenderJson(rw, destBuild) }
func BuildLogs(ws *websocket.Conn) *httperr.Error { vars := mux.Vars(ws.Request()) app := vars["app"] build := vars["build"] _, err := models.GetApp(app) if awsError(err) == "ValidationError" { return httperr.Errorf(404, "no such app: %s", app) } _, err = models.GetBuild(app, build) if err != nil { return httperr.Server(err) } // default to local docker socket host := "unix:///var/run/docker.sock" // in production loop through docker hosts that the rack is running on // to find the build if os.Getenv("DEVELOPMENT") != "true" { pss, err := models.ListProcesses(os.Getenv("RACK")) if err != nil { return httperr.Server(err) } for _, ps := range pss { client, err := ps.Docker() if err != nil { return httperr.Server(err) } res, err := client.ListContainers(docker.ListContainersOptions{ All: true, Filters: map[string][]string{ "name": []string{fmt.Sprintf("build-%s", build)}, }, }) if len(res) > 0 { host = fmt.Sprintf("http://%s:2376", ps.Host) break } } } fmt.Printf("host %+v\n", host) // proxy to docker container logs // https://docs.docker.com/reference/api/docker_remote_api_v1.19/#get-container-logs client, err := docker.NewClient(host) if err != nil { return httperr.Server(err) } r, w := io.Pipe() quit := make(chan bool) go scanLines(r, ws) go keepAlive(ws, quit) err = client.Logs(docker.LogsOptions{ Container: fmt.Sprintf("build-%s", build), Follow: true, Stdout: true, Stderr: true, Tail: "all", RawTerminal: false, OutputStream: w, ErrorStream: w, }) quit <- true return httperr.Server(err) }