digitalocean: support multiple droplets

This commit is contained in:
andrewsykim 2018-03-18 17:32:34 -04:00
parent fcd010044b
commit cc67ea84bd
2 changed files with 56 additions and 21 deletions

View File

@ -46,11 +46,15 @@ func (d *DropletBuilder) Build(c *fi.ModelBuilderContext) error {
// replace "." with "-" since DO API does not accept "."
clusterTag := "KubernetesCluster:" + strings.Replace(d.ClusterName(), ".", "-", -1)
// In the future, DigitalOcean will use Machine API to manage groups,
// for now create d.InstanceGroups.Spec.MinSize amount of droplets
for _, ig := range d.InstanceGroups {
name := d.AutoscalingGroupName(ig)
var droplet dotasks.Droplet
droplet.Count = int(fi.Int32Value(ig.Spec.MinSize))
droplet.Name = fi.String(name)
// during alpha support we only allow 1 region
// validation for only 1 region is done at this point
droplet.Region = fi.String(d.Cluster.Spec.Subnets[0].Region)

View File

@ -18,7 +18,7 @@ package dotasks
import (
"context"
"strconv"
"errors"
"github.com/digitalocean/godo"
@ -29,9 +29,10 @@ import (
)
//go:generate fitask -type=Droplet
// Droplet represents a group of droplets. In the future it
// will be managed by the Machines API
type Droplet struct {
Name *string
ID *string
Lifecycle *fi.Lifecycle
Region *string
@ -39,13 +40,14 @@ type Droplet struct {
Image *string
SSHKey *string
Tags []string
Count int
UserData *fi.ResourceHolder
}
var _ fi.CompareWithID = &Droplet{}
func (d *Droplet) CompareWithID() *string {
return d.ID
return d.Name
}
func (d *Droplet) Find(c *fi.Context) (*Droplet, error) {
@ -57,20 +59,32 @@ func (d *Droplet) Find(c *fi.Context) (*Droplet, error) {
return nil, err
}
found := false
count := 0
var foundDroplet godo.Droplet
for _, droplet := range droplets {
if droplet.Name == fi.StringValue(d.Name) {
return &Droplet{
Name: fi.String(droplet.Name),
ID: fi.String(strconv.Itoa(droplet.ID)),
Region: fi.String(droplet.Region.Slug),
Size: fi.String(droplet.Size.Slug),
Image: fi.String(droplet.Image.Slug),
Lifecycle: d.Lifecycle,
}, nil
found = true
count++
foundDroplet = droplet
}
}
return nil, nil
if !found {
return nil, nil
}
return &Droplet{
Name: fi.String(foundDroplet.Name),
Count: count,
Region: fi.String(foundDroplet.Region.Slug),
Size: fi.String(foundDroplet.Size.Slug),
Image: fi.String(foundDroplet.Image.Slug),
Tags: foundDroplet.Tags,
SSHKey: d.SSHKey, // TODO: get from droplet or ignore change
UserData: d.UserData, // TODO: get from droplet or ignore change
Lifecycle: d.Lifecycle,
}, nil
}
func (d *Droplet) Run(c *fi.Context) error {
@ -78,18 +92,38 @@ func (d *Droplet) Run(c *fi.Context) error {
}
func (_ *Droplet) RenderDO(t *do.DOAPITarget, a, e, changes *Droplet) error {
if a != nil {
return nil
}
userData, err := e.UserData.AsString()
if err != nil {
return err
}
var newDropletCount int
if a == nil {
newDropletCount = e.Count
} else {
expectedCount := e.Count
actualCount := a.Count
if expectedCount == actualCount {
return nil
}
if actualCount > expectedCount {
return errors.New("deleting droplets is not supported yet")
}
newDropletCount = expectedCount - actualCount
}
var dropletNames []string
for i := 0; i < newDropletCount; i++ {
dropletNames = append(dropletNames, fi.StringValue(e.Name))
}
dropletService := t.Cloud.Droplets()
_, _, err = dropletService.Create(context.TODO(), &godo.DropletCreateRequest{
Name: fi.StringValue(e.Name),
_, _, err = dropletService.CreateMultiple(context.TODO(), &godo.DropletMultiCreateRequest{
Names: dropletNames,
Region: fi.StringValue(e.Region),
Size: fi.StringValue(e.Size),
Image: godo.DropletCreateImage{Slug: fi.StringValue(e.Image)},
@ -106,9 +140,6 @@ func (_ *Droplet) CheckChanges(a, e, changes *Droplet) error {
if changes.Name != nil {
return fi.CannotChangeField("Name")
}
if changes.ID != nil {
return fi.CannotChangeField("ID")
}
if changes.Region != nil {
return fi.CannotChangeField("Region")
}