func cmdEnvGet(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) == 0 { stdcli.Error(errors.New("No variable specified")) return } if len(c.Args()) > 1 { stdcli.Error(errors.New("Only 1 variable can be retrieved at a time")) return } variable := c.Args()[0] resp, err := fetchEnv(app) if err != nil { stdcli.Error(err) return } var env map[string]string json.Unmarshal(resp, &env) fmt.Println(env[variable]) }
func cmdEnvGetAll(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } resp, err := fetchEnv(app) if err != nil { stdcli.Error(err) return } var env map[string]string err = json.Unmarshal(resp, &env) if err != nil { stdcli.Error(err) return } keys := []string{} for key, _ := range env { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { fmt.Printf("%s=%s\n", key, env[key]) } }
func processList(app string) { data, err := ConvoxGet(fmt.Sprintf("/apps/%s/processes", app)) if err != nil { stdcli.Error(err) return } var processes *Processes err = json.Unmarshal(data, &processes) if err != nil { stdcli.Error(err) return } longest := 7 for _, ps := range *processes { if len(ps.Name) > longest { longest = len(ps.Name) } } t := stdcli.NewTable("ID", "PROCESS", "RELEASE", "MEM", "COMMAND") for _, ps := range *processes { t.AddRow(ps.Id, ps.Name, ps.Release, fmt.Sprintf("%d", ps.Memory), ps.Command) } t.Print() }
func processList(app string) { data, err := ConvoxGet(fmt.Sprintf("/apps/%s/processes", app)) if err != nil { stdcli.Error(err) return } var processes *Processes err = json.Unmarshal(data, &processes) if err != nil { stdcli.Error(err) return } longest := 7 for _, ps := range *processes { if len(ps.Name) > longest { longest = len(ps.Name) } } fmt.Printf(fmt.Sprintf("%%-12s %%-%ds %%-11s %%-5s %%s\n", longest), "ID", "PROCESS", "RELEASE", "MEM", "COMMAND") for _, ps := range *processes { fmt.Printf(fmt.Sprintf("%%-12s %%-%ds %%-11s %%-5d %%s\n", longest), ps.Id, ps.Name, ps.Release, ps.Memory, ps.Command) } }
func cmdServiceInfo(c *cli.Context) { if len(c.Args()) != 1 { stdcli.Usage(c, "info") return } name := c.Args()[0] data, err := ConvoxGet("/services/" + name) if err != nil { stdcli.Error(err) return } var s *Service err = json.Unmarshal(data, &s) if err != nil { stdcli.Error(err) return } fmt.Printf("Name %s\n", s.Name) fmt.Printf("Status %s\n", s.Status) fmt.Printf("URL %s\n", fmt.Sprintf("%s://%s:%s@%s:%s/%s", s.Tags["Service"], s.Outputs["EnvPostgresUsername"], s.Outputs["EnvPostgresPassword"], s.Outputs["Port5432TcpAddr"], s.Outputs["Port5432TcpPort"], s.Outputs["EnvPostgresDatabase"])) }
func cmdServices(c *cli.Context) { data, err := ConvoxGet("/services") if err != nil { stdcli.Error(err) return } var services *Services err = json.Unmarshal(data, &services) if err != nil { stdcli.Error(err) return } longest := 7 for _, service := range *services { if len(service.Name) > longest { longest = len(service.Name) } } fmt.Printf(fmt.Sprintf("%%-%ds TYPE\n", longest), "SERVICE") for _, service := range *services { fmt.Printf(fmt.Sprintf("%%-%ds %%s\n", longest), service.Name, service.Tags["Service"]) } }
func cmdServiceInfo(c *cli.Context) { if len(c.Args()) != 1 { stdcli.Usage(c, "info") return } name := c.Args()[0] data, err := ConvoxGet("/services/" + name) if err != nil { stdcli.Error(err) return } var s *Service err = json.Unmarshal(data, &s) if err != nil { stdcli.Error(err) return } fmt.Printf("Name %s\n", s.Name) fmt.Printf("Status %s\n", s.Status) fmt.Printf("URL %s\n", s.URL) }
func cmdEnvGet(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) == 1 { variable := c.Args()[0] resp, err := fetchEnv(app) if err != nil { stdcli.Error(err) return } var env map[string]string json.Unmarshal(resp, &env) fmt.Println(env[variable]) } else { fmt.Printf("You supplied %d arguments to convox env get, 1 is required\n", len(c.Args())) } }
func cmdExec(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) < 1 { stdcli.Usage(c, "exec") return } ps := c.Args()[0] command := "" if len(c.Args()) > 1 { args := c.Args()[1:] command = strings.Join(args, " ") } err = stdcli.Run("docker", "exec", "-it", fmt.Sprintf("%s-%s", app, ps), "sh", "-c", command) if err != nil { stdcli.Error(err) return } }
func cmdRun(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) < 1 { stdcli.Usage(c, "run") return } ps := c.Args()[0] command := "" if len(c.Args()) > 1 { args := c.Args()[1:] command = strings.Join(args, " ") } v := url.Values{} v.Set("command", command) _, err = ConvoxPostForm(fmt.Sprintf("/apps/%s/processes/%s/run", app, ps), v) if err != nil { stdcli.Error(err) return } fmt.Printf("Running %s `%s`\n", ps, command) }
func cmdEnvUnset(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) == 1 { variable := c.Args()[0] path := fmt.Sprintf("/apps/%s/environment/%s", app, variable) _, err = ConvoxDelete(path) if err != nil { stdcli.Error(err) return } else { fmt.Printf("You supplied %d arguments to convox env unset, 1 is required\n", len(c.Args())) } } func fetchEnv(app string) ([]byte, error) { path := fmt.Sprintf("/apps/%s/environment", app) resp, err := ConvoxGet(path) if err != nil { return nil, err } return resp, nil }
func ConvoxPost(path string, body string) ([]byte, error) { client := convoxClient() req, err := convoxRequest("POST", path, strings.NewReader(body)) if err != nil { stdcli.Error(err) return nil, err } res, err := client.Do(req) if err != nil { stdcli.Error(err) return nil, err } defer res.Body.Close() data, err := ioutil.ReadAll(res.Body) if err != nil { stdcli.Error(err) return nil, err } if res.StatusCode/100 != 2 { return nil, errors.New(strings.TrimSpace(string(data))) } return data, nil }
func cmdEnvUnset(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) == 0 { stdcli.Error(errors.New("No variable specified")) return } if len(c.Args()) > 1 { stdcli.Error(errors.New("Only 1 variable can be unset at a time")) return } variable := c.Args()[0] path := fmt.Sprintf("/apps/%s/environment/%s", app, variable) _, err = ConvoxDelete(path) if err != nil { stdcli.Error(err) return } }
func cmdBuildsInfo(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) != 1 { stdcli.Usage(c, "info") return } build := c.Args()[0] path := fmt.Sprintf("/apps/%s/builds/%s", app, build) resp, err := ConvoxGet(path) if err != nil { stdcli.Error(err) return } var b Build err = json.Unmarshal(resp, &b) if err != nil { stdcli.Error(err) return } fmt.Println(b.Logs) }
func cmdBuilds(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } path := fmt.Sprintf("/apps/%s/builds", app) resp, err := ConvoxGet(path) if err != nil { stdcli.Error(err) return } var builds []Build err = json.Unmarshal(resp, &builds) if err != nil { stdcli.Error(err) return } fmt.Printf("%-12s %-12s %-9s %-22s %s\n", "ID", "RELEASE", "STATUS", "STARTED", "ENDED") for _, build := range builds { started := build.Started ended := build.Ended fmt.Printf("%-12s %-12s %-9s %-22s %s\n", build.Id, build.Release, build.Status, started.Format(time.RFC822Z), ended.Format(time.RFC822Z)) } }
func cmdServiceCreate(c *cli.Context) { if len(c.Args()) != 2 { stdcli.Usage(c, "create") return } name := c.Args()[0] t := c.Args()[1] fmt.Printf("Creating service %s (%s)... ", name, t) v := url.Values{} v.Set("name", name) v.Set("type", t) data, err := ConvoxPostForm("/services", v) if err != nil { stdcli.Error(err) return } data, err = ConvoxGet("/services/" + name) if err != nil { stdcli.Error(err) return } var s *Service err = json.Unmarshal(data, &s) if err != nil { stdcli.Error(err) return } // poll for complete for { data, err = ConvoxGet(fmt.Sprintf("/services/%s/status", name)) if err != nil { stdcli.Error(err) return } if string(data) == "running" { break } time.Sleep(3 * time.Second) } fmt.Printf("OK, %s\n", s.Name) }
func streamBuild(app, build string) error { host, password, err := currentLogin() if err != nil { stdcli.Error(err) return err } origin := fmt.Sprintf("https://%s", host) url := fmt.Sprintf("wss://%s/apps/%s/builds/%s/logs", host, app, build) config, err := websocket.NewConfig(url, origin) if err != nil { stdcli.Error(err) return err } userpass := fmt.Sprintf("convox:%s", password) userpass_encoded := base64.StdEncoding.EncodeToString([]byte(userpass)) config.Header.Add("Authorization", fmt.Sprintf("Basic %s", userpass_encoded)) config.TlsConfig = &tls.Config{ InsecureSkipVerify: true, } ws, err := websocket.DialConfig(config) if err != nil { stdcli.Error(err) return err } defer ws.Close() var message []byte for { err := websocket.Message.Receive(ws, &message) if err != nil { fmt.Fprintf(os.Stderr, "ws %s, retrying...\n", err.Error()) streamBuild(app, build) } fmt.Print(string(message)) } return nil }
func cmdEnvSet(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } resp, err := fetchEnv(app) if err != nil { stdcli.Error(err) return } var old map[string]string json.Unmarshal(resp, &old) data := "" for key, value := range old { data += fmt.Sprintf("%s=%s\n", key, value) } stat, _ := os.Stdin.Stat() if (stat.Mode() & os.ModeCharDevice) == 0 { in, err := ioutil.ReadAll(os.Stdin) if err != nil { stdcli.Error(err) return } data += string(in) } for _, value := range c.Args() { data += fmt.Sprintf("%s\n", value) } path := fmt.Sprintf("/apps/%s/environment", app) resp, err = ConvoxPost(path, data) if err != nil { stdcli.Error(err) return } }
func cmdReleases(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } data, err := ConvoxGet("/apps/" + app) if err != nil { stdcli.Error(err) return } var a *App err = json.Unmarshal(data, &a) data, err = ConvoxGet(fmt.Sprintf("/apps/%s/releases", a.Name)) if err != nil { stdcli.Error(err) return } var releases *Releases err = json.Unmarshal(data, &releases) if err != nil { stdcli.Error(err) return } t := stdcli.NewTable("ID", "CREATED", "ACTIVE") for _, r := range *releases { active := "" if a.Parameters["Release"] == r.Id { active = "yes" } t.AddRow(r.Id, humanize.Time(r.Created), active) } t.Print() }
func processTop(app, id string) { data, err := ConvoxGet(fmt.Sprintf("/apps/%s/processes/%s/top", app, id)) if err != nil { stdcli.Error(err) return } var top ProcessTop err = json.Unmarshal(data, &top) if err != nil { stdcli.Error(err) return } longest := make([]int, len(top.Titles)) for i, title := range top.Titles { longest[i] = len(title) } for _, process := range top.Processes { for i, data := range process { if len(data) > longest[i] { longest[i] = len(data) } } } fparts := make([]string, len(top.Titles)) for i, l := range longest { fparts[i] = fmt.Sprintf("%%-%ds", l) } fp := strings.Join(fparts, " ") + "\n" fmt.Printf(fp, interfaceStrings(top.Titles)...) for _, p := range top.Processes { fmt.Printf(fp, interfaceStrings(p)...) } }
func cmdScale(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } v := url.Values{} if c.IsSet("count") { v.Set("count", c.String("count")) } if c.IsSet("memory") { v.Set("mem", c.String("memory")) } if len(v) > 0 { _, err = ConvoxPostForm("/apps/"+app, v) if err != nil { stdcli.Error(err) return } } data, err := ConvoxGet("/apps/" + app) if err != nil { stdcli.Error(err) return } var a *App err = json.Unmarshal(data, &a) if err != nil { stdcli.Error(err) return } fmt.Printf("Count %v\n", a.Parameters["DesiredCount"]) fmt.Printf("Memory %v\n", a.Parameters["Memory"]) }
func getApps() *Apps { data, err := ConvoxGet("/apps") if err != nil { stdcli.Error(err) return nil } var apps *Apps err = json.Unmarshal(data, &apps) if err != nil { stdcli.Error(err) return nil } return apps }
func cmdEnvUnset(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } variable := c.Args()[0] path := fmt.Sprintf("/apps/%s/environment/%s", app, variable) _, err = ConvoxDelete(path) if err != nil { stdcli.Error(err) return } }
func convoxRequest(method, path string, body io.Reader) (*http.Request, error) { host, password, err := currentLogin() if err != nil { stdcli.Error(err) return nil, err } req, err := http.NewRequest(method, fmt.Sprintf("https://%s%s", host, path), body) if err != nil { stdcli.Error(err) return nil, err } req.SetBasicAuth("convox", string(password)) req.Header.Add("Content-Type", "application/json") return req, nil }
func cmdDebug(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } data, err := ConvoxGet(fmt.Sprintf("/apps/%s/events", app)) if err != nil { stdcli.Error(err) return } lines := strings.Split(string(data), "\n") for i := len(lines) - 1; i >= 0; i-- { fmt.Printf("%v\n", lines[i]) } }
func cmdBuild(c *cli.Context) { wd := "." if len(c.Args()) > 0 { wd = c.Args()[0] } dir, app, err := stdcli.DirApp(c, wd) if err != nil { stdcli.Error(err) return } _, err = executeBuild(dir, app) if err != nil { stdcli.Error(err) return } }
func cmdUpdate(c *cli.Context) { client, err := updateClient() if err != nil { stdcli.Error(err) } params := check.Params{ AppVersion: Version, AppId: "ap_TKxvw_eIPVyOzl6rKEonCU5DUY", Channel: "stable", } updater := update.New() updater.HTTPClient = client stdcli.Spinner.Prefix = "Updating: " stdcli.Spinner.Start() r, err := params.CheckForUpdate("https://api.equinox.io/1/Updates", updater) if err != nil { if err != check.NoUpdateAvailable { stdcli.Error(err) } fmt.Println("\x08\x08Already up to date") return } err, _ = r.Update() if err != nil { stdcli.Error(err) return } stdcli.Spinner.Stop() fmt.Printf("\x08\x08OK, %s\n", r.Version) }
func cmdEnvGet(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } variable := c.Args()[0] resp, err := fetchEnv(app) if err != nil { stdcli.Error(err) return } var env map[string]string json.Unmarshal(resp, &env) fmt.Println(env[variable]) }
func cmdReleasePromote(c *cli.Context) { if len(c.Args()) < 1 { stdcli.Usage(c, "release promote") return } release := c.Args()[0] _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } _, err = postRelease(app, release) if err != nil { stdcli.Error(err) return } }
func cmdSystemUpate(c *cli.Context) { version := "" if len(c.Args()) == 0 { resp, err := http.Get("http://convox.s3.amazonaws.com/release/latest/version") if err != nil { fmt.Printf("ERROR") stdcli.Error(err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { stdcli.Error(err) return } version = string(body) } else { version = c.Args()[0] } v := url.Values{} v.Set("version", version) _, err := ConvoxPostForm("/system", v) if err != nil { stdcli.Error(err) return } cmdSystem(c) }