diff --git a/Dockerfile b/Dockerfile index 4fbaf4e..a5d5a26 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,12 @@ FROM golang MAINTAINER Knut Ahlers +RUN set -ex \ + && apt-get update \ + && apt-get install -y texlive-full \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + ADD . /go/src/github.com/Luzifer/tex-api WORKDIR /go/src/github.com/Luzifer/tex-api @@ -9,13 +15,12 @@ RUN set -ex \ && apt-get update \ && apt-get install -y git ca-certificates \ && go install -ldflags "-X main.version=$(git describe --tags || git rev-parse --short HEAD || echo dev)" \ - && apt-get install -y texlive-full \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* EXPOSE 3000 -VOLUME ["/store"] +VOLUME ["/storage"] ENTRYPOINT ["/go/bin/tex-api"] CMD ["--"] diff --git a/main.go b/main.go index 7094539..c153370 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "io" "math" "net/http" + "net/url" "os" "os/exec" "path" @@ -24,7 +25,7 @@ import ( var ( cfg = struct { - ExecutionScript string `flag:"script" default:"tex-build.sh" description:"Script to execute (needs to generate output directory)"` + ExecutionScript string `flag:"script" default:"/go/src/github.com/Luzifer/tex-api/tex-build.sh" description:"Script to execute (needs to generate output directory)"` Listen string `flag:"listen" default:":3000" description:"IP/Port to listen on"` StorageDir string `flag:"storage-dir" default:"/storage" description:"Where to store uploaded ZIPs and resulting files"` VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"` @@ -89,6 +90,13 @@ func (s statusOutput) Save() error { return json.NewEncoder(f).Encode(s) } +func urlMust(u *url.URL, err error) *url.URL { + if err != nil { + log.Fatalf("Unable to retrieve URL from router: %s", err) + } + return u +} + func init() { if err := rconfig.Parse(&cfg); err != nil { log.Fatalf("Unable to parse commandline options: %s", err) @@ -128,8 +136,13 @@ func startNewJob(res http.ResponseWriter, r *http.Request) { } if f, err := os.Create(inputFile); err == nil { - io.Copy(f, r.Body) - f.Close() + defer f.Close() + if _, err := io.Copy(f, r.Body); err != nil { + log.Errorf("Unable to copy input file %q: %s", inputFile, err) + http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError) + return + } + f.Sync() } else { log.Errorf("Unable to write input file %q: %s", inputFile, err) http.Error(res, "An error ocurred. See details in log.", http.StatusInternalServerError) @@ -150,7 +163,7 @@ func startNewJob(res http.ResponseWriter, r *http.Request) { go jobProcessor(jobUUID) - u, _ := router.Get("getJobStatus").URL(jobUUID.String()) + u := urlMust(router.Get("waitForJob").URL("uid", jobUUID.String())) http.Redirect(res, r, u.String(), http.StatusFound) } @@ -216,7 +229,7 @@ func waitForJob(res http.ResponseWriter, r *http.Request) { } if status.Status != statusFinished { - u, _ := router.Get("waitForJob").URL(uid.String()) + u := urlMust(router.Get("waitForJob").URL("uid", uid.String())) u.Query().Set("loop", strconv.Itoa(loop)) <-time.After(time.Duration(math.Pow(sleepBase, float64(loop))) * time.Second) @@ -224,7 +237,7 @@ func waitForJob(res http.ResponseWriter, r *http.Request) { http.Redirect(res, r, u.String(), http.StatusFound) } - u, _ := router.Get("downloadAssets").URL(uid.String()) + u := urlMust(router.Get("downloadAssets").URL("uid", uid.String())) http.Redirect(res, r, u.String(), http.StatusFound) } @@ -307,6 +320,7 @@ func jobProcessor(uid uuid.UUID) { cmd := exec.Command("/bin/bash", cfg.ExecutionScript) cmd.Dir = processingDir + cmd.Stderr = log.StandardLogger().WriterLevel(log.ErrorLevel) status.UpdateStatus(statusStarted) if err := status.Save(); err != nil { diff --git a/tex-build.sh b/tex-build.sh index 0c61d9b..c83517f 100755 --- a/tex-build.sh +++ b/tex-build.sh @@ -3,8 +3,9 @@ set -ex set -o pipefail -BUILD_DIR=$1 +unzip input.zip -cd $BUILD_DIR +mkdir -p output -# TODO(kahlers): Add logic +xelatex -halt-on-error -output-directory=output *.tex +xelatex -halt-on-error -output-directory=output *.tex