terraform/builtin/providers/oneandone/resource_oneandone_vpn.go

218 lines
4.3 KiB
Go

package oneandone
import (
"crypto/md5"
"encoding/base64"
"fmt"
"github.com/1and1/oneandone-cloudserver-sdk-go"
"github.com/hashicorp/terraform/helper/schema"
"io"
"os"
fp "path/filepath"
"strings"
)
func resourceOneandOneVPN() *schema.Resource {
return &schema.Resource{
Create: resourceOneandOneVPNCreate,
Read: resourceOneandOneVPNRead,
Update: resourceOneandOneVPNUpdate,
Delete: resourceOneandOneVPNDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"download_path": {
Type: schema.TypeString,
Computed: true,
},
"datacenter": {
Type: schema.TypeString,
Optional: true,
},
"file_name": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceOneandOneVPNCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
var datacenter string
if raw, ok := d.GetOk("datacenter"); ok {
dcs, err := config.API.ListDatacenters()
if err != nil {
return fmt.Errorf("An error occured while fetching list of datacenters %s", err)
}
decenter := raw.(string)
for _, dc := range dcs {
if strings.ToLower(dc.CountryCode) == strings.ToLower(decenter) {
datacenter = dc.Id
break
}
}
}
var description string
if raw, ok := d.GetOk("description"); ok {
description = raw.(string)
}
vpn_id, vpn, err := config.API.CreateVPN(d.Get("name").(string), description, datacenter)
if err != nil {
return err
}
err = config.API.WaitForState(vpn, "ACTIVE", 10, config.Retries)
if err != nil {
return err
}
d.SetId(vpn_id)
return resourceOneandOneVPNRead(d, meta)
}
func resourceOneandOneVPNUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
if d.HasChange("name") || d.HasChange("description") {
vpn, err := config.API.ModifyVPN(d.Id(), d.Get("name").(string), d.Get("description").(string))
if err != nil {
return err
}
err = config.API.WaitForState(vpn, "ACTIVE", 10, config.Retries)
if err != nil {
return err
}
}
return resourceOneandOneVPNRead(d, meta)
}
func resourceOneandOneVPNRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
vpn, err := config.API.GetVPN(d.Id())
base64_str, err := config.API.GetVPNConfigFile(d.Id())
if err != nil {
if strings.Contains(err.Error(), "404") {
d.SetId("")
return nil
}
return err
}
var download_path string
if raw, ok := d.GetOk("download_path"); ok {
download_path = raw.(string)
}
path, fileName, err := writeCofnig(vpn, download_path, base64_str)
if err != nil {
return err
}
d.Set("name", vpn.Name)
d.Set("description", vpn.Description)
d.Set("download_path", path)
d.Set("file_name", fileName)
d.Set("datacenter", vpn.Datacenter.CountryCode)
return nil
}
func writeCofnig(vpn *oneandone.VPN, path, base64config string) (string, string, error) {
data, err := base64.StdEncoding.DecodeString(base64config)
if err != nil {
return "", "", err
}
var fileName string
if vpn.CloudPanelId != "" {
fileName = vpn.CloudPanelId + ".zip"
} else {
fileName = "vpn_" + fmt.Sprintf("%x", md5.Sum(data)) + ".zip"
}
if path == "" {
path, err = os.Getwd()
if err != nil {
return "", "", err
}
}
if !fp.IsAbs(path) {
path, err = fp.Abs(path)
if err != nil {
return "", "", err
}
}
_, err = os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
// make all dirs
os.MkdirAll(path, 0666)
} else {
return "", "", err
}
}
fpath := fp.Join(path, fileName)
f, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY, 0666)
defer f.Close()
if err != nil {
return "", "", err
}
n, err := f.Write(data)
if err == nil && n < len(data) {
err = io.ErrShortWrite
}
if err != nil {
return "", "", err
}
return path, fileName, nil
}
func resourceOneandOneVPNDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
vpn, err := config.API.DeleteVPN(d.Id())
if err != nil {
return err
}
err = config.API.WaitUntilDeleted(vpn)
if err != nil {
return err
}
fullPath := fp.Join(d.Get("download_path").(string), d.Get("file_name").(string))
if _, err := os.Stat(fullPath); !os.IsNotExist(err) {
os.Remove(fullPath)
}
return nil
}