func NewTree() *Tree { t := &Tree{ Server: libswarm.NewServer(), children: make(map[string]libswarm.Sender), } t.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error { if len(msg.Args) == 0 || msg.Args[0] == "" { msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: t}) return nil } if child, exists := t.children[msg.Args[0]]; exists { msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: child}) return nil } libswarm.AsClient(msg.Ret).Error("not found") return nil })) t.OnVerb(libswarm.Ls, libswarm.Handler(func(msg *libswarm.Message) error { names := make([]string, 0, len(t.children)) for name := range t.children { names = append(names, name) } sort.Strings(names) libswarm.AsClient(msg.Ret).Set(names...) return nil })) return t }
func postContainersStop(out libswarm.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 := libswarm.AsClient(out).Attach(name) container := libswarm.AsClient(containerOut) if err != nil { return err } if err := container.Stop(); err != nil { return err } w.WriteHeader(http.StatusNoContent) return nil }
func Simulator() libswarm.Sender { s := libswarm.NewServer() s.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { containers := ctx.Args instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { libswarm.AsClient(out).Log("[simulator] starting\n") s := libswarm.NewServer() s.OnVerb(libswarm.Ls, libswarm.Handler(func(msg *libswarm.Message) error { libswarm.AsClient(out).Log("[simulator] generating fake list of objects...\n") libswarm.AsClient(msg.Ret).Set(containers...) return nil })) libswarm.Copy(s, in) }) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance}) return nil })) return s }
func getContainerJson(out libswarm.Sender, containerID string) (containerJson, error) { o := libswarm.AsClient(out) _, containerOut, err := o.Attach(containerID) if err != nil { return containerJson{}, err } container := libswarm.AsClient(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 *stubServer) *libswarm.Client { url := "tcp://localhost:4243" if server != nil { url = strings.Replace(server.URL, "http://", "tcp://", 1) } backend := DockerClient() instance, err := libswarm.AsClient(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() *libswarm.Client { backends := utils.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("ec2", Ec2()) backends.Bind("tutum", Tutum()) return libswarm.AsClient(backends) }
func (c *ec2Client) initDockerClientInstance(instance *ec2.Instance) error { dockerClient := DockerClientWithConfig(&DockerClientConfig{ Scheme: "http", URLHost: "localhost", }) dockerBackend := libswarm.AsClient(dockerClient) url := fmt.Sprintf("tcp://localhost:%s", c.config.sshLocalPort) dockerInstance, err := dockerBackend.Spawn(url) c.dockerInstance = dockerInstance if err != nil { return err } return nil }
func FakeClient() libswarm.Sender { backend := libswarm.NewServer() backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { // Instantiate a new fakeclient instance instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { fmt.Printf("fake client!\n") defer fmt.Printf("end of fake client!\n") o := libswarm.AsClient(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(&libswarm.Message{Verb: libswarm.Ack, Ret: instance}) return err })) return backend }
func Orchard() libswarm.Sender { backend := libswarm.NewServer() backend.OnSpawn(func(cmd ...string) (libswarm.Sender, error) { if len(cmd) != 2 { return nil, fmt.Errorf("orchard: spawn expects 2 arguments: API token and name of host") } apiToken, hostName := cmd[0], cmd[1] apiClient := &api.HTTPClient{ BaseURL: "https://api.orchardup.com/v2", Token: apiToken, } host, err := apiClient.GetHost(hostName) if err != nil { return nil, err } url := fmt.Sprintf("tcp://%s:4243", host.IPAddress) tlsConfig, err := getTLSConfig([]byte(host.ClientCert), []byte(host.ClientKey)) if err != nil { return nil, err } backend := DockerClientWithConfig(&DockerClientConfig{ Scheme: "https", URLHost: host.IPAddress, TLSClientConfig: tlsConfig, }) forwardBackend := libswarm.AsClient(backend) forwardInstance, err := forwardBackend.Spawn(url) if err != nil { return nil, err } return forwardInstance, nil }) return backend }
func postContainersCreate(out libswarm.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 } name := r.Form.Get("name") if name != "" { var reqJson map[string]interface{} if err = json.Unmarshal(body, &reqJson); err != nil { return err } reqJson["name"] = name body, err = json.Marshal(reqJson) if err != nil { return err } } container, err := libswarm.AsClient(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 Exec() libswarm.Sender { e := libswarm.NewServer() e.OnVerb(libswarm.Spawn, libswarm.Handler(func(msg *libswarm.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: libswarm.NewServer(), } cmd.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error { stdout, err := cmd.StdoutPipe() if err != nil { return err } stdin, err := cmd.StdinPipe() if err != nil { return err } inR, inW := libswarm.Pipe() if _, err := msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: inW}); err != nil { return err } out := libswarm.AsClient(msg.Ret) go func() { defer stdin.Close() for { msg, err := inR.Receive(0) if err != nil { return } if msg.Verb == libswarm.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.OnVerb(libswarm.Start, libswarm.Handler(func(msg *libswarm.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 { libswarm.AsClient(msg.Ret).Log("%s exited status=%v", cmd.Cmd.Path, err) } }() msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack}) return nil })) if _, err := msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: cmd}); err != nil { return err } return nil })) return e }
func postContainersAttach(out libswarm.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 := dockerutils.NewStdWriter(outStream, dockerutils.Stderr) outStream = dockerutils.NewStdWriter(outStream, dockerutils.Stdout) _, containerOut, err := libswarm.AsClient(out).Attach(vars["name"]) if err != nil { return err } container := libswarm.AsClient(containerOut) containerR, _, err := container.Attach("") var tasks sync.WaitGroup go func() { defer tasks.Done() err := utils.DecodeStream(outStream, containerR, "stdout") if err != nil { fmt.Printf("decodestream: %v\n", err) } }() tasks.Add(1) go func() { defer tasks.Done() err := utils.DecodeStream(errStream, containerR, "stderr") if err != nil { fmt.Printf("decodestream: %v\n", err) } }() tasks.Add(1) tasks.Wait() return nil }
func getContainersJSON(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := r.ParseForm(); err != nil { return err } o := libswarm.AsClient(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{ PublicPort: 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) }