func cmdServiceCreate(c *cli.Context) { // ensure type included if !(len(c.Args()) > 0) { stdcli.Usage(c, "create") return } // ensure everything after type is a flag if len(c.Args()) > 1 && !strings.HasPrefix(c.Args()[1], "--") { stdcli.Usage(c, "create") return } t := c.Args()[0] if t == "help" { stdcli.Usage(c, "create") return } options := stdcli.ParseOpts(c.Args()[1:]) for key, value := range options { if value == "" { options[key] = "true" } } var optionsList []string for key, val := range options { optionsList = append(optionsList, fmt.Sprintf("%s=%q", key, val)) } if options["name"] == "" { options["name"] = fmt.Sprintf("%s-%d", t, (rand.Intn(8999) + 1000)) } fmt.Printf("Creating %s (%s", options["name"], t) if len(optionsList) > 0 { fmt.Printf(": %s", strings.Join(optionsList, " ")) } fmt.Printf(")... ") _, err := rackClient(c).CreateService(t, options) if err != nil { stdcli.Error(err) return } fmt.Println("CREATING") }
func cmdExec(c *cli.Context) { fd := os.Stdin.Fd() stdinState, err := terminal.GetState(int(fd)) defer terminal.Restore(int(fd), stdinState) _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) < 2 { stdcli.Usage(c, "exec") return } ps := c.Args()[0] code, err := rackClient(c).ExecProcessAttached(app, ps, strings.Join(c.Args()[1:], " "), os.Stdin, os.Stdout) terminal.Restore(int(fd), stdinState) if err != nil { stdcli.Error(err) return } os.Exit(code) }
func cmdEnvList(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.Error(err) } if len(c.Args()) > 0 { return stdcli.Error(fmt.Errorf("`convox env` does not take arguments. Perhaps you meant `convox env set`?")) } if c.Bool("help") { stdcli.Usage(c, "") return nil } env, err := rackClient(c).GetEnvironment(app) if err != nil { return stdcli.Error(err) } 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]) } return nil }
func cmdRegistryAdd(c *cli.Context) { if len(c.Args()) < 1 { stdcli.Usage(c, "add") return } server := c.Args()[0] username := c.String("username") password := c.String("password") email := c.String("email") if username == "" { username = promptForUsername() } if password == "" { password = promptForPassword() } _, err := rackClient(c).AddRegistry(server, username, password, email) if err != nil { stdcli.Error(err) return } fmt.Println("Done.") }
func cmdRackScale(c *cli.Context) error { // initialize to invalid values that indicate no change count := -1 typ := "" if c.IsSet("count") { count = c.Int("count") } if c.IsSet("type") { typ = c.String("type") } // validate no argument switch len(c.Args()) { case 0: if count == -1 && typ == "" { displaySystem(c) return nil } // fall through to scale API call default: stdcli.Usage(c, "scale") return nil } _, err := rackClient(c).ScaleSystem(count, typ) if err != nil { return stdcli.ExitError(err) } displaySystem(c) return nil }
func cmdRun(c *cli.Context) error { if c.Bool("detach") { return cmdRunDetached(c) } _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.Error(err) } if len(c.Args()) < 2 { stdcli.Usage(c, "run") return nil } ps := c.Args()[0] err = validateProcessId(c, app, ps) if err != nil { return stdcli.Error(err) } args := strings.Join(c.Args()[1:], " ") release := c.String("release") code, err := runAttached(c, app, ps, args, release) if err != nil { return stdcli.Error(err) } return cli.NewExitError("", code) }
func cmdBuildsInfo(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.Error(err) } if len(c.Args()) != 1 { stdcli.Usage(c, "info") return nil } build := c.Args()[0] b, err := rackClient(c).GetBuild(app, build) if err != nil { return stdcli.Error(err) } fmt.Printf("Build %s\n", b.Id) fmt.Printf("Status %s\n", b.Status) fmt.Printf("Release %s\n", b.Release) fmt.Printf("Description %s\n", b.Description) fmt.Printf("Started %s\n", humanizeTime(b.Started)) fmt.Printf("Elapsed %s\n", stdcli.Duration(b.Started, b.Ended)) return nil }
func cmdServiceURL(c *cli.Context) error { if len(c.Args()) != 1 { stdcli.Usage(c, "url") return nil } name := c.Args()[0] service, err := rackClient(c).GetService(name) if err != nil { return stdcli.ExitError(err) } if service.Status == "failed" { return stdcli.ExitError(fmt.Errorf("Service failure for %s", service.StatusReason)) } if service.URL == "" { return stdcli.ExitError(fmt.Errorf("URL does not exist for %s", service.Name)) } fmt.Printf("%s\n", service.URL) return nil }
func cmdSSLDelete(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) != 1 { stdcli.Usage(c, "delete") return } port := c.Args()[0] fmt.Printf("Deleting SSL listener on port %s... ", port) _, err = rackClient(c).DeleteSSL(app, port) if err != nil { stdcli.Error(err) return } fmt.Println("Done.") }
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 } r, err := rackClient(c).GetRelease(app, release) 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 cmdRun(c *cli.Context) { if c.Bool("detach") { cmdRunDetached(c) return } _, 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] args := strings.Join(c.Args()[1:], " ") code, err := runAttached(c, app, ps, args) if err != nil { stdcli.Error(err) return } os.Exit(code) }
func cmdRunDetached(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, " ") } fmt.Printf("Running `%s` on %s... ", command, ps) err = rackClient(c).RunProcessDetached(app, ps, command) if err != nil { stdcli.Error(err) return } fmt.Println("OK") }
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] fmt.Printf("Stopping %s... ", id) _, err = rackClient(c).StopProcess(app, id) if err != nil { stdcli.Error(err) return } fmt.Println("OK") }
func cmdSSLList(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } if len(c.Args()) > 0 { return stdcli.ExitError(fmt.Errorf("`convox ssl` does not take arguments. Perhaps you meant `convox ssl update`?")) } if c.Bool("help") { stdcli.Usage(c, "") return nil } ssls, err := rackClient(c).ListSSL(app) if err != nil { return stdcli.ExitError(err) } t := stdcli.NewTable("TARGET", "CERTIFICATE", "DOMAIN", "EXPIRES") for _, ssl := range *ssls { t.AddRow(fmt.Sprintf("%s:%d", ssl.Process, ssl.Port), ssl.Certificate, ssl.Domain, humanizeTime(ssl.Expiration)) } t.Print() return nil }
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 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 } fmt.Printf("Promoting %s... ", release) _, err = rackClient(c).PromoteRelease(app, release) if err != nil { stdcli.Error(err) return } fmt.Println("UPDATING") }
func cmdReleasePromote(c *cli.Context) error { if len(c.Args()) < 1 { stdcli.Usage(c, "releases promote") return nil } release := c.Args()[0] _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } fmt.Printf("Promoting %s... ", release) _, err = rackClient(c).PromoteRelease(app, release) if err != nil { return stdcli.ExitError(err) } fmt.Println("UPDATING") if c.Bool("wait") { fmt.Printf("Waiting for stabilization... ") if err := waitForReleasePromotion(c, app, release); err != nil { return stdcli.ExitError(err) } fmt.Println("OK") } return nil }
func cmdSSLDelete(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) != 1 { stdcli.Usage(c, "delete") return } target := c.Args()[0] parts := strings.Split(target, ":") if len(parts) != 2 { stdcli.Error(fmt.Errorf("target must be process:port")) return } fmt.Printf("Deleting SSL listener %s... ", target) _, err = rackClient(c).DeleteSSL(app, parts[0], parts[1]) if err != nil { stdcli.Error(err) return } fmt.Println("Done.") }
func cmdInstancesList(c *cli.Context) error { if len(c.Args()) > 0 { return stdcli.ExitError(fmt.Errorf("`convox instances` does not take arguments. Perhaps you meant `convox instances ssh`?")) } if c.Bool("help") { stdcli.Usage(c, "") return nil } instances, err := rackClient(c).GetInstances() if err != nil { return stdcli.ExitError(err) } t := stdcli.NewTable("ID", "AGENT", "STATUS", "STARTED", "PS", "CPU", "MEM") for _, i := range instances { agent := "off" if i.Agent { agent = "on" } t.AddRow(i.Id, agent, i.Status, humanizeTime(i.Started), strconv.Itoa(i.Processes), fmt.Sprintf("%0.2f%%", i.Cpu*100), fmt.Sprintf("%0.2f%%", i.Memory*100)) } t.Print() return nil }
func cmdScale(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } count := c.String("count") memory := c.String("memory") if len(c.Args()) == 0 && count == "" && memory == "" { displayFormation(c, app) return } if len(c.Args()) != 1 || (count == "" && memory == "") { stdcli.Usage(c, "scale") return } process := c.Args()[0] err = rackClient(c).SetFormation(app, process, count, memory) if err != nil { stdcli.Error(err) return } displayFormation(c, app) }
func cmdServiceCreate(c *cli.Context) { if len(c.Args()) != 2 { stdcli.Usage(c, "create") return } t := c.Args()[0] name := c.Args()[1] fmt.Printf("Creating %s (%s)... ", name, t) service, err := rackClient(c).CreateService(t, name) if err != nil { stdcli.Error(err) return } for { s, err := rackClient(c).GetService(service.Name) if err != nil { stdcli.Error(err) return } if s.Status == "running" { break } time.Sleep(3 * time.Second) } fmt.Println("OK") }
func cmdPsInfo(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 } id := c.Args()[0] p, err := rackClient(c).GetProcess(app, id) if err != nil { stdcli.Error(err) return } fmt.Printf("Id %s\n", p.Id) fmt.Printf("Name %s\n", p.Name) fmt.Printf("Release %s\n", p.Release) fmt.Printf("Size %d\n", p.Size) fmt.Printf("CPU %0.2f%%\n", p.Cpu) fmt.Printf("Memory %0.2f%%\n", p.Memory*100) fmt.Printf("Started %s\n", humanizeTime(p.Started)) fmt.Printf("Command %s\n", p.Command) }
func cmdSSLUpdate(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } if len(c.Args()) < 2 { stdcli.Usage(c, "update") return nil } target := c.Args()[0] parts := strings.Split(target, ":") if len(parts) != 2 { return stdcli.ExitError(fmt.Errorf("target must be process:port")) } fmt.Printf("Updating certificate... ") _, err = rackClient(c).UpdateSSL(app, parts[0], parts[1], c.Args()[1]) if err != nil { return stdcli.ExitError(err) } fmt.Println("OK") return nil }
func cmdServiceInfo(c *cli.Context) { if len(c.Args()) != 1 { stdcli.Usage(c, "info") return } name := c.Args()[0] service, err := rackClient(c).GetService(name) if err != nil { stdcli.Error(err) return } fmt.Printf("Name %s\n", service.Name) fmt.Printf("Status %s\n", service.Status) if service.Status == "failed" { fmt.Printf("Reason %s\n", service.StatusReason) } if len(service.Exports) > 0 { fmt.Printf("Exports\n") for key, value := range service.Exports { fmt.Printf(" %s: %s\n", key, value) } } else if service.URL != "" { // NOTE: this branch is deprecated fmt.Printf("URL %s\n", service.URL) } }
func cmdApi(c *cli.Context) error { if len(c.Args()) > 0 { return cli.NewExitError("ERROR: `convox api` does not take arguments. Perhaps you meant `convox api get`?", 1) } stdcli.Usage(c, "") return nil }
func cmdServiceProxy(c *cli.Context) error { if len(c.Args()) != 1 { stdcli.Usage(c, "info") return nil } name := c.Args()[0] service, err := rackClient(c).GetService(name) if err != nil { return stdcli.ExitError(err) } export, ok := service.Exports["URL"] if !ok { return stdcli.ExitError(fmt.Errorf("%s does not expose a URL", name)) } u, err := url.Parse(export) if err != nil { return stdcli.ExitError(err) } remotehost, remoteport, err := net.SplitHostPort(u.Host) if err != nil { return stdcli.ExitError(err) } localhost := "127.0.0.1" localport := remoteport if listen := c.String("listen"); listen != "" { parts := strings.Split(listen, ":") switch len(parts) { case 1: localport = parts[0] case 2: localhost = parts[0] localport = parts[1] } } lp, err := strconv.Atoi(localport) if err != nil { return stdcli.ExitError(err) } rp, err := strconv.Atoi(remoteport) if err != nil { return stdcli.ExitError(err) } proxy(localhost, lp, remotehost, rp, rackClient(c)) return nil }
func cmdServiceUpdate(c *cli.Context) { // ensure name included if !(len(c.Args()) > 0) { stdcli.Usage(c, "update") return } name := c.Args()[0] // ensure everything after type is a flag if len(c.Args()) > 1 && !strings.HasPrefix(c.Args()[1], "--") { stdcli.Usage(c, "update") return } options := stdcli.ParseOpts(c.Args()[1:]) for key, value := range options { if value == "" { options[key] = "true" } } var optionsList []string for key, val := range options { optionsList = append(optionsList, fmt.Sprintf("%s=%q", key, val)) } if len(optionsList) == 0 { stdcli.Usage(c, "update") return } fmt.Printf("Updating %s (%s)...", name, strings.Join(optionsList, " ")) _, err := rackClient(c).UpdateService(name, options) if err != nil { stdcli.Error(err) return } fmt.Println("UPDATING") }
func cmdProxy(c *cli.Context) { if len(c.Args()) == 0 { stdcli.Usage(c, "proxy") } for _, arg := range c.Args() { parts := strings.SplitN(arg, ":", 3) var host string var port, hostport int switch len(parts) { case 2: host = parts[0] p, err := strconv.Atoi(parts[1]) if err != nil { stdcli.Error(err) return } port = p hostport = p case 3: host = parts[1] p, err := strconv.Atoi(parts[0]) if err != nil { stdcli.Error(err) return } port = p p, err = strconv.Atoi(parts[2]) if err != nil { stdcli.Error(err) return } hostport = p default: stdcli.Error(fmt.Errorf("invalid argument: %s", arg)) return } go proxy(port, host, hostport, rackClient(c)) } // block forever select {} }
func cmdBuildsCopy(c *cli.Context) { _, app, err := stdcli.DirApp(c, ".") if err != nil { stdcli.Error(err) return } if len(c.Args()) != 2 { stdcli.Usage(c, "copy") return } build := c.Args()[0] destApp := c.Args()[1] fmt.Print("Copying build... ") b, err := rackClient(c).CopyBuild(app, build, destApp) if err != nil { stdcli.Error(err) return } fmt.Println("OK") releaseId, err := finishBuild(c, destApp, b) if err != nil { stdcli.Error(err) return } if releaseId != "" { if c.Bool("promote") { fmt.Printf("Promoting %s %s... ", destApp, releaseId) _, err = rackClient(c).PromoteRelease(destApp, releaseId) if err != nil { stdcli.Error(err) return } fmt.Println("OK") } else { fmt.Printf("To deploy this copy run `convox releases promote %s --app %s`\n", releaseId, destApp) } } }
func cmdInstancesTerminate(c *cli.Context) error { if len(c.Args()) != 1 { stdcli.Usage(c, "terminate") return nil } id := c.Args()[0] err := rackClient(c).TerminateInstance(id) if err != nil { return stdcli.ExitError(err) } fmt.Printf("Successfully sent terminate to instance %q\n", id) return nil }