Skip to content
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
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ GOFMT ?= gofmt -w

NAME = scw
SRC = .
PACKAGES = api commands utils
REV = $(shell git rev-parse HEAD || echo "nogit")
TAG = $(shell git describe --tags --always || echo "nogit")
BUILDER = scaleway-cli-builder


BUILD_LIST = $(foreach int, $(SRC), $(int)_build)
CLEAN_LIST = $(foreach int, $(SRC), $(int)_clean)
CLEAN_LIST = $(foreach int, $(SRC) $(PACKAGES), $(int)_clean)
INSTALL_LIST = $(foreach int, $(SRC), $(int)_install)
IREF_LIST = $(foreach int, $(SRC), $(int)_iref)
TEST_LIST = $(foreach int, $(SRC), $(int)_test)
FMT_LIST = $(foreach int, $(SRC), $(int)_fmt)
IREF_LIST = $(foreach int, $(SRC) $(PACKAGES), $(int)_iref)
TEST_LIST = $(foreach int, $(SRC) $(PACKAGES), $(int)_test)
FMT_LIST = $(foreach int, $(SRC) $(PACKAGES), $(int)_fmt)


.PHONY: $(CLEAN_LIST) $(TEST_LIST) $(FMT_LIST) $(INSTALL_LIST) $(BUILD_LIST) $(IREF_LIST)
Expand Down Expand Up @@ -84,3 +85,8 @@ travis_install:

travis_run: build
go test -v -covermode=count -coverprofile=profile.cov


golint:
@go get github.com/golang/lint/golint
@for dir in */; do golint $$dir; done
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ Development in progress

#### Fixes

