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 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 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 err = json.Unmarshal(resp, &old) if err != nil { stdcli.Error(err) return } data := "" for key, value := range old { data += fmt.Sprintf("%s=%s\n", key, value) } stat, err := os.Stdin.Stat() if err != nil { stdcli.Error(err) return } 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 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 TestApp_RunAsSubcommandParseFlags(t *testing.T) { var context *cli.Context a := cli.NewApp() a.Commands = []cli.Command{ { Name: "foo", Action: func(c *cli.Context) { context = c }, Flags: []cli.Flag{ cli.StringFlag{ Name: "lang", Value: "english", Usage: "language for the greeting", }, }, Before: func(_ *cli.Context) error { return nil }, }, } a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) expect(t, context.Args().Get(0), "abcd") expect(t, context.String("lang"), "spanish") }
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 cmdPs(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) == 0 { processList(app) } else { processTop(app, c.Args()[0]) } }
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 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 DirApp(c *cli.Context, wd string) (string, string, error) { abs, err := filepath.Abs(wd) if err != nil { return "", "", err } app := c.String("app") if app == "" { app = path.Base(abs) } return abs, app, nil }
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 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 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 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 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 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 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 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) }
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 } 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 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 cmdSystemScale(c *cli.Context) { v := url.Values{} if c.IsSet("count") { v.Set("count", c.String("count")) } if c.IsSet("type") { v.Set("type", c.String("type")) } if len(v) > 0 { _, err := ConvoxPostForm("/system", v) if err != nil { stdcli.Error(err) return } } cmdSystem(c) }
func cmdStart(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 } m, err := manifest.Generate(dir) if err != nil { stdcli.Error(err) return } missing := m.MissingEnvironment() if len(missing) > 0 { stdcli.Error(fmt.Errorf("env expected: %s", strings.Join(missing, ", "))) return } wanted, err := m.PortsWanted() if err != nil { stdcli.Error(err) return } conflicts := make([]string, 0) host := "127.0.0.1" if h := os.Getenv("DOCKER_HOST"); h != "" { u, err := url.Parse(h) if err != nil { stdcli.Error(err) return } parts := strings.Split(u.Host, ":") host = parts[0] } for _, p := range wanted { conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", host, p)) if err == nil { conflicts = append(conflicts, p) defer conn.Close() } } if len(conflicts) > 0 { stdcli.Error(fmt.Errorf("ports in use: %s", strings.Join(conflicts, ", "))) return } errors := m.Build(app, dir) if len(errors) != 0 { fmt.Printf("errors: %+v\n", errors) return } errors = m.Run(app) if len(errors) != 0 { // TODO figure out what to do here // fmt.Printf("errors: %+v\n", errors) return } }
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 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 cmdAppCreate(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) > 0 { app = c.Args()[0] } if app == "" { fmt.Printf("Creating app: ") } else { fmt.Printf("Creating app %s: ", app) } v := url.Values{} v.Set("name", app) data, err := ConvoxPostForm("/apps", 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 } // poll for complete for { data, err = ConvoxGet(fmt.Sprintf("/apps/%s/status", app)) if err != nil { stdcli.Error(err) return } if string(data) == "running" { break } time.Sleep(3 * time.Second) } if app == "" { fmt.Printf("OK, %s\n", a.Name) } else { fmt.Println("OK") } }
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) } }