Merge sandbox and frontend into one service

Since frontend was moved to the flex runtime, there is no longer
a reason to keep the two separate. Consolidate the two into one
service to reduce deployment complexity.

Change-Id: Ie64c17e1833ed94ac8bff7381963f683d824ca5d
Reviewed-on: https://go-review.googlesource.com/85456
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Andrew Bonventre 2017-12-23 18:02:41 -05:00
Родитель a9dcf4686e
Коммит fa48acca51
34 изменённых файлов: 252 добавлений и 428 удалений

Просмотреть файл

@ -24,7 +24,7 @@ Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html
before sending patches. before sending patches.
**We do not accept GitHub pull requests** **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 Unless otherwise noted, the Go source files are distributed under
the BSD-style license found in the LICENSE file. the BSD-style license found in the LICENSE file.

181
Dockerfile Normal file
Просмотреть файл

@ -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"]

12
Makefile Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -1,78 +1,31 @@
# playground # playground
This subrepository holds the source for various packages and tools that support This subrepository holds the source for the Go playground:
the Go playground: https://play.golang.org/ https://play.golang.org/
To submit changes to this repository, see http://golang.org/doc/contribute.html. To submit changes to this repository, see http://golang.org/doc/contribute.html.
## Frontend ## Building
### Building
``` ```
# build the frontend image # build the image
docker build -t frontend frontend/ docker build -t playground .
``` ```
### Running with an in-memory store ## Running
``` ```
docker run --rm -d -p 8080:8080 frontend docker run --rm -d -p 8080:8080 playground
```
### 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)
# run go some code # 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 # 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
``` ```
``` # Contributing
gcloud --project=golang-org --account=person@example.com app deploy sandbox/app-flex.yaml --no-promote
```
Use the Cloud Console's to set the new version as the default: To submit changes to this repository, see http://golang.org/doc/contribute.html.
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.

Просмотреть файл

Просмотреть файл

@ -1,6 +1,6 @@
// +build ignore // +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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -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"]

Просмотреть файл

@ -1,3 +0,0 @@
update-deps:
go install golang.org/x/build/cmd/gitlock
gitlock --update=Dockerfile golang.org/x/playground/frontend

Просмотреть файл

@ -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
}

Просмотреть файл

Просмотреть файл

@ -17,6 +17,11 @@ import (
var log = newStdLogger() var log = newStdLogger()
func main() { func main() {
if len(os.Args) > 1 && os.Args[1] == "test" {
test()
return
}
s, err := newServer(func(s *server) error { s, err := newServer(func(s *server) error {
pid := projectID() pid := projectID()
if pid == "" { if pid == "" {

Просмотреть файл

@ -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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.

Просмотреть файл

@ -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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.

Просмотреть файл

@ -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 // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// TODO(adg): add logging // TODO(andybons): add logging
// TODO(proppy): restrict memory use // TODO(andybons): restrict memory use
// TODO(adg): send exit code to user // 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 package main
import ( import (
"context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"go/parser" "go/parser"
"go/token" "go/token"
"io/ioutil" "io/ioutil"
"log" stdlog "log"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
@ -28,28 +26,22 @@ import (
const maxRunTime = 2 * time.Second const maxRunTime = 2 * time.Second
type Request struct { type request struct {
Body string Body string
} }
type Response struct { type response struct {
Errors string Errors string
Events []Event Events []Event
} }
func main() { func handleCompile(w http.ResponseWriter, r *http.Request) {
if len(os.Args) > 1 && os.Args[1] == "test" { var req request
test() // Until programs that depend on golang.org/x/tools/godoc/static/playground.js
return // are updated to always send JSON, this check is in place.
} if b := r.FormValue("body"); b != "" {
http.HandleFunc("/compile", compileHandler) req.Body = b
http.HandleFunc("/_ah/health", healthHandler) } else if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
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 {
http.Error(w, fmt.Sprintf("error decoding request: %v", err), http.StatusBadRequest) http.Error(w, fmt.Sprintf("error decoding request: %v", err), http.StatusBadRequest)
return 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") tmpDir, err := ioutil.TempDir("", "sandbox")
if err != nil { if err != nil {
return nil, fmt.Errorf("error creating temp directory: %v", err) 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) f, err := parser.ParseFile(fset, in, nil, parser.PackageClauseOnly)
if err == nil && f.Name.Name != "main" { 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") exe := filepath.Join(tmpDir, "a.out")
@ -98,17 +91,19 @@ func compileAndRun(req *Request) (*Response, error) {
// message before any compile errors; strip it. // message before any compile errors; strip it.
errs = strings.Replace(errs, "# command-line-arguments\n", "", 1) 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) 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) rec := new(Recorder)
cmd.Stdout = rec.Stdout() cmd.Stdout = rec.Stdout()
cmd.Stderr = rec.Stderr() cmd.Stderr = rec.Stderr()
if err := runTimeout(cmd, maxRunTime); err != nil { if err := cmd.Run(); err != nil {
if err == timeoutErr { if ctx.Err() == context.DeadlineExceeded {
return &Response{Errors: "process took too long"}, nil return &response{Errors: "process took too long"}, nil
} }
if _, ok := err.(*exec.ExitError); !ok { if _, ok := err.(*exec.ExitError); !ok {
return nil, fmt.Errorf("error running sandbox: %v", err) return nil, fmt.Errorf("error running sandbox: %v", err)
@ -118,40 +113,11 @@ func compileAndRun(req *Request) (*Response, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("error decoding events: %v", err) return nil, fmt.Errorf("error decoding events: %v", err)
} }
return &Response{Events: events}, nil 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")
} }
func healthCheck() error { func healthCheck() error {
resp, err := compileAndRun(&Request{Body: healthProg}) resp, err := compileAndRun(&request{Body: healthProg})
if err != nil { if err != nil {
return err return err
} }
@ -174,24 +140,24 @@ func main() { fmt.Print("ok") }
func test() { func test() {
if err := healthCheck(); err != nil { if err := healthCheck(); err != nil {
log.Fatal(err) stdlog.Fatal(err)
} }
for _, t := range tests { for _, t := range tests {
resp, err := compileAndRun(&Request{Body: t.prog}) resp, err := compileAndRun(&request{Body: t.prog})
if err != nil { if err != nil {
log.Fatal(err) stdlog.Fatal(err)
} }
if t.errors != "" { if t.errors != "" {
if resp.Errors != 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 continue
} }
if resp.Errors != "" { if resp.Errors != "" {
log.Fatal(resp.Errors) stdlog.Fatal(resp.Errors)
} }
if len(resp.Events) != 1 || !strings.Contains(resp.Events[0].Message, t.want) { 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") fmt.Println("OK")

Просмотреть файл

@ -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"]

Просмотреть файл

@ -1,6 +0,0 @@
docker: Dockerfile
docker build -t playground/sandbox .
test: docker
go test
docker run --rm playground/sandbox test

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -48,9 +48,9 @@ func newServer(options ...func(s *server) error) (*server, error) {
func (s *server) init() { func (s *server) init() {
s.mux.HandleFunc("/", s.handleEdit) s.mux.HandleFunc("/", s.handleEdit)
s.mux.HandleFunc("/compile", s.handleCompile)
s.mux.HandleFunc("/fmt", handleFmt) s.mux.HandleFunc("/fmt", handleFmt)
s.mux.HandleFunc("/share", s.handleShare) s.mux.HandleFunc("/share", s.handleShare)
s.mux.HandleFunc("/compile", handleCompile)
s.mux.HandleFunc("/playground.js", s.handlePlaygroundJS) s.mux.HandleFunc("/playground.js", s.handlePlaygroundJS)
s.mux.HandleFunc("/favicon.ico", handleFavicon) s.mux.HandleFunc("/favicon.ico", handleFavicon)
s.mux.HandleFunc("/_ah/health", handleHealthCheck) 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) { 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) { func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {

Просмотреть файл

Просмотреть файл

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 5.6 KiB

После

Ширина:  |  Высота:  |  Размер: 5.6 KiB

Просмотреть файл

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 7.9 KiB

После

Ширина:  |  Высота:  |  Размер: 7.9 KiB

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл