Beispiel #1
0
func main() {
	go worker()

	state, err := term.SetRawTerminal(os.Stdin.Fd())
	if err != nil {
		panic(err)
	}
	defer term.RestoreTerminal(os.Stdin.Fd(), state)

	winsize, _ = term.GetWinsize(os.Stdin.Fd())
	client, err := beam.NewClient(&beam.NetTransport{"tcp", ":6379"})
	if err != nil {
		panic(err)
	}
	defer client.Close()

	job := createJob(client)

	if err := job.Start(); err != nil {
		panic(err)
	}
	if err := job.Wait(); err != nil {
		panic(err)
	}
}
Beispiel #2
0
func createJob(client *beam.Client) *beam.Job {
	job, err := client.NewJob("tty")
	if err != nil {
		panic(err)
	}

	master, slave, err := pty.Open()
	if err != nil {
		panic(err)
	}

	_, err = term.SetRawTerminal(master.Fd())
	if err != nil {
		panic(err)
	}

	go job.WriteTo(slave, "stdout")
	go job.WriteTo(slave, "stderr")
	go job.ReadFrom(slave, "stdin")

	go io.Copy(os.Stdout, master)
	go io.Copy(os.Stderr, master)
	go io.Copy(master, os.Stdin)

	return job
}
Beispiel #3
0
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.File, out io.Writer) error {

	req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil)
	if err != nil {
		return err
	}
	req.Header.Set("User-Agent", "Docker-Client/"+VERSION)
	req.Header.Set("Content-Type", "plain/text")

	dial, err := net.Dial(cli.proto, cli.addr)
	if err != nil {
		return err
	}
	clientconn := httputil.NewClientConn(dial, nil)
	defer clientconn.Close()

	// Server hijacks the connection, error 'connection closed' expected
	clientconn.Do(req)

	rwc, br := clientconn.Hijack()
	defer rwc.Close()

	receiveStdout := utils.Go(func() error {
		_, err := io.Copy(out, br)
		return err
	})

	if in != nil && setRawTerminal && term.IsTerminal(in.Fd()) && os.Getenv("NORAW") == "" {
		oldState, err := term.SetRawTerminal()
		if err != nil {
			return err
		}
		defer term.RestoreTerminal(oldState)
	}
	sendStdin := utils.Go(func() error {
		io.Copy(rwc, in)
		if err := rwc.(*net.TCPConn).CloseWrite(); err != nil {
			utils.Debugf("Couldn't send EOF: %s\n", err)
		}
		// Discard errors due to pipe interruption
		return nil
	})

	if err := <-receiveStdout; err != nil {
		utils.Debugf("Error receiveStdout: %s", err)
		return err
	}

	if !term.IsTerminal(in.Fd()) {
		if err := <-sendStdin; err != nil {
			utils.Debugf("Error sendStdin: %s", err)
			return err
		}
	}
	return nil

}
Beispiel #4
0
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool) error {
	req, err := http.NewRequest(method, path, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "plain/text")
	dial, err := net.Dial("tcp", fmt.Sprintf("%s:%d", cli.host, cli.port))
	if err != nil {
		return err
	}
	clientconn := httputil.NewClientConn(dial, nil)
	clientconn.Do(req)
	defer clientconn.Close()

	rwc, br := clientconn.Hijack()
	defer rwc.Close()

	receiveStdout := utils.Go(func() error {
		_, err := io.Copy(os.Stdout, br)
		return err
	})

	if setRawTerminal && term.IsTerminal(int(os.Stdin.Fd())) && os.Getenv("NORAW") == "" {
		if oldState, err := term.SetRawTerminal(); err != nil {
			return err
		} else {
			defer term.RestoreTerminal(oldState)
		}
	}

	sendStdin := utils.Go(func() error {
		_, err := io.Copy(rwc, os.Stdin)
		if err := rwc.(*net.TCPConn).CloseWrite(); err != nil {
			fmt.Fprintf(os.Stderr, "Couldn't send EOF: %s\n", err)
		}
		return err
	})

	if err := <-receiveStdout; err != nil {
		return err
	}

	if !term.IsTerminal(int(os.Stdin.Fd())) {
		if err := <-sendStdin; err != nil {
			return err
		}
	}
	return nil

}
Beispiel #5
0
func (client *Client) Attach(in io.ReadCloser, out io.WriteCloser) {
	client.Connect()

	client.in = in
	if file, ok := client.in.(*os.File); ok {
		client.terminalFd = file.Fd()
		client.isTerminal = term.IsTerminal(client.terminalFd)
	}

	if !client.isTerminal {
		panic(fmt.Errorf("siphon: cannot attach, no tty"))
	}

	fmt.Fprintf(log.client, "attaching to tty\r\n")

	rawOldState, err := term.SetRawTerminal(client.terminalFd)
	if err != nil {
		panic(err)
	}
	defer term.RestoreTerminal(client.terminalFd, rawOldState)

	client.monitorTtySize()

	var track sync.WaitGroup

	track.Add(1)
	go func() {
		defer track.Done()
		io.Copy(out, client.stdout)
		fmt.Fprintf(log.client, "client output closed\r\n")
	}()

	// track.Add(1) // io.Copy will block indefinitely on 'in' regardless of if client.stdin has been closed, so we can't actually wait for this.
	go func() {
		io.Copy(client.stdin, in)
		fmt.Fprintf(log.client, "client input closed\r\n")
	}()

	track.Wait()
}
Beispiel #6
0
func (c *Client) hijack(method, path string, setRawTerminal bool, in *os.File, errStream io.Writer, out io.Writer) error {
	req, err := http.NewRequest(method, c.getURL(path), nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "plain/text")
	dial, err := net.Dial("tcp", c.endpointURL.Host)
	if err != nil {
		return err
	}
	clientconn := httputil.NewClientConn(dial, nil)
	clientconn.Do(req)
	defer clientconn.Close()
	rwc, br := clientconn.Hijack()
	defer rwc.Close()
	errStdout := make(chan error, 1)
	go func() {
		_, err := io.Copy(out, br)
		errStdout <- err
	}()
	if in != nil && setRawTerminal && term.IsTerminal(in.Fd()) && os.Getenv("NORAW") == "" {
		oldState, err := term.SetRawTerminal(in.Fd())
		if err != nil {
			return err
		}
		defer term.RestoreTerminal(in.Fd(), oldState)
	}
	go func() {
		io.Copy(rwc, in)
		if err := rwc.(*net.TCPConn).CloseWrite(); err != nil {
			fmt.Fprintf(errStream, "Couldn't send EOF: %s\n", err)
		}
	}()
	if err := <-errStdout; err != nil {
		return err
	}
	return nil
}
Beispiel #7
0
// 'docker login': login / register a user to registry service.
func (cli *DockerCli) CmdLogin(args ...string) error {
	var readStringOnRawTerminal = func(stdin io.Reader, stdout io.Writer, echo bool) string {
		char := make([]byte, 1)
		buffer := make([]byte, 64)
		var i = 0
		for i < len(buffer) {
			n, err := stdin.Read(char)
			if n > 0 {
				if char[0] == '\r' || char[0] == '\n' {
					stdout.Write([]byte{'\r', '\n'})
					break
				} else if char[0] == 127 || char[0] == '\b' {
					if i > 0 {
						if echo {
							stdout.Write([]byte{'\b', ' ', '\b'})
						}
						i--
					}
				} else if !unicode.IsSpace(rune(char[0])) &&
					!unicode.IsControl(rune(char[0])) {
					if echo {
						stdout.Write(char)
					}
					buffer[i] = char[0]
					i++
				}
			}
			if err != nil {
				if err != io.EOF {
					fmt.Fprintf(stdout, "Read error: %v\r\n", err)
				}
				break
			}
		}
		return string(buffer[:i])
	}
	var readAndEchoString = func(stdin io.Reader, stdout io.Writer) string {
		return readStringOnRawTerminal(stdin, stdout, true)
	}
	var readString = func(stdin io.Reader, stdout io.Writer) string {
		return readStringOnRawTerminal(stdin, stdout, false)
	}

	oldState, err := term.SetRawTerminal()
	if err != nil {
		return err
	} else {
		defer term.RestoreTerminal(oldState)
	}

	cmd := Subcmd("login", "", "Register or Login to the docker registry server")
	if err := cmd.Parse(args); err != nil {
		return nil
	}

	body, _, err := cli.call("GET", "/auth", nil)
	if err != nil {
		return err
	}

	var out auth.AuthConfig
	err = json.Unmarshal(body, &out)
	if err != nil {
		return err
	}

	var username string
	var password string
	var email string

	fmt.Print("Username (", out.Username, "): ")
	username = readAndEchoString(os.Stdin, os.Stdout)
	if username == "" {
		username = out.Username
	}
	if username != out.Username {
		fmt.Print("Password: "******"" {
			return fmt.Errorf("Error : Password Required")
		}

		fmt.Print("Email (", out.Email, "): ")
		email = readAndEchoString(os.Stdin, os.Stdout)
		if email == "" {
			email = out.Email
		}
	} else {
		email = out.Email
	}

	out.Username = username
	out.Password = password
	out.Email = email

	body, _, err = cli.call("POST", "/auth", out)
	if err != nil {
		return err
	}

	var out2 ApiAuth
	err = json.Unmarshal(body, &out2)
	if err != nil {
		return err
	}
	if out2.Status != "" {
		term.RestoreTerminal(oldState)
		fmt.Print(out2.Status)
	}
	return nil
}
Beispiel #8
0
// 'docker login': login / register a user to registry service.
func (cli *DockerCli) CmdLogin(args ...string) error {
	var readStringOnRawTerminal = func(stdin io.Reader, stdout io.Writer, echo bool) string {
		char := make([]byte, 1)
		buffer := make([]byte, 64)
		var i = 0
		for i < len(buffer) {
			n, err := stdin.Read(char)
			if n > 0 {
				if char[0] == '\r' || char[0] == '\n' {
					stdout.Write([]byte{'\r', '\n'})
					break
				} else if char[0] == 127 || char[0] == '\b' {
					if i > 0 {
						if echo {
							stdout.Write([]byte{'\b', ' ', '\b'})
						}
						i--
					}
				} else if !unicode.IsSpace(rune(char[0])) &&
					!unicode.IsControl(rune(char[0])) {
					if echo {
						stdout.Write(char)
					}
					buffer[i] = char[0]
					i++
				}
			}
			if err != nil {
				if err != io.EOF {
					fmt.Fprintf(stdout, "Read error: %v\r\n", err)
				}
				break
			}
		}
		return string(buffer[:i])
	}
	var readAndEchoString = func(stdin io.Reader, stdout io.Writer) string {
		return readStringOnRawTerminal(stdin, stdout, true)
	}
	var readString = func(stdin io.Reader, stdout io.Writer) string {
		return readStringOnRawTerminal(stdin, stdout, false)
	}

	cmd := Subcmd("login", "[OPTIONS]", "Register or Login to the docker registry server")
	flUsername := cmd.String("u", "", "username")
	flPassword := cmd.String("p", "", "password")
	flEmail := cmd.String("e", "", "email")
	err := cmd.Parse(args)
	if err != nil {
		return nil
	}

	var oldState *term.State
	if *flUsername == "" || *flPassword == "" || *flEmail == "" {
		oldState, err = term.SetRawTerminal(cli.terminalFd)
		if err != nil {
			return err
		}
		defer term.RestoreTerminal(cli.terminalFd, oldState)
	}

	var (
		username string
		password string
		email    string
	)

	if *flUsername == "" {
		fmt.Fprintf(cli.out, "Username (%s): ", cli.authConfig.Username)
		username = readAndEchoString(cli.in, cli.out)
		if username == "" {
			username = cli.authConfig.Username
		}
	} else {
		username = *flUsername
	}
	if username != cli.authConfig.Username {
		if *flPassword == "" {
			fmt.Fprintf(cli.out, "Password: "******"" {
				return fmt.Errorf("Error : Password Required")
			}
		} else {
			password = *flPassword
		}

		if *flEmail == "" {
			fmt.Fprintf(cli.out, "Email (%s): ", cli.authConfig.Email)
			email = readAndEchoString(cli.in, cli.out)
			if email == "" {
				email = cli.authConfig.Email
			}
		} else {
			email = *flEmail
		}
	} else {
		password = cli.authConfig.Password
		email = cli.authConfig.Email
	}
	if oldState != nil {
		term.RestoreTerminal(cli.terminalFd, oldState)
	}
	cli.authConfig.Username = username
	cli.authConfig.Password = password
	cli.authConfig.Email = email

	body, statusCode, err := cli.call("POST", "/auth", cli.authConfig)
	if statusCode == 401 {
		cli.authConfig.Username = ""
		cli.authConfig.Password = ""
		cli.authConfig.Email = ""
		auth.SaveConfig(cli.authConfig)
		return err
	}
	if err != nil {
		return err
	}

	var out2 APIAuth
	err = json.Unmarshal(body, &out2)
	if err != nil {
		auth.LoadConfig(os.Getenv("HOME"))
		return err
	}
	auth.SaveConfig(cli.authConfig)
	if out2.Status != "" {
		fmt.Fprintf(cli.out, "%s\n", out2.Status)
	}
	return nil
}
Beispiel #9
0
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, out io.Writer) error {

	req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil)
	if err != nil {
		return err
	}
	req.Header.Set("User-Agent", "Docker-Client/"+VERSION)
	req.Header.Set("Content-Type", "plain/text")
	req.Host = cli.addr

	dial, err := net.Dial(cli.proto, cli.addr)
	if err != nil {
		if strings.Contains(err.Error(), "connection refused") {
			return fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
		}
		return err
	}
	clientconn := httputil.NewClientConn(dial, nil)
	defer clientconn.Close()

	// Server hijacks the connection, error 'connection closed' expected
	clientconn.Do(req)

	rwc, br := clientconn.Hijack()
	defer rwc.Close()

	var receiveStdout (chan error)
	if out != nil {
		receiveStdout = utils.Go(func() error {
			_, err := io.Copy(out, br)
			utils.Debugf("[hijack] End of stdout")
			return err
		})
	}

	if in != nil && setRawTerminal && cli.isTerminal && os.Getenv("NORAW") == "" {
		oldState, err := term.SetRawTerminal(cli.terminalFd)
		if err != nil {
			return err
		}
		defer term.RestoreTerminal(cli.terminalFd, oldState)
	}

	sendStdin := utils.Go(func() error {
		if in != nil {
			io.Copy(rwc, in)
			utils.Debugf("[hijack] End of stdin")
		}
		if tcpc, ok := rwc.(*net.TCPConn); ok {
			if err := tcpc.CloseWrite(); err != nil {
				utils.Debugf("Couldn't send EOF: %s\n", err)
			}
		} else if unixc, ok := rwc.(*net.UnixConn); ok {
			if err := unixc.CloseWrite(); err != nil {
				utils.Debugf("Couldn't send EOF: %s\n", err)
			}
		}
		// Discard errors due to pipe interruption
		return nil
	})

	if out != nil {
		if err := <-receiveStdout; err != nil {
			utils.Debugf("Error receiveStdout: %s", err)
			return err
		}
	}

	if !cli.isTerminal {
		if err := <-sendStdin; err != nil {
			utils.Debugf("Error sendStdin: %s", err)
			return err
		}
	}
	return nil

}
Beispiel #10
0
func main() {
	disc, err := discover.NewClient()
	if err != nil {
		log.Fatal(err)
	}

	scheduler, err := client.New()
	if err != nil {
		log.Fatal(err)
	}

	state, err := scheduler.State()
	if err != nil {
		log.Fatal(err)
	}

	var firstHost string
	for k := range state {
		firstHost = k
		break
	}
	if firstHost == "" {
		log.Fatal("no hosts")
	}

	id := randomID()

	services, err := disc.Services("flynn-lorne-attach." + firstHost)
	if err != nil {
		log.Fatal(err)
	}
	conn, err := net.Dial("tcp", services.OnlineAddrs()[0])
	if err != nil {
		log.Fatal(err)
	}
	ws, _ := term.GetWinsize(os.Stdin.Fd())
	err = gob.NewEncoder(conn).Encode(&lorne.AttachReq{
		JobID:  id,
		Flags:  lorne.AttachFlagStdout | lorne.AttachFlagStderr | lorne.AttachFlagStdin | lorne.AttachFlagStream,
		Height: int(ws.Height),
		Width:  int(ws.Width),
	})
	if err != nil {
		log.Fatal(err)
	}
	attachState := make([]byte, 1)
	if _, err := conn.Read(attachState); err != nil {
		log.Fatal(err)
	}
	switch attachState[0] {
	case lorne.AttachError:
		log.Fatal("attach error")
	}

	schedReq := &sampi.ScheduleReq{
		Incremental: true,
		HostJobs: map[string][]*sampi.Job{firstHost: {{ID: id, Config: &docker.Config{
			Image:        "titanous/redis",
			Cmd:          []string{"/bin/bash", "-i"},
			Tty:          true,
			AttachStdin:  true,
			AttachStdout: true,
			AttachStderr: true,
			OpenStdin:    true,
			StdinOnce:    true,
			Env: []string{
				"COLUMNS=" + strconv.Itoa(int(ws.Width)),
				"LINES=" + strconv.Itoa(int(ws.Height)),
				"TERM=" + os.Getenv("TERM"),
			},
		}}}},
	}
	if _, err := scheduler.Schedule(schedReq); err != nil {
		log.Fatal(err)
	}

	if _, err := conn.Read(attachState); err != nil {
		log.Fatal(err)
	}

	oldState, err := term.SetRawTerminal(os.Stdin.Fd())
	if err != nil {
		log.Fatal(err)
	}
	go io.Copy(conn, os.Stdin)
	if _, err := io.Copy(os.Stdout, conn); err != nil {
		log.Fatal(err)
	}
	term.RestoreTerminal(os.Stdin.Fd(), oldState)
}