// serviceScale start service (without attach) func serviceScale(app string, service string, number int, destroy bool, batch bool) { if !batch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } // stream service events in a goroutine internal.EventStreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/events", app, service), nil, true) path := fmt.Sprintf("/applications/%s/services/%s/scale", app, service) args := Scale{ Number: number, Destroy: destroy, } data, err := json.Marshal(&args) internal.Check(err) buffer, _, err := internal.Stream("POST", path, data) internal.Check(err) line, err := internal.DisplayStream(buffer) internal.Check(err) if len(line) > 0 { var data map[string]interface{} err = json.Unmarshal(line, &data) internal.Check(err) fmt.Printf("Hostname: %v\n", data["hostname"]) } if !batch { internal.ExitAfterCtrlC() } }
func doServiceRedeploy(args Redeploy, app, service string) { path := fmt.Sprintf("/applications/%s/services/%s/redeploy", app, service) body, err := json.MarshalIndent(args, " ", " ") if err != nil { fmt.Fprintf(os.Stderr, "Fatal: %s\n", err) return } // Attach console if !redeployBatch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } // Redeploy buffer, _, err := internal.Stream("POST", path, body) if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) os.Exit(1) } line, err := internal.DisplayStream(buffer) internal.Check(err) if len(line) > 0 { var data map[string]interface{} err = json.Unmarshal(line, &data) internal.Check(err) fmt.Printf("Hostname: %v\n", data["hostname"]) } if !redeployBatch { internal.ExitAfterCtrlC() } }
// serviceStart start service (without attach) func serviceStart(app string, service string, batch bool) { if !batch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } // stream service events in a goroutine internal.EventStreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/events", app, service), nil, true) path := fmt.Sprintf("/applications/%s/services/%s/start", app, service) buffer, _, err := internal.Stream("POST", path, []byte("{}")) internal.Check(err) line, err := internal.DisplayStream(buffer) internal.Check(err) if len(line) > 0 { var data map[string]interface{} err = json.Unmarshal(line, &data) internal.Check(err) fmt.Printf("Hostname: %v\n", data["hostname"]) } if !batch { internal.ExitAfterCtrlC() } }
// serviceScale start service (without attach) func serviceScale(app string, service string, number int, destroy bool, batch bool) { if !batch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } path := fmt.Sprintf("/applications/%s/services/%s/scale?stream", app, service) args := Scale{ Number: number, Destroy: destroy, } data, err := json.Marshal(&args) internal.Check(err) buffer, _, err := internal.Stream("POST", path, data) internal.Check(err) 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"]) } if !batch { internal.ExitAfterCtrlC() } }
func cmdUp(cmd *cobra.Command, args []string) { // Check args if len(args) != 1 { internal.Exit("Invalid usage. sail compose up <namespace>. Please see sail compose up -h\n") } ns := args[0] // Try to read file payload, err := ioutil.ReadFile(upFile) if err != nil { internal.Exit("Error reading compose file: %s\n", err) } // Execute request path := fmt.Sprintf("/applications/%s/fig/up?stream", ns) buffer, _, err := internal.Stream("POST", path, payload, internal.SetHeader("Content-Type", "application/x-yaml")) internal.Check(err) // Display api stream 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"]) } }
func serviceDelete(namespace string, name string) { path := fmt.Sprintf("/applications/%s/services/%s?force=%t", namespace, name, deleteForce) buffer, _, err := internal.Stream("DELETE", path, nil) if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) os.Exit(1) } _, err = internal.DisplayStream(buffer) internal.Check(err) }
// serviceStop stop service (without attach) func serviceStop(app string, service string, batch bool) { if !batch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } path := fmt.Sprintf("/applications/%s/services/%s/stop?stream", app, service) buffer, _, err := internal.Stream("POST", path, []byte("{}")) if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) os.Exit(1) } _, err = internal.DisplayStream(buffer) internal.Check(err) }
func cmdUp(cmd *cobra.Command, args []string) { // FIXME: duplicate internal.ReadConfig() var ns string // Check args if len(args) > 1 { internal.Exit("Invalid usage. sail compose up [<application>]. Please see sail compose up -h\n") } else if len(args) > 1 { ns = args[0] } else { ns = internal.User } // Try to read file payload, err := ioutil.ReadFile(upFile) if err != nil { internal.Exit("Error reading compose file: %s\n", err) } // Execute request path := fmt.Sprintf("/applications/%s/fig/up", ns) buffer, _, err := internal.Stream("POST", path, payload, internal.SetHeader("Content-Type", "application/x-yaml")) internal.Check(err) // Display api stream line, err := internal.DisplayStream(buffer) internal.Check(err) if len(line) > 0 { var data []map[string]interface{} err = json.Unmarshal(line, &data) if err != nil { fmt.Printf("Error detected in API Return. Line: %s\n", line) return } for i := range data { fmt.Printf("Compose operation for service %v is %v\n", data[i]["name"], data[i]["result"]) } } }
// serviceStart start service (without attach) func serviceStart(app string, service string, batch bool) { if !batch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } path := fmt.Sprintf("/applications/%s/services/%s/start?stream", app, service) buffer, _, err := internal.Stream("POST", path, []byte("{}")) internal.Check(err) 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"]) } if !batch { internal.ExitAfterCtrlC() } }
func serviceAdd(args Add) { if args.ContainerEnvironment == nil { args.ContainerEnvironment = make([]string, 0) } // Parse command if cmdAddCommand != "" { command, err := shlex.Split(cmdAddCommand) if err != nil { fmt.Fprintf(os.Stderr, "Fatal, cannot split command %s\n", err) return } args.ContainerCommand = command } // Parse Entrypoint if cmdAddEntrypoint != "" { entrypoint, err := shlex.Split(cmdAddEntrypoint) if err != nil { fmt.Fprintf(os.Stderr, "Fatal, cannot split command %s\n", err) return } args.ContainerEntrypoint = entrypoint } // 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 } stream := "" if !addBatch { stream = "?stream" } buffer, code, err := internal.Stream("POST", path+stream, 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 } else if code >= 400 { body, err = ioutil.ReadAll(buffer) internal.Check(err) internal.FormatOutputError(body) return } line, err := internal.DisplayStream(buffer) // If we are in ensure mode, fallback to redeploy if err != nil { e := internal.DecodeError(line) if e != nil && e.Code == 409 && cmdAddRedeploy { ensureMode(args) return } internal.FormatOutputError(line) return } // 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, addBatch) }
func serviceRedeploy(args Redeploy) { // Parse volumes if len(redeployVolume) > 0 { args.Volumes = make(map[string]VolumeConfig) } // Parse command if redeployCommand != "" { command, err := shlex.Split(redeployCommand) if err != nil { fmt.Fprintf(os.Stderr, "Fatal, cannot split command %s\n", err) return } args.ContainerCommand = command } // Parse Entrypoint if redeployEntrypoint != "" { entrypoint, err := shlex.Split(redeployEntrypoint) if err != nil { fmt.Fprintf(os.Stderr, "Fatal, cannot split command %s\n", err) return } args.ContainerEntrypoint = entrypoint } for _, vol := range redeployVolume { 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 redeployLink { t := strings.Split(link, ":") if len(t) == 1 { args.Links[t[0]] = t[0] } else { args.Links[t[0]] = t[1] } } // Parse ContainerNetworks arguments if len(redeployNetwork) > 0 { args.ContainerNetwork = make(map[string]map[string][]string) } for _, network := range redeployNetwork { args.ContainerNetwork[network] = make(map[string][]string) } for _, gat := range redeployGateway { t := strings.Split(gat, ":") if len(t) != 2 { fmt.Fprintf(os.Stderr, "Invalid gateway parameter, should be \"input:output\". Typically, output will be 'predictor' or 'public'") os.Exit(1) } } // Load Pool args.Pool = redeployPool // Parse ContainerPorts args.ContainerPorts = parsePublishedPort(redeployPublished) app := args.Application service := args.Service path := fmt.Sprintf("/applications/%s/services/%s/redeploy", app, service) body, err := json.MarshalIndent(args, " ", " ") if err != nil { fmt.Fprintf(os.Stderr, "Fatal: %s\n", err) return } // Attach console if !redeployBatch { internal.StreamPrint("GET", fmt.Sprintf("/applications/%s/services/%s/attach", app, service), nil) } // Redeploy buffer, _, err := internal.Stream("POST", path+"?stream", body) if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) os.Exit(1) } 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"]) } if !redeployBatch { internal.ExitAfterCtrlC() } }
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"]) } }