* The project is now `go get`-able
* The project is now `go get`-able and splitted into packages
* Added timeout when polling SSH TCP port for `scw start -w` and `scw exec -w` ([#46](https://github.com/scaleway/scaleway-cli/issues/46))
* Improved resolver behavior for exact matching ([#53](https://github.com/scaleway/scaleway-cli/issues/53), [#55](https://github.com/scaleway/scaleway-cli/issues/55))
* Verbose error message when `scw exec` fails ([#42](https://github.com/scaleway/scaleway-cli/issues/42))
Expand Down
6 changes: 6 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Scaleway's API

This package contains facilities to play with the Scaleway API, in includes the following features:

- dedicated configuration file containing credentials to deal with the API
- caching to resolve UUIDs without contacting the API
5 changes: 3 additions & 2 deletions api.go → api/api.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package api

import (
"bytes"
Expand Down Expand Up @@ -452,7 +452,8 @@ type ScalewayImageDefinition struct {
Arch string `json:"arch"`
}

var funcMap = template.FuncMap{
// FuncMap used for json inspection
var FuncMap = template.FuncMap{
"json": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
Expand Down
31 changes: 8 additions & 23 deletions cache.go → api/cache.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package api

import (
"encoding/json"
Expand All @@ -9,6 +9,8 @@ import (
"strings"
"sync"

"github.com/scaleway/scaleway-cli/utils"

"code.google.com/p/go-uuid/uuid"
)

Expand Down Expand Up @@ -160,7 +162,7 @@ func (c *ScalewayCache) LookUpImages(needle string, acceptUUID bool) []string {
return exactMatches
}

return RemoveDuplicates(res)
return utils.RemoveDuplicates(res)
}

// LookUpSnapshots attempts to return identifiers matching a pattern
Expand Down Expand Up @@ -190,7 +192,7 @@ func (c *ScalewayCache) LookUpSnapshots(needle string, acceptUUID bool) []string
return exactMatches
}

return RemoveDuplicates(res)
return utils.RemoveDuplicates(res)
}

// LookUpVolumes attempts to return identifiers matching a pattern
Expand Down Expand Up @@ -219,7 +221,7 @@ func (c *ScalewayCache) LookUpVolumes(needle string, acceptUUID bool) []string {
return exactMatches
}

return RemoveDuplicates(res)
return utils.RemoveDuplicates(res)
}

// LookUpBootscripts attempts to return identifiers matching a pattern
Expand Down Expand Up @@ -248,7 +250,7 @@ func (c *ScalewayCache) LookUpBootscripts(needle string, acceptUUID bool) []stri
return exactMatches
}

return RemoveDuplicates(res)
return utils.RemoveDuplicates(res)
}

// LookUpServers attempts to return identifiers matching a pattern
Expand Down Expand Up @@ -277,7 +279,7 @@ func (c *ScalewayCache) LookUpServers(needle string, acceptUUID bool) []string {
return exactMatches
}

return RemoveDuplicates(res)
return utils.RemoveDuplicates(res)
}

// LookUpIdentifiers attempts to return identifiers matching a pattern
Expand Down Expand Up @@ -322,23 +324,6 @@ func (c *ScalewayCache) LookUpIdentifiers(needle string) []ScalewayIdentifier {
return results
}

// RemoveDuplicates transforms an array into a unique array
func RemoveDuplicates(elements []string) []string {
encountered := map[string]bool{}

// Create a map of all unique elements.
for v := range elements {
encountered[elements[v]] = true
}

// Place all keys from the map into a slice.
result := []string{}
for key := range encountered {
result = append(result, key)
}
return result
}

// InsertServer registers a server in the cache
func (c *ScalewayCache) InsertServer(identifier, name string) {
c.Lock.Lock()
Expand Down
74 changes: 39 additions & 35 deletions api_helpers.go → api/helpers.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package api

import (
"fmt"
Expand All @@ -10,8 +10,29 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/dustin/go-humanize"
"github.com/scaleway/scaleway-cli/utils"
)

// ScalewayResolvedIdentifier represents a list of matching identifier for a specifier pattern
type ScalewayResolvedIdentifier struct {
// Identifiers holds matching identifiers
Identifiers []ScalewayIdentifier

// Needle is the criteria used to lookup identifiers
Needle string
}

// ScalewayImageInterface is an interface to multiple Scaleway items
type ScalewayImageInterface struct {
CreationDate time.Time
Identifier string
Name string
Tag string
VirtualSize float64
Public bool
Type string
}

// CreateVolumeFromHumanSize creates a volume on the API with a human readable size
func CreateVolumeFromHumanSize(api *ScalewayAPI, size string) (*string, error) {
bytes, err := humanize.ParseBytes(size)
Expand All @@ -32,15 +53,6 @@ func CreateVolumeFromHumanSize(api *ScalewayAPI, size string) (*string, error) {
return &volumeID, nil
}

// ScalewayResolvedIdentifier represents a list of matching identifier for a specifier pattern
type ScalewayResolvedIdentifier struct {
// Identifiers holds matching identifiers
Identifiers []ScalewayIdentifier

// Needle is the criteria used to lookup identifiers
Needle string
}

// fillIdentifierCache fills the cache by fetching fro the API
func fillIdentifierCache(api *ScalewayAPI) {
log.Debugf("Filling the cache")
Expand Down Expand Up @@ -69,9 +81,9 @@ func fillIdentifierCache(api *ScalewayAPI) {
wg.Wait()
}

// getIdentifier returns a an identifier if the resolved needles only match one element, else, it exists the program
func getIdentifier(api *ScalewayAPI, needle string) *ScalewayIdentifier {
idents := resolveIdentifier(api, needle)
// GetIdentifier returns a an identifier if the resolved needles only match one element, else, it exists the program
func GetIdentifier(api *ScalewayAPI, needle string) *ScalewayIdentifier {
idents := ResolveIdentifier(api, needle)

if len(idents) == 1 {
return &idents[0]
Expand All @@ -88,8 +100,8 @@ func getIdentifier(api *ScalewayAPI, needle string) *ScalewayIdentifier {
return nil
}

// resolveIdentifier resolves needle provided by the user
func resolveIdentifier(api *ScalewayAPI, needle string) []ScalewayIdentifier {
// ResolveIdentifier resolves needle provided by the user
func ResolveIdentifier(api *ScalewayAPI, needle string) []ScalewayIdentifier {
idents := api.Cache.LookUpIdentifiers(needle)
if len(idents) > 0 {
return idents
Expand All @@ -101,8 +113,8 @@ func resolveIdentifier(api *ScalewayAPI, needle string) []ScalewayIdentifier {
return idents
}

// resolveIdentifiers resolves needles provided by the user
func resolveIdentifiers(api *ScalewayAPI, needles []string, out chan ScalewayResolvedIdentifier) {
// ResolveIdentifiers resolves needles provided by the user
func ResolveIdentifiers(api *ScalewayAPI, needles []string, out chan ScalewayResolvedIdentifier) {
// first attempt, only lookup from the cache
var unresolved []string
for _, needle := range needles {
Expand Down Expand Up @@ -131,8 +143,8 @@ func resolveIdentifiers(api *ScalewayAPI, needles []string, out chan ScalewayRes
close(out)
}

// inspectIdentifiers inspects identifiers concurrently
func inspectIdentifiers(api *ScalewayAPI, ci chan ScalewayResolvedIdentifier, cj chan interface{}) {
// InspectIdentifiers inspects identifiers concurrently
func InspectIdentifiers(api *ScalewayAPI, ci chan ScalewayResolvedIdentifier, cj chan interface{}) {
var wg sync.WaitGroup
for {
idents, ok := <-ci
Expand Down Expand Up @@ -187,7 +199,8 @@ func inspectIdentifiers(api *ScalewayAPI, ci chan ScalewayResolvedIdentifier, cj
close(cj)
}

func createServer(api *ScalewayAPI, imageName string, name string, bootscript string, env string, additionalVolumes string) (string, error) {
// CreateServer creates a server using API based on typical server fields
func CreateServer(api *ScalewayAPI, imageName string, name string, bootscript string, env string, additionalVolumes string) (string, error) {
if name == "" {
name = strings.Replace(namesgenerator.GetRandomName(0), "_", "-", -1)
}
Expand Down Expand Up @@ -268,33 +281,23 @@ func WaitForServerReady(api *ScalewayAPI, serverID string) (*ScalewayServer, err

dest := fmt.Sprintf("%s:22", server.PublicAddress.IP)

err = WaitForTCPPortOpen(dest)
err = utils.WaitForTCPPortOpen(dest)
if err != nil {
return nil, err
}

return server, nil
}

// ScalewayImageInterface is an interface to multiple Scaleway items
type ScalewayImageInterface struct {
CreationDate time.Time
Identifier string
Name string
Tag string
VirtualSize float64
Public bool
Type string
}

// ByCreationDate sorts images by CreationDate field
type ByCreationDate []ScalewayImageInterface

func (a ByCreationDate) Len() int { return len(a) }
func (a ByCreationDate) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByCreationDate) Less(i, j int) bool { return a[j].CreationDate.Before(a[i].CreationDate) }

func startServer(api *ScalewayAPI, needle string, wait bool) error {
// StartServer start a server based on its needle, can optionaly block while server is booting
func StartServer(api *ScalewayAPI, needle string, wait bool) error {
server := api.GetServerID(needle)

err := api.PostServerAction(server, "poweron")
Expand All @@ -313,8 +316,9 @@ func startServer(api *ScalewayAPI, needle string, wait bool) error {
return nil
}

func startServerOnce(api *ScalewayAPI, needle string, wait bool, successChan chan bool, errChan chan error) {
err := startServer(api, needle, wait)
// StartServerOnce wraps StartServer for golang channel
func StartServerOnce(api *ScalewayAPI, needle string, wait bool, successChan chan bool, errChan chan error) {
err := StartServer(api, needle, wait)

if err != nil {
errChan <- err
Expand Down
13 changes: 13 additions & 0 deletions api/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package api

// Config is a Scaleway CLI configuration file
type Config struct {
// APIEndpoint is the endpoint to the Scaleway API
APIEndPoint string `json:"api_endpoint"`

// Organization is the identifier of the Scaleway orgnization
Organization string `json:"organization"`

// Token is the authentication token for the Scaleway organization
Token string `json:"token"`
}
Loading