Skip to content

Commit

Permalink
Merge pull request #23 from src-d/resource-failover-ip
Browse files Browse the repository at this point in the history
Add resource online_failover_ip
  • Loading branch information
meyskens authored Oct 3, 2018
2 parents fef1af5 + 4404219 commit 264fe26
Show file tree
Hide file tree
Showing 6 changed files with 390 additions and 2 deletions.
4 changes: 4 additions & 0 deletions online/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ type Client interface {

GetRescueImages(serverID int) ([]string, error)

EditFailoverIP(source, destination string) error
GenerateMACFailoverIP(address, macType string) (string, error)
DeleteMACFailoverIP(address string) error

ListRPNv2() ([]*RPNv2, error)
RPNv2(id int) (*RPNv2, error)
RPNv2ByName(name string) (*RPNv2, error)
Expand Down
43 changes: 43 additions & 0 deletions online/failover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package online

import (
"fmt"
)

func (c *client) EditFailoverIP(source, destination string) error {
target := fmt.Sprintf("%s/failover/edit", serverEndPoint)
_, err := c.doPOST(target, map[string]string{
"source": source,
"destination": destination,
})
if err != nil {
return err
}

return nil
}

func (c *client) GenerateMACFailoverIP(address, macType string) (string, error) {
target := fmt.Sprintf("%s/failover/generateMac", serverEndPoint)
body, err := c.doPOST(target, map[string]string{
"address": address,
"type": macType,
})
if err != nil {
return "", err
}

return string(body), nil
}

func (c *client) DeleteMACFailoverIP(address string) error {
target := fmt.Sprintf("%s/failover/deleteMac", serverEndPoint)
_, err := c.doPOST(target, map[string]string{
"address": address,
})
if err != nil {
return err
}

return nil
}
18 changes: 18 additions & 0 deletions online/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,21 @@ func (o *OnlineClientMock) BootNormalMode(serverID int) error {
args := o.Called(serverID)
return args.Error(0)
}

// EditFailoverIP is a mock call
func (o *OnlineClientMock) EditFailoverIP(source, destination string) error {
args := o.Called(source, destination)
return args.Error(0)
}

// GenerateMACFailoverIP is a mock call
func (o *OnlineClientMock) GenerateMACFailoverIP(address, macType string) (string, error) {
args := o.Called(address, macType)
return args.String(0), args.Error(1)
}

// DeleteMACFailoverIP is a mock call
func (o *OnlineClientMock) DeleteMACFailoverIP(address string) error {
args := o.Called(address)
return args.Error(0)
}
5 changes: 3 additions & 2 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ func Provider() terraform.ResourceProvider {
},
},
ResourcesMap: map[string]*schema.Resource{
"online_server": resourceServer(),
"online_rpnv2": resourceRPNv2(),
"online_server": resourceServer(),
"online_rpnv2": resourceRPNv2(),
"online_failover_ip": resourceFailoverIP(),
},
DataSourcesMap: map[string]*schema.Resource{
"online_rescue_image": dataRescueImage(),
Expand Down
192 changes: 192 additions & 0 deletions provider/resource_failover_ip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package provider

import (
"errors"
"strings"

"github.com/hashicorp/terraform/helper/schema"
"github.com/src-d/terraform-provider-online-net/online"
)

func resourceFailoverIP() *schema.Resource {
return &schema.Resource{
Read: resourceFailoverIPRead,
Create: resourceFailoverIPCreate,
Delete: resourceFailoverIPDelete,
Update: resourceFailoverIPUpdate,
Schema: map[string]*schema.Schema{
"ip": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "the failover IP to modify",
},
"destination_server_id": {
Type: schema.TypeInt,
Optional: true,
Description: "The ID of the server to route the failover IP to",
ConflictsWith: []string{"destination_server_ip"},
},
"destination_server_ip": {
Type: schema.TypeString,
Optional: true,
Description: "The ID of the server to route the failover IP to",
ConflictsWith: []string{"destination_server_id"},
},
"generate_mac": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "should a virtual mac be created for the IP",
},
"generate_mac_type": {
Type: schema.TypeString,
Optional: true,
Description: "should a virtual mac be created for the IP",
Default: "kvm",
ValidateFunc: func(val interface{}, key string) (warns []string, errs []error) {
v := val.(string)
if v != "vmware" && v != "xen" && v != "kvm" && v != "" {
errs = append(errs, errors.New("generate_mac_type must be either vmware, xen or kvm"))
}
return
},
},
"mac": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: "the generated mac",
},
},
}
}

