2016-02-15 00:18:56 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"github.com/digitalocean/godo"
|
2016-02-26 00:33:53 -06:00
|
|
|
"time"
|
2016-02-15 00:18:56 -06:00
|
|
|
)
|
|
|
|
|
2016-02-26 00:33:53 -06:00
|
|
|
const DROPLET_NS = "dospin-"
|
|
|
|
|
2016-02-15 00:18:56 -06:00
|
|
|
type DropletManager struct {
|
|
|
|
client *godo.Client
|
|
|
|
settings Settings
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDropletManager(client *godo.Client, settings Settings) *DropletManager {
|
|
|
|
retval := new(DropletManager)
|
|
|
|
retval.client = client
|
|
|
|
retval.settings = settings
|
|
|
|
return retval
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Gets the Droplet if it already exists, instantiates it if it does not.
|
|
|
|
*/
|
|
|
|
func (me *DropletManager) SpinupMachine(name string) (string, error) {
|
|
|
|
if droplet, err := me.getDroplet(name); err == nil {
|
|
|
|
return droplet.PrivateIPv4()
|
|
|
|
} else {
|
|
|
|
image, err := me.getSnapshot(name)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
vd := me.settings.VirtualDroplets[name]
|
|
|
|
createRequest := &godo.DropletCreateRequest{
|
2016-02-26 00:33:53 -06:00
|
|
|
Name: DROPLET_NS + name,
|
|
|
|
Region: vd.Region,
|
|
|
|
Size: vd.Size,
|
|
|
|
PrivateNetworking: true,
|
2016-02-15 00:18:56 -06:00
|
|
|
Image: godo.DropletCreateImage{
|
|
|
|
ID: image.ID,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:33:53 -06:00
|
|
|
_, _, err = me.client.Droplets.Create(createRequest)
|
2016-02-15 00:18:56 -06:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:33:53 -06:00
|
|
|
// get the private IP and return it
|
|
|
|
ip := ""
|
|
|
|
for {
|
|
|
|
droplet, err = me.getDroplet(name)
|
|
|
|
ip, err = droplet.PrivateIPv4()
|
|
|
|
if ip != "" || (err != nil && err.Error() != "no networks have been defined") {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
}
|
|
|
|
return ip, err
|
2016-02-15 00:18:56 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (me *DropletManager) getDroplet(name string) (godo.Droplet, error) {
|
2016-02-26 00:33:53 -06:00
|
|
|
name = DROPLET_NS + name
|
2016-02-15 00:18:56 -06:00
|
|
|
page := 0
|
|
|
|
perPage := 200
|
|
|
|
var droplet godo.Droplet
|
|
|
|
for {
|
|
|
|
page++
|
|
|
|
// get list of droplets
|
|
|
|
opt := &godo.ListOptions{
|
|
|
|
Page: page,
|
|
|
|
PerPage: perPage,
|
|
|
|
}
|
|
|
|
images, _, err := me.client.Droplets.List(opt)
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
// find droplet
|
|
|
|
for _, a := range images {
|
|
|
|
if a.Name == name {
|
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// check next page?
|
|
|
|
if len(images) < perPage {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2016-02-26 00:33:53 -06:00
|
|
|
return droplet, errors.New("Could not find droplet: " + name)
|
2016-02-15 00:18:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (me *DropletManager) getSnapshot(name string) (godo.Image, error) {
|
2016-02-26 00:33:53 -06:00
|
|
|
name = DROPLET_NS + name
|
2016-02-15 00:18:56 -06:00
|
|
|
page := 0
|
|
|
|
perPage := 200
|
|
|
|
var image godo.Image
|
2016-02-26 00:33:53 -06:00
|
|
|
var err error
|
2016-02-15 00:18:56 -06:00
|
|
|
for {
|
|
|
|
page++
|
2016-02-26 00:33:53 -06:00
|
|
|
|
2016-02-15 00:18:56 -06:00
|
|
|
// get list of images
|
|
|
|
opt := &godo.ListOptions{
|
|
|
|
Page: page,
|
|
|
|
PerPage: perPage,
|
|
|
|
}
|
|
|
|
images, _, err := me.client.Images.ListUser(opt)
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
2016-02-26 00:33:53 -06:00
|
|
|
|
2016-02-15 00:18:56 -06:00
|
|
|
// find image
|
|
|
|
for _, a := range images {
|
|
|
|
if a.Name == name {
|
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
}
|
2016-02-26 00:33:53 -06:00
|
|
|
|
2016-02-15 00:18:56 -06:00
|
|
|
// check next page?
|
|
|
|
if len(images) < perPage {
|
2016-02-26 00:33:53 -06:00
|
|
|
err = errors.New("Could not find image: " + name)
|
2016-02-15 00:18:56 -06:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2016-02-26 00:33:53 -06:00
|
|
|
return image, err
|
2016-02-15 00:18:56 -06:00
|
|
|
}
|