Exemple #1
0
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
}
Exemple #3
0
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
}
Exemple #6
0
// 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)
}
Exemple #7
0
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
}
Exemple #8
0
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
}
Exemple #9
0
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)
}
Exemple #11
0
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)
}