playground: remove files from old location now that the repos have moved

Change-Id: Id0a0bb18de7df28032b10a129e6c09e1c5e5f4b2
diff --git a/tools/playground/.gitignore b/tools/playground/.gitignore
deleted file mode 100644
index a25285a..0000000
--- a/tools/playground/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-builder/netrc
diff --git a/tools/playground/README.md b/tools/playground/README.md
deleted file mode 100644
index 94c9355..0000000
--- a/tools/playground/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Building a Docker image and running the playground server locally
-
-## Docker setup
-
-Install Docker:
-
-* Goobuntu: http://go/installdocker
-* OS X: https://github.com/boot2docker/osx-installer/releases
-
-On Goobuntu, we recommend overriding the default graph dir (`/var/lib/docker`)
-to avoid filling up the root filesystem partition, which is quite small. To do
-so, add the following line to your `/etc/default/docker`:
-
-    DOCKER_OPTS="${DOCKER_OPTS} -g /usr/local/google/docker"
-
-Start (or restart) the Docker daemon:
-
-    $ sudo service docker restart
-
-Build the playground Docker image (this will take a while...):
-
-    $ cp ~/.netrc $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder/netrc
-    $ sudo docker build -t playground $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder/.
-
-Note: If you want to ensure an up-to-date version of veyron is installed in the
-Docker image, run the above command with the "--no-cache" flag.
-
-Test your image (without running compilerd):
-
-    $ sudo docker run -i playground < /usr/local/google/home/sadovsky/dev/veyron-www/content/playgrounds/code/fortune/ex0-go/bundle.json
-
-## Running the playground server (compilerd)
-
-Install the playground binaries:
-
-    $ veyron go install veyron.io/veyron/veyron/tools/playground/...
-
-Run the compiler binary as root:
-
-    $ sudo $VEYRON_ROOT/veyron/go/bin/compilerd --shutdown=false --address=localhost:8181
-
-The server should now be running at http://localhost:8181 and responding to
-compile requests at http://localhost:8181/compile. Add `?pgaddr=localhost:8181`
-to any veyron-www page to make its embedded playgrounds talk to your server.
diff --git a/tools/playground/builder/Dockerfile b/tools/playground/builder/Dockerfile
deleted file mode 100644
index 5d86ab7..0000000
--- a/tools/playground/builder/Dockerfile
+++ /dev/null
@@ -1,63 +0,0 @@
-FROM ubuntu
-RUN /usr/sbin/useradd -d /home/playground -m playground
-
-# Install various prereqs.
-RUN apt-get update
-RUN apt-get install -y curl g++ git libc6-i386 make python
-
-# Install Go. Note, the apt-get "golang" target is too old.
-RUN (cd /tmp; curl -O https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz)
-RUN tar -C /usr/local -xzf /tmp/go1.3.3.linux-amd64.tar.gz
-ENV PATH /usr/local/go/bin:$PATH
-
-ENV HOME /root
-ENV VEYRON_ROOT /usr/local/veyron
-ENV GOPATH /home/playground:$VEYRON_ROOT/veyron/go
-ENV VDLPATH $GOPATH
-
-# Setup veyron and veyron profiles.
-# Note: This will be cached! If you want to re-build the docker image using
-# fresh veyron code, you must pass "--no-cache" to the docker build command.
-# See README.md.
-ADD netrc /root/.netrc
-RUN curl -u veyron:D6HT]P,LrJ7e https://www.envyor.com/noproxy/veyron-setup.sh | bash
-RUN rm /root/.netrc
-RUN $VEYRON_ROOT/bin/veyron profile setup web
-
-# Install the veyron.js library.
-# TODO(nlacasse): Switch to "npm install -g veyron" once veyron.js is publicly
-# visible in NPM.
-WORKDIR /usr/local/veyron/veyron.js/
-# NOTE(sadovsky): NPM is flaky. If any of the NPM commands below fail, simply
-# retry them.
-RUN $VEYRON_ROOT/environment/cout/node/bin/npm install --production
-RUN $VEYRON_ROOT/environment/cout/node/bin/npm link
-WORKDIR /home/playground
-RUN $VEYRON_ROOT/environment/cout/node/bin/npm link veyron
-
-# Install Veyron Go dependencies.
-WORKDIR /usr/local/veyron/veyron
-ENV PATH $VEYRON_ROOT/veyron/go/bin:$VEYRON_ROOT/bin:$PATH
-RUN veyron go install veyron.io/veyron/...
-
-# Uncomment the following lines to install a version of the builder tool using
-# your local version of the code. This is useful when developing and testing
-# local changes.
-#RUN rm $VEYRON_ROOT/veyron/go/bin/builder
-#ADD main.go $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder/main.go
-#ADD identity.go $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder/identity.go
-#ADD services.go $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder/services.go
-#ADD multi_writer.go $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder/multi_writer.go
-#RUN veyron go install veyron.io/veyron/veyron/tools/playground/builder
-
-# Copy proxyd's main.go to builder/proxyd_main.go, then uncomment the following
-# lines to install a version of proxyd (used by the builder tool) using your
-# local version of the code. This is useful when developing and testing local
-# changes.
-#RUN rm $VEYRON_ROOT/veyron/go/bin/proxyd
-#ADD proxyd_main.go $VEYRON_ROOT/veyron/go/src/veyron.io/veyron/veyron/services/proxy/proxyd/main.go
-#RUN veyron go install veyron.io/veyron/veyron/services/proxy/proxyd
-
-USER playground
-WORKDIR /home/playground
-ENTRYPOINT /usr/local/veyron/veyron/go/bin/builder
diff --git a/tools/playground/builder/identity.go b/tools/playground/builder/identity.go
deleted file mode 100644
index 81584e5..0000000
--- a/tools/playground/builder/identity.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Functions to create and bless identities.
-
-package main
-
-import (
-	"os"
-	"path"
-)
-
-type identity struct {
-	Name     string
-	Blesser  string
-	Duration string
-	Files    []string
-}
-
-func (id identity) create() error {
-	if err := id.generate(); err != nil {
-		return err
-	}
-	if id.Blesser != "" || id.Duration != "" {
-		return id.bless()
-	}
-	return nil
-}
-
-func (id identity) generate() error {
-	args := []string{"generate"}
-	if id.Blesser == "" && id.Duration == "" {
-		args = append(args, id.Name)
-	}
-	return runIdentity(args, path.Join("ids", id.Name))
-}
-
-func (id identity) bless() error {
-	filename := path.Join("ids", id.Name)
-	var blesser string
-	if id.Blesser == "" {
-		blesser = filename
-	} else {
-		blesser = path.Join("ids", id.Blesser)
-	}
-	args := []string{"bless", "--with", blesser}
-	if id.Duration != "" {
-		args = append(args, "--for", id.Duration)
-	}
-	args = append(args, filename, id.Name)
-	tempfile := filename + ".tmp"
-	if err := runIdentity(args, tempfile); err != nil {
-		return err
-	}
-	return os.Rename(tempfile, filename)
-}
-
-func createIdentities(ids []identity) error {
-	debug("Generating identities")
-	if err := os.MkdirAll("ids", 0777); err != nil {
-		return err
-	}
-	for _, id := range ids {
-		if err := id.create(); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func runIdentity(args []string, filename string) error {
-	cmd := makeCmd("", false, "identity", args...)
-	out, err := os.Create(filename)
-	if err != nil {
-		return err
-	}
-	defer out.Close()
-	// Note, here we actually overwrite cmd.Stdout (rather than adding a writer to
-	// the multiWriter), so only stderr will be streamed back to the client.
-	cmd.Stdout = out
-	return cmd.Run()
-}
diff --git a/tools/playground/builder/main.go b/tools/playground/builder/main.go
deleted file mode 100644
index a249051..0000000
--- a/tools/playground/builder/main.go
+++ /dev/null
@@ -1,411 +0,0 @@
-// Compiles and runs code for the Veyron playground. Code is passed via os.Stdin
-// as a JSON encoded request struct.
-
-// NOTE(nlacasse): We use log.Panic() instead of log.Fatal() everywhere in this
-// file.  We do this because log.Panic calls panic(), which allows any deferred
-// function to run.  In particular, this will cause the mounttable and proxy
-// processes to be killed in the event of a compilation error.  log.Fatal, on
-// the other hand, calls os.Exit(1), which does not call deferred functions,
-// and will leave proxy and mounttable processes running.  This is not a big
-// deal for production environment, because the Docker instance gets cleaned up
-// after each run, but during development and testing these extra processes can
-// cause issues.
-
-package main
-
-import (
-	"encoding/json"
-	"flag"
-	"fmt"
-	"go/parser"
-	"go/token"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"os/exec"
-	"path"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"sync"
-	"syscall"
-	"time"
-
-	"veyron.io/veyron/veyron/tools/playground/event"
-)
-
-const runTimeout = 3 * time.Second
-
-var (
-	verbose = flag.Bool("v", false, "Whether to output debug messages")
-
-	includeServiceOutput = flag.Bool("includeServiceOutput", false,
-		"Whether to stream service (mounttable, wspr, proxy) output to clients")
-
-	// Whether we have stopped execution of running files.
-	stopped = false
-
-	mu sync.Mutex
-)
-
-// Type of data sent to the builder on stdin.  Input should contain Files.  We
-// look for a file whose Name ends with .id, and parse that into Identities.
-//
-// TODO(nlacasse): Update the identity parsing and usage to the new identity
-// APIs.
-//
-// TODO(ribrdb): Consider moving identity parsing into the http server.
-type request struct {
-	Files      []*codeFile
-	Identities []identity
-}
-
-// Type of file data.  Only Name and Body should be initially set.  The other
-// fields are added as the file is parsed.
-type codeFile struct {
-	Name string
-	Body string
-	// Language the file is written in.  Inferred from the file extension.
-	lang string
-	// Identity to associate with the file's process.
-	identity string
-	// The executable flag denotes whether the file should be executed as
-	// part of the playground run. This is currently used only for
-	// javascript files, and go files with package "main".
-	executable bool
-	// Name of the binary (for go files).
-	binaryName string
-	// Running cmd process for the file.
-	cmd *exec.Cmd
-	// Any subprocesses that are needed to support running the file (e.g. wspr).
-	subprocs []*os.Process
-	// The index of the file in the request.
-	index int
-}
-
-type exit struct {
-	name string
-	err  error
-}
-
-func debug(args ...interface{}) {
-	if *verbose {
-		log.Println(args...)
-	}
-}
-
-func panicOnError(err error) {
-	if err != nil {
-		log.Panic(err)
-	}
-}
-
-func parseRequest(in io.Reader) (r request, err error) {
-	debug("Parsing input")
-	data, err := ioutil.ReadAll(in)
-	if err == nil {
-		err = json.Unmarshal(data, &r)
-	}
-	m := make(map[string]*codeFile)
-	for i := 0; i < len(r.Files); i++ {
-		f := r.Files[i]
-		f.index = i
-		if path.Ext(f.Name) == ".id" {
-			err = json.Unmarshal([]byte(f.Body), &r.Identities)
-			if err != nil {
-				return
-			}
-			r.Files = append(r.Files[:i], r.Files[i+1:]...)
-			i--
-		} else {
-			switch path.Ext(f.Name) {
-			case ".js":
-				// JavaScript files are always executable.
-				f.executable = true
-				f.lang = "js"
-			case ".go":
-				// Go files will be marked as executable if their package name is
-				// "main". This happens in the "maybeSetExecutableAndBinaryName"
-				// function.
-				f.lang = "go"
-			case ".vdl":
-				f.lang = "vdl"
-			default:
-				return r, fmt.Errorf("Unknown file type: %q", f.Name)
-			}
-
-			basename := path.Base(f.Name)
-			if _, ok := m[basename]; ok {
-				return r, fmt.Errorf("Two files with same basename: %q", basename)
-			}
-			m[basename] = f
-		}
-	}
-	if len(r.Identities) == 0 {
-		// Run everything with the same identity if none are specified.
-		r.Identities = append(r.Identities, identity{Name: "default"})
-		for _, f := range r.Files {
-			f.identity = "default"
-		}
-	} else {
-		for _, identity := range r.Identities {
-			for _, basename := range identity.Files {
-				// Check that the file associated with the identity exists.  We ignore
-				// cases where it doesn't because the test .id files get used for
-				// multiple different code files.  See testdata/ids/authorized.id, for
-				// example.
-				if m[basename] != nil {
-					m[basename].identity = identity.Name
-				}
-			}
-		}
-	}
-	return
-}
-
-func writeFiles(files []*codeFile) error {
-	debug("Writing files")
-	for _, f := range files {
-		if err := f.write(); err != nil {
-			return fmt.Errorf("Error writing %s: %v", f.Name, err)
-		}
-	}
-	return nil
-}
-
-func compileFiles(files []*codeFile) error {
-	needToCompile := false
-	for _, f := range files {
-		if f.lang == "vdl" || f.lang == "go" {
-			needToCompile = true
-			break
-		}
-	}
-	if !needToCompile {
-		return nil
-	}
-
-	debug("Compiling files")
-	pwd, err := os.Getwd()
-	if err != nil {
-		return err
-	}
-	os.Setenv("GOPATH", pwd+":"+os.Getenv("GOPATH"))
-	os.Setenv("VDLPATH", pwd+":"+os.Getenv("VDLPATH"))
-	// We set isService=false for compilation because "go install" only produces
-	// output on error, and we always want clients to see such errors.
-	return makeCmd("", false, "veyron", "go", "install", "./...").Run()
-}
-
-func runFiles(files []*codeFile) {
-	debug("Running files")
-	exit := make(chan exit)
-	running := 0
-	for _, f := range files {
-		if f.executable {
-			f.run(exit)
-			running++
-		}
-	}
-
-	timeout := time.After(runTimeout)
-
-	for running > 0 {
-		select {
-		case <-timeout:
-			panicOnError(writeEvent("", "stderr", "Playground exceeded deadline."))
-			stopAll(files)
-		case status := <-exit:
-			if status.err == nil {
-				panicOnError(writeEvent(status.name, "stdout", "Exited cleanly."))
-			} else {
-				panicOnError(writeEvent(status.name, "stderr", fmt.Sprintf("Exited with error: %v", status.err)))
-			}
-			running--
-			stopAll(files)
-		}
-	}
-}
-
-func stopAll(files []*codeFile) {
-	mu.Lock()
-	defer mu.Unlock()
-	if !stopped {
-		stopped = true
-		for _, f := range files {
-			f.stop()
-		}
-	}
-}
-
-func (f *codeFile) maybeSetExecutableAndBinaryName() error {
-	debug("Parsing package from", f.Name)
-	file, err := parser.ParseFile(token.NewFileSet(), f.Name,
-		strings.NewReader(f.Body), parser.PackageClauseOnly)
-	if err != nil {
-		return err
-	}
-	pkg := file.Name.String()
-	if pkg == "main" {
-		f.executable = true
-		basename := path.Base(f.Name)
-		f.binaryName = basename[:len(basename)-len(path.Ext(basename))]
-	}
-	return nil
-}
-
-func (f *codeFile) write() error {
-	debug("Writing file", f.Name)
-	if f.lang == "go" || f.lang == "vdl" {
-		if err := f.maybeSetExecutableAndBinaryName(); err != nil {
-			return err
-		}
-	}
-	// Retain the original file tree structure.
-	if err := os.MkdirAll(path.Dir(f.Name), 0755); err != nil {
-		return err
-	}
-	return ioutil.WriteFile(f.Name, []byte(f.Body), 0644)
-}
-
-func (f *codeFile) startJs() error {
-	wsprProc, wsprPort, err := startWspr(f.Name, f.identity)
-	if err != nil {
-		return fmt.Errorf("Error starting wspr: %v", err)
-	}
-	f.subprocs = append(f.subprocs, wsprProc)
-	os.Setenv("WSPR", "http://localhost:"+strconv.Itoa(wsprPort))
-	node := filepath.Join(os.Getenv("VEYRON_ROOT"), "environment", "cout", "node", "bin", "node")
-	f.cmd = makeCmd(f.Name, false, node, f.Name)
-	return f.cmd.Start()
-}
-
-func (f *codeFile) startGo() error {
-	f.cmd = makeCmd(f.Name, false, filepath.Join("bin", f.binaryName))
-	if f.identity != "" {
-		f.cmd.Env = append(f.cmd.Env, fmt.Sprintf("VEYRON_IDENTITY=%s", filepath.Join("ids", f.identity)))
-	}
-	return f.cmd.Start()
-}
-
-func (f *codeFile) run(ch chan exit) {
-	debug("Running", f.Name)
-	err := func() error {
-		mu.Lock()
-		defer mu.Unlock()
-		if stopped {
-			return fmt.Errorf("Execution has stopped; not running %s", f.Name)
-		}
-
-		switch f.lang {
-		case "go":
-			return f.startGo()
-		case "js":
-			return f.startJs()
-		default:
-			return fmt.Errorf("Cannot run file: %v", f.Name)
-		}
-	}()
-	if err != nil {
-		debug("Failed to start", f.Name)
-		ch <- exit{f.Name, err}
-		return
-	}
-
-	// Wait for the process to exit and send result to channel.
-	go func() {
-		debug("Waiting for", f.Name)
-		err := f.cmd.Wait()
-		debug("Done waiting for", f.Name)
-		ch <- exit{f.Name, err}
-	}()
-}
-
-func (f *codeFile) stop() {
-	debug("Attempting to stop", f.Name)
-	if f.cmd == nil {
-		debug("Cannot stop:", f.Name, "cmd is nil")
-	} else if f.cmd.Process == nil {
-		debug("Cannot stop:", f.Name, "cmd is not nil, but cmd.Process is nil")
-	} else {
-		debug("Sending SIGTERM to", f.Name)
-		f.cmd.Process.Signal(syscall.SIGTERM)
-	}
-	for i, subproc := range f.subprocs {
-		debug("Killing subprocess", i, "for", f.Name)
-		subproc.Kill()
-	}
-}
-
-// Creates a cmd whose outputs (stdout and stderr) are streamed to stdout as
-// json-encoded Event objects. If you want to watch the output streams yourself,
-// add your own writer(s) to the multiWriter before starting the command.
-func makeCmd(fileName string, isService bool, progName string, args ...string) *exec.Cmd {
-	cmd := exec.Command(progName, args...)
-	cmd.Env = os.Environ()
-	stdout, stderr := newMultiWriter(), newMultiWriter()
-	// TODO(sadovsky): Maybe annotate service output in the event stream.
-	if !isService || *includeServiceOutput {
-		stdout.Add(newEventStreamer(fileName, "stdout"))
-		stderr.Add(newEventStreamer(fileName, "stderr"))
-	}
-	cmd.Stdout, cmd.Stderr = stdout, stderr
-	return cmd
-}
-
-// Initialize using newEventStreamer.
-type eventStreamer struct {
-	fileName   string
-	streamName string
-}
-
-var _ io.Writer = (*eventStreamer)(nil)
-
-func newEventStreamer(fileName, streamName string) *eventStreamer {
-	return &eventStreamer{fileName: fileName, streamName: streamName}
-}
-
-func (es *eventStreamer) Write(p []byte) (n int, err error) {
-	if err := writeEvent(es.fileName, es.streamName, string(p)); err != nil {
-		return 0, err
-	}
-	return len(p), nil
-}
-
-func writeEvent(fileName, streamName, message string) error {
-	e := event.Event{
-		File:      fileName,
-		Message:   message,
-		Stream:    streamName,
-		Timestamp: time.Now().UnixNano(),
-	}
-	jsonEvent, err := json.Marshal(e)
-	if err != nil {
-		return err
-	}
-	// TODO(nlacasse): When we switch over to actually streaming events, we'll
-	// probably need to trigger a flush here.
-	os.Stdout.Write(append(jsonEvent, '\n'))
-	return nil
-}
-
-func main() {
-	flag.Parse()
-	r, err := parseRequest(os.Stdin)
-	panicOnError(err)
-
-	panicOnError(createIdentities(r.Identities))
-
-	mt, err := startMount(runTimeout)
-	panicOnError(err)
-	defer mt.Kill()
-
-	proxy, err := startProxy()
-	panicOnError(err)
-	defer proxy.Kill()
-
-	panicOnError(writeFiles(r.Files))
-	panicOnError(compileFiles(r.Files))
-	runFiles(r.Files)
-}
diff --git a/tools/playground/builder/multi_writer.go b/tools/playground/builder/multi_writer.go
deleted file mode 100644
index 60f3e88..0000000
--- a/tools/playground/builder/multi_writer.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// MultiWriter creates a writer that duplicates its writes to all the
-// provided writers, similar to the Unix tee(1) command.
-//
-// Similar to http://golang.org/src/pkg/io/multi.go.
-
-package main
-
-import (
-	"io"
-	"sync"
-)
-
-// Initialize using newMultiWriter.
-type multiWriter struct {
-	writers []io.Writer
-	mu      sync.Mutex
-	wrote   bool
-}
-
-var _ io.Writer = (*multiWriter)(nil)
-
-func newMultiWriter() *multiWriter {
-	return &multiWriter{writers: []io.Writer{}}
-}
-
-// Returns self for convenience.
-func (t *multiWriter) Add(w io.Writer) *multiWriter {
-	t.mu.Lock()
-	defer t.mu.Unlock()
-	if t.wrote {
-		panic("Tried to add writer after data has been written.")
-	}
-	t.writers = append(t.writers, w)
-	return t
-}
-
-func (t *multiWriter) Write(p []byte) (n int, err error) {
-	t.mu.Lock()
-	t.wrote = true
-	t.mu.Unlock()
-	for _, w := range t.writers {
-		n, err = w.Write(p)
-		if err != nil {
-			return
-		}
-		if n != len(p) {
-			err = io.ErrShortWrite
-			return
-		}
-	}
-	return len(p), nil
-}
diff --git a/tools/playground/builder/services.go b/tools/playground/builder/services.go
deleted file mode 100644
index 346d286..0000000
--- a/tools/playground/builder/services.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Functions to start services needed by the Veyron playground.
-// These should never trigger program exit.
-
-package main
-
-import (
-	"bufio"
-	"fmt"
-	"io"
-	"math/rand"
-	"os"
-	"os/exec"
-	"path"
-	"regexp"
-	"strconv"
-	"syscall"
-	"time"
-)
-
-var (
-	proxyName = "proxy"
-)
-
-// Note: This was copied from veyron/go/src/veyron/tools/findunusedport.
-// I would like to be able to import that package directly, but it defines a
-// main(), so can't be imported.  An alternative solution would be to call the
-// 'findunusedport' binary, but that would require starting another process and
-// parsing the output.  It seemed simpler to just copy the function here.
-func findUnusedPort() (int, error) {
-	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
-	for i := 0; i < 1000; i++ {
-		port := 1024 + rnd.Int31n(64512)
-		fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
-		if err != nil {
-			continue
-		}
-		sa := &syscall.SockaddrInet4{Port: int(port)}
-		if err := syscall.Bind(fd, sa); err != nil {
-			continue
-		}
-		syscall.Close(fd)
-		return int(port), nil
-	}
-	return 0, fmt.Errorf("Can't find unused port.")
-}
-
-// startMount starts a mounttabled process, and sets the NAMESPACE_ROOT env
-// variable to the mounttable's location.  We run one mounttabled process for
-// the entire environment.
-func startMount(timeLimit time.Duration) (proc *os.Process, err error) {
-	cmd := makeCmd("", true, "mounttabled", "--veyron.tcp.address=127.0.0.1:0")
-
-	matches, err := startAndWaitFor(cmd, timeLimit, regexp.MustCompile("Mount table .+ endpoint: (.+)\n"))
-	if err != nil {
-		return nil, fmt.Errorf("Error starting mounttabled: %v", err)
-	}
-	endpoint := matches[1]
-	if endpoint == "" {
-		return nil, fmt.Errorf("Failed to get mounttable endpoint")
-	}
-	return cmd.Process, os.Setenv("NAMESPACE_ROOT", endpoint)
-}
-
-// startProxy starts a proxyd process.  We run one proxyd process for the
-// entire environment.
-func startProxy() (proc *os.Process, err error) {
-	port, err := findUnusedPort()
-	if err != nil {
-		return nil, err
-	}
-	cmd := makeCmd("", true, "proxyd", "-name="+proxyName, "-address=127.0.0.1:"+strconv.Itoa(port), "-http=")
-	err = cmd.Start()
-	if err != nil {
-		return nil, err
-	}
-	return cmd.Process, err
-}
-
-// startWspr starts a wsprd process. We run one wsprd process for each
-// javascript file being run.
-func startWspr(fileName, identity string) (proc *os.Process, port int, err error) {
-	port, err = findUnusedPort()
-	if err != nil {
-		return nil, port, err
-	}
-	cmd := makeCmd(fileName, true,
-		"wsprd",
-		// Verbose logging so we can watch the output for "Listening" log line.
-		"-v=3",
-		"-veyron.proxy="+proxyName,
-		"-port="+strconv.Itoa(port),
-		// Retry RPC calls for 3 seconds. If a client makes an RPC call before the
-		// server is running, it won't immediately fail, but will retry while the
-		// server is starting.
-		// TODO(nlacasse): Remove this when javascript can tell wspr how long to
-		// retry for. Right now it's a global setting in wspr.
-		"-retry-timeout=3",
-		// The identd server won't be used, so pass a fake name.
-		"-identd=/unused")
-	if identity != "" {
-		cmd.Env = append(cmd.Env, fmt.Sprintf("VEYRON_IDENTITY=%s", path.Join("ids", identity)))
-	}
-	if _, err := startAndWaitFor(cmd, 3*time.Second, regexp.MustCompile("Listening")); err != nil {
-		return nil, 0, fmt.Errorf("Error starting wspr: %v", err)
-	}
-	return cmd.Process, port, nil
-}
-
-// Helper function to start a command and wait for output.  Arguments are a cmd
-// to run, a timeout, and a regexp.  The slice of strings matched by the regexp
-// is returned.
-// TODO(nlacasse): Consider standardizing how services log when they start
-// listening, and their endpoints (if any).  Then this could become a common
-// util function.
-func startAndWaitFor(cmd *exec.Cmd, timeout time.Duration, outputRegexp *regexp.Regexp) ([]string, error) {
-	reader, writer := io.Pipe()
-	// TODO(sadovsky): Why must we listen to both stdout and stderr? We should
-	// know which one produces the "Listening" log line...
-	cmd.Stdout.(*multiWriter).Add(writer)
-	cmd.Stderr.(*multiWriter).Add(writer)
-	err := cmd.Start()
-	if err != nil {
-		return nil, err
-	}
-
-	buf := bufio.NewReader(reader)
-	t := time.After(timeout)
-	ch := make(chan []string)
-	go (func() {
-		for line, err := buf.ReadString('\n'); err == nil; line, err = buf.ReadString('\n') {
-			if matches := outputRegexp.FindStringSubmatch(line); matches != nil {
-				ch <- matches
-			}
-		}
-		close(ch)
-	})()
-	select {
-	case <-t:
-		return nil, fmt.Errorf("Timeout starting service.")
-	case matches := <-ch:
-		return matches, nil
-	}
-}
diff --git a/tools/playground/compilerd/main.go b/tools/playground/compilerd/main.go
deleted file mode 100644
index d9d3827..0000000
--- a/tools/playground/compilerd/main.go
+++ /dev/null
@@ -1,282 +0,0 @@
-package main
-
-import (
-	"bytes"
-	"crypto/sha1"
-	"encoding/json"
-	"flag"
-	"fmt"
-	"io"
-	"log"
-	"math/rand"
-	"net/http"
-	"os"
-	"os/exec"
-	"os/signal"
-	"syscall"
-	"time"
-
-	"github.com/golang/groupcache/lru"
-
-	"veyron.io/veyron/veyron/tools/playground/event"
-)
-
-type ResponseBody struct {
-	Errors string
-	Events []event.Event
-}
-
-type CachedResponse struct {
-	Status int
-	Body   ResponseBody
-}
-
-var (
-	// This channel is closed when the server begins shutting down.
-	// No values are ever sent to it.
-	lameduck chan bool = make(chan bool)
-
-	address = flag.String("address", ":8181", "address to listen on")
-
-	// Note, shutdown triggers on SIGTERM or when the time limit is hit.
-	shutdown = flag.Bool("shutdown", true, "whether to ever shutdown the machine")
-
-	// Maximum request and response size. Same limit as imposed by Go tour.
-	maxSize = 1 << 16
-
-	// In-memory LRU cache of request/response bodies. Keys are sha1 sum of
-	// request bodies (20 bytes each), values are of type CachedResponse.
-	// NOTE(nlacasse): The cache size (10k) was chosen arbitrarily and should
-	// perhaps be optimized.
-	cache = lru.New(10000)
-)
-
-func healthz(w http.ResponseWriter, r *http.Request) {
-	select {
-	case <-lameduck:
-		w.WriteHeader(http.StatusInternalServerError)
-	default:
-		w.Write([]byte("ok"))
-	}
-}
-
-func handler(w http.ResponseWriter, r *http.Request) {
-	// CORS headers.
-	// TODO(nlacasse): Fill the origin header in with actual playground origin
-	// before going to production.
-	w.Header().Set("Access-Control-Allow-Origin", "*")
-	w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
-	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding")
-
-	// CORS sends an OPTIONS pre-flight request to make sure the request will be
-	// allowed.
-	if r.Method == "OPTIONS" {
-		w.WriteHeader(http.StatusOK)
-		return
-	}
-
-	if r.Body == nil || r.Method != "POST" {
-		w.WriteHeader(http.StatusBadRequest)
-		return
-	}
-
-	requestBody := streamToBytes(r.Body)
-
-	if len(requestBody) > maxSize {
-		responseBody := new(ResponseBody)
-		responseBody.Errors = "Program too large."
-		respondWithBody(w, http.StatusBadRequest, responseBody)
-		return
-	}
-
-	// Hash the body and see if it's been cached. If so, return the cached
-	// response status and body.
-	// NOTE(sadovsky): In the client we may shift timestamps (based on current
-	// time) and introduce a fake delay.
-	requestBodyHash := sha1.Sum(requestBody)
-	if cachedResponse, ok := cache.Get(requestBodyHash); ok {
-		if cachedResponseStruct, ok := cachedResponse.(CachedResponse); ok {
-			respondWithBody(w, cachedResponseStruct.Status, cachedResponseStruct.Body)
-			return
-		} else {
-			log.Printf("Invalid cached response: %v\n", cachedResponse)
-			cache.Remove(requestBodyHash)
-		}
-	}
-
-	// TODO(nlacasse): It would be cool if we could stream the output
-	// messages while the process is running, rather than waiting for it to
-	// exit and dumping all the output then.
-
-	id := <-uniq
-
-	// TODO(sadovsky): Set runtime constraints on CPU and memory usage.
-	// http://docs.docker.com/reference/run/#runtime-constraints-on-cpu-and-memory
-	cmd := Docker("run", "-i", "--name", id, "playground")
-	cmd.Stdin = bytes.NewReader(requestBody)
-
-	// Builder will return all normal output as json events on stdout, and will
-	// return unexpected errors on stderr.
-	stdoutBuf, stderrBuf := new(bytes.Buffer), new(bytes.Buffer)
-	cmd.Stdout, cmd.Stderr = stdoutBuf, stderrBuf
-
-	// Arbitrary deadline (enough to compile, run, shutdown).
-	timeout := time.After(5000 * time.Millisecond)
-	exit := make(chan error)
-
-	go func() { exit <- cmd.Run() }()
-
-	select {
-	case <-exit:
-	case <-timeout:
-		// TODO(sadovsky): Race condition. More output could show up after this
-		// message.
-		stderrBuf.Write([]byte("\nTime exceeded, killing...\n"))
-	}
-
-	// TODO(nlacasse): This takes a long time, during which the client is waiting
-	// for a response.  I tried moving it to after the response is sent, but a
-	// subsequent request will trigger a new "docker run", which somehow has to
-	// wait for this "docker rm" to finish.  This caused some requests to timeout
-	// unexpectedly.
-	//
-	// We should figure out a better way to run this, so that we can return
-	// quickly, and not mess up other requests.
-	//
-	// Setting GOMAXPROCS may or may not help.  See
-	// https://github.com/docker/docker/issues/6480
-	Docker("rm", "-f", id).Run()
-
-	// If the response is bigger than the limit, cache the response and return an
-	// error.
-	if stdoutBuf.Len() > maxSize {
-		status := http.StatusBadRequest
-		responseBody := new(ResponseBody)
-		responseBody.Errors = "Program output too large."
-		cache.Add(requestBodyHash, CachedResponse{
-			Status: status,
-			Body:   *responseBody,
-		})
-		respondWithBody(w, status, responseBody)
-		return
-	}
-
-	responseBody := new(ResponseBody)
-	// TODO(nlacasse): Make these errors Events, so that we can send them
-	// back in the Events array.  This will simplify streaming the events to the
-	// client in realtime.
-	responseBody.Errors = stderrBuf.String()
-
-	// Decode the json events from stdout and add them to the responseBody.
-	for line, err := stdoutBuf.ReadBytes('\n'); err == nil; line, err = stdoutBuf.ReadBytes('\n') {
-		var e event.Event
-		json.Unmarshal(line, &e)
-		responseBody.Events = append(responseBody.Events, e)
-	}
-
-	cache.Add(requestBodyHash, CachedResponse{
-		Status: http.StatusOK,
-		Body:   *responseBody,
-	})
-	respondWithBody(w, http.StatusOK, responseBody)
-}
-
-func respondWithBody(w http.ResponseWriter, status int, body interface{}) {
-	bodyJson, _ := json.Marshal(body)
-	w.Header().Add("Content-Type", "application/json")
-	w.Header().Add("Content-Length", fmt.Sprintf("%d", len(bodyJson)))
-	w.Write(bodyJson)
-
-	// TODO(nlacasse): This flush doesn't really help us right now, but
-	// we'll definitly need something like it when we switch to the
-	// streaming model.
-	if f, ok := w.(http.Flusher); ok {
-		f.Flush()
-	} else {
-		log.Println("Cannot flush.")
-	}
-}
-
-func streamToBytes(stream io.Reader) []byte {
-	buf := new(bytes.Buffer)
-	buf.ReadFrom(stream)
-	return buf.Bytes()
-}
-
-func Docker(args ...string) *exec.Cmd {
-	fullArgs := []string{"docker"}
-	fullArgs = append(fullArgs, args...)
-	return exec.Command("sudo", fullArgs...)
-}
-
-// A channel which returns unique ids for the containers.
-var uniq = make(chan string)
-
-func init() {
-	val := time.Now().UnixNano()
-	go func() {
-		for {
-			uniq <- fmt.Sprintf("playground_%d", val)
-			val++
-		}
-	}()
-}
-
-func main() {
-	flag.Parse()
-
-	if *shutdown {
-		limit_min := 60
-		delay_min := limit_min/2 + rand.Intn(limit_min/2)
-
-		// VMs will be periodically killed to prevent any owned VMs from causing
-		// damage. We want to shutdown cleanly before then so we don't cause
-		// requests to fail.
-		go WaitForShutdown(time.Minute * time.Duration(delay_min))
-	}
-
-	http.HandleFunc("/compile", handler)
-	http.HandleFunc("/healthz", healthz)
-
-	log.Printf("Serving %s\n", *address)
-	http.ListenAndServe(*address, nil)
-}
-
-func WaitForShutdown(limit time.Duration) {
-	var beforeExit func() error
-
-	// Shutdown if we get a SIGTERM.
-	term := make(chan os.Signal, 1)
-	signal.Notify(term, syscall.SIGTERM)
-
-	// Or if the time limit expires.
-	deadline := time.After(limit)
-	log.Println("Shutting down at", time.Now().Add(limit))
-Loop:
-	for {
-		select {
-		case <-deadline:
-			// Shutdown the VM.
-			log.Println("Deadline expired, shutting down.")
-			beforeExit = exec.Command("sudo", "halt").Run
-			break Loop
-		case <-term:
-			log.Println("Got SIGTERM, shutting down.")
-			// VM is probably already shutting down, so just exit.
-			break Loop
-		}
-	}
-	// Fail health checks so we stop getting requests.
-	close(lameduck)
-	// Give running requests time to finish.
-	time.Sleep(30 * time.Second)
-
-	// Then go ahead and shutdown.
-	if beforeExit != nil {
-		err := beforeExit()
-		if err != nil {
-			panic(err)
-		}
-	}
-	os.Exit(0)
-}
diff --git a/tools/playground/compilerd/pool_template.json b/tools/playground/compilerd/pool_template.json
deleted file mode 100644
index 41b54e4..0000000
--- a/tools/playground/compilerd/pool_template.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "template": {
-    "action": {
-      "commands": [
-        "sudo mount /dev/sdb1 /mnt",
-        "sudo docker load < /mnt/playground.tar.gz",
-        "start-stop-daemon --start -c ribrdb --exec /mnt/compilerd &> /tmp/compilerd.out &"
-      ]
-    },
-    "healthChecks": [{
-      "name": "healthz",
-      "path": "/healthz",
-      "port": "8181",
-    }],
-    "vmParams": {
-      "machineType": "n1-standard-1",
-      "baseInstanceName": "pg-replica",
-      "disksToCreate": [{
-        "boot": "true",
-        "initializeParams": {
-          "sourceImage": "https://www.googleapis.com/compute/v1/projects/google-containers/global/images/container-vm-v20140522",
-          "diskSizeGb": "200"
-        }
-      }],
-      "disksToAttach": [{
-        "source": "pg-data-20140820"
-      }],
-      "networkInterfaces": [{
-        "network": "playground",
-        "accessConfigs": [{
-          "type": "ONE_TO_ONE_NAT",
-          "name": "External NAT"
-        }]
-      }]
-    }
-  }
-}
diff --git a/tools/playground/compilerd/update.sh b/tools/playground/compilerd/update.sh
deleted file mode 100644
index e4d07fa..0000000
--- a/tools/playground/compilerd/update.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash
-
-# Script to rebuild and deploy the docker image and compiler to the playground
-# backends.
-#
-# Usage:
-#     gcutil ssh --project google.com:veyron playground-master
-#     sudo su - veyron
-#     veyron project update
-#     bash $VEYRON_ROOT/go/src/veyron.io/veyron/veyron/tools/playground/compilerd/update.sh
-
-set -e
-readonly DATE=$(date +%F)
-readonly DISK="pg-data-${DATE}"
-
-function unmount() {
-  sudo umount /mnt
-  gcloud compute --project "google.com:veyron" instances detach-disk --disk="$DISK" $(hostname) --zone us-central1-a
-}
-
-function cleanup() {
-  if [[ -e /mnt/compilerd ]]; then
-    unmount
-    # if the disk was still mounted, nothing is using it so go ahead
-    # and delete it.
-    gcloud compute --project "google.com:veyron" disks delete "${DISK}" --zone "us-central1-a"
-  fi
-  sudo docker rm "${DISK}" || true
-}
-trap cleanup EXIT
-
-function main() {
-  if [[ ! -e ~/.netrc ]]; then
-    echo "Unable to access git, missing ~/.netrc"
-    exit 1
-  fi
-
-  gcloud compute --project "google.com:veyron" disks create "${DISK}" --size "200" --zone "us-central1-a" --source-snapshot "pg-data-20140702" --type "pd-standard"
-  gcloud compute --project "google.com:veyron" instances attach-disk --disk="$DISK" $(hostname) --zone us-central1-a
-  sudo mount /dev/sdb1 /mnt
-
-  # Build the docker image.
-  cd ${VEYRON_ROOT}/veyron/go/src/veyron.io/veyron/veyron/tools/playground/builder
-  cp ~/.netrc ./netrc
-  sudo docker build --no-cache -t playground .
-  rm -f ./netrc
-
-  # Export the docker image to disk.
-  sudo docker save -o /mnt/playground.tar.gz playground
-
-  # Copy the compilerd binary from the docker image to the disk.
-  sudo docker run --name=${DISK} playground || true
-  sudo docker cp ${DISK}:/usr/local/veyron/veyron/go/bin/compilerd /tmp
-  sudo mv /tmp/compilerd /mnt/compilerd
-  sudo docker rm ${DISK}
-
-  # Detach the disk so the backends can mount it.
-  unmount
-
-  # Update the template to use the new disk.
-  cd ../compilerd
-  sed -i -e s/pg-data-20140820/${DISK}/ pool_template.json
-  gcloud preview replica-pools --zone=us-central1-a update-template --template=pool_template.json playground-pool
-  git checkout -- pool_template.json
-
-  # Rolling restart of the replicas.
-  INSTANCES=$(gcloud preview replica-pools --zone=us-central1-a replicas --pool=playground-pool list|grep name:|cut -d: -f2)
-  for i in ${INSTANCES}; do
-    gcloud preview replica-pools --zone=us-central1-a replicas --pool=playground-pool restart ${i}
-    sleep 5m
-  done
-}
-
-main "$@"
diff --git a/tools/playground/event/event.go b/tools/playground/event/event.go
deleted file mode 100644
index 5a1c6cb..0000000
--- a/tools/playground/event/event.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package event
-
-// Note: This is in a seperate package because it is shared by both the builder
-// package and the compilerd package.  Both of those define a main(), so one
-// cannot import the other.
-
-// Typed representation of data sent to stdin/stdout from a command.  These
-// will be json-encoded and sent to the client.
-type Event struct {
-	// File associated with the command.
-	File string
-	// The text sent to stdin/stderr.
-	Message string
-	// Stream that the message was sent to, either "stdout" or "stderr".
-	Stream string
-	// Unix time, the number of nanoseconds elapsed since January 1, 1970 UTC.
-	Timestamp int64
-}
diff --git a/tools/playground/monitor.py b/tools/playground/monitor.py
deleted file mode 100755
index 300ef85..0000000
--- a/tools/playground/monitor.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/python2.7
-
-# This needs to run on a gce vm with the replica pool
-# service account scope (https://www.googleapis.com/auth/ndev.cloudman).
-#
-# You also need to enable preview in gcloud:
-# $ gcloud components update preview
-#
-# Then add it to your crontab, e.g.
-# */10 * * * * gcloud preview replica-pools --zone us-central1-a replicas --pool playground-pool list|monitor.py
-
-import os
-import datetime
-import subprocess
-import sys
-import yaml
-
-DESIRED = 2
-MAX_ALIVE_MIN = 60
-POOL = "playground-pool"
-
-def runCommand(*args):
-    cmd = ['gcloud', 'preview', 'replica-pools', '--zone', 'us-central1-a']
-    cmd.extend(args)
-    subprocess.check_call(cmd)
-
-def resizePool(size):
-    runCommand("resize", "--new-size", str(size), POOL)
-
-
-def shouldRestart(replica):
-    if replica['status']['state'] == 'PERMANENTLY_FAILING':
-        print "replica %s failed: %s" % (replica['name'], replica['status']['details'])
-        return True
-    return isTooOld(replica)
-
-
-def isTooOld(replica):
-    start_text = replica['status']['vmStartTime']
-    if start_text:
-        start = yaml.load(start_text)
-        uptime = datetime.datetime.now() - start
-        return uptime.seconds > MAX_ALIVE_MIN * 60
-
-
-def restartReplica(replica):
-    print "Restarting replica " + replica['name']
-    resizePool(DESIRED + 1)
-    runCommand("replicas", "--pool", POOL, "delete", replica['name'])
-
-
-def maybeRestartReplica(replica):
-    if shouldRestart(replica):
-        restartReplica(replica)
-
-
-def main():
-    replicas = yaml.load_all(sys.stdin.read())
-    for replica in replicas:
-        maybeRestartReplica(replica)
-
-
-if __name__ == "__main__":
-    main()
diff --git a/tools/playground/pgbundle/.gitignore b/tools/playground/pgbundle/.gitignore
deleted file mode 100644
index 93f1361..0000000
--- a/tools/playground/pgbundle/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules
-npm-debug.log
diff --git a/tools/playground/pgbundle/.jshintignore b/tools/playground/pgbundle/.jshintignore
deleted file mode 100644
index 3c3629e..0000000
--- a/tools/playground/pgbundle/.jshintignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/tools/playground/pgbundle/.jshintrc b/tools/playground/pgbundle/.jshintrc
deleted file mode 100644
index b264540..0000000
--- a/tools/playground/pgbundle/.jshintrc
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "camelcase": true,
-  "eqeqeq": true,
-  "expr": true,
-  "forin": true,
-  "freeze": true,
-  "immed": true,
-  "indent": 2,
-  "latedef": "nofunc",
-  "maxlen": 80,
-  "newcap": true,
-  "noarg": true,
-  "nonbsp": true,
-  "nonew": true,
-  "quotmark": "single",
-  "sub": true,
-  "trailing": true,
-  "undef": true,
-  "unused": "vars",
-
-  "browser": true,
-  "devel": true,
-  "node": true,
-
-  "globals": {
-  }
-}
diff --git a/tools/playground/pgbundle/Makefile b/tools/playground/pgbundle/Makefile
deleted file mode 100644
index 43cd1c5..0000000
--- a/tools/playground/pgbundle/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-export SHELL := /bin/bash -euo pipefail
-
-node_modules: package.json
-	npm prune
-	npm install
-	touch node_modules
-
-lint:
-	jshint .
-
-.PHONY: lint
diff --git a/tools/playground/pgbundle/bin/pgbundle b/tools/playground/pgbundle/bin/pgbundle
deleted file mode 100755
index 599c379..0000000
--- a/tools/playground/pgbundle/bin/pgbundle
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/env node
-require('../index.js').run();
diff --git a/tools/playground/pgbundle/index.js b/tools/playground/pgbundle/index.js
deleted file mode 100644
index af60a98..0000000
--- a/tools/playground/pgbundle/index.js
+++ /dev/null
@@ -1,119 +0,0 @@
-var _ = require('lodash');
-var fs = require('fs');
-var glob = require('glob');
-var path = require('path');
-
-// Filename to write the data to.
-var BUNDLE_NAME = 'bundle.json';
-
-module.exports = {run: run};
-
-// TODO(nlacasse): improve this.
-function usage() {
-  console.log('Usage: pgbundle [options] <path> [<path> <path> ...]');
-  console.log('Options: --verbose: Enable verbose output.');
-  process.exit(1);
-}
-
-// If the first line is "// +build OMIT", strip the line and return the
-// remaining lines.
-function stripBuildOmit(lines) {
-  if (lines[0] === '// +build OMIT') {
-    return _.rest(lines);
-  }
-  return lines;
-}
-
-// If the first line is an index comment, strip the line and return the index
-// and remaining lines.
-function getIndex(lines) {
-  var index = null;
-  var match = lines[0].match(/^\/\/\s*index=(\d+)/);
-  if (match && match[1]) {
-    index = match[1];
-    lines = _.rest(lines);
-  }
-  return {
-    index: index,
-    lines: lines
-  };
-}
-
-function shouldIgnore(fileName) {
-  // Ignore directories.
-  if (_.last(fileName) === '/') {
-    return true;
-  }
-  // Ignore bundle files.
-  if (fileName === BUNDLE_NAME) {
-    return true;
-  }
-  // Ignore generated .vdl.go files.
-  if ((/\.vdl\.go$/i).test(fileName)) {
-    return true;
-  }
-  return false;
-}
-
-// Main function.
-function run() {
-  // Get the paths from process.argv.
-  var argv = require('minimist')(process.argv.slice(2));
-  var dirs = argv._;
-
-  // Make sure there is at least one path.
-  if (!dirs || dirs.length === 0) {
-    return usage();
-  }
-
-  // Loop over each path.
-  _.each(dirs, function(dir) {
-    var relpaths = glob.sync('**', {
-      cwd: dir,
-      mark: true  // Add a '/' char to directory matches.
-    });
-
-    if (relpaths.length === 0) {
-      return usage();
-    }
-
-    var out = {files: []};
-
-    // Loop over each file.
-    _.each(relpaths, function(relpath) {
-      if (shouldIgnore(relpath)) {
-        return;
-      }
-
-      var abspath = path.resolve(dir, relpath);
-      var text = fs.readFileSync(abspath, {encoding: 'utf8'});
-
-      var lines = text.split('\n');
-      lines = stripBuildOmit(lines);
-      var indexAndLines = getIndex(lines);
-      var index = indexAndLines.index;
-      lines = indexAndLines.lines;
-
-      out.files.push({
-        name: relpath,
-        body: lines.join('\n'),
-        index: index
-      });
-    });
-
-    out.files = _.sortBy(out.files, 'index');
-
-    // Drop the index fields -- we don't need them anymore.
-    out.files = _.map(out.files, function(f) {
-      return _.omit(f, 'index');
-    });
-
-    // Write the bundle.json.
-    var outFile = path.resolve(dir, BUNDLE_NAME);
-    fs.writeFileSync(outFile, JSON.stringify(out));
-
-    if (argv.verbose) {
-      console.log('Wrote ' + outFile);
-    }
-  });
-}
diff --git a/tools/playground/pgbundle/package.json b/tools/playground/pgbundle/package.json
deleted file mode 100644
index 71ef866..0000000
--- a/tools/playground/pgbundle/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "name": "pgbundle",
-  "description": "Playground file bundler",
-  "version": "0.0.1",
-  "bin": "./bin/pgbundle",
-  "bugs": {
-    "url": "https://github.com/veyron/pgbundle/issues"
-  },
-  "dependencies": {
-    "glob": "^4.0.6",
-    "lodash": "^2.4.1",
-    "minimist": "^1.1.0"
-  },
-  "homepage": "https://github.com/veyron/pgbundle",
-  "private": true,
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/veyron/pgbundle.git"
-  }
-}
diff --git a/tools/playground/test.sh b/tools/playground/test.sh
deleted file mode 100755
index 9a8687a..0000000
--- a/tools/playground/test.sh
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/bash
-
-# Tests the playground builder tool.
-
-# TODO(sadovsky): Much of the setup code below also exists in
-# veyron-www/test/playground_test.sh.
-
-source "${VEYRON_ROOT}/scripts/lib/shell_test.sh"
-
-# Installs the veyron.js library and makes it accessible to javascript files in
-# the veyron playground test folder under the module name 'veyron'.
-install_veyron_js() {
-  # TODO(nlacasse): Once veyron.js is publicly available in npm, replace this
-  # with "npm install veyron".
-  pushd "${VEYRON_ROOT}/veyron.js"
-  npm link
-  popd
-  npm link veyron
-}
-
-# Installs the pgbundle tool.
-install_pgbundle() {
-  pushd "${VEYRON_ROOT}/veyron/go/src/veyron.io/veyron/veyron/tools/playground/pgbundle"
-  npm link
-  popd
-  npm link pgbundle
-}
-
-# Installs various go binaries.
-build_go_binaries() {
-  # Note that "go build" puts built binaries in $(pwd), but only if they are
-  # built one at a time. So much for the principle of least surprise...
-  local -r V="veyron.io/veyron/veyron"
-  veyron go build $V/tools/identity || shell_test::fail "line ${LINENO}: failed to build 'identity'"
-  veyron go build $V/services/proxy/proxyd || shell_test::fail "line ${LINENO}: failed to build 'proxyd'"
-  veyron go build $V/services/mounttable/mounttabled || shell_test::fail "line ${LINENO}: failed to build 'mounttabled'"
-  veyron go build $V/tools/playground/builder || shell_test::fail "line ${LINENO}: failed to build 'builder'"
-  veyron go build veyron.io/veyron/veyron2/vdl/vdl || shell_test::fail "line ${LINENO}: failed to build 'vdl'"
-  veyron go build veyron.io/wspr/veyron/services/wsprd || shell_test::fail "line ${LINENO}: failed to build 'wsprd'"
-}
-
-# Sets up a directory with the given files, then runs builder.
-test_with_files() {
-  local -r TESTDATA_DIR="$(shell::go_package_dir veyron.io/veyron/veyron/tools/playground/testdata)"
-
-  # Write input files to a fresh dir, then run pgbundle.
-  local -r PGBUNDLE_DIR=$(shell::tmp_dir)
-  for f in $@; do
-    fdir="${PGBUNDLE_DIR}/$(dirname ${f})"
-    mkdir -p "${fdir}"
-    cp "${TESTDATA_DIR}/${f}" "${fdir}/"
-  done
-
-  ./node_modules/.bin/pgbundle "${PGBUNDLE_DIR}"
-
-  # Create a fresh dir to run bundler from.
-  local -r ORIG_DIR=$(pwd)
-  pushd $(shell::tmp_dir)
-  ln -s "${ORIG_DIR}/node_modules" ./  # for veyron.js
-  "${ORIG_DIR}/builder" < "${PGBUNDLE_DIR}/bundle.json" 2>&1 | tee builder.out
-  # Move builder output to original dir for verification.
-  mv builder.out "${ORIG_DIR}"
-  popd
-}
-
-main() {
-  cd $(shell::tmp_dir)
-
-  export GOPATH="$(pwd):$(veyron env GOPATH)"
-  export VDLPATH="$(pwd):$(veyron env VDLPATH)"
-  export PATH="$(pwd):${VEYRON_ROOT}/environment/cout/node/bin:${PATH}"
-
-  build_go_binaries
-  install_veyron_js
-  install_pgbundle
-
-  echo -e "\n\n>>>>> Test without identities\n\n"
-
-  test_with_files "src/pingpong/wire.vdl" "src/pong/pong.go" "src/ping/ping.go" || shell_test::fail "line ${LINENO}: basic ping (go -> go)"
-  grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
-  grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
-
-  test_with_files "src/pong/pong.js" "src/ping/ping.js" || shell_test::fail "line ${LINENO}: basic ping (js -> js)"
-  grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
-  grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
-
-  test_with_files "src/pong/pong.go" "src/ping/ping.js" "src/pingpong/wire.vdl" || shell_test::fail "line ${LINENO}: basic ping (js -> go)"
-  grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
-  grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
-
-  test_with_files "src/pong/pong.js" "src/ping/ping.go" "src/pingpong/wire.vdl" || shell_test::fail "line ${LINENO}: basic ping (go -> js)"
-  grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
-  grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
-
-  echo -e "\n\n>>>>> Test with authorized identities\n\n"
-
-  test_with_files "src/pong/pong.go" "src/ping/ping.go" "src/pingpong/wire.vdl" "src/ids/authorized.id" || shell_test::fail "line ${LINENO}: authorized id (go -> go)"
-  grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
-  grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
-
-  test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/ids/authorized.id" || shell_test::fail "line ${LINENO}: authorized id (js -> js)"
-  grep -q PING builder.out || shell_test::fail "line ${LINENO}: no PING"
-  grep -q PONG builder.out || shell_test::fail "line ${LINENO}: no PONG"
-
-  echo -e "\n\n>>>>> Test with expired identities\n\n"
-
-  test_with_files "src/pong/pong.go" "src/ping/ping.go" "src/pingpong/wire.vdl" "src/ids/expired.id" || shell_test::fail  "line ${LINENO}: failed to build with expired id (go -> go)"
-  grep -q "ipc: not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded"
-
-  test_with_files "src/pong/pong.js" "src/ping/ping.js" "src/ids/expired.id" || shell_test::fail  "line ${LINENO}: failed to build with expired id (js -> js)"
-  grep -q "ipc: not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with expired id succeeded"
-
-  echo -e "\n\n>>>>> Test with unauthorized identities\n\n"
-
-  test_with_files "src/pong/pong.go" "src/ping/ping.go" "src/pingpong/wire.vdl" "src/ids/unauthorized.id" || shell_test::fail  "line ${LINENO}: failed to build with unauthorized id (go -> go)"
-  grep -q "ipc: not authorized" builder.out || shell_test::fail "line ${LINENO}: rpc with unauthorized id succeeded"
-
-  # TODO(nlacasse): Write the javascript version of this test once the
-  # javascript implementation is capable of checking that an identity is
-  # authorized.
-
-  shell_test::pass
-}
-
-main "$@"
diff --git a/tools/playground/testdata/src/ids/authorized.id b/tools/playground/testdata/src/ids/authorized.id
deleted file mode 100644
index cca29d1..0000000
--- a/tools/playground/testdata/src/ids/authorized.id
+++ /dev/null
@@ -1,15 +0,0 @@
-[
-{
-  "Name": "myorg"
-},
-{
-  "Name": "myserver",
-  "Blesser": "myorg",
-  "Files": ["pong.go", "pong.js"]
-},
-{
-  "Name": "myclient",
-  "Blesser": "myserver",
-  "Files": ["ping.go", "ping.js"]
-}
-]
diff --git a/tools/playground/testdata/src/ids/expired.id b/tools/playground/testdata/src/ids/expired.id
deleted file mode 100644
index 2fee1f3..0000000
--- a/tools/playground/testdata/src/ids/expired.id
+++ /dev/null
@@ -1,7 +0,0 @@
-[
-{
-  "Name": "expired",
-  "Duration": "0s",
-  "Files": ["ping.go", "pong.go", "ping.js", "pong.js"]
-}
-]
diff --git a/tools/playground/testdata/src/ids/unauthorized.id b/tools/playground/testdata/src/ids/unauthorized.id
deleted file mode 100644
index cd39f52..0000000
--- a/tools/playground/testdata/src/ids/unauthorized.id
+++ /dev/null
@@ -1,15 +0,0 @@
-[
-{
-  "Name": "myorg"
-},
-{
-  "Name": "myserver",
-  "Blesser": "myorg",
-  "Files": ["pong.go", "pong.js"]
-},
-{
-  "Name": "myclient",
-  "Blesser": "myorg",
-  "Files": ["ping.go", "ping.js"]
-}
-]
diff --git a/tools/playground/testdata/src/ping/ping.go b/tools/playground/testdata/src/ping/ping.go
deleted file mode 100644
index 75593b8..0000000
--- a/tools/playground/testdata/src/ping/ping.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// +build OMIT
-package main
-
-import (
-	"fmt"
-
-	_ "veyron.io/veyron/veyron/profiles"
-	"veyron.io/veyron/veyron2/rt"
-
-	"pingpong"
-)
-
-func main() {
-	runtime := rt.Init()
-	log := runtime.Logger()
-
-	s, err := pingpong.BindPingPong("pingpong")
-	if err != nil {
-		log.Fatal("error binding to server: ", err)
-	}
-
-	pong, err := s.Ping(runtime.NewContext(), "PING")
-	if err != nil {
-		log.Fatal("error pinging: ", err)
-	}
-	fmt.Println(pong)
-}
diff --git a/tools/playground/testdata/src/ping/ping.js b/tools/playground/testdata/src/ping/ping.js
deleted file mode 100644
index 1b6f2d8..0000000
--- a/tools/playground/testdata/src/ping/ping.js
+++ /dev/null
@@ -1,16 +0,0 @@
-var veyron = require('veyron');
-
-veyron.init(function(err, rt){
-  if (err) throw err;
-
-  rt.bindTo('pingpong', function(err, s){
-    if (err) throw err;
-
-    s.ping('PING', function(err, pong){
-      if (err) throw err;
-
-      console.log(pong);
-      process.exit(0);
-    });
-  });
-});
diff --git a/tools/playground/testdata/src/pingpong/wire.vdl b/tools/playground/testdata/src/pingpong/wire.vdl
deleted file mode 100644
index 539231e..0000000
--- a/tools/playground/testdata/src/pingpong/wire.vdl
+++ /dev/null
@@ -1,7 +0,0 @@
-package pingpong
-
-import "veyron.io/veyron/veyron2/security"
-
-type PingPong interface {
-	Ping(message string) (string, error) {security.ReadLabel}
-}
diff --git a/tools/playground/testdata/src/pingpong/wire.vdl.go b/tools/playground/testdata/src/pingpong/wire.vdl.go
deleted file mode 100644
index e1aa5db..0000000
--- a/tools/playground/testdata/src/pingpong/wire.vdl.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// This file was auto-generated by the veyron vdl tool.
-// Source: wire.vdl
-
-package pingpong
-
-import (
-	"veyron.io/veyron/veyron2/security"
-
-	// The non-user imports are prefixed with "_gen_" to prevent collisions.
-	_gen_veyron2 "veyron.io/veyron/veyron2"
-	_gen_context "veyron.io/veyron/veyron2/context"
-	_gen_ipc "veyron.io/veyron/veyron2/ipc"
-	_gen_naming "veyron.io/veyron/veyron2/naming"
-	_gen_vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
-	_gen_wiretype "veyron.io/veyron/veyron2/wiretype"
-)
-
-// TODO(bprosnitz) Remove this line once signatures are updated to use typevals.
-// It corrects a bug where _gen_wiretype is unused in VDL pacakges where only bootstrap types are used on interfaces.
-const _ = _gen_wiretype.TypeIDInvalid
-
-// PingPong is the interface the client binds and uses.
-// PingPong_ExcludingUniversal is the interface without internal framework-added methods
-// to enable embedding without method collisions.  Not to be used directly by clients.
-type PingPong_ExcludingUniversal interface {
-	Ping(ctx _gen_context.T, message string, opts ..._gen_ipc.CallOpt) (reply string, err error)
-}
-type PingPong interface {
-	_gen_ipc.UniversalServiceMethods
-	PingPong_ExcludingUniversal
-}
-
-// PingPongService is the interface the server implements.
-type PingPongService interface {
-	Ping(context _gen_ipc.ServerContext, message string) (reply string, err error)
-}
-
-// BindPingPong returns the client stub implementing the PingPong
-// interface.
-//
-// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
-// global Runtime is used.
-func BindPingPong(name string, opts ..._gen_ipc.BindOpt) (PingPong, error) {
-	var client _gen_ipc.Client
-	switch len(opts) {
-	case 0:
-		// Do nothing.
-	case 1:
-		if clientOpt, ok := opts[0].(_gen_ipc.Client); opts[0] == nil || ok {
-			client = clientOpt
-		} else {
-			return nil, _gen_vdlutil.ErrUnrecognizedOption
-		}
-	default:
-		return nil, _gen_vdlutil.ErrTooManyOptionsToBind
-	}
-	stub := &clientStubPingPong{defaultClient: client, name: name}
-
-	return stub, nil
-}
-
-// NewServerPingPong creates a new server stub.
-//
-// It takes a regular server implementing the PingPongService
-// interface, and returns a new server stub.
-func NewServerPingPong(server PingPongService) interface{} {
-	return &ServerStubPingPong{
-		service: server,
-	}
-}
-
-// clientStubPingPong implements PingPong.
-type clientStubPingPong struct {
-	defaultClient _gen_ipc.Client
-	name          string
-}
-
-func (__gen_c *clientStubPingPong) client(ctx _gen_context.T) _gen_ipc.Client {
-	if __gen_c.defaultClient != nil {
-		return __gen_c.defaultClient
-	}
-	return _gen_veyron2.RuntimeFromContext(ctx).Client()
-}
-
-func (__gen_c *clientStubPingPong) Ping(ctx _gen_context.T, message string, opts ..._gen_ipc.CallOpt) (reply string, err error) {
-	var call _gen_ipc.Call
-	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Ping", []interface{}{message}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&reply, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (__gen_c *clientStubPingPong) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
-	var call _gen_ipc.Call
-	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&reply, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (__gen_c *clientStubPingPong) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
-	var call _gen_ipc.Call
-	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&reply, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (__gen_c *clientStubPingPong) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
-	var call _gen_ipc.Call
-	if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&reply, &err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-// ServerStubPingPong wraps a server that implements
-// PingPongService and provides an object that satisfies
-// the requirements of veyron2/ipc.ReflectInvoker.
-type ServerStubPingPong struct {
-	service PingPongService
-}
-
-func (__gen_s *ServerStubPingPong) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
-	// TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
-	// Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
-	// This will change when it is replaced with Signature().
-	switch method {
-	case "Ping":
-		return []interface{}{security.Label(2)}, nil
-	default:
-		return nil, nil
-	}
-}
-
-func (__gen_s *ServerStubPingPong) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
-	result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
-	result.Methods["Ping"] = _gen_ipc.MethodSignature{
-		InArgs: []_gen_ipc.MethodArgument{
-			{Name: "message", Type: 3},
-		},
-		OutArgs: []_gen_ipc.MethodArgument{
-			{Name: "", Type: 3},
-			{Name: "", Type: 65},
-		},
-	}
-
-	result.TypeDefs = []_gen_vdlutil.Any{
-		_gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
-	return result, nil
-}
-
-func (__gen_s *ServerStubPingPong) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
-	if unresolver, ok := __gen_s.service.(_gen_ipc.Unresolver); ok {
-		return unresolver.UnresolveStep(call)
-	}
-	if call.Server() == nil {
-		return
-	}
-	var published []string
-	if published, err = call.Server().Published(); err != nil || published == nil {
-		return
-	}
-	reply = make([]string, len(published))
-	for i, p := range published {
-		reply[i] = _gen_naming.Join(p, call.Name())
-	}
-	return
-}
-
-func (__gen_s *ServerStubPingPong) Ping(call _gen_ipc.ServerCall, message string) (reply string, err error) {
-	reply, err = __gen_s.service.Ping(call, message)
-	return
-}
diff --git a/tools/playground/testdata/src/pong/pong.go b/tools/playground/testdata/src/pong/pong.go
deleted file mode 100644
index 7a30485..0000000
--- a/tools/playground/testdata/src/pong/pong.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// +build OMIT
-package main
-
-import (
-	"fmt"
-
-	"veyron.io/veyron/veyron/lib/signals"
-	_ "veyron.io/veyron/veyron/profiles"
-	sflag "veyron.io/veyron/veyron/security/flag"
-	"veyron.io/veyron/veyron2/ipc"
-	"veyron.io/veyron/veyron2/rt"
-
-	"pingpong"
-)
-
-type pongd struct{}
-
-func (f *pongd) Ping(_ ipc.ServerContext, message string) (result string, err error) {
-	fmt.Println(message)
-	return "PONG", nil
-}
-
-func main() {
-	r := rt.Init()
-	log := r.Logger()
-	s, err := r.NewServer()
-	if err != nil {
-		log.Fatal("failure creating server: ", err)
-	}
-	log.Info("Waiting for ping")
-
-	serverPong := pingpong.NewServerPingPong(&pongd{})
-
-	if endpoint, err := s.Listen("tcp", "127.0.0.1:0"); err == nil {
-		fmt.Printf("Listening at: %v\n", endpoint)
-	} else {
-		log.Fatal("error listening to service: ", err)
-	}
-
-	if err := s.Serve("pingpong", ipc.LeafDispatcher(serverPong, sflag.NewAuthorizerOrDie())); err != nil {
-		log.Fatal("error serving service: ", err)
-	}
-
-	// Wait forever.
-	<-signals.ShutdownOnSignals()
-}
diff --git a/tools/playground/testdata/src/pong/pong.js b/tools/playground/testdata/src/pong/pong.js
deleted file mode 100644
index 71d31e3..0000000
--- a/tools/playground/testdata/src/pong/pong.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var veyron = require('veyron');
-var leafDispatcher = require('veyron/src/ipc/leaf_dispatcher');
-
-var pingPongService = {
-  ping: function(msg){
-    console.log(msg);
-    return 'PONG';
-  }
-};
-
-veyron.init(function(err, rt) {
-  if (err) throw err;
-
-  rt.serve('pingpong', leafDispatcher(pingPongService), function(err) {
-    if (err) throw err;
-  });
-});