Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(instance): add stocks in server-type list #827

Merged
merged 5 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/mattn/go-colorable v0.1.4
github.com/mattn/go-isatty v0.0.11
github.com/pkg/errors v0.9.1 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200403105108-eb943ac1f1dc
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200403173805-25a10631420d
github.com/sergi/go-diff v1.0.0 // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200331160105-1181c3dc1bcd
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200331160105-1181c3dc1bcd/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200403105108-eb943ac1f1dc h1:YJloAPPmGOEF+nufGL4a9Ppj6jnIMs8FjIorEM3ZBoE=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200403105108-eb943ac1f1dc/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200403173805-25a10631420d h1:oAG5xtIkUri9hwveoJPv0K3JTSREckKG3MfmNmnXAEQ=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6.0.20200403173805-25a10631420d/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
Expand Down
29 changes: 20 additions & 9 deletions internal/human/marshal_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,28 @@ func isMarshalable(t reflect.Type) bool {
(t.Kind() == reflect.Ptr && isMarshalable(t.Elem()))
}

// BindAttributesMarshalFunc will apply the Attributes bindings to the value i
func BindAttributesMarshalFunc(attributes Attributes) MarshalerFunc {
// EnumMarshalSpec contains specs used by EnumMarshalFunc.
type EnumMarshalSpec struct {
// Attribute (mainly colors) to use.
Attribute color.Attribute

// Value is the value that will be printed for the given value.
Value string
}

type EnumMarshalSpecs map[interface{}]*EnumMarshalSpec

// EnumMarshalFunc returns a marshal func to marshal an enum.
func EnumMarshalFunc(specs EnumMarshalSpecs) MarshalerFunc {
return func(i interface{}, opt *MarshalOpt) (s string, e error) {
s, _ = defaultMarshalerFunc(i, opt)
attribute, exist := attributes[i]
value, _ := defaultMarshalerFunc(i, opt)
spec, exist := specs[i]
if exist {
s = terminal.Style(s, attribute)
if spec.Value != "" {
value = spec.Value
}
value = terminal.Style(value, spec.Attribute)
}
return s, nil
return value, nil
}
}

// Attributes makes the binding between a value and a color.Attribute
type Attributes map[interface{}]color.Attribute
10 changes: 6 additions & 4 deletions internal/namespaces/instance/v1/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func GetCommands() *core.Commands {
// Server
//
human.RegisterMarshalerFunc(instance.CreateServerResponse{}, marshallNestedField("Server"))
human.RegisterMarshalerFunc(instance.ServerState(0), serverStateMarshalerFunc)
human.RegisterMarshalerFunc(instance.ServerState(0), human.EnumMarshalFunc(serverStateMarshalSpecs))
human.RegisterMarshalerFunc(instance.ServerLocation{}, serverLocationMarshalerFunc)
human.RegisterMarshalerFunc([]*instance.Server{}, serversMarshalerFunc)
human.RegisterMarshalerFunc(instance.GetServerResponse{}, getServerResponseMarshalerFunc)
Expand All @@ -46,6 +46,8 @@ func GetCommands() *core.Commands {
//
// Server-Type
//
human.RegisterMarshalerFunc(instance.ServerTypesAvailability(""), human.EnumMarshalFunc(serverTypesAvailabilityMarshalSpecs))

cmds.MustFind("instance", "server-type", "list").Override(serverTypeListBuilder)

//
Expand All @@ -70,15 +72,15 @@ func GetCommands() *core.Commands {
// Volume
//
human.RegisterMarshalerFunc(instance.CreateVolumeResponse{}, marshallNestedField("Volume"))
human.RegisterMarshalerFunc(instance.VolumeState(0), human.BindAttributesMarshalFunc(volumeStateAttributes))
human.RegisterMarshalerFunc(instance.VolumeState(0), human.EnumMarshalFunc(volumeStateMarshalSpecs))
human.RegisterMarshalerFunc(instance.VolumeSummary{}, volumeSummaryMarshalerFunc)
human.RegisterMarshalerFunc(map[string]*instance.Volume{}, volumeMapMarshalerFunc)

//
// Security Group
//
human.RegisterMarshalerFunc(instance.CreateSecurityGroupResponse{}, marshallNestedField("SecurityGroup"))
human.RegisterMarshalerFunc(instance.SecurityGroupPolicy(0), human.BindAttributesMarshalFunc(securityGroupPolicyAttribute))
human.RegisterMarshalerFunc(instance.SecurityGroupPolicy(0), human.EnumMarshalFunc(securityGroupPolicyMarshalSpecs))

cmds.MustFind("instance", "security-group", "get").Override(securityGroupGetBuilder)
cmds.MustFind("instance", "security-group", "delete").Override(securityGroupDeleteBuilder)
Expand All @@ -92,7 +94,7 @@ func GetCommands() *core.Commands {
// Security Group Rule
//
human.RegisterMarshalerFunc(instance.CreateSecurityGroupRuleResponse{}, marshallNestedField("Rule"))
human.RegisterMarshalerFunc(instance.SecurityGroupRuleAction(0), human.BindAttributesMarshalFunc(securityGroupRuleActionAttribute))
human.RegisterMarshalerFunc(instance.SecurityGroupRuleAction(0), human.EnumMarshalFunc(securityGroupRuleActionMarshalSpecs))

//
// Placement Group
Expand Down
12 changes: 6 additions & 6 deletions internal/namespaces/instance/v1/custom_security_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ import (
//

var (
securityGroupPolicyAttribute = human.Attributes{
instance.SecurityGroupPolicyDrop: color.FgRed,
instance.SecurityGroupPolicyAccept: color.FgGreen,
securityGroupPolicyMarshalSpecs = human.EnumMarshalSpecs{
instance.SecurityGroupPolicyDrop: &human.EnumMarshalSpec{Attribute: color.FgRed},
instance.SecurityGroupPolicyAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen},
}

securityGroupRuleActionAttribute = human.Attributes{
instance.SecurityGroupRuleActionDrop: color.FgRed,
instance.SecurityGroupRuleActionAccept: color.FgGreen,
securityGroupRuleActionMarshalSpecs = human.EnumMarshalSpecs{
instance.SecurityGroupRuleActionDrop: &human.EnumMarshalSpec{Attribute: color.FgRed},
instance.SecurityGroupRuleActionAccept: &human.EnumMarshalSpec{Attribute: color.FgGreen},
}
)

Expand Down
23 changes: 0 additions & 23 deletions internal/namespaces/instance/v1/custom_security_group_rule.go

This file was deleted.

19 changes: 11 additions & 8 deletions internal/namespaces/instance/v1/custom_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (
"time"

"github.com/fatih/color"

"github.com/hashicorp/go-multierror"
"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-cli/internal/human"
"github.com/scaleway/scaleway-cli/internal/interactive"
"github.com/scaleway/scaleway-cli/internal/terminal"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/logger"
"github.com/scaleway/scaleway-sdk-go/scw"
Expand All @@ -28,14 +28,17 @@ const (
// Marshalers
//

// serverStateMarshalerFunc marshals a instance.ServerState.
func serverStateMarshalerFunc(i interface{}, opt *human.MarshalOpt) (string, error) {
// The Scaleway console shows "archived" for a stopped server.
if i.(instance.ServerState) == instance.ServerStateStopped {
return terminal.Style("archived", color.Faint), nil
// serverStateMarshalSpecs allows to override the displayed instance.ServerState.
var (
serverStateMarshalSpecs = human.EnumMarshalSpecs{
instance.ServerStateRunning: &human.EnumMarshalSpec{Attribute: color.FgGreen},
instance.ServerStateStopped: &human.EnumMarshalSpec{Attribute: color.Faint, Value: "archived"},
instance.ServerStateStoppedInPlace: &human.EnumMarshalSpec{Attribute: color.Faint},
instance.ServerStateStarting: &human.EnumMarshalSpec{Attribute: color.FgBlue},
instance.ServerStateStopping: &human.EnumMarshalSpec{Attribute: color.FgBlue},
instance.ServerStateLocked: &human.EnumMarshalSpec{Attribute: color.FgRed},
}
return human.BindAttributesMarshalFunc(serverStateAttributes)(i, opt)
}
)

// serverLocationMarshalerFunc marshals a instance.ServerLocation.
func serverLocationMarshalerFunc(i interface{}, opt *human.MarshalOpt) (string, error) {
Expand Down
49 changes: 35 additions & 14 deletions internal/namespaces/instance/v1/custom_server_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@ import (
"sort"
"strings"

"github.com/fatih/color"
"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-cli/internal/human"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

//
// Marshalers
//

var (
serverTypesAvailabilityMarshalSpecs = human.EnumMarshalSpecs{
instance.ServerTypesAvailabilityAvailable: &human.EnumMarshalSpec{Attribute: color.FgGreen},
instance.ServerTypesAvailabilityScarce: &human.EnumMarshalSpec{Attribute: color.FgYellow, Value: "low stock"},
instance.ServerTypesAvailabilityShortage: &human.EnumMarshalSpec{Attribute: color.FgRed, Value: "out of stock"},
}
)

//
// Builders
//
Expand All @@ -33,30 +47,36 @@ func serverTypeListBuilder(c *core.Command) *core.Command {
"X64-60GB": {},
}

originalRun := c.Run

c.Run = func(ctx context.Context, argsI interface{}) (interface{}, error) {
type customServerType struct {
Name string `json:"name"`
MonthlyPrice *scw.Money `json:"monthly_price"`
HourlyPrice *scw.Money `json:"hourly_price"`
LocalVolumeSize scw.Size `json:"local_volume_size"`
CPU uint32 `json:"cpu"`
GPU *uint64 `json:"gpu"`
RAM scw.Size `json:"ram"`
Arch instance.Arch `json:"arch"`
Name string `json:"name"`
MonthlyPrice *scw.Money `json:"monthly_price"`
HourlyPrice *scw.Money `json:"hourly_price"`
LocalVolumeSize scw.Size `json:"local_volume_size"`
CPU uint32 `json:"cpu"`
GPU *uint64 `json:"gpu"`
RAM scw.Size `json:"ram"`
Arch instance.Arch `json:"arch"`
Availability instance.ServerTypesAvailability `json:"availability"`
}

originalRes, err := originalRun(ctx, argsI)
api := instance.NewAPI(core.ExtractClient(ctx))

// Get server types.
request := argsI.(*instance.ListServersTypesRequest)
listServersTypesResponse, err := api.ListServersTypes(request)
if err != nil {
return nil, err
}

listServersTypesResponse := originalRes.(*instance.ListServersTypesResponse)
serverTypes := []*customServerType(nil)

for name, serverType := range listServersTypesResponse.Servers {
// Get server availabilities.
availabilitiesResponse, err := api.GetServerTypesAvailability(&instance.GetServerTypesAvailabilityRequest{})
if err != nil {
return nil, err
}

for name, serverType := range listServersTypesResponse.Servers {
_, isDeprecated := deprecatedNames[name]
if isDeprecated {
continue
Expand All @@ -71,6 +91,7 @@ func serverTypeListBuilder(c *core.Command) *core.Command {
GPU: serverType.Gpu,
RAM: scw.Size(serverType.RAM),
Arch: serverType.Arch,
Availability: availabilitiesResponse.Servers[name].Availability,
})
}

Expand Down
2 changes: 1 addition & 1 deletion internal/namespaces/instance/v1/custom_server_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/scaleway/scaleway-cli/internal/core"
)

func Test_serverTypeListBuilder(t *testing.T) {
func Test_ServerTypeList(t *testing.T) {
t.Run("server-type list", core.Test(&core.TestConfig{
Commands: GetCommands(),
Cmd: "scw instance server-type list",
Expand Down
6 changes: 3 additions & 3 deletions internal/namespaces/instance/v1/custom_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
//

var (
volumeStateAttributes = human.Attributes{
instance.VolumeStateError: color.FgRed,
instance.VolumeStateAvailable: color.FgGreen,
volumeStateMarshalSpecs = human.EnumMarshalSpecs{
instance.VolumeStateError: &human.EnumMarshalSpec{Attribute: color.FgRed},
instance.VolumeStateAvailable: &human.EnumMarshalSpec{Attribute: color.FgGreen},
}
)

Expand Down
Loading