Esempio n. 1
0
File: http.go Progetto: yannski/cli
// Execute an API request and return its response/error
func (req *APIRequest) Do() (*http.Response, error) {
	err := req.FillDefaultValues()
	if err != nil {
		return nil, errgo.Mask(err, errgo.Any)
	}

	endpoint := req.URL + req.Endpoint

	// Execute the HTTP request according to the HTTP method
	switch req.Method {
	case "PATCH":
		fallthrough
	case "POST":
		fallthrough
	case "WITH_BODY":
		buffer, err := json.Marshal(req.Params)
		if err != nil {
			return nil, errgo.Mask(err, errgo.Any)
		}
		reader := bytes.NewReader(buffer)
		req.HTTPRequest, err = http.NewRequest(req.Method, endpoint, reader)
		if err != nil {
			return nil, errgo.Mask(err, errgo.Any)
		}
	case "GET", "DELETE":
		values, err := req.BuildQueryFromParams()
		if err != nil {
			return nil, errgo.Mask(err, errgo.Any)
		}
		endpoint = fmt.Sprintf("%s?%s", endpoint, values.Encode())
		req.HTTPRequest, err = http.NewRequest(req.Method, endpoint, nil)
		if err != nil {
			return nil, errgo.Mask(err, errgo.Any)
		}
	}

	debug.Printf("[API] %v %v\n", req.HTTPRequest.Method, req.HTTPRequest.URL)
	debug.Printf(io.Indent(fmt.Sprintf("Headers: %v", req.HTTPRequest.Header), 6))
	debug.Printf(io.Indent("Params : %v", 6), req.Params)

	req.HTTPRequest.SetBasicAuth("", req.Token)
	res, err := httpclient.Do(req.HTTPRequest)
	if err != nil {
		fmt.Printf("Fail to query %s: %v\n", req.HTTPRequest.Host, err)
		os.Exit(1)
	}

	if req.Expected.Contains(res.StatusCode) {
		return res, nil
	}

	return nil, NewRequestFailedError(res, req)
}
Esempio n. 2
0
func updateTtySize(url string) error {
	cols, err := term.Cols()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	lines, err := term.Lines()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	params := UpdateTtyParams{
		fmt.Sprintf("%d", cols),
		fmt.Sprintf("%d", lines),
	}
	paramsJson, err := json.Marshal(&params)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	req, err := http.NewRequest("PUT", url, bytes.NewReader(paramsJson))
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	req.SetBasicAuth("", config.ScalingoClient().APIToken)
	debug.Printf("Updating TTY Size: PUT %v %+v", url, params)

	res, err := httpclient.Do(req)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return errgo.Newf("Invalid error code from run server: %s", res.Status)
	}

	return nil
}
Esempio n. 3
0
func Run(opts RunOpts) error {
	c := config.ScalingoClient()

	firstReadDone := make(chan struct{})
	ctx := &runContext{
		waitingTextOutputWriter: os.Stderr,
		stdinCopyFunc:           stdio.Copy,
		stdoutCopyFunc:          io.CopyWithFirstReadChan(firstReadDone),
	}
	if opts.Type != "" {
		processes, err := c.AppsPs(opts.App)
		if err != nil {
			return errgo.Mask(err)
		}
		for _, p := range processes {
			if p.Name == opts.Type {
				opts.Cmd = strings.Split(p.Command, " ")
			}
		}
		if strings.Join(opts.Cmd, "") == "" {
			return errgo.New("no such type")
		}
	}

	if opts.CmdEnv == nil {
		opts.CmdEnv = []string{}
	}
	if opts.Files == nil {
		opts.Files = []string{}
	}
	if opts.Silent {
		ctx.waitingTextOutputWriter = new(bytes.Buffer)
	}
	if opts.StdinCopyFunc != nil {
		ctx.stdinCopyFunc = opts.StdinCopyFunc
	}
	if opts.StdoutCopyFunc != nil {
		ctx.stdoutCopyFunc = opts.StdoutCopyFunc
	}

	env, err := ctx.buildEnv(opts.CmdEnv)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	err = ctx.validateFiles(opts.Files)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	res, err := c.Run(opts.App, opts.Cmd, env)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	runStruct := make(map[string]interface{})
	scalingo.ParseJSON(res, &runStruct)
	debug.Printf("%+v\n", runStruct)

	if res.StatusCode == http.StatusNotFound {
		return errgo.Newf("application %s not found", opts.App)
	}

	var ok bool
	ctx.attachURL, ok = runStruct["attach_url"].(string)
	if !ok {
		return errgo.New("unexpected answer from server")
	}

	debug.Println("Run Service URL is", ctx.attachURL)

	if len(opts.Files) > 0 {
		err := ctx.uploadFiles(ctx.attachURL+"/files", opts.Files)
		if err != nil {
			return err
		}
	}

	fmt.Fprintf(ctx.waitingTextOutputWriter, "-----> Connecting to container [%v-%v]...  ",
		runStruct["container"].(map[string]interface{})["type"],
		runStruct["container"].(map[string]interface{})["type_index"],
	)

	attachSpinner := io.NewSpinner(ctx.waitingTextOutputWriter)
	attachSpinner.PostHook = func() {
		var displayCmd string
		if opts.DisplayCmd != "" {
			displayCmd = opts.DisplayCmd
		} else {
			displayCmd = strings.Join(opts.Cmd, " ")
		}
		fmt.Fprintf(ctx.waitingTextOutputWriter, "\n-----> Process '%v' is starting...  ", displayCmd)
	}
	go attachSpinner.Start()

	res, socket, err := ctx.connectToRunServer()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	if res.StatusCode != http.StatusOK {
		return errgo.Newf("Fail to attach: %s", res.Status)
	}

	if term.IsATTY(os.Stdin) {
		if err := term.MakeRaw(os.Stdin); err != nil {
			return errgo.Mask(err, errgo.Any)
		}
	}

	stopSignalsMonitoring := make(chan bool)
	defer close(stopSignalsMonitoring)

	go func() {
		signals.CatchQuitSignals = false
		signals := run.NotifiedSignals()
		defer close(signals)

		go run.NofityTermSizeUpdate(signals)
		for {
			select {
			case s := <-signals:
				run.HandleSignal(s, socket, ctx.attachURL)
			case <-stopSignalsMonitoring:
				signal.Stop(signals)
				return
			}
		}
	}()

	attachSpinner.Stop()
	startSpinner := io.NewSpinnerWithStopChan(ctx.waitingTextOutputWriter, firstReadDone)
	startSpinner.PostHook = func() {
		fmt.Fprintf(ctx.waitingTextOutputWriter, "\n\n")
	}
	go startSpinner.Start()

	go func() {
		_, err := ctx.stdinCopyFunc(socket, os.Stdin)
		if err != nil {
			debug.Println("error after reading stdin", err)
		} else {
			// Send EOT when stdin returns
			// 'scalingo run < file'
			socket.Write([]byte("\x04"))
		}
	}()
	_, err = ctx.stdoutCopyFunc(os.Stdout, socket)

	stopSignalsMonitoring <- true

	if term.IsATTY(os.Stdin) {
		if err := term.Restore(os.Stdin); err != nil {
			return errgo.Mask(err, errgo.Any)
		}
	}

	exitCode, err := ctx.exitCode()
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	os.Exit(exitCode)
	return nil
}
Esempio n. 4
0
File: run.go Progetto: yannski/cli
func Run(opts RunOpts) error {
	if opts.CmdEnv == nil {
		opts.CmdEnv = []string{}
	}
	if opts.Files == nil {
		opts.Files = []string{}
	}
	if opts.StdinCopyFunc == nil {
		opts.StdinCopyFunc = io.Copy
	}
	if opts.StdoutCopyFunc == nil {
		opts.StdoutCopyFunc = io.Copy
	}

	env, err := buildEnv(opts.CmdEnv)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	err = validateFiles(opts.Files)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	res, err := api.Run(opts.App, opts.Cmd, env)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	runStruct := make(map[string]interface{})
	api.ParseJSON(res, &runStruct)
	debug.Printf("%+v\n", runStruct)

	if res.StatusCode == http.StatusNotFound {
		return errgo.Newf("application %s not found", opts.App)
	}

	attachURL, ok := runStruct["attach_url"].(string)
	if !ok {
		return errgo.New("unexpected answer from server")
	}

	debug.Println("Run Service URL is", attachURL)

	if len(opts.Files) > 0 {
		err := uploadFiles(attachURL+"/files", opts.Files)
		if err != nil {
			return err
		}
	}

	res, socket, err := connectToRunServer(attachURL)
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	if res.StatusCode != http.StatusOK {
		return errgo.Newf("Fail to attach: %s", res.Status)
	}

	if err := term.MakeRaw(os.Stdin); err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	stopSignalsMonitoring := make(chan bool)
	defer close(stopSignalsMonitoring)

	go func() {
		signals.CatchQuitSignals = false
		signals := run.NotifiedSignals()
		defer close(signals)

		go run.NofityTermSizeUpdate(signals)
		for {
			select {
			case s := <-signals:
				run.HandleSignal(s, socket, attachURL)
			case <-stopSignalsMonitoring:
				signal.Stop(signals)
				return
			}
		}
	}()

	go opts.StdinCopyFunc(socket, os.Stdin)
	_, err = opts.StdinCopyFunc(os.Stdout, socket)

	stopSignalsMonitoring <- true

	if err := term.Restore(os.Stdin); err != nil {
		return errgo.Mask(err, errgo.Any)
	}

	return nil
}