func resourceFailoverIPRead(d *schema.ResourceData, meta interface{}) error {
ip := d.Get("ip").(string)
d.SetId(ip)

return nil
}

func resourceFailoverIPCreate(d *schema.ResourceData, meta interface{}) error {
c := meta.(online.Client)

ip := d.Get("ip").(string)
serverIDInterface, hasServerID := d.GetOk("destination_server_id")
serverIPInterface, hasServerIP := d.GetOk("destination_server_ip")
generateMac := d.Get("generate_mac").(bool)
macType := d.Get("generate_mac_type").(string)

dstIP := ""

if hasServerIP {
dstIP = serverIPInterface.(string)
}

if hasServerID {
server, err := c.Server(serverIDInterface.(int))
if err != nil {
return err
}
dstIP = server.InterfaceByType(online.Public).Address
}

err := c.EditFailoverIP(ip, dstIP)
if err != nil && !strings.Contains(err.Error(), "Address already provisioned") {
return err
}

if generateMac {
mac, err := c.GenerateMACFailoverIP(ip, macType)
if err != nil {
return err
}
d.Set("mac", mac)
}

d.SetId(ip)
return nil
}

func resourceFailoverIPDelete(d *schema.ResourceData, meta interface{}) error {
ip := d.Get("ip").(string)
_, macExists := d.GetOkExists("mac")
c := meta.(online.Client)

if macExists {
err := c.DeleteMACFailoverIP(ip)
if err != nil {
return err
}
d.Set("mac", "")
}

err := c.EditFailoverIP(ip, "")
return err
}

func resourceFailoverIPUpdate(d *schema.ResourceData, meta interface{}) error {
ip := d.Get("ip").(string)
c := meta.(online.Client)

hasNewMACRequest := d.HasChange("generate_mac")

hasNewServerID := d.HasChange("destination_server_id")
hasNewServerIP := d.HasChange("destination_server_ip")

if hasNewServerID && hasNewServerIP {
// we switched here!
_, hasdID := d.GetOkExists("destination_server_id")
_, hasIP := d.GetOkExists("destination_server_ip")
serverID := d.Get("destination_server_id").(int)

// make sure the next steps will use the correct key
if hasdID && serverID != 0 {
hasNewServerIP = false
} else if hasIP {
hasNewServerID = false
}
}

if hasNewServerID {
serverID := d.Get("destination_server_id").(int)
server, err := c.Server(serverID)
if err != nil {
return err
}

dstIP := server.InterfaceByType(online.Public).Address
err = c.EditFailoverIP(ip, dstIP)
if err != nil {
return err
}
} else if hasNewServerIP {
dstIP := d.Get("destination_server_ip").(string)
err := c.EditFailoverIP(ip, dstIP)
if err != nil {
return err
}
}

if hasNewMACRequest {
// we need to enable or disable the generated MAC
_, newValue := d.GetChange("generate_mac")
if newValue.(bool) {
macType := d.Get("generate_mac_type").(string)
mac, err := c.GenerateMACFailoverIP(ip, macType)
if err != nil {
return err
}

d.Set("mac", mac)
} else {
err := c.DeleteMACFailoverIP(ip)
if err != nil {
return err
}
}
}

return nil
}
Loading

0 comments on commit 264fe26

Please sign in to comment.