func runContainerStop(c *cli.Context) { if len(c.Args()) == 0 { cli.ShowSubcommandHelp(c) os.Exit(2) } stack := mustStack(c) w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() containerUid := c.Args()[0] container, err := client.GetContainer(stack.Uid, containerUid) must(err) if container == nil { printFatal("Container with Id '" + containerUid + "' not found") } asyncId, err := startContainerStop(stack.Uid, containerUid) if err != nil { printFatal(err.Error()) } genericRes, err := endServerSet(*asyncId, stack.Uid) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) return }
func runServerReboot(c *cli.Context) { stack := mustStack(c) if len(c.Args()) != 0 { cli.ShowSubcommandHelp(c) os.Exit(2) } serverName := c.String("server") servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) // confirmation is needed if the stack is production if !c.Bool("y") { mustConfirm("This operation will reboot your server during which time your server will not be available. Proceed with reboot? [yes/N]", "yes") } executeServerReboot(*stack, *server) }
func runSettings(c *cli.Context) { w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() var settings []cloud66.StackSetting var err error stack := mustStack(c) settings, err = client.StackSettings(stack.Uid) must(err) settingNames := c.Args() sort.Strings(settingNames) if len(settingNames) == 0 { printSettingList(w, settings) } else { // filter out the unwanted settings var filteredSettings []cloud66.StackSetting for _, i := range settings { sorted := sort.SearchStrings(settingNames, i.Key) if sorted < len(settingNames) && settingNames[sorted] == i.Key { filteredSettings = append(filteredSettings, i) } } printSettingList(w, filteredSettings) } }
func runServers(c *cli.Context) { stack := mustStack(c) w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() var servers []cloud66.Server var err error servers, err = client.Servers(stack.Uid) must(err) serverNames := c.Args() for idx, i := range serverNames { serverNames[idx] = strings.ToLower(i) } sort.Strings(serverNames) if len(serverNames) == 0 { printServerList(w, servers) } else { // filter out the unwanted servers var filteredServers []cloud66.Server for _, i := range servers { sorted := sort.SearchStrings(serverNames, strings.ToLower(i.Name)) if sorted < len(serverNames) && strings.ToLower(serverNames[sorted]) == strings.ToLower(i.Name) { filteredServers = append(filteredServers, i) } } printServerList(w, filteredServers) } }
func runUploadManifestYaml(c *cli.Context, stackUid string) { manifestYamlFile := c.Args().First() if manifestYamlFile == "" { printFatal("manifest_yaml file path is required") } else { manifestYamlFile = expandPath(manifestYamlFile) } manifestYamlBytes, err := ioutil.ReadFile(manifestYamlFile) must(err) manifestYaml := string(manifestYamlBytes) comments := c.String("comments") if comments == "" { fmt.Println("\nComments can't be blank, Please add one:") if term.IsTerminal(os.Stdin) { fmt.Printf("> ") } reader := bufio.NewReader(os.Stdin) if comments, err = reader.ReadString('\n'); err != nil { printFatal(err.Error()) } } _, err = client.CreateManifestYaml(stackUid, manifestYaml, comments) must(err) }
func runEasyDeploy(c *cli.Context) { appNames := c.Args() if len(appNames) != 0 { w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() var items []cloud66.EasyDeploy for _, appName := range appNames { item, err := client.EasyDeployInfo(appName) if err != nil { printFatal(err.Error()) return } items = append(items, *item) } printEasyDeployList(w, items) } else { list, err := client.EasyDeployList() if err != nil { printFatal("Error during fetching the list: " + err.Error()) return } for _, easyDeploy := range list { fmt.Println(easyDeploy) } } }
func runServerSettings(c *cli.Context) { stack := mustStack(c) // get the server serverName := c.String("server") if len(serverName) == 0 { cli.ShowSubcommandHelp(c) os.Exit(2) } servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) getServerSettings(*stack, *server, c.Args()) }
func runEnvVars(c *cli.Context) { w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() var envVars []cloud66.StackEnvVar var err error stack := mustStack(c) envVars, err = client.StackEnvVars(stack.Uid) must(err) envVarKeys := c.Args() flagShowHistory := c.Bool("history") sort.Strings(envVarKeys) if len(envVarKeys) == 0 { printEnvVarsList(w, envVars, flagShowHistory) } else { // filter out the unwanted env_vars var filteredEnvVars []cloud66.StackEnvVar for _, i := range envVars { sorted := sort.SearchStrings(envVarKeys, i.Key) if sorted < len(envVarKeys) && envVarKeys[sorted] == i.Key { filteredEnvVars = append(filteredEnvVars, i) } } printEnvVarsList(w, filteredEnvVars, flagShowHistory) } }
func beforeCommand(c *cli.Context) error { // set the env vars from global options if c.GlobalString("runenv") != "production" { tokenFile = "cx_" + c.GlobalString("runenv") + ".json" fmt.Printf(ansi.Color(fmt.Sprintf("Running against %s environment\n", c.GlobalString("runenv")), "grey")) honeybadger.Environment = c.GlobalString("runenv") } else { honeybadger.Environment = "production" } if c.GlobalString("fayeEndpoint") != "" { fayeEndpoint = c.GlobalString("fayeEndpoint") } debugMode = c.GlobalBool("debug") var command string if len(c.Args()) >= 1 { command = c.Args().First() } if (command != "version") && (command != "help") && (command != "update") { initClients(c) } if (command != "update") && (VERSION != "dev") { defer backgroundRun() } return nil }
func runContainerAttach(c *cli.Context) { if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } fmt.Println("Attaching to container...") stack := mustStack(c) w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() containerUid := c.Args()[0] container, err := client.GetContainer(stack.Uid, containerUid) must(err) if container == nil { printFatal("Container with Id '" + containerUid + "' not found") } server, err := client.GetServer(stack.Uid, container.ServerUid, 0) must(err) userCommand := fmt.Sprintf("sudo docker attach --no-stdin=true --sig-proxy=false %s", container.Uid) err = SshToServerForCommand(*server, userCommand, false) if err != nil { printFatal(err.Error()) } }
func runJobRun(c *cli.Context) { stack := mustStack(c) // get the job if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } jobName := c.Args()[0] jobs, err := client.GetJobs(stack.Uid, nil) if err != nil { printFatal(err.Error()) } var jobNames []string for _, job := range jobs { jobNames = append(jobNames, job.GetBasicJob().Name) } idx, err := fuzzyFind(jobNames, jobName, false) if err != nil { printFatal(err.Error()) } jobUid := string(jobs[idx].GetBasicJob().Uid) jobArgs := "" if len(c.StringSlice("arg")) > 0 { for i, arg := range c.StringSlice("arg") { if i > 0 { jobArgs = jobArgs + " " } jobArgs = jobArgs + "\"" + arg + "\"" } } asyncId, err := startJobRun(stack.Uid, jobUid, &jobArgs) if err != nil { printFatal(err.Error()) } genericRes, err := endJobRun(*asyncId, stack.Uid) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) return }
func runEnvVarsSet(c *cli.Context) { if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } kv := c.Args()[0] kvs := strings.Split(kv, "=") if len(kvs) != 2 { cli.ShowSubcommandHelp(c) os.Exit(2) } key := strings.ToUpper(kvs[0]) value := kvs[1] stack := mustStack(c) envVars, err := client.StackEnvVars(stack.Uid) must(err) existing := false for _, i := range envVars { if i.Key == key { if i.Readonly == true { printFatal("The selected environment variable is readonly") } else { existing = true } } } fmt.Println("Please wait while your environment variable setting is applied...") asyncId, err := startEnvVarSet(stack.Uid, key, value, existing) if err != nil { printFatal(err.Error()) } genericRes, err := endEnvVarSet(*asyncId, stack.Uid) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) return }
func runStacks(c *cli.Context) { w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() var stacks []cloud66.Stack names := c.Args() flagForcedEnvironment := c.String("environment") if len(names) == 0 { var err error stacks, err = client.StackListWithFilter(func(item interface{}) bool { if flagForcedEnvironment == "" { return true } return strings.HasPrefix(strings.ToLower(item.(cloud66.Stack).Environment), strings.ToLower(flagForcedEnvironment)) }) must(err) } else { stackch := make(chan *cloud66.Stack, len(names)) errch := make(chan error, len(names)) for _, name := range names { if name == "" { stackch <- nil } else { go func(stackname string) { if stack, err := client.StackInfoWithEnvironment(stackname, flagForcedEnvironment); err != nil { errch <- err } else { stackch <- stack } }(name) } } for _ = range names { select { case err := <-errch: printFatal(err.Error()) case stack := <-stackch: if stack != nil { stacks = append(stacks, *stack) } } } } printStackList(w, stacks) }
func runServiceStop(c *cli.Context) { if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } stack := mustStack(c) serviceName := c.Args()[0] flagServer := c.String("server") var serverUid *string if flagServer == "" { serverUid = nil } else { servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, flagServer) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + flagServer + "' not found") } if !server.HasRole("docker") { printFatal("Server '" + flagServer + "' can not host containers") } fmt.Printf("Server: %s\n", server.Name) serverUid = &server.Uid } asyncId, err := startServiceStop(stack.Uid, serviceName, serverUid) if err != nil { printFatal(err.Error()) } genericRes, err := endServiceStop(*asyncId, stack.Uid) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) return }
func runServiceInfo(c *cli.Context) { if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() stack := mustStack(c) serviceName := c.Args()[0] flagServer := c.String("server") var serverUid *string if flagServer == "" { serverUid = nil } else { servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, flagServer) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + flagServer + "' not found") } if !server.HasRole("docker") { printFatal("Server '" + flagServer + "' is not a docker server") } fmt.Printf("Server: %s\n", server.Name) serverUid = &server.Uid } service, err := client.GetService(stack.Uid, serviceName, serverUid, nil) must(err) printServiceInfoList(w, service) return }
func runUpload(c *cli.Context) { if runtime.GOOS == "windows" { printFatal("Not supported on Windows") os.Exit(2) } stack := mustStack(c) // args start after stack name // and check if user specified target directory var targetDirectory string = "" if len(c.Args()) < 1 { cli.ShowCommandHelp(c, "upload") os.Exit(2) } else if len(c.Args()) == 2 { targetDirectory = c.Args()[1] } // get the server serverName := c.String("server") // get the file path filePath := c.Args()[0] servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printError("server not found, please ensure correct server is specified in command.") os.Exit(2) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) if targetDirectory == "" { err = sshToServerToUpload(*server, filePath) } else { err = sshToServerToUpload(*server, filePath, targetDirectory) } if err != nil { printFatal(err.Error()) } }
func runSet(c *cli.Context) { if len(c.Args()) != 2 { //cmd.printUsage() os.Exit(2) } key := c.Args()[0] value := c.Args()[1] stack := mustStack(c) settings, err := client.StackSettings(stack.Uid) must(err) // check to see if it's a valid setting for _, i := range settings { if key == i.Key { // yup. it's a good one fmt.Printf("Please wait while your setting is applied...\n") asyncId, err := startSet(stack.Uid, key, value) if err != nil { printFatal(err.Error()) } genericRes, err := endSet(*asyncId, stack.Uid) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) return } } printFatal(key + " is not a valid setting or does not apply to this stack") }
func runSlaveResync(c *cli.Context) { stack := mustStack(c) if len(c.Args()) < 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } // get the server serverName := c.Args()[0] flagDbType := c.String("dbtype") servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) currenttime := time.Now().Local() fmt.Printf("Started: %s\n", currenttime.Format("2006-01-02 15:04:05")) asyncId, err := startSlaveResync(stack.Uid, server.Uid, &flagDbType) if err != nil { printFatal(err.Error()) } genericRes, err := endSlaveResync(*asyncId, stack.Uid) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) }
func runContainerExec(c *cli.Context) { if len(c.Args()) != 2 { cli.ShowSubcommandHelp(c) os.Exit(2) } fmt.Println("Running exec on container...") stack := mustStack(c) w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() containerUid := c.Args()[0] command := c.Args()[1] container, err := client.GetContainer(stack.Uid, containerUid) must(err) if container == nil { printFatal("Container with Id '" + containerUid + "' not found") } server, err := client.GetServer(stack.Uid, container.ServerUid, 0) must(err) dockerFlags := c.String("docker-flags") userCommand := fmt.Sprintf("sudo docker exec %s %s %s", dockerFlags, container.Uid, command) err = SshToServerForCommand(*server, userCommand, true) if err != nil { printFatal(err.Error()) } }
func runSsh(c *cli.Context) { if runtime.GOOS == "windows" { printFatal("Not supported on Windows") os.Exit(2) } stack := mustStack(c) if len(c.Args()) != 1 { cli.ShowCommandHelp(c, "ssh") os.Exit(2) } // get the server serverName := c.Args()[0] servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) err = sshToServer(*server) if err != nil { printError("If you're having issues connecting to your server, you may find some help at http://help.cloud66.com/managing-your-stack/ssh-to-your-server") printFatal(err.Error()) } }
func runRun(c *cli.Context) { if runtime.GOOS == "windows" { printFatal("Not supported on Windows") os.Exit(2) } stack := mustStack(c) if c.String("service") != "" && stack.Framework != "docker" { printFatal("The service option only applies to docker stacks") os.Exit(2) } serverName := c.String("server") if !c.IsSet("service") { if len(c.Args()) != 1 { cli.ShowCommandHelp(c, "run") os.Exit(2) } } userCommand := "" if len(c.Args()) == 1 { userCommand = c.Args()[0] } servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } if c.String("service") != "" { // fetch service information for existing server/command service, err := client.GetService(stack.Uid, c.String("service"), &server.Uid, &userCommand) must(err) userCommand = service.WrapCommand } includeTty := c.String("service") != "" err = SshToServerForCommand(*server, userCommand, includeTty) if err != nil { printFatal(err.Error()) } }
func runOpen(c *cli.Context) { stack := mustStack(c) if len(c.Args()) > 1 { //cmd.printUsage() os.Exit(2) } var toOpen string // are we connecting to a server? if len(c.Args()) == 1 { // get the server serverName := c.Args()[0] servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) toOpen = "http://" + server.DnsRecord } else { // is the stack load balanced? if stack.HasLoadBalancer { toOpen = "http://" + stack.Fqdn } else { // use the first web server servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } fmt.Printf("Server: %s\n", servers[0].Name) toOpen = "http://" + servers[0].DnsRecord } } // open server's fqdn fmt.Printf("Opening %s\n", toOpen) err := openURL(toOpen) if err != nil { printFatal(err.Error()) } }
func runServerSet(c *cli.Context) { fmt.Println(c.Args()) stack := mustStack(c) if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) os.Exit(2) } // get the server args := c.Args() serverName := c.String("server") // filter out the server name kvs := args[0] kva := strings.Split(kvs, "=") if len(kva) != 2 { cli.ShowSubcommandHelp(c) os.Exit(2) } key := kva[0] value := kva[1] servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) executeServerSet(*stack, *server, c, key, value) }
func runTail(c *cli.Context) { if runtime.GOOS == "windows" { printFatal("Not supported on Windows") os.Exit(2) } stack := mustStack(c) if len(c.Args()) != 2 { //cmd.printUsage() os.Exit(2) } // get the server serverName := c.Args()[0] logName := c.Args()[1] servers, err := client.Servers(stack.Uid) if err != nil { printFatal(err.Error()) } server, err := findServer(servers, serverName) if err != nil { printFatal(err.Error()) } if server == nil { printFatal("Server '" + serverName + "' not found") } fmt.Printf("Server: %s\n", server.Name) err = tailLog(*stack, *server, logName) if err != nil { printFatal(err.Error()) } }
func runServiceScale(c *cli.Context) { if len(c.Args()) != 2 { cli.ShowSubcommandHelp(c) os.Exit(2) } stack := mustStack(c) serviceName := c.Args()[0] count := c.Args()[1] flagServer := c.String("server") flagGroup := c.String("group") // fetch servers info servers, err := client.Servers(stack.Uid) must(err) if flagServer != "" { server, err := findServer(servers, flagServer) must(err) if server == nil { printFatal("Server '" + flagServer + "' not found") } if !server.HasRole("docker") { printFatal("Server '" + flagServer + "' can not host containers") } fmt.Printf("Server: %s\n", server.Name) // filter servers collection down servers = make([]cloud66.Server, 1) servers[0] = *server } if flagGroup != "" { if flagGroup != "web" { printFatal("Only web group is supported at the moment") } } // param for api call serverCountDesired := make(map[string]int) var absoluteCount int if strings.ContainsAny(count, "+ & -") { // fetch service information for existing counts service, err := client.GetService(stack.Uid, serviceName, nil, nil) must(err) serverCountCurrent := service.ServerContainerCountMap() relativeCount, _ := strconv.Atoi(count) for _, server := range servers { if _, present := serverCountCurrent[server.Name]; present { serverCountDesired[server.Uid] = relativeCount + serverCountCurrent[server.Name] } else { serverCountDesired[server.Uid] = relativeCount } } } else { absoluteCount, _ = strconv.Atoi(count) for _, server := range servers { serverCountDesired[server.Uid] = absoluteCount } } // validate non < 0 for serverUid, count := range serverCountDesired { if count < 0 { serverCountDesired[serverUid] = 0 } } fmt.Println("Scaling your '" + serviceName + "' service") var asyncId *int if flagGroup != "" { var groupMap = make(map[string]int) groupMap["web"] = absoluteCount asyncId, err = startServiceScaleByGroup(stack.Uid, serviceName, groupMap) } else { asyncId, err = startServiceScale(stack.Uid, serviceName, serverCountDesired) } must(err) genericRes, err := endServiceScale(*asyncId, stack.Uid) must(err) printGenericResponse(*genericRes) return }
func runDownloadBackup(c *cli.Context) { if len(c.Args()) == 0 { //cmd.printUsage() os.Exit(2) } stack := mustStack(c) backupId, err := strconv.Atoi(c.Args()[0]) if err != nil { //cmd.printUsage() os.Exit(2) } segmentIndeces, err := client.GetBackupSegmentIndeces(stack.Uid, backupId) must(err) if len(segmentIndeces) < 1 { printFatal("Cannot find file segments associated with this backup") } flagDownloadDir := c.String("directory") mainDir := filepath.Join(homePath(), "cx_backups") if flagDownloadDir != "" { mainDir = flagDownloadDir } // create a download tmp folder dir := filepath.Join(mainDir, "tmp", c.Args()[0]) err = os.MkdirAll(dir, 0777) must(err) var files = []string{} for _, segmentIndex := range segmentIndeces { segment, err := client.GetBackupSegment(stack.Uid, backupId, segmentIndex.Extension) must(err) fmt.Printf("Downloading %s to %s\n", segmentIndex.Filename, dir) // this should be moved to go routines toFile := filepath.Join(dir, segmentIndex.Filename) err = downloadFile(segment.Url, toFile) must(err) files = append(files, toFile) } toFile := filepath.Join(mainDir, "backup_"+c.Args()[0]+".tar") fmt.Printf("Concatenating files to %s\n", toFile) err = appendFiles(files, toFile) if err != nil { printFatal("Error during concatenation: " + err.Error()) return } // remove the temp if !debugMode { os.RemoveAll(dir) fmt.Printf("Deleting %s\n", dir) } fmt.Println("Done") }