func postContainersCreate(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := r.ParseForm(); err != nil { return nil } body, err := ioutil.ReadAll(r.Body) if err != nil { return err } container, err := beam.Obj(out).Spawn(string(body)) if err != nil { return err } responseJson, err := container.Get() if err != nil { return err } var response struct{ Id string } if err = json.Unmarshal([]byte(responseJson), &response); err != nil { return err } return writeJSON(w, http.StatusCreated, response) }
func postContainersStop(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } name := vars["name"] _, containerOut, err := beam.Obj(out).Attach(name) container := beam.Obj(containerOut) if err != nil { return err } if err := container.Stop(); err != nil { return err } w.WriteHeader(http.StatusNoContent) return nil }
func Simulator() beam.Sender { s := beam.NewServer() s.OnSpawn(beam.Handler(func(ctx *beam.Message) error { containers := ctx.Args instance := beam.Task(func(in beam.Receiver, out beam.Sender) { beam.Obj(out).Log("[simulator] starting\n") s := beam.NewServer() s.OnLs(beam.Handler(func(msg *beam.Message) error { beam.Obj(out).Log("[simulator] generating fake list of objects...\n") beam.Obj(msg.Ret).Set(containers...) return nil })) beam.Copy(s, in) }) ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance}) return nil })) return s }
func getContainerJson(out beam.Sender, containerID string) (containerJson, error) { o := beam.Obj(out) _, containerOut, err := o.Attach(containerID) if err != nil { return containerJson{}, err } container := beam.Obj(containerOut) responseJson, err := container.Get() if err != nil { return containerJson{}, err } var response containerJson if err = json.Unmarshal([]byte(responseJson), &response); err != nil { return containerJson{}, err } return response, nil }
func instance(t *testing.T, server *httptest.Server) *beam.Object { url := "tcp://localhost:4243" if server != nil { url = strings.Replace(server.URL, "http://", "tcp://", 1) } backend := DockerClient() instance, err := beam.Obj(backend).Spawn(url) if err != nil { t.Fatal(err) } return instance }
// New returns a new engine, with all backends // registered but not activated. // To activate a backend, call a job on the resulting // engine, named after the desired backend. // // Example: `New().Job("debug").Run()` func New() *beam.Object { backends := beam.NewTree() backends.Bind("simulator", Simulator()) backends.Bind("debug", debug.Debug()) backends.Bind("fakeclient", FakeClient()) backends.Bind("dockerclient", DockerClient()) backends.Bind("exec", Exec()) backends.Bind("dockerserver", DockerServer()) backends.Bind("orchard", Orchard()) backends.Bind("aggregate", Aggregate()) backends.Bind("shipyard", Shipyard()) backends.Bind("tutum", Tutum()) return beam.Obj(backends) }
func FakeClient() beam.Sender { backend := beam.NewServer() backend.OnSpawn(beam.Handler(func(ctx *beam.Message) error { // Instantiate a new fakeclient instance instance := beam.Task(func(in beam.Receiver, out beam.Sender) { fmt.Printf("fake client!\n") defer fmt.Printf("end of fake client!\n") o := beam.Obj(out) o.Log("fake client starting") defer o.Log("fake client terminating") for { time.Sleep(1 * time.Second) o.Log("fake client heartbeat!") } }) _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance}) return err })) return backend }
func Orchard() beam.Sender { backend := beam.NewServer() backend.OnSpawn(beam.Handler(func(ctx *beam.Message) error { if len(ctx.Args) != 2 { return fmt.Errorf("orchard: spawn expects 2 arguments: API token and name of host") } apiToken, hostName := ctx.Args[0], ctx.Args[1] apiClient := &api.HTTPClient{ BaseURL: "https://api.orchardup.com/v2", Token: apiToken, } host, err := apiClient.GetHost(hostName) if err != nil { return err } url := fmt.Sprintf("tcp://%s:4243", host.IPAddress) tlsConfig, err := getTLSConfig([]byte(host.ClientCert), []byte(host.ClientKey)) if err != nil { return err } backend := DockerClientWithConfig(&DockerClientConfig{ Scheme: "https", URLHost: host.IPAddress, TLSClientConfig: tlsConfig, }) forwardBackend := beam.Obj(backend) forwardInstance, err := forwardBackend.Spawn(url) if err != nil { return err } _, err = ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: forwardInstance}) return err })) return backend }
func postContainersAttach(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := r.ParseForm(); err != nil { return err } if vars == nil { return fmt.Errorf("Missing parameter") } inStream, outStream, err := hijackServer(w) if err != nil { return err } defer func() { if tcpc, ok := inStream.(*net.TCPConn); ok { tcpc.CloseWrite() } else { inStream.Close() } }() defer func() { if tcpc, ok := outStream.(*net.TCPConn); ok { tcpc.CloseWrite() } else if closer, ok := outStream.(io.Closer); ok { closer.Close() } }() fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") // TODO: if a TTY, then no multiplexing is done errStream := utils.NewStdWriter(outStream, utils.Stderr) outStream = utils.NewStdWriter(outStream, utils.Stdout) _, containerOut, err := beam.Obj(out).Attach(vars["name"]) if err != nil { return err } container := beam.Obj(containerOut) containerR, _, err := container.Attach("") var tasks sync.WaitGroup go func() { defer tasks.Done() err := beam.DecodeStream(outStream, containerR, "stdout") if err != nil { fmt.Printf("decodestream: %v\n", err) } }() tasks.Add(1) go func() { defer tasks.Done() err := beam.DecodeStream(errStream, containerR, "stderr") if err != nil { fmt.Printf("decodestream: %v\n", err) } }() tasks.Add(1) tasks.Wait() return nil }
func getContainersJSON(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := r.ParseForm(); err != nil { return err } o := beam.Obj(out) names, err := o.Ls() if err != nil { return err } var responses []interface{} for _, name := range names { response, err := getContainerJson(out, name) if err != nil { return err } created, err := time.Parse(time.RFC3339, response.Created) if err != nil { return err } var state string if response.State.Running { state = "Up" } else { state = fmt.Sprintf("Exited (%d)", response.State.ExitCode) } type port struct { IP string PrivatePort int PublicPort int Type string } var ports []port for p, mappings := range response.NetworkSettings.Ports { var portnum int var proto string _, err := fmt.Sscanf(p, "%d/%s", &portnum, &proto) if err != nil { return err } if len(mappings) > 0 { for _, mapping := range mappings { hostPort, err := strconv.Atoi(mapping["HostPort"]) if err != nil { return err } newport := port{ IP: mapping["HostIp"], PrivatePort: portnum, PublicPort: hostPort, Type: proto, } ports = append(ports, newport) } } else { newport := port{ PrivatePort: portnum, Type: proto, } ports = append(ports, newport) } } responses = append(responses, map[string]interface{}{ "Id": response.ID, "Command": strings.Join(response.Config.Cmd, " "), "Created": created.Unix(), "Image": response.Config.Image, "Names": []string{response.Name}, "Ports": ports, "Status": state, }) } return writeJSON(w, http.StatusOK, responses) }
func getContainersJSON(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := r.ParseForm(); err != nil { return err } o := beam.Obj(out) names, err := o.Ls() if err != nil { return err } var responses []interface{} for _, name := range names { _, containerOut, err := o.Attach(name) if err != nil { return err } container := beam.Obj(containerOut) responseJson, err := container.Get() if err != nil { return err } var response struct { ID string Created string Name string Config struct { Cmd []string Image string } State struct { Running bool StartedAt string FinishedAt string ExitCode int } } if err = json.Unmarshal([]byte(responseJson), &response); err != nil { return err } created, err := time.Parse(time.RFC3339, response.Created) if err != nil { return err } var state string if response.State.Running { state = "Up" } else { state = fmt.Sprintf("Exited (%d)", response.State.ExitCode) } responses = append(responses, map[string]interface{}{ "Id": response.ID, "Command": strings.Join(response.Config.Cmd, " "), "Created": created.Unix(), "Image": response.Config.Image, "Names": []string{response.Name}, "Ports": []string{}, "Status": state, }) } return writeJSON(w, http.StatusOK, responses) }
func Exec() beam.Sender { e := beam.NewServer() e.OnSpawn(beam.Handler(func(msg *beam.Message) error { if len(msg.Args) < 1 { return fmt.Errorf("usage: SPAWN exec|... <config>") } if msg.Args[0] != "exec" { return fmt.Errorf("invalid command: %s", msg.Args[0]) } var config struct { Path string Args []string } if err := json.Unmarshal([]byte(msg.Args[1]), &config); err != nil { config.Path = msg.Args[1] config.Args = msg.Args[2:] } cmd := &command{ Cmd: exec.Command(config.Path, config.Args...), Server: beam.NewServer(), } cmd.OnAttach(beam.Handler(func(msg *beam.Message) error { stdout, err := cmd.StdoutPipe() if err != nil { return err } stdin, err := cmd.StdinPipe() if err != nil { return err } inR, inW := beam.Pipe() if _, err := msg.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: inW}); err != nil { return err } out := beam.Obj(msg.Ret) go func() { defer stdin.Close() for { msg, err := inR.Receive(0) if err != nil { return } if msg.Verb == beam.Log && len(msg.Args) > 0 { fmt.Fprintf(stdin, "%s\n", strings.TrimRight(msg.Args[0], "\r\n")) } } }() cmd.tasks.Add(1) go func() { defer cmd.tasks.Done() scanner := bufio.NewScanner(stdout) for scanner.Scan() { if scanner.Err() != io.EOF && scanner.Err() != nil { return } if err := out.Log(scanner.Text()); err != nil { out.Error("%v", err) return } } }() cmd.tasks.Wait() return nil })) cmd.OnStart(beam.Handler(func(msg *beam.Message) error { cmd.tasks.Add(1) if err := cmd.Cmd.Start(); err != nil { return err } go func() { defer cmd.tasks.Done() if err := cmd.Cmd.Wait(); err != nil { beam.Obj(msg.Ret).Log("%s exited status=%v", cmd.Cmd.Path, err) } }() msg.Ret.Send(&beam.Message{Verb: beam.Ack}) return nil })) if _, err := msg.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: cmd}); err != nil { return err } return nil })) return e }