func networkShow(networkID string) { // Split namespace and repository host, app, net, tag, err := internal.ParseResourceName(networkID) internal.Check(err) if !internal.CheckHostConsistent(host) { fmt.Fprintf(os.Stderr, "Error: Invalid Host %s for endpoint %s\n", host, internal.Host) os.Exit(1) } else if len(tag) > 0 { fmt.Fprintf(os.Stderr, "Error: Invalid network name. Please see sail network show --help\n") os.Exit(1) } var network map[string]interface{} var ranges []string b := internal.ReqWant("GET", http.StatusOK, fmt.Sprintf("/applications/%s/networks/%s", app, net), nil) internal.Check(json.Unmarshal(b, &network)) brange := internal.ReqWant("GET", http.StatusOK, fmt.Sprintf("/applications/%s/networks/%s/ranges", app, net), nil) internal.Check(json.Unmarshal(brange, &ranges)) network["range"] = ranges n, err := json.Marshal(network) internal.Check(err) internal.FormatOutputDef(n) }
func serviceShow(serviceID string) { t := strings.Split(serviceID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail service show <applicationName>/<serviceId>. Please see sail service show --help") } else { internal.FormatOutputDef(internal.GetWantJSON(fmt.Sprintf("/applications/%s/services/%s", t[0], t[1]))) } }
func networkRemove(networkID string) { t := strings.Split(networkID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail network delete <applicationName>/<networkId>. Please see sail network delete --help") return } path := fmt.Sprintf("/applications/%s/networks/%s", t[0], t[1]) internal.FormatOutputDef(internal.DeleteWantJSON(path)) }
func repositoryRemove(repositoryID string) { t := strings.Split(repositoryID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail repository delete <applicationName>/<repositoryId>. Please see sail repository delete --help") return } path := fmt.Sprintf("/repositories/%s/%s", t[0], t[1]) internal.FormatOutputDef(internal.DeleteWantJSON(path)) }
func networkRangeAdd(networkID, ipFrom, ipTo string) { t := strings.Split(networkID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail network range-add <applicationName>/<networkId> <ipFrom> <ipTo>. Please see sail network range-add --help") return } path := fmt.Sprintf("/applications/%s/networks/%s/ranges/%s-%s", t[0], t[1], ipFrom, ipTo) internal.FormatOutputDef(internal.PostWantJSON(path)) }
func cmdCreate(cmd *cobra.Command, args []string) { usage := "Invalid usage. sail metric token create <applicationName>. Please see sail metric token create --help\n" if len(args) != 1 { fmt.Fprintf(os.Stderr, usage) return } // Get args application := args[0] path := fmt.Sprintf("/applications/%s/metrics/token", application) internal.FormatOutputDef(internal.PostWantJSON(path)) }
func webhookAdd(namespace, webhookURL string) { path := fmt.Sprintf("/applications/%s/hook", namespace) rawBody := webhookStruct{URL: webhookURL} body, err := json.MarshalIndent(rawBody, " ", " ") if err != nil { fmt.Fprintf(os.Stderr, "Fatal: %s\n", err) return } internal.FormatOutputDef(internal.PostBodyWantJSON(path, body)) }
func cmdRevoke(cmd *cobra.Command, args []string) { usage := "Invalid usage. sail metric token revoke <applicationName> <token>. Please see sail metric token revoke --help\n" if len(args) != 2 { fmt.Fprintf(os.Stderr, usage) return } // Get args application := args[0] token := args[1] path := fmt.Sprintf("/applications/%s/metrics/token/%s", application, token) internal.FormatOutputDef(internal.DeleteWantJSON(path)) }
func webhookDelete(namespace, webhookURL string) { urlEscape := url.QueryEscape(webhookURL) path := fmt.Sprintf("/applications/%s/hook", namespace) // pass urlEscape as query string argument BaseURL, err := url.Parse(path) internal.Check(err) params := url.Values{} params.Add("url", urlEscape) BaseURL.RawQuery = params.Encode() internal.FormatOutputDef(internal.DeleteWantJSON(BaseURL.String())) }
func networkAdd(networkID string, args networkAddStruct) { t := strings.Split(networkID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail network add <applicationName>/<networkId>. Please see sail network add --help") return } body, err := json.Marshal(args) internal.Check(err) path := fmt.Sprintf("/applications/%s/networks/%s", t[0], t[1]) internal.FormatOutputDef(internal.PostBodyWantJSON(path, body)) }
func serviceDomainDetach(serviceID, domain string, args domainStruct) { t := strings.Split(serviceID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, usageDomainDetach) return } body, err := json.Marshal(args) internal.Check(err) path := fmt.Sprintf("/applications/%s/services/%s/attached-routes/%s", t[0], t[1], domain) internal.FormatOutputDef(internal.DeleteBodyWantJSON(path, body)) }
func serviceDomainAttach(serviceID, domain, pattern, method string) { t := strings.Split(serviceID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, usageDomainAttach) return } args := domainStruct{Pattern: pattern, Method: method} body, err := json.Marshal(args) internal.Check(err) path := fmt.Sprintf("/applications/%s/services/%s/attached-routes/%s", t[0], t[1], domain) internal.FormatOutputDef(internal.PostBodyWantJSON(path, body)) }
func sshKeyAdd(keyLine, keyName string) { path := "/user/keys" rawBody := sshkeyStruct{ KeyLine: string(keyLine), KeyName: string(keyName), } body, err := json.MarshalIndent(rawBody, " ", " ") if err != nil { fmt.Fprintf(os.Stderr, "Fatal: %s\n", err) return } internal.FormatOutputDef(internal.PostBodyWantJSON(path, body)) }
func cmdListEnv(cmd *cobra.Command, args []string) { var applicationName string switch len(args) { case 0: applicationName = internal.GetUserName() case 1: applicationName = args[0] default: fmt.Fprintln(os.Stderr, "Invalid usage. Please see sail application env list --help") return } internal.FormatOutputDef(internal.GetWantJSON(fmt.Sprintf("/applications/%s/env", applicationName))) }
func sshKeyDelete(fingerprint string) { urlEscape := url.QueryEscape(fingerprint) path := "/user/keys" // pass urlEscape as query string argument BaseURL, err := url.Parse(path) internal.Check(err) params := url.Values{} params.Add("fingerprint", urlEscape) BaseURL.RawQuery = params.Encode() internal.FormatOutputDef(internal.DeleteWantJSON(BaseURL.String())) }
func networkRangeAdd(networkID, ipFrom, ipTo string) { // Split namespace and repository host, app, net, tag, err := internal.ParseResourceName(networkID) internal.Check(err) if !internal.CheckHostConsistent(host) { fmt.Fprintf(os.Stderr, "Error: Invalid Host %s for endpoint %s\n", host, internal.Host) os.Exit(1) } else if len(tag) > 0 { fmt.Fprintf(os.Stderr, "Error: Invalid network name. Please see sail network show --help\n") os.Exit(1) } path := fmt.Sprintf("/applications/%s/networks/%s/ranges/%s-%s", app, net, ipFrom, ipTo) internal.FormatOutputDef(internal.PostWantJSON(path)) }
func cmdDelEnv(cmd *cobra.Command, args []string) { var applicationName string var key string switch len(args) { case 1: applicationName = internal.GetUserName() key = args[0] case 2: applicationName = args[0] key = args[1] default: fmt.Fprintln(os.Stderr, "Invalid usage. Please see sail application env set --help") return } internal.FormatOutputDef(internal.DeleteWantJSON(fmt.Sprintf("/applications/%s/env/%s", applicationName, key))) }
func networkAdd(networkID string, args networkAddStruct) { // Split namespace and repository host, app, net, tag, err := internal.ParseResourceName(networkID) internal.Check(err) if !internal.CheckHostConsistent(host) { fmt.Fprintf(os.Stderr, "Error: Invalid Host %s for endpoint %s\n", host, internal.Host) os.Exit(1) } else if len(tag) > 0 { fmt.Fprintf(os.Stderr, "Error: Invalid network name. Please see sail network add --help\n") os.Exit(1) } body, err := json.Marshal(args) internal.Check(err) path := fmt.Sprintf("/applications/%s/networks/%s", app, net) internal.FormatOutputDef(internal.PostBodyWantJSON(path, body)) }
func repositoryAdd(repositoryName string, args repositoryAddStruct) { // Split namespace and repository host, app, repo, tag, err := internal.ParseResourceName(repositoryName) internal.Check(err) if !internal.CheckHostConsistent(host) { fmt.Fprintf(os.Stderr, "Error: Invalid Host %s for endpoint %s\n", host, internal.Host) os.Exit(1) } else if len(tag) > 0 { fmt.Fprintf(os.Stderr, "Error: Invalid repository name. Please see sail repository add --help\n") os.Exit(1) } body, err := json.Marshal(args) internal.Check(err) path := fmt.Sprintf("/repositories/%s/%s", app, repo) internal.FormatOutputDef(internal.PostBodyWantJSON(path, body)) }
func networkShow(networkID string) { t := strings.Split(networkID, "/") if len(t) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail network show <applicationName>/<networkId>. Please see sail network show --help") } else { var network map[string]interface{} var ranges []string b := internal.ReqWant("GET", http.StatusOK, fmt.Sprintf("/applications/%s/networks/%s", t[0], t[1]), nil) internal.Check(json.Unmarshal(b, &network)) brange := internal.ReqWant("GET", http.StatusOK, fmt.Sprintf("/applications/%s/networks/%s/ranges", t[0], t[1]), nil) internal.Check(json.Unmarshal(brange, &ranges)) network["range"] = ranges n, err := json.Marshal(network) internal.Check(err) internal.FormatOutputDef(n) } }
func cmdSetEnv(cmd *cobra.Command, args []string) { var cmdEnvBody env var applicationName string var parsedData []string switch len(args) { case 1: applicationName = internal.GetUserName() parsedData = strings.SplitN(args[0], "=", 2) case 2: applicationName = args[0] parsedData = strings.SplitN(args[1], "=", 2) default: fmt.Fprintln(os.Stderr, "Invalid usage. Please see sail application env set --help") return } cmdEnvBody.Data = parsedData[1] jsonStr, err := json.Marshal(cmdEnvBody) internal.Check(err) internal.FormatOutputDef(internal.PostBodyWantJSON(fmt.Sprintf("/applications/%s/env/%s", applicationName, parsedData[0]), jsonStr)) }
package me import ( "github.com/runabove/sail/internal" "github.com/spf13/cobra" ) var cmdMeShow = &cobra.Command{ Use: "show", Short: "Show account details: sail me show", Run: func(cmd *cobra.Command, args []string) { internal.FormatOutputDef(internal.GetWantJSON("/users")) }, }
package application import ( "github.com/runabove/sail/internal" "github.com/spf13/cobra" ) var cmdApplicationList = &cobra.Command{ Use: "list", Short: "List granted apps: sail application list", Aliases: []string{"ls", "ps"}, Run: func(cmd *cobra.Command, args []string) { internal.FormatOutputDef(internal.GetWantJSON("/applications")) }, }
func serviceDelete(namespace string, name string) { path := fmt.Sprintf("/applications/%s/services/%s", namespace, name) data := internal.ReqWant("DELETE", http.StatusOK, path, nil) // TODO Check for json error here internal.FormatOutputDef(data) }
Run: func(cmd *cobra.Command, args []string) { var applicationName string switch len(args) { case 0: applicationName = internal.GetUserName() case 1: applicationName = args[0] default: fmt.Fprintln(os.Stderr, "Invalid usage. Please see sail application webhook list --help") return } // Sanity err := internal.CheckName(applicationName) internal.Check(err) internal.FormatOutputDef(internal.GetWantJSON(fmt.Sprintf("/applications/%s/hook", applicationName))) }, } var cmdApplicationWebhookAdd = &cobra.Command{ Use: "add", Short: "Add a webhook to an application ; sail application webhook add [<applicationName>] <WebhookURL>", Long: `Add a webhook to an application ; sail application webhook add [<applicationName>] <WebhookURL> example: sail application webhook add http://www.endpoint.com/hook sail application webhook add my-app http://www.endpoint.com/hook Endpoint url must accept POST with json body. `, Run: func(cmd *cobra.Command, args []string) { var applicationName string var webhookURL string
package me import ( "encoding/json" "net/http" "github.com/runabove/sail/internal" "github.com/spf13/cobra" ) var cmdMeSetAcl = &cobra.Command{ Use: "setAcl", Short: "Set ip based account access restrictions: sail me setAcl <ip> [<ip> ... ]", Long: `Set ip based account access restrictions: sail me setAcl <ip> [<ip> ... ] \"example: sail me setAcl 1.2.3.4/24 4.5.6.7/32\" `, Aliases: []string{"setAcls", "set-acls", "set-acl"}, Run: func(cmd *cobra.Command, args []string) { jsonStr, err := json.Marshal(args) internal.Check(err) internal.FormatOutputDef(internal.ReqWantJSON("PUT", http.StatusOK, "/user/acl", jsonStr)) }, }
func serviceAdd(args Add) { if args.ContainerEnvironment == nil { args.ContainerEnvironment = make([]string, 0) } // Parse volumes if len(cmdAddVolume) > 0 { args.Volumes = make(map[string]VolumeConfig) } for _, vol := range cmdAddVolume { t := strings.Split(vol, ":") if len(t) == 2 { args.Volumes[t[0]] = VolumeConfig{Size: t[1]} } else if len(t) == 1 { args.Volumes[t[0]] = VolumeConfig{Size: "10"} } else { fmt.Fprintf(os.Stderr, "Error: Volume parameter '%s' not formated correctly\n", vol) os.Exit(1) } } // Parse links if len(redeployLink) > 0 { args.Links = make(map[string]string) } for _, link := range cmdAddLink { t := strings.Split(link, ":") if len(t) == 1 { args.Links[t[0]] = t[0] } else { args.Links[t[0]] = t[1] } } // Parse ContainerNetworks arguments for _, network := range cmdAddNetwork { args.ContainerNetwork[network] = make(map[string][]string) } for _, gat := range cmdAddGateway { t := strings.Split(gat, ":") if len(t) != 2 { fmt.Fprintf(os.Stderr, "Invalid gateway parameter, should be \"input:output\". Typically, output will be one of 'predictor', 'public'") os.Exit(1) } if _, ok := args.ContainerNetwork[t[0]]; !ok { fmt.Fprintf(os.Stderr, "Automatically adding %s to network list\n", t[0]) args.ContainerNetwork[t[0]] = make(map[string][]string) } if _, ok := args.ContainerNetwork[t[1]]; !ok { fmt.Fprintf(os.Stderr, "Automatically adding %s to network list\n", t[0]) args.ContainerNetwork[t[1]] = make(map[string][]string) } args.ContainerNetwork[t[0]]["gateway_to"] = append(args.ContainerNetwork[t[0]]["gateway_to"], t[1]) } // Parse ContainerPorts args.ContainerPorts = parsePublishedPort(addPublish) path := fmt.Sprintf("/applications/%s/services/%s", args.Application, args.Service) body, err := json.MarshalIndent(args, " ", " ") if err != nil { fmt.Fprintf(os.Stderr, "Fatal: %s\n", err) return } if addBatch { ret, code, err := internal.Request("POST", path, body) // http.Request failed for some reason if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) return } // If we are in ensure mode, fallback to redeploy if code == 409 && cmdAddRedeploy { ensureMode(args) return } // If API returned a json error e := internal.DecodeError(ret) if e != nil { fmt.Fprintf(os.Stderr, "%s\n", e) return } // Just print data internal.FormatOutputDef(ret) // Always start service if internal.Format == "pretty" { fmt.Fprintf(os.Stderr, "Starting service %s/%s...\n", args.Application, args.Service) } serviceStart(args.Application, args.Service, false) return } buffer, code, err := internal.Stream("POST", path+"?stream", body) if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) return } if code == 409 && cmdAddRedeploy { ensureMode(args) return } line, err := internal.DisplayStream(buffer) internal.Check(err) if line != nil { var data map[string]interface{} err = json.Unmarshal(line, &data) internal.Check(err) fmt.Printf("Hostname: %v\n", data["hostname"]) fmt.Printf("Running containers: %v/%v\n", data["container_number"], data["container_target"]) } }
// Cmd container var Cmd = &cobra.Command{ Use: "container", Short: "Container commands: sail container --help", Long: `Container commands: sail container <command>`, Aliases: []string{"c", "containers"}, } var cmdContainerShow = &cobra.Command{ Use: "show", Aliases: []string{"inspect"}, Short: "Show a docker container: sail container show <containerId>", Long: `Show a docker container: sail container show <containerId> \"example: sail container show my-app my-container" `, Run: func(cmd *cobra.Command, args []string) { var container string switch len(args) { case 1: container = args[0] case 2: container = args[1] default: fmt.Fprintln(os.Stderr, "Invalid usage. sail container show <containerId>. Please see sail container show --help") os.Exit(1) } internal.FormatOutputDef(internal.GetWantJSON(fmt.Sprintf("/containers/%s", container))) }, }
func init() { Cmd.AddCommand(cmdContainerList) Cmd.AddCommand(cmdContainerShow) Cmd.AddCommand(cmdContainerAttach) Cmd.AddCommand(cmdContainerLogs()) } // Cmd container var Cmd = &cobra.Command{ Use: "container", Short: "Container commands: sail container --help", Long: `Container commands: sail container <command>`, Aliases: []string{"c", "containers"}, } var cmdContainerShow = &cobra.Command{ Use: "show", Aliases: []string{"inspect"}, Short: "Show a docker container: sail container show <applicationName> <containerId>", Long: `Show a docker container: sail container show <applicationName> <containerId> \"example: sail container show my-app my-container" `, Run: func(cmd *cobra.Command, args []string) { if len(args) != 2 { fmt.Fprintln(os.Stderr, "Invalid usage. sail container show <applicationName> <containerId>. Please see sail container show --help") } else { internal.FormatOutputDef(internal.GetWantJSON(fmt.Sprintf("/applications/%s/containers/%s", args[0], args[1]))) } }, }