Skip to content

Commit cfa747c

Browse files
committed
Add the products command
This command allow user to list products features. At the moment only the `servers` product is supported.
1 parent d48bac1 commit cfa747c

File tree

8 files changed

+209
-3
lines changed

8 files changed

+209
-3
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Read the [blog post](https://blog.scaleway.com/2015/05/20/manage-baremetal-serve
4545
* [`logout [OPTIONS]`](#scw-logout)
4646
* [`logs [OPTIONS] SERVER`](#scw-logs)
4747
* [`port [OPTIONS] SERVER [PRIVATE_PORT[/PROTO]]`](#scw-port)
48+
* [`products [OPTIONS]`] PRODUCT(#scw-products)
4849
* [`ps [OPTIONS]`](#scw-ps)
4950
* [`rename [OPTIONS] SERVER NEW_NAME`](#scw-rename)
5051
* [`restart [OPTIONS] SERVER [SERVER...]`](#scw-restart)
@@ -201,6 +202,7 @@ Commands:
201202
logout Log out from the Scaleway API
202203
logs Fetch the logs of a server
203204
port Lookup the public-facing port that is NAT-ed to PRIVATE_PORT
205+
products Display products information
204206
ps List servers
205207
rename Rename a server
206208
restart Restart a running server
@@ -588,6 +590,19 @@ Options:
588590
```
589591

590592

593+
#### `scw products`
594+
595+
```console
596+
Usage: scw products [OPTIONS] PRODUCT
597+
598+
Display products PRODUCT information.
599+
600+
Options:
601+
602+
-s, --short Print only commercial names
603+
```
604+
605+
591606
#### `scw ps`
592607

593608
```console

contrib/completion/bash/scw

100644100755
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,17 @@ _scw_port() {
628628
esac
629629
}
630630

631+
_scw_products() {
632+
case "$cur" in
633+
-*)
634+
COMPREPLY=( $( compgen -W "--help -s --short" -- "$cur" ) )
635+
;;
636+
*)
637+
COMPREPLY=( $( compgen -W "servers" -- "$cur" ) )
638+
;;
639+
esac
640+
}
641+
631642
_scw_ps() {
632643
case "$prev" in
633644
--before|--since)
@@ -1130,6 +1141,7 @@ _scw() {
11301141
logs
11311142
# pause
11321143
port
1144+
products
11331145
ps
11341146
# pull
11351147
# push

contrib/completion/zsh/_scw

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ __scw_subcommand () {
201201
'1:servers:__scw_runningservers' \
202202
'2:port:_ports'
203203
;;
204+
(products)
205+
_arguments \
206+
{-s,--short}'[Display only commercial types]' \
207+
'*:products:(servers)'
208+
;;
204209
(start)
205210
_arguments \
206211
{-T,--timeout=0}'[Set timeout values to seconds]' \

pkg/api/api.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,41 @@ type ScalewayImages struct {
273273
Images []ScalewayImage `json:"images,omitempty"`
274274
}
275275

276+
// ProductNetworkInterface gives interval and external allowed bandwidth
277+
type ProductNetworkInterface struct {
278+
InternalBandwidth uint64 `json:"internal_bandwidth,omitempty"`
279+
InternetBandwidth uint64 `json:"internet_bandwidth,omitempty"`
280+
}
281+
282+
// ProductNetwork lists all the network interfaces
283+
type ProductNetwork struct {
284+
Interfaces []ProductNetworkInterface `json:"interfaces,omitempty"`
285+
TotalInternalBandwidth uint64 `json:"sum_internal_bandwidth,omitempty"`
286+
TotalInternetBandwidth uint64 `json:"sum_internet_bandwidth,omitempty"`
287+
IPv6_Support bool `json:"ipv6_support,omitempty"`
288+
}
289+
290+
// ProductVolumeConstraint contains any volume constraint that the offer has
291+
type ProductVolumeConstraint struct {
292+
MinSize uint64 `json:"min_size,omitempty"`
293+
MaxSize uint64 `json:"max_size,omitempty"`
294+
}
295+
296+
// ProductServerOffer represents a specific offer
297+
type ProductServer struct {
298+
Arch string `json:"arch,omitempty"`
299+
Ncpus uint64 `json:"ncpus,omitempty"`
300+
Ram uint64 `json:"ram,omitempty"`
301+
Baremetal bool `json:"baremetal,omitempty"`
302+
VolumesConstraint ProductVolumeConstraint `json:"volumes_constraint,omitempty"`
303+
Network ProductNetwork `json:"network,omitempty"`
304+
}
305+
306+
// Products holds a map of all Scaleway servers
307+
type ScalewayProductsServers struct {
308+
Servers map[string]ProductServer `json:"servers"`
309+
}
310+
276311
// ScalewaySnapshot represents a Scaleway Snapshot
277312
type ScalewaySnapshot struct {
278313
// Identifier is a unique identifier for the snapshot
@@ -2781,3 +2816,24 @@ func (s *ScalewayAPI) ResolveTTYUrl() string {
27812816
}
27822817
return ""
27832818
}
2819+
2820+
// GetProductServers Fetches all the server type and their constraints from the Products API
2821+
func (s *ScalewayAPI) GetProductsServers() (*ScalewayProductsServers, error) {
2822+
resp, err := s.GetResponsePaginate(s.computeAPI, "products/servers", url.Values{})
2823+
if err != nil {
2824+
return nil, err
2825+
}
2826+
defer resp.Body.Close()
2827+
2828+
body, err := s.handleHTTPError([]int{http.StatusOK}, resp)
2829+
if err != nil {
2830+
return nil, err
2831+
}
2832+
2833+
var productServers ScalewayProductsServers
2834+
if err = json.Unmarshal(body, &productServers); err != nil {
2835+
return nil, err
2836+
}
2837+
2838+
return &productServers, nil
2839+
}

pkg/cli/cmd_products.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (C) 2015 Scaleway. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE.md file.
4+
5+
package cli
6+
7+
import "github.com/scaleway/scaleway-cli/pkg/commands"
8+
9+
var cmdProducts = &Command{
10+
Exec: runProducts,
11+
UsageLine: "products [OPTIONS] PRODUCT",
12+
Description: "Display product PRODUCT information",
13+
Help: "Display products PRODUCT information. At the moment only `servers` is supported.",
14+
Examples: `
15+
$ scw products servers
16+
$ scw products --short servers
17+
`,
18+
}
19+
20+
func init() {
21+
cmdProducts.Flag.BoolVar(&productsHelp, []string{"h", "-help"}, false, "Print usage")
22+
cmdProducts.Flag.BoolVar(&productsShort, []string{"s", "-short"}, false, "Print only commercial names")
23+
}
24+
25+
// Flags
26+
var productsHelp bool // -h, --help flag
27+
var productsShort bool // -s, --short flag
28+
29+
func runProducts(cmd *Command, rawArgs []string) error {
30+
if productsHelp {
31+
return cmd.PrintUsage()
32+
}
33+
if len(rawArgs) != 1 {
34+
return cmd.PrintShortUsage()
35+
}
36+
37+
args := commands.ProductsArgs{
38+
Short: productsShort,
39+
Products: rawArgs,
40+
}
41+
42+
ctx := cmd.GetContext(rawArgs)
43+
return commands.RunProducts(ctx, args)
44+
}

pkg/cli/commands.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var Commands = []*Command{
2626
cmdLogout,
2727
cmdLogs,
2828
cmdPort,
29+
cmdProducts,
2930
cmdPs,
3031
cmdRename,
3132
cmdRestart,

pkg/cli/test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ var (
1212
"help", "attach", "commit", "cp", "create",
1313
"events", "exec", "history", "images", "info",
1414
"inspect", "kill", "login", "logout", "logs",
15-
"port", "ps", "rename", "restart", "rm", "rmi",
16-
"run", "search", "start", "stop", "tag", "top",
17-
"version", "wait",
15+
"port", "products", "ps", "rename", "restart",
16+
"rm", "rmi", "run", "search", "start", "stop",
17+
"tag", "top", "version", "wait",
1818
}
1919
secretCommands = []string{
2020
"_patch", "_completion", "_flush-cache", "_userdata", "_billing",

pkg/commands/products.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (C) 2015 Scaleway. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE.md file.
4+
5+
package commands
6+
7+
import (
8+
"fmt"
9+
"sort"
10+
11+
"github.com/dustin/go-humanize"
12+
"github.com/scaleway/scaleway-cli/pkg/api"
13+
)
14+
15+
// ProductsArgs are flags for the `RunProducts` function
16+
type ProductsArgs struct {
17+
Short bool
18+
Products []string
19+
}
20+
21+
// DisplayServerFunc
22+
type displayServerFunc func(CommandContext, *api.ScalewayProductsServers)
23+
24+
// RunProducts is the handler for 'scw products'
25+
func RunProducts(ctx CommandContext, args ProductsArgs) error {
26+
for _, product := range args.Products {
27+
switch product {
28+
case "servers":
29+
products, err := ctx.API.GetProductsServers()
30+
if err != nil {
31+
return fmt.Errorf("Unable to fetch products from the Scaleway API: %v", err)
32+
}
33+
34+
var displayFunc displayServerFunc = DisplayServerFull
35+
if args.Short {
36+
displayFunc = DisplayServerShort
37+
}
38+
displayFunc(ctx, products)
39+
default:
40+
return fmt.Errorf("Unknow product '%v'", product)
41+
}
42+
}
43+
44+
return nil
45+
}
46+
47+
// DisplayServerShort only display the product name
48+
func DisplayServerShort(ctx CommandContext, products *api.ScalewayProductsServers) {
49+
for name := range products.Servers {
50+
fmt.Fprintf(ctx.Stdout, "%v\n", name)
51+
}
52+
}
53+
54+
// DisplayServerFull only display the server product information
55+
func DisplayServerFull(ctx CommandContext, products *api.ScalewayProductsServers) {
56+
fmt.Fprintf(ctx.Stdout, "%-12s %8s %8s %8s %10s\n",
57+
"COMMERCIAL TYPE", "ARCH", "CPUs", "RAM", "BAREMETAL")
58+
59+
names := make([]string, len(products.Servers))
60+
i := 0
61+
for k := range products.Servers {
62+
names[i] = k
63+
i++
64+
}
65+
sort.Strings(names)
66+
67+
for _, name := range names {
68+
offer := products.Servers[name]
69+
70+
fmt.Fprintf(ctx.Stdout, "%-15s %8s %8d %8s %10t\n",
71+
name, offer.Arch, offer.Ncpus, humanize.Bytes(offer.Ram), offer.Baremetal)
72+
}
73+
}

0 commit comments

Comments
 (0)