func cmdRackUpdate(c *cli.Context) error { versions, err := version.All() if err != nil { return stdcli.ExitError(err) } specified := "stable" if len(c.Args()) > 0 { specified = c.Args()[0] } version, err := versions.Resolve(specified) if err != nil { return stdcli.ExitError(err) } system, err := rackClient(c).UpdateSystem(version.Version) if err != nil { return stdcli.ExitError(err) } fmt.Printf("Name %s\n", system.Name) fmt.Printf("Status %s\n", system.Status) fmt.Printf("Version %s\n", system.Version) fmt.Printf("Count %d\n", system.Count) fmt.Printf("Type %s\n", system.Type) fmt.Println() fmt.Printf("Updating to version: %s\n", version.Version) return nil }
func cmdAppParams(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } params, err := rackClient(c).ListParameters(app) if err != nil { return stdcli.ExitError(err) } keys := []string{} for key, _ := range params { keys = append(keys, key) } sort.Strings(keys) t := stdcli.NewTable("NAME", "VALUE") for _, key := range keys { t.AddRow(key, params[key]) } t.Print() 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.ExitError(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.ExitError(err) } args := strings.Join(c.Args()[1:], " ") release := c.String("release") code, err := runAttached(c, app, ps, args, release) if err != nil { return stdcli.ExitError(err) } return cli.NewExitError("", code) }
func cmdAppParamsSet(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } params := map[string]string{} for _, arg := range c.Args() { parts := strings.SplitN(arg, "=", 2) if len(parts) != 2 { return stdcli.ExitError(fmt.Errorf("invalid argument: %s", arg)) } params[parts[0]] = parts[1] } fmt.Print("Updating parameters... ") err = rackClient(c).SetParameters(app, params) if err != nil { return stdcli.ExitError(err) } fmt.Println("OK") return nil }
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 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 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 cmdAppCreate(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } if len(c.Args()) > 0 { app = c.Args()[0] } if app == "" { return stdcli.ExitError(fmt.Errorf("must specify an app name")) } fmt.Printf("Creating app %s... ", app) _, err = rackClient(c).CreateApp(app) if err != nil { return stdcli.ExitError(err) } fmt.Println("CREATING") if c.Bool("wait") { fmt.Printf("Waiting for %s... ", app) if err := waitForAppRunning(c, app); err != nil { stdcli.ExitError(err) } fmt.Println("OK") } return nil }
func cmdLogin(c *cli.Context) error { var host string if len(c.Args()) < 1 { host = "console.convox.com" } else { host = c.Args()[0] } u, err := url.Parse(host) if err != nil { return stdcli.ExitError(err) } if u.Host != "" { host = u.Host } password := os.Getenv("CONVOX_PASSWORD") if password == "" { password = c.String("password") } if password != "" { // password flag err = testLogin(host, password, c.App.Version) } else { // first try current login password, err = getLogin(host) err = testLogin(host, password, c.App.Version) // then prompt for password if err != nil { password = promptForPassword() err = testLogin(host, password, c.App.Version) } } if err != nil { if strings.Contains(err.Error(), "401") { return stdcli.ExitError(fmt.Errorf("invalid login")) } else { return stdcli.ExitError(err) } } err = addLogin(host, password) if err != nil { return stdcli.ExitError(err) } err = switchHost(host) if err != nil { return stdcli.ExitError(err) } fmt.Println("Logged in successfully.") return nil }
func cmdEnvList(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 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.ExitError(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 cmdReleaseInfo(c *cli.Context) error { if len(c.Args()) < 1 { stdcli.Usage(c, "release info") return nil } release := c.Args()[0] _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } r, err := rackClient(c).GetRelease(app, release) if err != nil { return stdcli.ExitError(err) } 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)) return nil }
func cmdRackPs(c *cli.Context) error { system, err := rackClient(c).GetSystem() if err != nil { return stdcli.ExitError(err) } ps, err := rackClient(c).GetProcesses(system.Name, c.Bool("stats")) if err != nil { return stdcli.ExitError(err) } if c.Bool("stats") { fm, err := rackClient(c).ListFormation(system.Name) if err != nil { return stdcli.ExitError(err) } displayProcessesStats(ps, fm) return nil } displayProcesses(ps) return nil }
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 cmdRackParams(c *cli.Context) error { system, err := rackClient(c).GetSystem() if err != nil { return stdcli.ExitError(err) } params, err := rackClient(c).ListParameters(system.Name) if err != nil { return stdcli.ExitError(err) } keys := []string{} for key, _ := range params { keys = append(keys, key) } sort.Strings(keys) t := stdcli.NewTable("NAME", "VALUE") for _, key := range keys { t.AddRow(key, params[key]) } t.Print() return nil }
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 cmdPsInfo(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } if len(c.Args()) != 1 { stdcli.Usage(c, "info") return nil } id := c.Args()[0] p, err := rackClient(c).GetProcess(app, id) if err != nil { return stdcli.ExitError(err) } fmt.Printf("Id %s\n", p.Id) fmt.Printf("Name %s\n", p.Name) fmt.Printf("Release %s\n", p.Release) 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) return nil }
func cmdPs(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } ps, err := rackClient(c).GetProcesses(app, c.Bool("stats")) if err != nil { return stdcli.ExitError(err) } if c.Bool("stats") { fm, err := rackClient(c).ListFormation(app) if err != nil { return stdcli.ExitError(err) } displayProcessesStats(ps, fm) return nil } displayProcesses(ps) return nil }
func cmdUpdate(c *cli.Context) error { client, err := updateClient() if err != nil { return stdcli.ExitError(err) } stdcli.Spinner.Prefix = "Updating convox/proxy: " stdcli.Spinner.Start() if err := updateProxy(); err != nil { fmt.Printf("\x08\x08FAILED\n") } else { fmt.Printf("\x08\x08OK\n") } stdcli.Spinner.Stop() stdcli.Spinner.Prefix = "Updating convox: " stdcli.Spinner.Start() opts := equinox.Options{ CurrentVersion: Version, Channel: "stable", HTTPClient: client, } if err := opts.SetPublicKeyPEM(publicKey); err != nil { return stdcli.ExitError(err) } // check for update r, err := equinox.Check("app_i8m2L26DxKL", opts) switch { case err == equinox.NotAvailableErr: fmt.Println("\x08\x08Already up to date") return nil case err != nil: return stdcli.ExitError(err) } // apply update err = r.Apply() if err != nil { return stdcli.ExitError(err) } fmt.Printf("\x08\x08OK, %s\n", r.ReleaseVersion) stdcli.Spinner.Stop() return nil }
func cmdProxy(c *cli.Context) error { if len(c.Args()) == 0 { stdcli.Usage(c, "proxy") return nil } 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 { return stdcli.ExitError(err) } port = p hostport = p case 3: host = parts[1] p, err := strconv.Atoi(parts[0]) if err != nil { return stdcli.ExitError(err) } port = p p, err = strconv.Atoi(parts[2]) if err != nil { return stdcli.ExitError(err) } hostport = p default: return stdcli.ExitError(fmt.Errorf("invalid argument: %s", arg)) } go proxy("127.0.0.1", port, host, hostport, rackClient(c)) } // block forever select {} }
func cmdServiceInfo(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) } 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) } return nil }
func cmdInit(c *cli.Context) error { ep := stdcli.QOSEventProperties{Start: time.Now()} distinctId, err := currentId() if err != nil { stdcli.QOSEventSend("cli-init", distinctId, stdcli.QOSEventProperties{Error: err}) } wd := "." if len(c.Args()) > 0 { wd = c.Args()[0] } dir, _, err := stdcli.DirApp(c, wd) if err != nil { return stdcli.QOSEventSend("cli-init", distinctId, stdcli.QOSEventProperties{Error: err}) } // TODO parse the Dockerfile and build a docker-compose.yml if exists("docker-compose.yml") { return stdcli.ExitError(fmt.Errorf("Cannot initialize a project that already contains a docker-compose.yml")) } err = initApplication(dir) if err != nil { return stdcli.QOSEventSend("cli-init", distinctId, stdcli.QOSEventProperties{Error: err}) } return stdcli.QOSEventSend("cli-init", distinctId, ep) }
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 cmdRegistryAdd(c *cli.Context) error { if len(c.Args()) < 1 { stdcli.Usage(c, "add") return nil } 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 { return stdcli.ExitError(err) } fmt.Println("Done.") return nil }
func cmdLogsStream(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 logs` does not take arguments. Perhaps you meant `convox logs`?")) } err = rackClient(c).StreamAppLogs(app, c.String("filter"), c.BoolT("follow"), c.Duration("since"), os.Stdout) if err != nil { return stdcli.ExitError(err) } return nil }
func cmdRackLogs(c *cli.Context) error { err := rackClient(c).StreamRackLogs(c.String("filter"), c.BoolT("follow"), c.Duration("since"), os.Stdout) if err != nil { return stdcli.ExitError(err) } return nil }
func cmdRackReleases(c *cli.Context) error { system, err := rackClient(c).GetSystem() if err != nil { return stdcli.ExitError(err) } pendingVersion := system.Version releases, err := rackClient(c).GetSystemReleases() if err != nil { return stdcli.ExitError(err) } t := stdcli.NewTable("VERSION", "UPDATED", "STATUS") for i, r := range releases { status := "" if system.Status == "updating" && i == 0 { pendingVersion = r.Id status = "updating" } if system.Version == r.Id { status = "active" } t.AddRow(r.Id, humanizeTime(r.Created), status) } t.Print() next, err := version.Next(system.Version) if err != nil { return stdcli.ExitError(err) } if next > pendingVersion { // if strings.Compare(next, pendingVersion) == 1 { fmt.Println() fmt.Printf("New version available: %s\n", next) } return nil }
func cmdBuildsCopy(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } if len(c.Args()) != 2 { stdcli.Usage(c, "copy") return nil } build := c.Args()[0] destApp := c.Args()[1] fmt.Print("Copying build... ") b, err := rackClient(c).CopyBuild(app, build, destApp) if err != nil { return stdcli.ExitError(err) } fmt.Println("OK") releaseID, err := finishBuild(c, destApp, b) if err != nil { return stdcli.ExitError(err) } if releaseID != "" { if c.Bool("promote") { fmt.Printf("Promoting %s %s... ", destApp, releaseID) _, err = rackClient(c).PromoteRelease(destApp, releaseID) if err != nil { return stdcli.ExitError(err) } fmt.Println("OK") } else { fmt.Printf("To deploy this copy run `convox releases promote %s --app %s`\n", releaseID, destApp) } } return nil }
func cmdInstancesKeyroll(c *cli.Context) error { err := rackClient(c).InstanceKeyroll() if err != nil { return stdcli.ExitError(err) } fmt.Println("Rebooting instances") return nil }
func cmdDeploy(c *cli.Context) error { wd := "." if len(c.Args()) > 0 { wd = c.Args()[0] } dir, app, err := stdcli.DirApp(c, wd) if err != nil { return stdcli.ExitError(err) } fmt.Printf("Deploying %s\n", app) a, err := rackClient(c).GetApp(app) if err != nil { return stdcli.ExitError(err) } switch a.Status { case "creating": return stdcli.ExitError(fmt.Errorf("app is still creating: %s", app)) case "running", "updating": default: return stdcli.ExitError(fmt.Errorf("unable to build app: %s", app)) } // build release, err := executeBuild(c, dir, app, c.String("file"), c.String("description")) if err != nil { return stdcli.ExitError(err) } if release == "" { return nil } 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 %s... ", release) if err := waitForReleasePromotion(c, app, release); err != nil { return stdcli.ExitError(err) } fmt.Println("OK") } return nil }
func cmdEnvUnset(c *cli.Context) error { _, app, err := stdcli.DirApp(c, ".") if err != nil { return stdcli.ExitError(err) } if len(c.Args()) == 0 { return stdcli.ExitError(errors.New("No variable specified")) } if len(c.Args()) > 1 { return stdcli.ExitError(errors.New("Only 1 variable can be unset at a time")) } key := c.Args()[0] fmt.Print("Updating environment... ") _, releaseID, err := rackClient(c).DeleteEnvironment(app, key) if err != nil { return stdcli.ExitError(err) } fmt.Println("OK") if releaseID != "" { if c.Bool("promote") { fmt.Printf("Promoting %s... ", releaseID) _, err = rackClient(c).PromoteRelease(app, releaseID) if err != nil { return stdcli.ExitError(err) } fmt.Println("OK") } else { fmt.Printf("To deploy these changes run `convox releases promote %s`\n", releaseID) } } return nil }