diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88dff59..b252820 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html before sending patches. **We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). +(we use [Gerrit](https://www.gerritcodereview.com/) instead for code review). Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a99db1e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,181 @@ +# Copyright 2017 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. +FROM debian:jessie +LABEL maintainer "golang-dev@googlegroups.com" + +ENV GOPATH /go +ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH +ENV GOROOT_BOOTSTRAP /usr/local/gobootstrap +ENV GO_VERSION 1.9.2 +ENV BUILD_DEPS 'curl bzip2 git ca-certificates gcc patch libc6-dev' + +# Fake time +COPY enable-fake-time.patch /usr/local/playground/ +# Fake file system +COPY fake_fs.lst /usr/local/playground/ + +RUN set -x && \ + apt-get update && apt-get install -y ${BUILD_DEPS} --no-install-recommends && rm -rf /var/lib/apt/lists/* + +RUN curl -s https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/49.0.2623.87/naclsdk_linux.tar.bz2 | tar -xj -C /usr/local/bin --strip-components=2 pepper_49/tools/sel_ldr_x86_64 + +# Get the Go binary. +RUN curl -sSL https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz -o /tmp/go.tar.gz && \ + curl -sSL https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz.sha256 -o /tmp/go.tar.gz.sha256 && \ + echo "$(cat /tmp/go.tar.gz.sha256) /tmp/go.tar.gz" | sha256sum -c - && \ + tar -C /usr/local/ -vxzf /tmp/go.tar.gz && \ + rm /tmp/go.tar.gz /tmp/go.tar.gz.sha256 && \ + # Make a copy for GOROOT_BOOTSTRAP, because we rebuild the toolchain and make.bash removes bin/go as its first step. + cp -R /usr/local/go $GOROOT_BOOTSTRAP && \ + # Apply the fake time and fake filesystem patches. + patch /usr/local/go/src/runtime/rt0_nacl_amd64p32.s /usr/local/playground/enable-fake-time.patch && \ + cd /usr/local/go && go run misc/nacl/mkzip.go -p syscall /usr/local/playground/fake_fs.lst src/syscall/fstest_nacl.go && \ + # Re-build the Go toolchain. + cd /usr/local/go/src && GOOS=nacl GOARCH=amd64p32 ./make.bash --no-clean && \ + # Clean up. + rm -rf $GOROOT_BOOTSTRAP + +# Add and compile tour packages +RUN GOOS=nacl GOARCH=amd64p32 go get \ + golang.org/x/tour/pic \ + golang.org/x/tour/reader \ + golang.org/x/tour/tree \ + golang.org/x/tour/wc \ + golang.org/x/talks/2016/applicative/google && \ + rm -rf $GOPATH/src/golang.org/x/tour/.git && \ + rm -rf $GOPATH/src/golang.org/x/talks/.git + +# Add tour packages under their old import paths (so old snippets still work) +RUN mkdir -p $GOPATH/src/code.google.com/p/go-tour && \ + cp -R $GOPATH/src/golang.org/x/tour/* $GOPATH/src/code.google.com/p/go-tour/ && \ + sed -i 's_// import_// public import_' $(find $GOPATH/src/code.google.com/p/go-tour/ -name *.go) && \ + go install \ + code.google.com/p/go-tour/pic \ + code.google.com/p/go-tour/reader \ + code.google.com/p/go-tour/tree \ + code.google.com/p/go-tour/wc + +# BEGIN deps (run `make update-deps` to update) + +# Repo cloud.google.com/go at 558b56d (2017-07-03) +ENV REV=558b56dfa3c56acc26fef35cb07f97df0bb18b39 +RUN go get -d cloud.google.com/go/compute/metadata `#and 5 other pkgs` &&\ + (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo github.com/golang/protobuf at 748d386 (2017-07-26) +ENV REV=748d386b5c1ea99658fd69fe9f03991ce86a90c1 +RUN go get -d github.com/golang/protobuf/proto `#and 6 other pkgs` &&\ + (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/net at 66aacef (2017-08-28) +ENV REV=66aacef3dd8a676686c7ae3716979581e8b03c47 +RUN go get -d golang.org/x/net/context `#and 8 other pkgs` &&\ + (cd /go/src/golang.org/x/net && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/oauth2 at cce311a (2017-06-29) +ENV REV=cce311a261e6fcf29de72ca96827bdb0b7d9c9e6 +RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\ + (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/text at 2bf8f2a (2017-06-30) +ENV REV=2bf8f2a19ec09c670e931282edfe6567f6be21c9 +RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\ + (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/tools at 89c69fd (2017-09-01) +ENV REV=89c69fd3045b723bb4d9f75d73b881c50ab481c0 +RUN go get -d golang.org/x/tools/go/ast/astutil `#and 3 other pkgs` &&\ + (cd /go/src/golang.org/x/tools && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo google.golang.org/api at e6586c9 (2017-06-27) +ENV REV=e6586c9293b9d514c7f5d5076731ec977cff1be6 +RUN go get -d google.golang.org/api/googleapi/transport `#and 5 other pkgs` &&\ + (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo google.golang.org/genproto at aa2eb68 (2017-06-01) +ENV REV=aa2eb687b4d3e17154372564ad8d6bf11c3cf21f +RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 4 other pkgs` &&\ + (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo google.golang.org/grpc at 3c33c26 (2017-06-27) +ENV REV=3c33c26290b747350f8650c7d38bcc51b42dc785 +RUN go get -d google.golang.org/grpc `#and 15 other pkgs` &&\ + (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Optimization to speed up iterative development, not necessary for correctness: +RUN go install cloud.google.com/go/compute/metadata \ + cloud.google.com/go/datastore \ + cloud.google.com/go/internal/atomiccache \ + cloud.google.com/go/internal/fields \ + cloud.google.com/go/internal/version \ + github.com/golang/protobuf/proto \ + github.com/golang/protobuf/protoc-gen-go/descriptor \ + github.com/golang/protobuf/ptypes/any \ + github.com/golang/protobuf/ptypes/struct \ + github.com/golang/protobuf/ptypes/timestamp \ + github.com/golang/protobuf/ptypes/wrappers \ + golang.org/x/net/context \ + golang.org/x/net/context/ctxhttp \ + golang.org/x/net/http2 \ + golang.org/x/net/http2/hpack \ + golang.org/x/net/idna \ + golang.org/x/net/internal/timeseries \ + golang.org/x/net/lex/httplex \ + golang.org/x/net/trace \ + golang.org/x/oauth2 \ + golang.org/x/oauth2/google \ + golang.org/x/oauth2/internal \ + golang.org/x/oauth2/jws \ + golang.org/x/oauth2/jwt \ + golang.org/x/text/secure/bidirule \ + golang.org/x/text/transform \ + golang.org/x/text/unicode/bidi \ + golang.org/x/text/unicode/norm \ + golang.org/x/tools/go/ast/astutil \ + golang.org/x/tools/godoc/static \ + golang.org/x/tools/imports \ + google.golang.org/api/googleapi/transport \ + google.golang.org/api/internal \ + google.golang.org/api/iterator \ + google.golang.org/api/option \ + google.golang.org/api/transport \ + google.golang.org/genproto/googleapis/api/annotations \ + google.golang.org/genproto/googleapis/datastore/v1 \ + google.golang.org/genproto/googleapis/rpc/status \ + google.golang.org/genproto/googleapis/type/latlng \ + google.golang.org/grpc \ + google.golang.org/grpc/codes \ + google.golang.org/grpc/credentials \ + google.golang.org/grpc/credentials/oauth \ + google.golang.org/grpc/grpclb/grpc_lb_v1 \ + google.golang.org/grpc/grpclog \ + google.golang.org/grpc/internal \ + google.golang.org/grpc/keepalive \ + google.golang.org/grpc/metadata \ + google.golang.org/grpc/naming \ + google.golang.org/grpc/peer \ + google.golang.org/grpc/stats \ + google.golang.org/grpc/status \ + google.golang.org/grpc/tap \ + google.golang.org/grpc/transport +# END deps + +RUN apt-get purge -y --auto-remove ${BUILD_DEPS} + +# Add and compile playground daemon +COPY . /go/src/playground/ +RUN go install playground + +RUN mkdir /app + +COPY edit.html /app +COPY static /app/static + +WORKDIR /app + +# Run tests +RUN /go/bin/playground test + +EXPOSE 8080 +ENTRYPOINT ["/go/bin/playground"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0854a90 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: update-deps docker test + +update-deps: + go install golang.org/x/build/cmd/gitlock + gitlock --update=Dockerfile golang.org/x/playground/frontend + +docker: Dockerfile + docker build -t playground . + +test: docker + go test + docker run --rm playground test diff --git a/README.md b/README.md index 2fd7edc..ec92d82 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,31 @@ # playground -This subrepository holds the source for various packages and tools that support -the Go playground: https://play.golang.org/ +This subrepository holds the source for the Go playground: +https://play.golang.org/ To submit changes to this repository, see http://golang.org/doc/contribute.html. -## Frontend - -### Building +## Building ``` -# build the frontend image -docker build -t frontend frontend/ +# build the image +docker build -t playground . ``` -### Running with an in-memory store +## Running ``` -docker run --rm -d -p 8080:8080 frontend -``` - -### Running with the Cloud Datastore Emulator - -``` -# install it if needed -gcloud components install cloud-datastore-emulator -# run the datastore emulator -gcloud --project=golang-org beta emulators datastore start -# set env vars -$(gcloud beta emulators datastore env-init) -# run the frontend -cd frontend && go install && frontend -``` - -Now visit localhost:8080 to ensure it worked. - -``` -# unset any env vars once finished -$(gcloud beta emulators datastore env-unset) -``` - -## Sandbox - -### Building - -``` -# build the sandbox image -docker build -t sandbox sandbox/ -``` - -### Running - -``` -# run the sandbox -docker run -d -p 8080:8080 sandbox -# get docker host ip, try boot2docker fallback on localhost. -DOCKER_HOST_IP=$(boot2docker ip || echo localhost) +docker run --rm -d -p 8080:8080 playground # run go some code -cat /path/to/code.go | go run ./sandbox/client.go | curl --data @- $DOCKER_HOST_IP:8080/compile +cat /path/to/code.go | go run client.go | curl --data @- localhost:8080/compile ``` -To submit changes to this repository, see http://golang.org/doc/contribute.html. - # Deployment ``` -gcloud --project=golang-org --account=person@example.com app deploy frontend/app.yaml +gcloud --project=golang-org --account=person@example.com app deploy app.yaml ``` -``` -gcloud --project=golang-org --account=person@example.com app deploy sandbox/app-flex.yaml --no-promote -``` +# Contributing -Use the Cloud Console's to set the new version as the default: -https://cloud.google.com/console/appengine/versions?project=golang-org&moduleId=sandbox-flex -Then test that play.golang.org and tour.golang.org are working before deleting -the old version. +To submit changes to this repository, see http://golang.org/doc/contribute.html. \ No newline at end of file diff --git a/frontend/app.yaml b/app.yaml similarity index 100% rename from frontend/app.yaml rename to app.yaml diff --git a/sandbox/client.go b/client.go similarity index 87% rename from sandbox/client.go rename to client.go index eee62f9..c168c3c 100644 --- a/sandbox/client.go +++ b/client.go @@ -1,6 +1,6 @@ // +build ignore -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/frontend/edit.go b/edit.go similarity index 100% rename from frontend/edit.go rename to edit.go diff --git a/frontend/edit.html b/edit.html similarity index 100% rename from frontend/edit.html rename to edit.html diff --git a/sandbox/enable-fake-time.patch b/enable-fake-time.patch similarity index 100% rename from sandbox/enable-fake-time.patch rename to enable-fake-time.patch diff --git a/sandbox/fake_fs.lst b/fake_fs.lst similarity index 100% rename from sandbox/fake_fs.lst rename to fake_fs.lst diff --git a/frontend/fmt.go b/fmt.go similarity index 100% rename from frontend/fmt.go rename to fmt.go diff --git a/frontend/Dockerfile b/frontend/Dockerfile deleted file mode 100644 index 1594a89..0000000 --- a/frontend/Dockerfile +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2017 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. -FROM golang:1.9.2 -LABEL maintainer "golang-dev@googlegroups.com" - -# BEGIN deps (run `make update-deps` to update) - -# Repo cloud.google.com/go at 3051b91 (2017-12-06) -ENV REV=3051b919da3b8d62bc3a57ab4b353ca1c72402d5 -RUN go get -d cloud.google.com/go/compute/metadata `#and 6 other pkgs` &&\ - (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo github.com/golang/protobuf at 1e59b77 (2017-11-13) -ENV REV=1e59b77b52bf8e4b449a57e6f79f21226d571845 -RUN go get -d github.com/golang/protobuf/proto `#and 8 other pkgs` &&\ - (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo github.com/googleapis/gax-go at 317e000 (2017-09-15) -ENV REV=317e0006254c44a0ac427cc52a0e083ff0b9622f -RUN go get -d github.com/googleapis/gax-go &&\ - (cd /go/src/github.com/googleapis/gax-go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo golang.org/x/net at faacc1b (2017-12-07) -ENV REV=faacc1b5e36e3ff02cbec9661c69ac63dd5a83ad -RUN go get -d golang.org/x/net/context `#and 8 other pkgs` &&\ - (cd /go/src/golang.org/x/net && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo golang.org/x/oauth2 at 6a2004c (2017-12-06) -ENV REV=6a2004c8907a86949d71c664c81574897a4e55a6 -RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\ - (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo golang.org/x/text at be25de4 (2017-12-07) -ENV REV=be25de41fadfae372d6470bda81ca6beb55ef551 -RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\ - (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo golang.org/x/tools at 5d8e38b (2017-12-10) -ENV REV=5d8e38b9550d35d893ff8276756b4118ec1bf360 -RUN go get -d golang.org/x/tools/go/ast/astutil `#and 3 other pkgs` &&\ - (cd /go/src/golang.org/x/tools && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo google.golang.org/api at 9a048ca (2017-12-07) -ENV REV=9a048cac3675aa589c62a35d7d42b25451dd15f1 -RUN go get -d google.golang.org/api/googleapi `#and 6 other pkgs` &&\ - (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo google.golang.org/genproto at 7f0da29 (2017-11-23) -ENV REV=7f0da29060c682909f650ad8ed4e515bd74fa12a -RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 4 other pkgs` &&\ - (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Repo google.golang.org/grpc at b8191e5 (2017-12-06) -ENV REV=b8191e57b23de650278db4d23bf596219e5f3665 -RUN go get -d google.golang.org/grpc `#and 24 other pkgs` &&\ - (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) - -# Optimization to speed up iterative development, not necessary for correctness: -RUN go install cloud.google.com/go/compute/metadata \ - cloud.google.com/go/datastore \ - cloud.google.com/go/internal \ - cloud.google.com/go/internal/atomiccache \ - cloud.google.com/go/internal/fields \ - cloud.google.com/go/internal/version \ - github.com/golang/protobuf/proto \ - github.com/golang/protobuf/protoc-gen-go/descriptor \ - github.com/golang/protobuf/ptypes \ - github.com/golang/protobuf/ptypes/any \ - github.com/golang/protobuf/ptypes/duration \ - github.com/golang/protobuf/ptypes/struct \ - github.com/golang/protobuf/ptypes/timestamp \ - github.com/golang/protobuf/ptypes/wrappers \ - github.com/googleapis/gax-go \ - golang.org/x/net/context \ - golang.org/x/net/context/ctxhttp \ - golang.org/x/net/http2 \ - golang.org/x/net/http2/hpack \ - golang.org/x/net/idna \ - golang.org/x/net/internal/timeseries \ - golang.org/x/net/lex/httplex \ - golang.org/x/net/trace \ - golang.org/x/oauth2 \ - golang.org/x/oauth2/google \ - golang.org/x/oauth2/internal \ - golang.org/x/oauth2/jws \ - golang.org/x/oauth2/jwt \ - golang.org/x/text/secure/bidirule \ - golang.org/x/text/transform \ - golang.org/x/text/unicode/bidi \ - golang.org/x/text/unicode/norm \ - golang.org/x/tools/go/ast/astutil \ - golang.org/x/tools/godoc/static \ - golang.org/x/tools/imports \ - google.golang.org/api/googleapi \ - google.golang.org/api/googleapi/internal/uritemplates \ - google.golang.org/api/internal \ - google.golang.org/api/iterator \ - google.golang.org/api/option \ - google.golang.org/api/transport/grpc \ - google.golang.org/genproto/googleapis/api/annotations \ - google.golang.org/genproto/googleapis/datastore/v1 \ - google.golang.org/genproto/googleapis/rpc/status \ - google.golang.org/genproto/googleapis/type/latlng \ - google.golang.org/grpc \ - google.golang.org/grpc/balancer \ - google.golang.org/grpc/balancer/base \ - google.golang.org/grpc/balancer/roundrobin \ - google.golang.org/grpc/codes \ - google.golang.org/grpc/connectivity \ - google.golang.org/grpc/credentials \ - google.golang.org/grpc/credentials/oauth \ - google.golang.org/grpc/encoding \ - google.golang.org/grpc/grpclb/grpc_lb_v1/messages \ - google.golang.org/grpc/grpclog \ - google.golang.org/grpc/internal \ - google.golang.org/grpc/keepalive \ - google.golang.org/grpc/metadata \ - google.golang.org/grpc/naming \ - google.golang.org/grpc/peer \ - google.golang.org/grpc/resolver \ - google.golang.org/grpc/resolver/dns \ - google.golang.org/grpc/resolver/manual \ - google.golang.org/grpc/resolver/passthrough \ - google.golang.org/grpc/stats \ - google.golang.org/grpc/status \ - google.golang.org/grpc/tap \ - google.golang.org/grpc/transport -# END deps - -# Add and compile frontend daemon -COPY . /go/src/frontend/ -RUN go install frontend - -RUN mkdir /app - -COPY edit.html /app -COPY static /app/static - -WORKDIR /app - -EXPOSE 8080 -ENTRYPOINT ["/go/bin/frontend"] diff --git a/frontend/Makefile b/frontend/Makefile deleted file mode 100644 index 2b5f1b5..0000000 --- a/frontend/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -update-deps: - go install golang.org/x/build/cmd/gitlock - gitlock --update=Dockerfile golang.org/x/playground/frontend \ No newline at end of file diff --git a/frontend/compile.go b/frontend/compile.go deleted file mode 100644 index 0c4deb5..0000000 --- a/frontend/compile.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "io" - "net/http" -) - -const runURL = "https://golang.org/compile?output=json" - -func (s *server) handleCompile(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { - http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) - return - } - if err := s.passThru(w, r); err != nil { - http.Error(w, "Compile server error.", http.StatusInternalServerError) - return - } -} - -func (s *server) passThru(w io.Writer, req *http.Request) error { - defer req.Body.Close() - r, err := http.Post(runURL, req.Header.Get("Content-type"), req.Body) - if err != nil { - s.log.Errorf("error making POST request: %v", err) - return err - } - defer r.Body.Close() - if _, err := io.Copy(w, r.Body); err != nil { - s.log.Errorf("error copying response Body: %v", err) - return err - } - return nil -} diff --git a/frontend/logger.go b/logger.go similarity index 100% rename from frontend/logger.go rename to logger.go diff --git a/frontend/main.go b/main.go similarity index 94% rename from frontend/main.go rename to main.go index 497f49c..acef3f6 100644 --- a/frontend/main.go +++ b/main.go @@ -17,6 +17,11 @@ import ( var log = newStdLogger() func main() { + if len(os.Args) > 1 && os.Args[1] == "test" { + test() + return + } + s, err := newServer(func(s *server) error { pid := projectID() if pid == "" { diff --git a/sandbox/play.go b/play.go similarity index 98% rename from sandbox/play.go rename to play.go index 601666f..fd56676 100644 --- a/sandbox/play.go +++ b/play.go @@ -1,4 +1,4 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/sandbox/play_test.go b/play_test.go similarity index 95% rename from sandbox/play_test.go rename to play_test.go index bdf2a0b..69f9dd4 100644 --- a/sandbox/play_test.go +++ b/play_test.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Go Authors. All rights reserved. +// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/sandbox/sandbox.go b/sandbox.go similarity index 70% rename from sandbox/sandbox.go rename to sandbox.go index 69ca24f..97ba0ba 100644 --- a/sandbox/sandbox.go +++ b/sandbox.go @@ -1,23 +1,21 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(adg): add logging -// TODO(proppy): restrict memory use -// TODO(adg): send exit code to user +// TODO(andybons): add logging +// TODO(andybons): restrict memory use +// TODO(andybons): send exit code to user -// Command sandbox is an HTTP server that takes requests containing go -// source files, and builds and executes them in a NaCl sanbox. package main import ( + "context" "encoding/json" - "errors" "fmt" "go/parser" "go/token" "io/ioutil" - "log" + stdlog "log" "net/http" "os" "os/exec" @@ -28,28 +26,22 @@ import ( const maxRunTime = 2 * time.Second -type Request struct { +type request struct { Body string } -type Response struct { +type response struct { Errors string Events []Event } -func main() { - if len(os.Args) > 1 && os.Args[1] == "test" { - test() - return - } - http.HandleFunc("/compile", compileHandler) - http.HandleFunc("/_ah/health", healthHandler) - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func compileHandler(w http.ResponseWriter, r *http.Request) { - var req Request - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { +func handleCompile(w http.ResponseWriter, r *http.Request) { + var req request + // Until programs that depend on golang.org/x/tools/godoc/static/playground.js + // are updated to always send JSON, this check is in place. + if b := r.FormValue("body"); b != "" { + req.Body = b + } else if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, fmt.Sprintf("error decoding request: %v", err), http.StatusBadRequest) return } @@ -64,7 +56,8 @@ func compileHandler(w http.ResponseWriter, r *http.Request) { } } -func compileAndRun(req *Request) (*Response, error) { +func compileAndRun(req *request) (*response, error) { + // TODO(andybons): Add semaphore to limit number of running programs at once. tmpDir, err := ioutil.TempDir("", "sandbox") if err != nil { return nil, fmt.Errorf("error creating temp directory: %v", err) @@ -80,7 +73,7 @@ func compileAndRun(req *Request) (*Response, error) { f, err := parser.ParseFile(fset, in, nil, parser.PackageClauseOnly) if err == nil && f.Name.Name != "main" { - return &Response{Errors: "package name must be main"}, nil + return &response{Errors: "package name must be main"}, nil } exe := filepath.Join(tmpDir, "a.out") @@ -98,17 +91,19 @@ func compileAndRun(req *Request) (*Response, error) { // message before any compile errors; strip it. errs = strings.Replace(errs, "# command-line-arguments\n", "", 1) - return &Response{Errors: errs}, nil + return &response{Errors: errs}, nil } return nil, fmt.Errorf("error building go source: %v", err) } - cmd = exec.Command("sel_ldr_x86_64", "-l", "/dev/null", "-S", "-e", exe) + ctx, cancel := context.WithTimeout(context.Background(), maxRunTime) + defer cancel() + cmd = exec.CommandContext(ctx, "sel_ldr_x86_64", "-l", "/dev/null", "-S", "-e", exe) rec := new(Recorder) cmd.Stdout = rec.Stdout() cmd.Stderr = rec.Stderr() - if err := runTimeout(cmd, maxRunTime); err != nil { - if err == timeoutErr { - return &Response{Errors: "process took too long"}, nil + if err := cmd.Run(); err != nil { + if ctx.Err() == context.DeadlineExceeded { + return &response{Errors: "process took too long"}, nil } if _, ok := err.(*exec.ExitError); !ok { return nil, fmt.Errorf("error running sandbox: %v", err) @@ -118,40 +113,11 @@ func compileAndRun(req *Request) (*Response, error) { if err != nil { return nil, fmt.Errorf("error decoding events: %v", err) } - return &Response{Events: events}, nil -} - -var timeoutErr = errors.New("process timed out") - -func runTimeout(cmd *exec.Cmd, d time.Duration) error { - if err := cmd.Start(); err != nil { - return err - } - errc := make(chan error, 1) - go func() { - errc <- cmd.Wait() - }() - t := time.NewTimer(d) - select { - case err := <-errc: - t.Stop() - return err - case <-t.C: - cmd.Process.Kill() - return timeoutErr - } -} - -func healthHandler(w http.ResponseWriter, r *http.Request) { - if err := healthCheck(); err != nil { - http.Error(w, "Health check failed: "+err.Error(), http.StatusInternalServerError) - return - } - fmt.Fprint(w, "ok") + return &response{Events: events}, nil } func healthCheck() error { - resp, err := compileAndRun(&Request{Body: healthProg}) + resp, err := compileAndRun(&request{Body: healthProg}) if err != nil { return err } @@ -174,24 +140,24 @@ func main() { fmt.Print("ok") } func test() { if err := healthCheck(); err != nil { - log.Fatal(err) + stdlog.Fatal(err) } for _, t := range tests { - resp, err := compileAndRun(&Request{Body: t.prog}) + resp, err := compileAndRun(&request{Body: t.prog}) if err != nil { - log.Fatal(err) + stdlog.Fatal(err) } if t.errors != "" { if resp.Errors != t.errors { - log.Fatalf("resp.Errors = %q, want %q", resp.Errors, t.errors) + stdlog.Fatalf("resp.Errors = %q, want %q", resp.Errors, t.errors) } continue } if resp.Errors != "" { - log.Fatal(resp.Errors) + stdlog.Fatal(resp.Errors) } if len(resp.Events) != 1 || !strings.Contains(resp.Events[0].Message, t.want) { - log.Fatalf("unexpected output: %v, want %q", resp.Events, t.want) + stdlog.Fatalf("unexpected output: %v, want %q", resp.Events, t.want) } } fmt.Println("OK") diff --git a/sandbox/Dockerfile b/sandbox/Dockerfile deleted file mode 100644 index b20cbc4..0000000 --- a/sandbox/Dockerfile +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2014 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -FROM debian:jessie - -ENV GOPATH /go -ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH -ENV GOROOT_BOOTSTRAP /usr/local/gobootstrap -ENV GO_VERSION 1.9.2 - -# Fake time -COPY enable-fake-time.patch /usr/local/sandbox/ -# Fake file system -COPY fake_fs.lst /usr/local/sandbox/ - -RUN set -x && buildDeps='curl ca-certificates bzip2'; \ - apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* && \ - curl -s https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/44.0.2403.157/naclsdk_linux.tar.bz2 | tar -xj -C /usr/local/bin --strip-components=2 pepper_44/tools/sel_ldr_x86_64 && \ - apt-get purge -y --auto-remove $buildDeps - -RUN set -x && buildDeps='curl ca-certificates gcc patch libc6-dev'; \ - apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* && \ - # Get the Go binary. - curl -sSL https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz -o /tmp/go.tar.gz && \ - curl -sSL https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz.sha256 -o /tmp/go.tar.gz.sha256 && \ - echo "$(cat /tmp/go.tar.gz.sha256) /tmp/go.tar.gz" | sha256sum -c - && \ - tar -C /usr/local/ -vxzf /tmp/go.tar.gz && \ - rm /tmp/go.tar.gz /tmp/go.tar.gz.sha256 && \ - # Make a copy for GOROOT_BOOTSTRAP, because we rebuild the toolchain and make.bash removes bin/go as its first step. - cp -R /usr/local/go $GOROOT_BOOTSTRAP && \ - # Apply the fake time and fake filesystem patches. - patch /usr/local/go/src/runtime/rt0_nacl_amd64p32.s /usr/local/sandbox/enable-fake-time.patch && \ - cd /usr/local/go && go run misc/nacl/mkzip.go -p syscall /usr/local/sandbox/fake_fs.lst src/syscall/fstest_nacl.go && \ - # Re-build the Go toolchain. - cd /usr/local/go/src && GOOS=nacl GOARCH=amd64p32 ./make.bash --no-clean && \ - # Clean up. - rm -rf $GOROOT_BOOTSTRAP && \ - apt-get purge -y --auto-remove $buildDeps - -# Add and compile tour packages -RUN set -x && buildDeps='git ca-certificates'; \ - apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* && \ - GOOS=nacl GOARCH=amd64p32 go get \ - golang.org/x/tour/pic \ - golang.org/x/tour/reader \ - golang.org/x/tour/tree \ - golang.org/x/tour/wc \ - golang.org/x/talks/2016/applicative/google && \ - rm -rf $GOPATH/src/golang.org/x/tour/.git && \ - rm -rf $GOPATH/src/golang.org/x/talks/.git && \ - apt-get purge -y --auto-remove $buildDeps - -# Add tour packages under their old import paths (so old snippets still work) -RUN mkdir -p $GOPATH/src/code.google.com/p/go-tour && \ - cp -R $GOPATH/src/golang.org/x/tour/* $GOPATH/src/code.google.com/p/go-tour/ && \ - sed -i 's_// import_// public import_' $(find $GOPATH/src/code.google.com/p/go-tour/ -name *.go) && \ - go install \ - code.google.com/p/go-tour/pic \ - code.google.com/p/go-tour/reader \ - code.google.com/p/go-tour/tree \ - code.google.com/p/go-tour/wc - -# Add and compile sandbox daemon -COPY . /go/src/sandbox/ -RUN go install sandbox - -# Run tests -RUN /go/bin/sandbox test - -EXPOSE 8080 -ENTRYPOINT ["/go/bin/sandbox"] diff --git a/sandbox/Makefile b/sandbox/Makefile deleted file mode 100644 index 72cdfc2..0000000 --- a/sandbox/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -docker: Dockerfile - docker build -t playground/sandbox . - -test: docker - go test - docker run --rm playground/sandbox test diff --git a/sandbox/app-flex.yaml b/sandbox/app-flex.yaml deleted file mode 100644 index fad29f8..0000000 --- a/sandbox/app-flex.yaml +++ /dev/null @@ -1,11 +0,0 @@ -service: sandbox-flex -runtime: custom -env: flex - -automatic_scaling: - min_num_instances: 5 - max_num_instances: 20 - -health_check: - check_interval_sec: 20 - restart_threshold: 10 diff --git a/sandbox/app.yaml b/sandbox/app.yaml deleted file mode 100644 index 8e6a30d..0000000 --- a/sandbox/app.yaml +++ /dev/null @@ -1,16 +0,0 @@ -service: sandbox -runtime: custom -vm: true - -automatic_scaling: - min_num_instances: 5 - max_num_instances: 20 - -health_check: - check_interval_sec: 20 - restart_threshold: 10 - -handlers: -- url: /.* - script: _go_app - diff --git a/sandbox/container-vm.yaml b/sandbox/container-vm.yaml deleted file mode 100644 index 3bd498f..0000000 --- a/sandbox/container-vm.yaml +++ /dev/null @@ -1,8 +0,0 @@ -version: v1beta2 -containers: - - name: sandbox - # TODO(proppy): publish the sandbox image to the hub - image: golang/playground-sandbox - ports: - - containerPort: 8080 - hostPort: 80 diff --git a/frontend/server.go b/server.go similarity index 91% rename from frontend/server.go rename to server.go index 136124c..350b384 100644 --- a/frontend/server.go +++ b/server.go @@ -48,9 +48,9 @@ func newServer(options ...func(s *server) error) (*server, error) { func (s *server) init() { s.mux.HandleFunc("/", s.handleEdit) - s.mux.HandleFunc("/compile", s.handleCompile) s.mux.HandleFunc("/fmt", handleFmt) s.mux.HandleFunc("/share", s.handleShare) + s.mux.HandleFunc("/compile", handleCompile) s.mux.HandleFunc("/playground.js", s.handlePlaygroundJS) s.mux.HandleFunc("/favicon.ico", handleFavicon) s.mux.HandleFunc("/_ah/health", handleHealthCheck) @@ -70,7 +70,11 @@ func handleFavicon(w http.ResponseWriter, r *http.Request) { } func handleHealthCheck(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "ok") + if err := healthCheck(); err != nil { + http.Error(w, "Health check failed: "+err.Error(), http.StatusInternalServerError) + return + } + fmt.Fprint(w, "ok") } func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/frontend/server_test.go b/server_test.go similarity index 100% rename from frontend/server_test.go rename to server_test.go diff --git a/frontend/share.go b/share.go similarity index 100% rename from frontend/share.go rename to share.go diff --git a/frontend/static/favicon.ico b/static/favicon.ico similarity index 100% rename from frontend/static/favicon.ico rename to static/favicon.ico diff --git a/frontend/static/godoc.css b/static/godoc.css similarity index 100% rename from frontend/static/godoc.css rename to static/godoc.css diff --git a/frontend/static/gopher.png b/static/gopher.png similarity index 100% rename from frontend/static/gopher.png rename to static/gopher.png diff --git a/frontend/static/jquery-linedtextarea.js b/static/jquery-linedtextarea.js similarity index 100% rename from frontend/static/jquery-linedtextarea.js rename to static/jquery-linedtextarea.js diff --git a/frontend/static/playground-embed.js b/static/playground-embed.js similarity index 100% rename from frontend/static/playground-embed.js rename to static/playground-embed.js diff --git a/frontend/static/style.css b/static/style.css similarity index 100% rename from frontend/static/style.css rename to static/style.css diff --git a/frontend/store.go b/store.go similarity index 100% rename from frontend/store.go rename to store.go