Skip to content

Commit

Permalink
feat(baremetal): add create server with type (#768)
Browse files Browse the repository at this point in the history
Co-authored-by: Quentin Brosse <quentin.brosse@icloud.com>
Co-authored-by: Loïc Bourgois <loic@bourgois.pro>
  • Loading branch information
3 people authored Apr 9, 2020
1 parent c58750e commit 0c5827c
Show file tree
Hide file tree
Showing 25 changed files with 3,905 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,33 @@ Create a new server. Once the server is created, you probably want to install an
USAGE:
scw baremetal server create [arg=value ...]

EXAMPLES:
Create instance
scw baremetal server create

Create a GP-BM1-M instance, give it a name and add tags
scw baremetal server create name=foo tags.0=prod tags.1=blue type=GP-BM1-M

ARGS:
offer-id Offer ID of the new server
name Name of the server (≠hostname)
description Description associated to the server, max 255 characters
name=<generated> Name of the server (≠hostname)
[description] Description associated to the server, max 255 characters
[type=GP-BM1-S] Server commercial type (GP-BM1-L | GP-BM1-M | GP-BM1-S | HC-BM1-L | HC-BM1-S | HM-BM1-XL | HM-BM1-M)
[tags.{index}] Tags to associate to the server
[organization-id] Organization ID to use. If none is passed will use default organization ID from the config
[zone] Zone to target. If none is passed will use default zone from the config (fr-par-2)

FLAGS:
-h, --help help for create
-w, --wait wait until the server is ready

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use

SEE ALSO:
# List os
scw baremetal os list

# Install an OS on your server
scw baremetal server install
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ARGS:

FLAGS:
-h, --help help for reboot
-w, --wait wait until the server is ready

GLOBAL FLAGS:
-D, --debug Enable debug mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ARGS:

FLAGS:
-h, --help help for start
-w, --wait wait until the server is ready

GLOBAL FLAGS:
-D, --debug Enable debug mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ARGS:

FLAGS:
-h, --help help for stop
-w, --wait wait until the server is ready

GLOBAL FLAGS:
-D, --debug Enable debug mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ AVAILABLE COMMANDS:
reboot Reboot server
start Start server
stop Stop server
wait Wait for a server to reach a stable state

FLAGS:
-h, --help help for server
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Wait for a server to reach a stable state. This is similar to using --wait flag on other action commands, but without requiring a new action on the server.

USAGE:
scw baremetal server wait [arg=value ...]

EXAMPLES:
Wait for a server to reach a stable state
scw baremetal server wait server-id=11111111-1111-1111-1111-111111111111

ARGS:
server-id ID of the server affected by the action.
[zone] Zone to target. If none is passed will use default zone from the config

FLAGS:
-h, --help help for wait

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use
2 changes: 1 addition & 1 deletion internal/namespaces/baremetal/v1alpha1/baremetal_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"reflect"

"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1"
baremetal "github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

Expand Down
4 changes: 2 additions & 2 deletions internal/namespaces/baremetal/v1alpha1/baremetal_cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import (
"testing"

"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
baremetal "github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

func init() {
if !core.UpdateCassettes {
instance.RetryInterval = 0
baremetal.RetryInterval = 0
}
}

Expand Down
12 changes: 12 additions & 0 deletions internal/namespaces/baremetal/v1alpha1/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,17 @@ import "github.com/scaleway/scaleway-cli/internal/core"

func GetCommands() *core.Commands {
cmds := GetGeneratedCommands()

cmds.Merge(core.NewCommands(
serverWaitCommand(),
))

cmds.MustFind("baremetal", "server", "create").Override(serverCreateBuilder)

// Action commands
cmds.MustFind("baremetal", "server", "start").Override(serverStartBuilder)
cmds.MustFind("baremetal", "server", "stop").Override(serverStopBuilder)
cmds.MustFind("baremetal", "server", "reboot").Override(serverRebootBuilder)

return cmds
}
95 changes: 95 additions & 0 deletions internal/namespaces/baremetal/v1alpha1/custom_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package baremetal

import (
"context"
"reflect"
"time"

"github.com/scaleway/scaleway-cli/internal/core"
baremetal "github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

const (
serverActionTimeout = 20 * time.Minute
)

func serverWaitCommand() *core.Command {
type serverWaitRequest struct {
ServerID string
Zone scw.Zone
}

return &core.Command{
Short: `Wait for a server to reach a stable state`,
Long: `Wait for a server to reach a stable state. This is similar to using --wait flag on other action commands, but without requiring a new action on the server.`,
Namespace: "baremetal",
Resource: "server",
Verb: "wait",
ArgsType: reflect.TypeOf(serverWaitRequest{}),
Run: func(ctx context.Context, argsI interface{}) (i interface{}, err error) {
api := baremetal.NewAPI(core.ExtractClient(ctx))
return api.WaitForServer(&baremetal.WaitForServerRequest{
ServerID: argsI.(*serverWaitRequest).ServerID,
Zone: argsI.(*serverWaitRequest).Zone,
Timeout: serverActionTimeout,
})
},
ArgSpecs: core.ArgSpecs{
{
Name: "server-id",
Short: `ID of the server affected by the action.`,
Required: true,
},
core.ZoneArgSpec(),
},
Examples: []*core.Example{
{
Short: "Wait for a server to reach a stable state",
Request: `{"server_id": "11111111-1111-1111-1111-111111111111"}`,
},
},
}
}

// serverStartBuilder overrides the baremetalServerStart command
func serverStartBuilder(c *core.Command) *core.Command {
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := baremetal.NewAPI(core.ExtractClient(ctx))
return api.WaitForServer(&baremetal.WaitForServerRequest{
Zone: argsI.(*baremetal.StartServerRequest).Zone,
ServerID: respI.(*baremetal.StartServerRequest).ServerID,
Timeout: serverActionTimeout,
})
}

return c
}

// serverStopBuilder overrides the baremetalServerStop command
func serverStopBuilder(c *core.Command) *core.Command {
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := baremetal.NewAPI(core.ExtractClient(ctx))
return api.WaitForServer(&baremetal.WaitForServerRequest{
Zone: argsI.(*baremetal.StopServerRequest).Zone,
ServerID: respI.(*baremetal.StopServerRequest).ServerID,
Timeout: serverActionTimeout,
})
}

return c
}

// serverRebootBuilder overrides the baremetalServerReboot command
func serverRebootBuilder(c *core.Command) *core.Command {
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := baremetal.NewAPI(core.ExtractClient(ctx))
return api.WaitForServer(&baremetal.WaitForServerRequest{
Zone: argsI.(*baremetal.RebootServerRequest).Zone,
ServerID: respI.(*baremetal.RebootServerRequest).ServerID,
Timeout: serverActionTimeout,
})
}

return c
}
119 changes: 119 additions & 0 deletions internal/namespaces/baremetal/v1alpha1/custom_server_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package baremetal

