// 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) }
func List() error { apps, err := scalingo.AppsList() if err != nil { return errgo.Mask(err, errgo.Any) } if len(apps) == 0 { fmt.Println(io.Indent("\nYou haven't created any app yet, create your first application using:\n→ scalingo create <app_name>\n", 2)) return nil } t := tablewriter.NewWriter(os.Stdout) t.SetHeader([]string{"Name", "Role", "Owner"}) for _, app := range apps { if app.Owner.Email == scalingo.CurrentUser.Email { t.Append([]string{app.Name, "owner", "-"}) } else { t.Append([]string{app.Name, "collaborator", fmt.Sprintf("%s <%s>", app.Owner.Username, app.Owner.Email)}) } } t.Render() return nil }
func Scale(app string, sync bool, types []string) error { var size string scaleParams := &scalingo.AppsScaleParams{} for _, t := range types { splitT := strings.Split(t, ":") if len(splitT) != 2 && len(splitT) != 3 { return errgo.Newf("%s is invalid, format is <type>:<amount>[:<size>]", t) } typeName, typeAmount := splitT[0], splitT[1] if len(splitT) == 3 { size = splitT[2] } amount, err := strconv.ParseInt(typeAmount, 10, 32) if err != nil { return errgo.Newf("%s in %s should be an integer", typeAmount, t) } scaleParams.Containers = append(scaleParams.Containers, scalingo.Container{Name: typeName, Amount: int(amount), Size: size}) } res, err := scalingo.AppsScale(app, scaleParams) if err != nil { return errgo.Mask(err) } defer res.Body.Close() if res.StatusCode == 422 { var scaleUnprocessableEntity ScaleUnprocessableEntity err = scalingo.ParseJSON(res, &scaleUnprocessableEntity) if err != nil { return errgo.Mask(err) } return scaleUnprocessableEntity } var scaleRes ScaleRes err = scalingo.ParseJSON(res, &scaleRes) if err != nil { return errgo.Mask(err) } fmt.Printf("Your application is being scaled to:\n") for _, ct := range scaleRes.Containers { fmt.Println(io.Indent(fmt.Sprintf("%s: %d - %s", ct.Name, ct.Amount, ct.Size), 2)) } if !sync { return nil } err = handleOperation(app, res) if err != nil { return errgo.Mask(err) } fmt.Println("Your application has been scaled.") return nil }
func errorQuit(err error) { if errgo.Cause(err) == api.LoginAbortedErr { fmt.Printf("... %v\n", err) os.Exit(1) } if api.IsRequestFailedError(errgo.Cause(err)) { code := errgo.Cause(err).(*api.RequestFailedError).Code if code == 401 { session.DestroyToken() } } newReportError(err).Report() rollbar.Wait() io.Error("An error occured:") fmt.Println(io.Indent(err.Error(), 7)) os.Exit(1) }
func Scale(app string, sync bool, types []string) error { var ( size string containers []scalingo.Container modificator byte err error ) scaleParams := &scalingo.AppsScaleParams{} for _, t := range types { splitT := strings.Split(t, ":") if len(splitT) != 2 && len(splitT) != 3 { return errgo.Newf("%s is invalid, format is <type>:<amount>[:<size>]", t) } typeName, typeAmount := splitT[0], splitT[1] if len(splitT) == 3 { size = splitT[2] } if typeAmount[0] == '-' || typeAmount[0] == '+' { modificator = typeAmount[0] typeAmount = typeAmount[1:] if size != "" { return errgo.Newf("%s is invalid, can't use relative modificator with size, change the size first", t) } if containers == nil { c := config.ScalingoClient() containers, err = c.AppsPs(app) if err != nil { return errgo.Notef(err, "fail to get list of running containers") } debug.Println("get container list", containers) } } amount, err := strconv.ParseInt(typeAmount, 10, 32) if err != nil { return errgo.Newf("%s in %s should be an integer", typeAmount, t) } newContainerConfig := scalingo.Container{Name: typeName, Size: size} if modificator != 0 { for _, container := range containers { if container.Name == typeName { if modificator == '-' { newContainerConfig.Amount = container.Amount - int(amount) } else if modificator == '+' { newContainerConfig.Amount = container.Amount + int(amount) } break } } } else { newContainerConfig.Amount = int(amount) } scaleParams.Containers = append(scaleParams.Containers, newContainerConfig) } c := config.ScalingoClient() res, err := c.AppsScale(app, scaleParams) if err != nil { return errgo.Mask(err) } defer res.Body.Close() var scaleRes ScaleRes err = scalingo.ParseJSON(res, &scaleRes) if err != nil { return errgo.Mask(err) } fmt.Printf("Your application is being scaled to:\n") for _, ct := range scaleRes.Containers { fmt.Println(io.Indent(fmt.Sprintf("%s: %d - %s", ct.Name, ct.Amount, ct.Size), 2)) } if !sync { return nil } err = handleOperation(app, res) if err != nil { return errgo.Mask(err) } fmt.Println("Your application has been scaled.") return nil }