DodoApp: Logs

Change-Id: Idb429c417b639b53352642d1d59a6b29622d499f
diff --git a/apps/app-runner/server.go b/apps/app-runner/server.go
index f3ee563..5969160 100644
--- a/apps/app-runner/server.go
+++ b/apps/app-runner/server.go
@@ -4,6 +4,7 @@
 	"bytes"
 	"encoding/json"
 	"fmt"
+	"io"
 	"net/http"
 	"os"
 	"os/exec"
@@ -25,6 +26,7 @@
 	runCommands []Command
 	self        string
 	managerAddr string
+	logs        *Log
 }
 
 func NewServer(port int, appId string, repoAddr string, signer ssh.Signer, appDir string, runCommands []Command, self string, manager string) *Server {
@@ -39,12 +41,14 @@
 		runCommands: runCommands,
 		self:        self,
 		managerAddr: manager,
+		logs:        &Log{},
 	}
 }
 
 func (s *Server) Start() error {
 	http.HandleFunc("/update", s.handleUpdate)
 	http.HandleFunc("/ready", s.handleReady)
+	http.HandleFunc("/logs", s.handleLogs)
 	if err := s.run(); err != nil {
 		return err
 	}
@@ -52,6 +56,10 @@
 	return http.ListenAndServe(fmt.Sprintf(":%d", s.port), nil)
 }
 
+func (s *Server) handleLogs(w http.ResponseWriter, r *http.Request) {
+	fmt.Fprint(w, s.logs.Contents())
+}
+
 func (s *Server) handleReady(w http.ResponseWriter, r *http.Request) {
 	s.l.Lock()
 	defer s.l.Unlock()
@@ -93,6 +101,7 @@
 	if err := CloneRepository(s.repoAddr, s.signer, s.appDir); err != nil {
 		return err
 	}
+	logM := io.MultiWriter(os.Stdout, s.logs)
 	for i, c := range s.runCommands {
 		args := []string{c.Bin}
 		args = append(args, c.Args...)
@@ -101,8 +110,8 @@
 			Path:   c.Bin,
 			Args:   args,
 			Env:    c.Env,
-			Stdout: os.Stdout,
-			Stderr: os.Stderr,
+			Stdout: logM,
+			Stderr: logM,
 		}
 		fmt.Printf("Running: %s\n", c.Bin)
 		if i < len(s.runCommands)-1 {
@@ -121,6 +130,7 @@
 
 type pingReq struct {
 	Address string `json:"address"`
+	Logs    string `json:"logs"`
 }
 
 func (s *Server) pingManager() {
@@ -132,6 +142,7 @@
 	}()
 	buf, err := json.Marshal(pingReq{
 		Address: fmt.Sprintf("%s:%d", s.self, s.port),
+		Logs:    s.logs.Contents(),
 	})
 	if err != nil {
 		return