diff --git a/README.md b/README.md index 6f79130f85..eceed0d469 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ Options: -q, --quiet=false Enable quiet mode --sensitive=false Show sensitive data in outputs, i.e. API Token/Organization -v, --version=false Print version information and quit - --region=par1 Change the default region + --region=par1 Change the default region (e.g. ams1) Commands: help help of the scw command line @@ -1203,6 +1203,10 @@ $ scw inspect myserver | jq '.[0].public_ip.address' ### master (unreleased) +* new Compute URL `api.scaleway.com` -> `cp-par1.scaleway.com` +* new TTY URL `tty.scaleway.com/v2` -> `https://tty-par1.scaleway.com/v2` +* Region: add `ams1`, you can start a server at Amsterdam with `scw --region="ams1" run yakkety` +* API: Support multi-zone * API: Add ZoneID field in server location * `scw image -a -f type=volume` fix unmarshal error on size field * `scw ps` do not display empty server with --filter diff --git a/pkg/api/api.go b/pkg/api/api.go index ef4dbffaff..21eac4151c 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -35,8 +35,11 @@ var ( AccountAPI = "https://account.scaleway.com/" MetadataAPI = "http://169.254.42.42/" MarketplaceAPI = "https://api-marketplace.scaleway.com" - URLPublicDNS = ".pub.cloud.scaleway.com" - URLPrivateDNS = ".priv.cloud.scaleway.com" + ComputeAPIPar1 = "https://cp-par1.scaleway.com/" + ComputeAPIAms1 = "https://cp-ams1.scaleway.com" + + URLPublicDNS = ".pub.cloud.scaleway.com" + URLPrivateDNS = ".priv.cloud.scaleway.com" ) func init() { @@ -74,6 +77,8 @@ type ScalewayAPI struct { client *http.Client verbose bool computeAPI string + + Region string // Logger } @@ -885,10 +890,13 @@ func NewScalewayAPI(organization, token, userAgent, region string, options ...fu } switch region { case "par1", "": - s.computeAPI = "https://api.scaleway.com/" + s.computeAPI = ComputeAPIPar1 + case "ams1": + s.computeAPI = ComputeAPIAms1 default: return nil, fmt.Errorf("%s isn't a valid region", region) } + s.Region = region if url := os.Getenv("SCW_COMPUTE_API"); url != "" { s.computeAPI = url } @@ -1098,6 +1106,30 @@ func (s *ScalewayAPI) handleHTTPError(goodStatusCode []int, resp *http.Response) return body, nil } +func (s *ScalewayAPI) fetchServers(api string, query url.Values, out chan<- ScalewayServers) func() error { + return func() error { + resp, err := s.GetResponsePaginate(api, "servers", query) + if resp != nil { + defer resp.Body.Close() + } + if err != nil { + return err + } + + body, err := s.handleHTTPError([]int{http.StatusOK}, resp) + if err != nil { + return err + } + var servers ScalewayServers + + if err = json.Unmarshal(body, &servers); err != nil { + return err + } + out <- servers + return nil + } +} + // GetServers gets the list of servers from the ScalewayAPI func (s *ScalewayAPI) GetServers(all bool, limit int) (*[]ScalewayServer, error) { query := url.Values{} @@ -1112,32 +1144,34 @@ func (s *ScalewayAPI) GetServers(all bool, limit int) (*[]ScalewayServer, error) if all && limit == 0 { s.Cache.ClearServers() } - resp, err := s.GetResponsePaginate(s.computeAPI, "servers", query) - if resp != nil { - defer resp.Body.Close() - } - if err != nil { - return nil, err + var ( + g errgroup.Group + apis = []string{ + ComputeAPIPar1, + ComputeAPIAms1, + } + ) + + serverChan := make(chan ScalewayServers, 2) + for _, api := range apis { + g.Go(s.fetchServers(api, query, serverChan)) } - body, err := s.handleHTTPError([]int{http.StatusOK}, resp) - if err != nil { + if err := g.Wait(); err != nil { return nil, err } + close(serverChan) var servers ScalewayServers - if err = json.Unmarshal(body, &servers); err != nil { - return nil, err + + for server := range serverChan { + servers.Servers = append(servers.Servers, server.Servers...) } + for i, server := range servers.Servers { - // FIXME arch, owner, title servers.Servers[i].DNSPublic = server.Identifier + URLPublicDNS servers.Servers[i].DNSPrivate = server.Identifier + URLPrivateDNS s.Cache.InsertServer(server.Identifier, server.Location.ZoneID, server.Arch, server.Organization, server.Name) } - // FIXME: when API limit is ready, remove the following code - if limit > 0 && limit < len(servers.Servers) { - servers.Servers = servers.Servers[0:limit] - } return &servers.Servers, nil } @@ -2081,11 +2115,12 @@ func showResolverResults(needle string, results ScalewayResolverResults) error { w := tabwriter.NewWriter(os.Stderr, 20, 1, 3, ' ', 0) defer w.Flush() sort.Sort(results) + fmt.Fprintf(w, " IMAGEID\tFROM\tNAME\tZONE\tARCH\n") for _, result := range results { if result.Arch == "" { result.Arch = "n/a" } - fmt.Fprintf(w, "- %s\t%s\t%s\t%s\n", result.TruncIdentifier(), result.CodeName(), result.Name, result.Arch) + fmt.Fprintf(w, "- %s\t%s\t%s\t%s\t%s\n", result.TruncIdentifier(), result.CodeName(), result.Name, result.Region, result.Arch) } return fmt.Errorf("Too many candidates for %s (%d)", needle, len(results)) } @@ -2139,6 +2174,19 @@ func FilterImagesByArch(res ScalewayResolverResults, arch string) (ret ScalewayR return } +// FilterImagesByRegion removes entry that doesn't match with region +func FilterImagesByRegion(res ScalewayResolverResults, region string) (ret ScalewayResolverResults) { + if region == "*" { + return res + } + for _, result := range res { + if result.Region == region { + ret = append(ret, result) + } + } + return +} + // GetImageID returns exactly one image matching func (s *ScalewayAPI) GetImageID(needle, arch string) (*ScalewayImageIdentifier, error) { // Parses optional type prefix, i.e: "image:name" -> "name" @@ -2149,17 +2197,18 @@ func (s *ScalewayAPI) GetImageID(needle, arch string) (*ScalewayImageIdentifier, return nil, fmt.Errorf("Unable to resolve image %s: %s", needle, err) } images = FilterImagesByArch(images, arch) + images = FilterImagesByRegion(images, s.Region) if len(images) == 1 { return &ScalewayImageIdentifier{ Identifier: images[0].Identifier, Arch: images[0].Arch, // FIXME region, owner hardcoded - Region: "", + Region: images[0].Region, Owner: "", }, nil } if len(images) == 0 { - return nil, fmt.Errorf("No such image: %s", needle) + return nil, fmt.Errorf("No such image (zone %s, arch %s) : %s", s.Region, arch, needle) } return nil, showResolverResults(needle, images) } @@ -2817,3 +2866,14 @@ func (s *ScalewayAPI) DeleteMarketPlaceLocalImage(uuidImage, uuidVersion, uuidLo _, err = s.handleHTTPError([]int{http.StatusNoContent}, resp) return err } + +// ResolveTTYUrl return an URL to get a tty +func (s *ScalewayAPI) ResolveTTYUrl() string { + switch s.Region { + case "par1", "": + return "https://tty-par1.scaleway.com/v2/" + case "ams1": + return "https://tty-ams1.scaleway.com" + } + return "" +} diff --git a/pkg/api/cache.go b/pkg/api/cache.go index 587d06e888..1d9771a0ee 100644 --- a/pkg/api/cache.go +++ b/pkg/api/cache.go @@ -29,7 +29,6 @@ const ( CacheTitle // CacheMarketPlaceUUID is used to determine the UUID of local images CacheMarketPlaceUUID - // CacheMaxfield is used to determine the size of array CacheMaxfield ) @@ -87,13 +86,14 @@ type ScalewayResolverResult struct { Arch string Needle string RankMatch int + Region string } // ScalewayResolverResults is a list of `ScalewayResolverResult` type ScalewayResolverResults []ScalewayResolverResult // NewScalewayResolverResult returns a new ScalewayResolverResult -func NewScalewayResolverResult(Identifier, Name, Arch string, Type int) (ScalewayResolverResult, error) { +func NewScalewayResolverResult(Identifier, Name, Arch, Region string, Type int) (ScalewayResolverResult, error) { if err := anonuuid.IsUUID(Identifier); err != nil { return ScalewayResolverResult{}, err } @@ -102,6 +102,7 @@ func NewScalewayResolverResult(Identifier, Name, Arch string, Type int) (Scalewa Type: Type, Name: Name, Arch: Arch, + Region: Region, }, nil } @@ -268,7 +269,7 @@ func (c *ScalewayCache) LookUpImages(needle string, acceptUUID bool) (ScalewayRe if acceptUUID && anonuuid.IsUUID(needle) == nil { if fields, ok := c.Images[needle]; ok { - entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], IdentifierImage) + entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierImage) if err != nil { return ScalewayResolverResults{}, err } @@ -282,7 +283,7 @@ func (c *ScalewayCache) LookUpImages(needle string, acceptUUID bool) (ScalewayRe nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*")) for identifier, fields := range c.Images { if fields[CacheTitle] == needle { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierImage) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierImage) if err != nil { return ScalewayResolverResults{}, err } @@ -290,14 +291,14 @@ func (c *ScalewayCache) LookUpImages(needle string, acceptUUID bool) (ScalewayRe exactMatches = append(exactMatches, entry) } if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierImage) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierImage) if err != nil { return ScalewayResolverResults{}, err } entry.ComputeRankMatch(needle) res = append(res, entry) } else if strings.HasPrefix(fields[CacheMarketPlaceUUID], needle) || nameRegex.MatchString(fields[CacheMarketPlaceUUID]) { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierImage) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierImage) if err != nil { return ScalewayResolverResults{}, err } @@ -323,7 +324,7 @@ func (c *ScalewayCache) LookUpSnapshots(needle string, acceptUUID bool) (Scalewa if acceptUUID && anonuuid.IsUUID(needle) == nil { if fields, ok := c.Snapshots[needle]; ok { - entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], IdentifierSnapshot) + entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierSnapshot) if err != nil { return ScalewayResolverResults{}, err } @@ -336,7 +337,7 @@ func (c *ScalewayCache) LookUpSnapshots(needle string, acceptUUID bool) (Scalewa nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*")) for identifier, fields := range c.Snapshots { if fields[CacheTitle] == needle { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierSnapshot) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierSnapshot) if err != nil { return ScalewayResolverResults{}, err } @@ -344,7 +345,7 @@ func (c *ScalewayCache) LookUpSnapshots(needle string, acceptUUID bool) (Scalewa exactMatches = append(exactMatches, entry) } if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierSnapshot) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierSnapshot) if err != nil { return ScalewayResolverResults{}, err } @@ -370,7 +371,7 @@ func (c *ScalewayCache) LookUpVolumes(needle string, acceptUUID bool) (ScalewayR if acceptUUID && anonuuid.IsUUID(needle) == nil { if fields, ok := c.Volumes[needle]; ok { - entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], IdentifierVolume) + entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierVolume) if err != nil { return ScalewayResolverResults{}, err } @@ -382,7 +383,7 @@ func (c *ScalewayCache) LookUpVolumes(needle string, acceptUUID bool) (ScalewayR nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*")) for identifier, fields := range c.Volumes { if fields[CacheTitle] == needle { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierVolume) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierVolume) if err != nil { return ScalewayResolverResults{}, err } @@ -390,7 +391,7 @@ func (c *ScalewayCache) LookUpVolumes(needle string, acceptUUID bool) (ScalewayR exactMatches = append(exactMatches, entry) } if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierVolume) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierVolume) if err != nil { return ScalewayResolverResults{}, err } @@ -416,7 +417,7 @@ func (c *ScalewayCache) LookUpBootscripts(needle string, acceptUUID bool) (Scale if acceptUUID && anonuuid.IsUUID(needle) == nil { if fields, ok := c.Bootscripts[needle]; ok { - entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], IdentifierBootscript) + entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierBootscript) if err != nil { return ScalewayResolverResults{}, err } @@ -428,7 +429,7 @@ func (c *ScalewayCache) LookUpBootscripts(needle string, acceptUUID bool) (Scale nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*")) for identifier, fields := range c.Bootscripts { if fields[CacheTitle] == needle { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierBootscript) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierBootscript) if err != nil { return ScalewayResolverResults{}, err } @@ -436,7 +437,7 @@ func (c *ScalewayCache) LookUpBootscripts(needle string, acceptUUID bool) (Scale exactMatches = append(exactMatches, entry) } if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierBootscript) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierBootscript) if err != nil { return ScalewayResolverResults{}, err } @@ -462,7 +463,7 @@ func (c *ScalewayCache) LookUpServers(needle string, acceptUUID bool) (ScalewayR if acceptUUID && anonuuid.IsUUID(needle) == nil { if fields, ok := c.Servers[needle]; ok { - entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], IdentifierServer) + entry, err := NewScalewayResolverResult(needle, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierServer) if err != nil { return ScalewayResolverResults{}, err } @@ -474,7 +475,7 @@ func (c *ScalewayCache) LookUpServers(needle string, acceptUUID bool) (ScalewayR nameRegex := regexp.MustCompile(`(?i)` + regexp.MustCompile(`[_-]`).ReplaceAllString(needle, ".*")) for identifier, fields := range c.Servers { if fields[CacheTitle] == needle { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierServer) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierServer) if err != nil { return ScalewayResolverResults{}, err } @@ -482,7 +483,7 @@ func (c *ScalewayCache) LookUpServers(needle string, acceptUUID bool) (ScalewayR exactMatches = append(exactMatches, entry) } if strings.HasPrefix(identifier, needle) || nameRegex.MatchString(fields[CacheTitle]) { - entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], IdentifierServer) + entry, err := NewScalewayResolverResult(identifier, fields[CacheTitle], fields[CacheArch], fields[CacheRegion], IdentifierServer) if err != nil { return ScalewayResolverResults{}, err } @@ -551,7 +552,7 @@ func (c *ScalewayCache) LookUpIdentifiers(needle string) (ScalewayResolverResult return ScalewayResolverResults{}, err } for _, result := range servers { - entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, IdentifierServer) + entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, IdentifierServer) if err != nil { return ScalewayResolverResults{}, err } @@ -566,7 +567,7 @@ func (c *ScalewayCache) LookUpIdentifiers(needle string) (ScalewayResolverResult return ScalewayResolverResults{}, err } for _, result := range images { - entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, IdentifierImage) + entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, IdentifierImage) if err != nil { return ScalewayResolverResults{}, err } @@ -581,7 +582,7 @@ func (c *ScalewayCache) LookUpIdentifiers(needle string) (ScalewayResolverResult return ScalewayResolverResults{}, err } for _, result := range snapshots { - entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, IdentifierSnapshot) + entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, IdentifierSnapshot) if err != nil { return ScalewayResolverResults{}, err } @@ -596,7 +597,7 @@ func (c *ScalewayCache) LookUpIdentifiers(needle string) (ScalewayResolverResult return ScalewayResolverResults{}, err } for _, result := range volumes { - entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, IdentifierVolume) + entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, IdentifierVolume) if err != nil { return ScalewayResolverResults{}, err } @@ -611,7 +612,7 @@ func (c *ScalewayCache) LookUpIdentifiers(needle string) (ScalewayResolverResult return ScalewayResolverResults{}, err } for _, result := range bootscripts { - entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, IdentifierBootscript) + entry, err := NewScalewayResolverResult(result.Identifier, result.Name, result.Arch, result.Region, IdentifierBootscript) if err != nil { return ScalewayResolverResults{}, err } diff --git a/pkg/api/helpers.go b/pkg/api/helpers.go index 07eff4343a..d05eb1ad67 100644 --- a/pkg/api/helpers.go +++ b/pkg/api/helpers.go @@ -41,7 +41,7 @@ type ScalewayImageInterface struct { Type string Organization string Archs []string - Region string + Region []string } // ResolveGateway tries to resolve a server public ip address, else returns the input string, i.e. IPv4, hostname @@ -445,7 +445,7 @@ func CreateServer(api *ScalewayAPI, c *ConfigCreateServer) (string, error) { return "", err } currentVolume := createdServer.Volumes["0"] - size := currentVolume.Size.(uint64) + size := uint64(currentVolume.Size.(float64)) var volumePayload ScalewayVolumePutDefinition newName := fmt.Sprintf("%s-%s", createdServer.Hostname, currentVolume.Name) diff --git a/pkg/cli/cmd_help.go b/pkg/cli/cmd_help.go index 7cd96ce1d8..4117f73d30 100644 --- a/pkg/cli/cmd_help.go +++ b/pkg/cli/cmd_help.go @@ -43,7 +43,7 @@ Options: -q, --quiet=false Enable quiet mode --sensitive=false Show sensitive data in outputs, i.e. API Token/Organization -v, --version=false Print version information and quit - --region=par1 Change the default region + --region=par1 Change the default region (e.g. ams1) Commands: {{range .}}{{if not .Hidden}} {{.Name | printf "%-9s"}} {{.Description}} diff --git a/pkg/cli/main.go b/pkg/cli/main.go index c9faf4bce9..b47b8fdb9f 100644 --- a/pkg/cli/main.go +++ b/pkg/cli/main.go @@ -32,7 +32,7 @@ var ( flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit") flQuiet = flag.Bool([]string{"q", "-quiet"}, false, "Enable quiet mode") flSensitive = flag.Bool([]string{"-sensitive"}, false, "Show sensitive data in outputs, i.e. API Token/Organization") - flRegion = flag.String([]string{"-region"}, "par1", "Change the default region") + flRegion = flag.String([]string{"-region"}, "par1", "Change the default region (e.g. ams1)") ) // Start is the entrypoint diff --git a/pkg/commands/attach.go b/pkg/commands/attach.go index b522e30093..e2ff07fe23 100644 --- a/pkg/commands/attach.go +++ b/pkg/commands/attach.go @@ -18,7 +18,7 @@ func RunAttach(ctx CommandContext, args AttachArgs) error { if err != nil { return err } - _, done, err := utils.AttachToSerial(serverID, ctx.API.Token) + _, done, err := utils.AttachToSerial(serverID, ctx.API.Token, ctx.API.ResolveTTYUrl()) if err != nil { return err } diff --git a/pkg/commands/images.go b/pkg/commands/images.go index ae3f4e0fce..2083dd80b3 100644 --- a/pkg/commands/images.go +++ b/pkg/commands/images.go @@ -51,15 +51,26 @@ func RunImages(ctx CommandContext, args ImagesArgs) error { errChan <- fmt.Errorf("unable to parse creation date from the Scaleway API: %v", err) return } - archs := []string{} + archAvailable := make(map[string]struct{}) + zoneAvailable := make(map[string]struct{}) + for _, version := range val.Versions { if val.CurrentPublicVersion == version.ID { for _, local := range version.LocalImages { - archs = append(archs, local.Arch) + archAvailable[local.Arch] = struct{}{} + zoneAvailable[local.Zone] = struct{}{} } break } } + regions := []string{} + for k := range zoneAvailable { + regions = append(regions, k) + } + archs := []string{} + for k := range archAvailable { + archs = append(archs, k) + } chEntries <- api.ScalewayImageInterface{ Type: "image", CreationDate: creationDate, @@ -68,9 +79,8 @@ func RunImages(ctx CommandContext, args ImagesArgs) error { Tag: "latest", Organization: val.Organization.ID, Public: val.Public, - // FIXME the region should not be hardcoded - Region: "fr-1", - Archs: archs, + Region: regions, + Archs: archs, } } }() @@ -102,7 +112,7 @@ func RunImages(ctx CommandContext, args ImagesArgs) error { Public: false, Organization: val.Organization, // FIXME the region should not be hardcoded - Region: "fr-1", + Region: []string{"fr-1"}, } } }() @@ -125,7 +135,7 @@ func RunImages(ctx CommandContext, args ImagesArgs) error { Tag: "", Public: false, // FIXME the region should not be hardcoded - Region: "fr-1", + Region: []string{"fr-1"}, Archs: []string{val.Arch}, } } @@ -157,7 +167,7 @@ func RunImages(ctx CommandContext, args ImagesArgs) error { Public: false, Organization: val.Organization, // FIXME the region should not be hardcoded - Region: "fr-1", + Region: []string{"fr-1"}, } } }() diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 734e3d965b..c6ebd19369 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -99,10 +99,10 @@ func addUserData(ctx CommandContext, userdatas []string, serverID string) { } } -func runShowBoot(ctx CommandContext, args RunArgs, serverID string, closeTimeout chan struct{}, timeoutExit chan struct{}) error { +func runShowBoot(ctx CommandContext, args RunArgs, serverID, region string, closeTimeout chan struct{}, timeoutExit chan struct{}) error { // Attach to server serial logrus.Info("Attaching to server console ...") - gottycli, done, err := utils.AttachToSerial(serverID, ctx.API.Token) + gottycli, done, err := utils.AttachToSerial(serverID, ctx.API.Token, ctx.API.ResolveTTYUrl()) if err != nil { close(closeTimeout) return fmt.Errorf("cannot attach to server serial: %v", err) @@ -242,11 +242,11 @@ func Run(ctx CommandContext, args RunArgs) error { }() } if args.ShowBoot { - return runShowBoot(ctx, args, serverID, closeTimeout, timeoutExit) + return runShowBoot(ctx, args, serverID, ctx.API.Region, closeTimeout, timeoutExit) } else if args.Attach { // Attach to server serial logrus.Info("Attaching to server console ...") - gottycli, done, err := utils.AttachToSerial(serverID, ctx.API.Token) + gottycli, done, err := utils.AttachToSerial(serverID, ctx.API.Token, ctx.API.ResolveTTYUrl()) close(closeTimeout) if err != nil { return fmt.Errorf("cannot attach to server serial: %v", err) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index f76721ba84..c11263be91 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -191,10 +191,10 @@ func RemoveDuplicates(elements []string) []string { } // AttachToSerial tries to connect to server serial using 'gotty-client' and fallback with a help message -func AttachToSerial(serverID string, apiToken string) (*gottyclient.Client, chan bool, error) { +func AttachToSerial(serverID, apiToken, url string) (*gottyclient.Client, chan bool, error) { gottyURL := os.Getenv("SCW_GOTTY_URL") if gottyURL == "" { - gottyURL = "https://tty.scaleway.com/v2/" + gottyURL = url } URL := fmt.Sprintf("%s?arg=%s&arg=%s", gottyURL, apiToken, serverID)