Skip to content

Commit c925277

Browse files
committed
Replace hardcoded volume values by an API call
Some servers need to match a minimum volume size in order to be created. Those criteria were hardcoded into the server creation. Replace those by a call to the Products API. Then given the minimum volume size, partition it into predefined volume sizes.
1 parent cfa747c commit c925277

File tree

2 files changed

+67
-29
lines changed

2 files changed

+67
-29
lines changed

pkg/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ type ProductServer struct {
300300
Ram uint64 `json:"ram,omitempty"`
301301
Baremetal bool `json:"baremetal,omitempty"`
302302
VolumesConstraint ProductVolumeConstraint `json:"volumes_constraint,omitempty"`
303+
AltNames []string `json:"alt_names,omitempty"`
303304
Network ProductNetwork `json:"network,omitempty"`
304305
}
305306

pkg/api/helpers.go

Lines changed: 66 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package api
77
import (
88
"errors"
99
"fmt"
10+
"math"
1011
"os"
1112
"sort"
1213
"strings"
@@ -94,6 +95,36 @@ func CreateVolumeFromHumanSize(api *ScalewayAPI, size string) (*string, error) {
9495
return &volumeID, nil
9596
}
9697

98+
// VolumesFromSize returns a string of standard sized volumes from a given size
99+
func VolumesFromSize(size uint64) string {
100+
const DefaultVolumeSize float64 = 50000000000
101+
StdVolumeSizes := []struct {
102+
kind string
103+
capacity float64
104+
}{
105+
{"150G", 150000000000},
106+
{"100G", 100000000000},
107+
{"50G", 50000000000},
108+
}
109+
110+
RequiredSize := float64(size) - DefaultVolumeSize
111+
Volumes := ""
112+
for _, v := range StdVolumeSizes {
113+
q := RequiredSize / v.capacity
114+
r := math.Mod(RequiredSize, v.capacity)
115+
RequiredSize = r
116+
117+
if q > 0 {
118+
Volumes += strings.Repeat(v.kind+" ", int(q))
119+
}
120+
if r == 0 {
121+
break
122+
}
123+
}
124+
125+
return strings.TrimSpace(Volumes)
126+
}
127+
97128
// fillIdentifierCache fills the cache by fetching from the API
98129
func fillIdentifierCache(api *ScalewayAPI, identifierType int) {
99130
log.Debugf("Filling the cache")
@@ -290,6 +321,25 @@ type ConfigCreateServer struct {
290321
EnableIPV6 bool
291322
}
292323

324+
// Return offer from any of the product name or alternate names
325+
func OfferNameFromName(name string, products *ScalewayProductsServers) (*ProductServer, error) {
326+
offer, ok := products.Servers[name]
327+
if ok {
328+
return &offer, nil
329+
}
330+
331+
for _, v := range products.Servers {
332+
for _, alt := range v.AltNames {
333+
alt := strings.ToUpper(alt)
334+
if alt == name {
335+
return &v, nil
336+
}
337+
}
338+
}
339+
340+
return nil, fmt.Errorf("Unknow commercial type: %v", name)
341+
}
342+
293343
// CreateServer creates a server using API based on typical server fields
294344
func CreateServer(api *ScalewayAPI, c *ConfigCreateServer) (string, error) {
295345
commercialType := os.Getenv("SCW_COMMERCIAL_TYPE")
@@ -306,7 +356,7 @@ func CreateServer(api *ScalewayAPI, c *ConfigCreateServer) (string, error) {
306356

307357
var server ScalewayServerDefinition
308358

309-
server.CommercialType = commercialType
359+
server.CommercialType = strings.ToUpper(commercialType)
310360
server.Volumes = make(map[string]string)
311361
server.DynamicIPRequired = &c.DynamicIPRequired
312362
server.EnableIPV6 = c.EnableIPV6
@@ -336,32 +386,19 @@ func CreateServer(api *ScalewayAPI, c *ConfigCreateServer) (string, error) {
336386
if c.Env != "" {
337387
server.Tags = strings.Split(c.Env, " ")
338388
}
339-
switch c.CommercialType {
340-
case "VC1M", "X64-4GB", "ARM64-4GB":
341-
if c.AdditionalVolumes == "" {
342-
c.AdditionalVolumes = "50G"
343-
log.Debugf("This server needs a least 50G")
344-
}
345-
case "VC1L", "X64-8GB", "X64-15GB", "ARM64-8GB":
346-
if c.AdditionalVolumes == "" {
347-
c.AdditionalVolumes = "150G"
348-
log.Debugf("This server needs a least 150G")
349-
}
350-
case "X64-30GB":
351-
if c.AdditionalVolumes == "" {
352-
c.AdditionalVolumes = "100G 150G"
353-
log.Debugf("This server needs a least 300G")
354-
}
355-
case "X64-60GB":
356-
if c.AdditionalVolumes == "" {
357-
c.AdditionalVolumes = "50G 150G 150G"
358-
log.Debugf("This server needs a least 400G")
359-
}
360-
case "X64-120GB":
361-
if c.AdditionalVolumes == "" {
362-
c.AdditionalVolumes = "150G 150G 150G"
363-
log.Debugf("This server needs a least 500G")
364-
}
389+
390+
products, err := api.GetProductsServers()
391+
if err != nil {
392+
return "", fmt.Errorf("Unable to fetch products list from the Scaleway API: %v", err)
393+
}
394+
offer, err := OfferNameFromName(server.CommercialType, products)
395+
if err != nil {
396+
return "", fmt.Errorf("Unknow commercial type %v: %v", server.CommercialType, err)
397+
}
398+
if offer.VolumesConstraint.MinSize > 0 && c.AdditionalVolumes == "" {
399+
c.AdditionalVolumes = VolumesFromSize(offer.VolumesConstraint.MinSize)
400+
log.Debugf("%s needs at least %s. Automatically creates the following volumes: %s",
401+
server.CommercialType, humanize.Bytes(offer.VolumesConstraint.MinSize), c.AdditionalVolumes)
365402
}
366403
if c.AdditionalVolumes != "" {
367404
volumes := strings.Split(c.AdditionalVolumes, " ")
@@ -375,9 +412,9 @@ func CreateServer(api *ScalewayAPI, c *ConfigCreateServer) (string, error) {
375412
server.Volumes[volumeIDx] = *volumeID
376413
}
377414
}
415+
378416
arch := os.Getenv("SCW_TARGET_ARCH")
379417
if arch == "" {
380-
server.CommercialType = strings.ToUpper(server.CommercialType)
381418
switch server.CommercialType[:2] {
382419
case "C1":
383420
arch = "arm"
@@ -394,7 +431,7 @@ func CreateServer(api *ScalewayAPI, c *ConfigCreateServer) (string, error) {
394431
}
395432
server.Name = c.Name
396433
inheritingVolume := false
397-
_, err := humanize.ParseBytes(c.ImageName)
434+
_, err = humanize.ParseBytes(c.ImageName)
398435
if err == nil {
399436
// Create a new root volume
400437
volumeID, errCreateVol := CreateVolumeFromHumanSize(api, c.ImageName)

0 commit comments

Comments
 (0)