import (
"context"
"fmt"
"reflect"

"github.com/scaleway/scaleway-cli/internal/core"
baremetal "github.com/scaleway/scaleway-sdk-go/api/baremetal/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

func serverCreateBuilder(c *core.Command) *core.Command {
type baremetalCreateServerRequestCustom struct {
Zone scw.Zone `json:"-"`
// OrganizationID with which the server will be created
OrganizationID string `json:"organization_id"`
// Name of the server (≠hostname)
Name string `json:"name"`
// Description associated to the server, max 255 characters
Description string `json:"description"`
// Tags associated with the server
Tags []string `json:"tags"`
// Type of the server
Type string
}

c.ArgsType = reflect.TypeOf(baremetalCreateServerRequestCustom{})

c.ArgSpecs.DeleteByName("offer-id")

c.ArgSpecs.GetByName("name").Default = core.RandomValueGenerator("bm")
c.ArgSpecs.GetByName("description").Required = false

c.ArgSpecs.AddBefore("tags.{index}", &core.ArgSpec{
Name: "type",
Short: "Server commercial type",
Default: core.DefaultValueSetter("GP-BM1-S"),

EnumValues: []string{
// General Purpose offers
"GP-BM1-L",
"GP-BM1-M",
"GP-BM1-S",

// High-computing offers
"HC-BM1-L",
"HC-BM1-S",

// High-Memory offers
"HM-BM1-XL",
"HM-BM1-M",
},
})

c.Run = func(ctx context.Context, argsI interface{}) (i interface{}, e error) {
client := core.ExtractClient(ctx)
api := baremetal.NewAPI(client)

tmpRequest := argsI.(*baremetalCreateServerRequestCustom)
request := &baremetal.CreateServerRequest{
Zone: tmpRequest.Zone,
OrganizationID: tmpRequest.OrganizationID,
Name: tmpRequest.Name,
Description: tmpRequest.Description,
Tags: tmpRequest.Tags,
}

// We need to find the offer ID.
// While baremetal does not have list offer name filter we are forced to iterate
// on the list of offers provided.
offer, err := api.GetOfferFromName(&baremetal.GetOfferFromOfferNameRequest{
OfferName: tmpRequest.Type,
Zone: tmpRequest.Zone,
})
if err != nil {
return nil, err
}
if offer == nil {
return nil, fmt.Errorf("could not match an offer with the type: %s", tmpRequest.Type)
}
request.OfferID = offer.ID

return api.CreateServer(request)
}

c.SeeAlsos = []*core.SeeAlso{
{
Short: "List os",
Command: "scw baremetal os list",
},
{
Short: "Install an OS on your server",
Command: "scw baremetal server install",
},
}

c.Examples = []*core.Example{
{
Short: "Create instance",
Request: `{}`,
},
{
Short: "Create a GP-BM1-M instance, give it a name and add tags",
Request: `{"type":"GP-BM1-M","name":"foo","tags":["prod","blue"]}`,
},
}

c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := baremetal.NewAPI(core.ExtractClient(ctx))
return api.WaitForServer(&baremetal.WaitForServerRequest{
Zone: argsI.(*baremetalCreateServerRequestCustom).Zone,
ServerID: respI.(*baremetal.Server).ID,
Timeout: serverActionTimeout,
})
}

return c
}
Loading

0 comments on commit 0c5827c

Please sign in to comment.