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 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 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 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 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 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 cmdSwitch(c *cli.Context) { if len(c.Args()) < 1 { stdcli.Usage(c, "switch") return } host := c.Args()[0] err := switchHost(host) if err != nil { stdcli.Error(err) return } fmt.Printf("Switched to %s\n", host) }
func cmdAppDelete(c *cli.Context) { if len(c.Args()) < 1 { stdcli.Usage(c, "delete") return } app := c.Args()[0] fmt.Printf("Deleting %s: ", app) _, err := ConvoxDelete(fmt.Sprintf("/apps/%s", app)) if err != nil { stdcli.Error(err) return } fmt.Println("OK") }
func cmdServiceDelete(c *cli.Context) { if len(c.Args()) != 1 { stdcli.Usage(c, "delete") return } name := c.Args()[0] fmt.Printf("Deleting %s... ", name) _, err := ConvoxDelete(fmt.Sprintf("/services/%s", name)) if err != nil { stdcli.Error(err) return } fmt.Println("OK") }
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 cmdReleaseInfo(c *cli.Context) { if len(c.Args()) < 1 { stdcli.Usage(c, "release info") return } release := c.Args()[0] _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } data, err := ConvoxGet(fmt.Sprintf("/apps/%s/releases/%s", app, release)) if err != nil { stdcli.Error(err) return } var r Release err = json.Unmarshal(data, &r) if err != nil { stdcli.Error(err) return } fmt.Printf("Id %s\n", r.Id) fmt.Printf("Build %s\n", r.Build) fmt.Printf("Created %s\n", r.Created) fmt.Printf("Env ") fmt.Println(strings.Replace(r.Env, "\n", "\n ", -1)) }
func cmdPsStop(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) != 1 { stdcli.Usage(c, "stop") return } id := c.Args()[0] _, err = ConvoxDelete(fmt.Sprintf("/apps/%s/processes/%s", app, id)) if err != nil { stdcli.Error(err) return } fmt.Printf("Stopping %s\n", id) }
func cmdScale(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) < 1 { stdcli.Usage(c, "scale") 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 { v.Set("process", c.Args()[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 } processes := make(map[string]Process, 0) longest := 7 for k, v := range a.Parameters { if !strings.HasSuffix(k, "DesiredCount") { continue } ps := strings.Replace(k, "DesiredCount", "", 1) p := strings.ToLower(ps) i, err := strconv.ParseInt(v, 10, 64) if err != nil { stdcli.Error(err) return } m, err := strconv.ParseInt(a.Parameters[ps+"Memory"], 10, 64) if err != nil { stdcli.Error(err) return } processes[p] = Process{Name: p, Count: i, Memory: m} } fmt.Printf(fmt.Sprintf("%%-%ds %%-5s %%-5s\n", longest), "PROCESS", "COUNT", "MEM") for _, ps := range processes { fmt.Printf(fmt.Sprintf("%%-%ds %%-5d %%-5d\n", longest), ps.Name, ps.Count, ps.Memory) } }
func cmdAppInfo(c *cli.Context) { if len(c.Args()) < 1 { stdcli.Usage(c, "info") return } app := c.Args()[0] 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 } matcher := regexp.MustCompile(`^(\w+)Port\d+Balancer`) ports := []string{} for key, value := range a.Outputs { if m := matcher.FindStringSubmatch(key); m != nil { ports = append(ports, fmt.Sprintf("%s:%s", strings.ToLower(m[1]), value)) } } processes := []string{} for key, _ := range a.Parameters { if strings.HasSuffix(key, "Image") { processes = append(processes, strings.ToLower(key[0:len(key)-5])) } } sort.Strings(processes) if len(processes) == 0 { processes = append(processes, "(none)") } if len(ports) == 0 { ports = append(ports, "(none)") } release := a.Parameters["Release"] if release == "" { release = "(none)" } fmt.Printf("Name %s\n", a.Name) fmt.Printf("Status %s\n", a.Status) fmt.Printf("Release %s\n", release) fmt.Printf("Processes %s\n", strings.Join(processes, " ")) if a.Outputs["BalancerHost"] != "" { fmt.Printf("Hostname %s\n", a.Outputs["BalancerHost"]) fmt.Printf("Ports %s\n", strings.Join(ports, " ")) } }
func cmdLogin(c *cli.Context) { if len(c.Args()) != 1 { stdcli.Usage(c, "login") } host := c.Args()[0] u, err := url.Parse(host) if err != nil { stdcli.Error(err) return } if u.Host != "" { host = u.Host } password := c.String("password") if password == "" { fmt.Print("Password: "******"GET", fmt.Sprintf("https://%s/apps", host), nil) if err != nil { stdcli.Error(err) return } req.SetBasicAuth("convox", string(password)) res, err := client.Do(req) if err != nil { stdcli.Error(err) return } defer res.Body.Close() if res.StatusCode != 200 { stdcli.Error(fmt.Errorf("invalid login")) return } err = addLogin(host, password) if err != nil { stdcli.Error(err) return } err = switchHost(host) if err != nil { stdcli.Error(err) return } fmt.Println("Logged in successfully.") }
func cmdRunAttached(c *cli.Context) { fd := os.Stdin.Fd() oldState, err := term.SetRawTerminal(fd) if err != nil { stdcli.Error(err) return } defer term.RestoreTerminal(fd, oldState) _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) < 2 { stdcli.Usage(c, "run") return } ps := c.Args()[0] host, password, err := currentLogin() if err != nil { stdcli.Error(err) return } origin := fmt.Sprintf("https://%s", host) url := fmt.Sprintf("wss://%s/apps/%s/processes/%s/run", host, app, ps) config, err := websocket.NewConfig(url, origin) if err != nil { stdcli.Error(err) return } command := strings.Join(c.Args()[1:], " ") config.Header.Set("Command", command) userpass := fmt.Sprintf("convox:%s", password) userpass_encoded := b64.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 } defer ws.Close() ch := make(chan int) go io.Copy(ws, os.Stdin) go messageReceive(ws, os.Stdout, ch) code := <-ch term.RestoreTerminal(os.Stdin.Fd(), oldState) os.Exit(code) }