예제 #1
0
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)
}
예제 #2
0
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
}
예제 #3
0
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
}
예제 #4
0
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
}
예제 #5
0
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
}
예제 #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() *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)
}
예제 #7
0
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
}
예제 #8
0
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
}
예제 #9
0
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
}
예제 #10
0
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)
}
예제 #11
0
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)
}
예제 #12
0
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
}