Пример #1
0
Файл: run.go Проект: herokai/hk
func runRun(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.PrintUsage()
		os.Exit(2)
	}
	appname := mustApp()

	cols, err := term.Cols()
	if err != nil {
		printFatal(err.Error())
	}
	lines, err := term.Lines()
	if err != nil {
		printFatal(err.Error())
	}

	attached := !detachedRun
	opts := heroku.DynoCreateOpts{Attach: &attached}
	if attached {
		env := map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
		opts.Env = &env
	}
	if dynoSize != "" {
		if !strings.HasSuffix(dynoSize, "X") {
			cmd.PrintUsage()
			os.Exit(2)
		}
		opts.Size = &dynoSize
	}

	command := strings.Join(args, " ")
	dyno, err := client.DynoCreate(appname, command, &opts)
	must(err)

	if detachedRun {
		log.Printf("Ran `%s` on %s as %s, detached.", dyno.Command, appname, dyno.Name)
		return
	}
	log.Printf("Running `%s` on %s as %s:", dyno.Command, appname, dyno.Name)

	u, err := url.Parse(*dyno.AttachURL)
	if err != nil {
		printFatal(err.Error())
	}

	cn, err := tls.Dial("tcp", u.Host, nil)
	if err != nil {
		printFatal(err.Error())
	}
	defer cn.Close()

	br := bufio.NewReader(cn)

	_, err = io.WriteString(cn, u.Path[1:]+"\r\n")
	if err != nil {
		printFatal(err.Error())
	}

	for {
		_, pre, err := br.ReadLine()
		if err != nil {
			printFatal(err.Error())
		}
		if !pre {
			break
		}
	}

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			printFatal(err.Error())
		}
		defer term.Restore(os.Stdin)

		sig := make(chan os.Signal)
		signal.Notify(sig, os.Signal(syscall.SIGQUIT), os.Interrupt)
		go func() {
			defer term.Restore(os.Stdin)
			for sg := range sig {
				switch sg {
				case os.Interrupt:
					cn.Write([]byte{3})
				case os.Signal(syscall.SIGQUIT):
					cn.Write([]byte{28})
				default:
					panic("not reached")
				}
			}
		}()
	}

	errc := make(chan error)
	cp := func(a io.Writer, b io.Reader) {
		_, err := io.Copy(a, b)
		errc <- err
	}

	go cp(os.Stdout, br)
	go cp(cn, os.Stdin)
	if err = <-errc; err != nil {
		printFatal(err.Error())
	}
}
Пример #2
0
func runRun(cmd *Command, args []string, client *controller.Client) error {
	if len(args) == 0 {
		cmd.printUsage(true)
	}
	if runRelease == "" {
		release, err := client.GetAppRelease(mustApp())
		if err == controller.ErrNotFound {
			return errors.New("No app release, specify a release with -release")
		}
		if err != nil {
			return err
		}
		runRelease = release.ID
	}
	req := &ct.NewJob{
		Cmd:       args,
		TTY:       term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) && !runDetached,
		ReleaseID: runRelease,
	}
	if req.TTY {
		cols, err := term.Cols()
		if err != nil {
			return err
		}
		lines, err := term.Lines()
		if err != nil {
			return err
		}
		req.Columns = cols
		req.Lines = lines
		req.Env = map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
	}

	if runDetached {
		job, err := client.RunJobDetached(mustApp(), req)
		if err != nil {
			return err
		}
		log.Println(job.ID)
		return nil
	}

	rwc, err := client.RunJobAttached(mustApp(), req)
	if err != nil {
		return err
	}
	defer rwc.Close()

	if req.TTY {
		if err := term.MakeRaw(os.Stdin); err != nil {
			return err
		}
		defer term.Restore(os.Stdin)
	}

	go func() {
		io.Copy(rwc, os.Stdin)
		rwc.CloseWrite()
	}()
	if req.TTY {
		_, err = io.Copy(os.Stdout, rwc)
	} else {
		err = demultiplex.Copy(os.Stdout, os.Stderr, rwc)
	}
	// TODO: get exit code and use it
	return err
}
Пример #3
0
Файл: run.go Проект: Jacke/hk
func runRun(cmd *Command, args []string) {
	cols, err := term.Cols()
	if err != nil {
		log.Fatal(err)
	}
	lines, err := term.Lines()
	if err != nil {
		log.Fatal(err)
	}
	data := make(map[string]interface{})
	data["command"] = strings.Join(args, " ")
	if !detachedRun {
		data["attach"] = true
		data["env"] = map[string]interface{}{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
	}

	resp := struct {
		Url *string `json:"attach_url,omitempty"`
	}{}

	must(Post(&resp, "/apps/"+mustApp()+"/dynos", data))

	if detachedRun {
		return
	}

	u, err := url.Parse(*resp.Url)
	if err != nil {
		log.Fatal(err)
	}

	cn, err := tls.Dial("tcp", u.Host, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer cn.Close()

	br := bufio.NewReader(cn)

	_, err = io.WriteString(cn, u.Path[1:]+"\r\n")
	if err != nil {
		log.Fatal(err)
	}

	for {
		_, pre, err := br.ReadLine()
		if err != nil {
			log.Fatal(err)
		}
		if !pre {
			break
		}
	}

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			log.Fatal(err)
		}
		defer term.Restore(os.Stdin)

		sig := make(chan os.Signal)
		signal.Notify(sig, os.Signal(syscall.SIGQUIT), os.Interrupt)
		go func() {
			defer term.Restore(os.Stdin)
			for sg := range sig {
				switch sg {
				case os.Interrupt:
					cn.Write([]byte{3})
				case os.Signal(syscall.SIGQUIT):
					cn.Write([]byte{28})
				default:
					panic("not reached")
				}
			}
		}()
	}

	errc := make(chan error)
	cp := func(a io.Writer, b io.Reader) {
		_, err := io.Copy(a, b)
		errc <- err
	}

	go cp(os.Stdout, br)
	go cp(cn, os.Stdin)
	if err = <-errc; err != nil {
		log.Fatal(err)
	}
}
Пример #4
0
func runRun(cmd *Command, args []string) {
	req := &newJob{
		Cmd:    args,
		TTY:    term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) && !detachedRun,
		Attach: !detachedRun,
	}
	if req.TTY {
		cols, err := term.Cols()
		if err != nil {
			log.Fatal(err)
		}
		lines, err := term.Lines()
		if err != nil {
			log.Fatal(err)
		}
		req.Columns = cols
		req.Lines = lines
		req.Env = map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
	}
	path := "/apps/" + mustApp() + "/jobs"
	if detachedRun {
		must(Post(nil, path, req))
		return
	}

	data, err := json.Marshal(req)
	if err != nil {
		log.Fatal(err)
	}
	httpReq, err := http.NewRequest("POST", path, bytes.NewBuffer(data))
	if err != nil {
		log.Fatal(err)
	}
	c, err := net.Dial("tcp", apiURL[7:])
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()
	clientconn := httputil.NewClientConn(c, nil)
	res, err := clientconn.Do(httpReq)
	if err != nil {
		log.Fatal(err)
	}
	if res.StatusCode != 200 {
		log.Fatalf("Expected 200, got %d", res.StatusCode)
	}
	conn, bufr := clientconn.Hijack()

	if req.TTY {
		if err := term.MakeRaw(os.Stdin); err != nil {
			log.Fatal(err)
		}
		defer term.Restore(os.Stdin)
	}

	errc := make(chan error)
	go func() {
		buf := make([]byte, bufr.Buffered())
		bufr.Read(buf)
		os.Stdout.Write(buf)
		_, err := io.Copy(os.Stdout, conn)
		errc <- err
	}()
	if _, err := io.Copy(conn, os.Stdin); err != nil {
		log.Fatal(err)
	}
	if err := <-errc; err != nil {
		log.Fatal(err)
	}
}