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 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 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 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 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 runBackups(c *cli.Context) { var dbType = c.String("dbtype") w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() stack := mustStack(c) backups, err := client.ManagedBackups(stack.Uid) must(err) var dbTypeGroup = map[string][]cloud66.ManagedBackup{} if c.Bool("latest") { for _, i := range backups { if dbTypeGroup[i.DbType] == nil { // it's a new one dbTypeGroup[i.DbType] = []cloud66.ManagedBackup{i} } else { dbTypeGroup[i.DbType] = append(dbTypeGroup[i.DbType], i) } } // now sort each group topResults := []cloud66.ManagedBackup{} for _, v := range dbTypeGroup { sort.Sort(backupsByDate(v)) topResults = append(topResults, v[0]) } printBackupList(w, topResults, dbType) } else { printBackupList(w, backups, dbType) } }
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 initClients(c *cli.Context) { // is there a token file? _, err := os.Stat(filepath.Join(cxHome(), tokenFile)) if err != nil { fmt.Println("No previous authentication found.") cloud66.Authorize(cxHome(), tokenFile) os.Exit(1) } else { client = cloud66.GetClient(cxHome(), tokenFile, VERSION) debugMode = c.GlobalBool("debug") client.Debug = debugMode } }
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 runJobs(c *cli.Context) { flagServer := c.String("server") flagServiceName := c.String("service") stack := mustStack(c) w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() 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 } var ( jobs []cloud66.Job err error ) if flagServiceName == "" { jobs, err = client.GetJobs(stack.Uid, serverUid) must(err) } // else { // service, err := client.GetService(stack.Uid, flagServiceName, serverUid, nil) // must(err) // if service == nil { // printFatal("Service '" + flagServiceName + "' not found on specified stack") // } else { // services = make([]cloud66.Service, 1) // services[0] = *service // } // } printJobsList(w, jobs, flagServer) }
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 runUpdate(c *cli.Context) { debugMode = c.GlobalBool("debug") flagForcedVersion = c.String("force") if debugMode { fmt.Printf("Current version is %s\n", VERSION) if flagForcedVersion == "" { fmt.Println("No forced version") } else { fmt.Printf("Forced version is %s\n", flagForcedVersion) } } updateIt, err := needUpdate() if err != nil { if debugMode { fmt.Printf("Cannot verify need for update %v\n", err) } return } if !updateIt { if debugMode { fmt.Println("No need for update") } return } // houston we have an update. which one do we need? download, err := getVersionManifest(flagForcedVersion) if err != nil { if debugMode { fmt.Printf("Error fetching manifest %v\n", err) } } if download == nil { if debugMode { fmt.Println("Found no matching download for the current OS and ARCH") } return } err = download.update() if err != nil { if debugMode { fmt.Printf("Failed to update: %v\n", err) } 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 runDownloadManifestYaml(c *cli.Context, stackUid string) { version := c.String("version") if version == "" { version = "latest" } manifestYaml, err := client.ManifestYamlInfo(stackUid, version) must(err) output := c.String("output") if output != "" { err := writeFile(output, manifestYaml.Body) must(err) } else { fmt.Println(manifestYaml.Body) } }
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 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 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 runContainers(c *cli.Context) { stack := mustStack(c) w := tabwriter.NewWriter(os.Stdout, 1, 2, 2, ' ', 0) defer w.Flush() flagServer := c.String("server") flagServiceName := c.String("service") flagTruncate := c.Bool("trunc") 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") } fmt.Printf("Server: %s\n", server.Name) serverUid = &server.Uid } containers, err := client.GetContainers(stack.Uid, serverUid, &flagServiceName) must(err) printContainerList(w, containers, flagTruncate) }
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 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 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 runLease(c *cli.Context) { stack := mustStack(c) from := c.String("from") tto := c.Int("tto") port := c.Int("port") fmt.Printf("Attempting to lease from %s to port %d for %d minutes...\n", from, port, tto) genericRes, err := client.LeaseSync(stack.Uid, &from, &tto, &port, nil) if err != nil { printFatal(err.Error()) } printGenericResponse(*genericRes) }
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 mustFile(c *cli.Context) ConfigureFile { var file ConfigureFile switch c.String("file") { case "service.yml": file = ConfigureFile{ Name: c.String("file"), ListFunc: runServiceYamlList, DownloadFunc: runDownloadServiceYaml, UploadFunc: runUploadServiceYaml} case "manifest.yml": file = ConfigureFile{ Name: c.String("file"), ListFunc: runManifestYamlList, DownloadFunc: runDownloadManifestYaml, UploadFunc: runUploadManifestYaml} default: printFatal("No file type specified or file type is not supported. Use --file flag to choose file type. supported values are: service.yml , manifest.yml") } return file }
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 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()) } }