Provider Oneandone (#13633)
* Terraform Provider 1&1 * Addressing pull request remarks * Fixed imports * Fixing remarks * Test optimiziation
This commit is contained in:
parent
525a21a104
commit
61499cfcf0
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=countHookAction hook_count_action.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=countHookAction hook_count_action.go"; DO NOT EDIT
|
||||||
|
|
||||||
package local
|
package local
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=OperationType operation_type.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=OperationType operation_type.go"; DO NOT EDIT
|
||||||
|
|
||||||
package backend
|
package backend
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Token string
|
||||||
|
Retries int
|
||||||
|
Endpoint string
|
||||||
|
API *oneandone.API
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) Client() (*Config, error) {
|
||||||
|
token := oneandone.SetToken(c.Token)
|
||||||
|
|
||||||
|
if len(c.Endpoint) > 0 {
|
||||||
|
c.API = oneandone.New(token, c.Endpoint)
|
||||||
|
} else {
|
||||||
|
c.API = oneandone.New(token, oneandone.BaseUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Provider() terraform.ResourceProvider {
|
||||||
|
return &schema.Provider{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"token": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("ONEANDONE_TOKEN", nil),
|
||||||
|
Description: "1&1 token for API operations.",
|
||||||
|
},
|
||||||
|
"retries": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: 50,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("ONEANDONE_RETRIES", nil),
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: oneandone.BaseUrl,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("ONEANDONE_ENDPOINT", nil),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
"oneandone_server": resourceOneandOneServer(),
|
||||||
|
"oneandone_firewall_policy": resourceOneandOneFirewallPolicy(),
|
||||||
|
"oneandone_private_network": resourceOneandOnePrivateNetwork(),
|
||||||
|
"oneandone_public_ip": resourceOneandOnePublicIp(),
|
||||||
|
"oneandone_shared_storage": resourceOneandOneSharedStorage(),
|
||||||
|
"oneandone_monitoring_policy": resourceOneandOneMonitoringPolicy(),
|
||||||
|
"oneandone_loadbalancer": resourceOneandOneLoadbalancer(),
|
||||||
|
"oneandone_vpn": resourceOneandOneVPN(),
|
||||||
|
},
|
||||||
|
ConfigureFunc: providerConfigure,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||||
|
var endpoint string
|
||||||
|
if d.Get("endpoint").(string) != oneandone.BaseUrl {
|
||||||
|
endpoint = d.Get("endpoint").(string)
|
||||||
|
}
|
||||||
|
config := Config{
|
||||||
|
Token: d.Get("token").(string),
|
||||||
|
Retries: d.Get("retries").(int),
|
||||||
|
Endpoint: endpoint,
|
||||||
|
}
|
||||||
|
return config.Client()
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
var testAccProviders map[string]terraform.ResourceProvider
|
||||||
|
var testAccProvider *schema.Provider
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testAccProvider = Provider().(*schema.Provider)
|
||||||
|
testAccProviders = map[string]terraform.ResourceProvider{
|
||||||
|
"oneandone": testAccProvider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider(t *testing.T) {
|
||||||
|
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_impl(t *testing.T) {
|
||||||
|
var _ terraform.ResourceProvider = Provider()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccPreCheck(t *testing.T) {
|
||||||
|
if v := os.Getenv("ONEANDONE_TOKEN"); v == "" {
|
||||||
|
t.Fatal("ONEANDONE_TOKEN must be set for acceptance tests")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,274 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/helper/validation"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOneFirewallPolicy() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
|
||||||
|
Create: resourceOneandOneFirewallCreate,
|
||||||
|
Read: resourceOneandOneFirewallRead,
|
||||||
|
Update: resourceOneandOneFirewallUpdate,
|
||||||
|
Delete: resourceOneandOneFirewallDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"protocol": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"port_from": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
ValidateFunc: validation.IntBetween(1, 65535),
|
||||||
|
},
|
||||||
|
"port_to": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
ValidateFunc: validation.IntBetween(1, 65535),
|
||||||
|
},
|
||||||
|
"source_ip": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneFirewallCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
req := oneandone.FirewallPolicyRequest{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if desc, ok := d.GetOk("description"); ok {
|
||||||
|
req.Description = desc.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Rules = getRules(d)
|
||||||
|
|
||||||
|
fw_id, fw, err := config.API.CreateFirewallPolicy(&req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(fw, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(fw_id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneFirewallRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneFirewallUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
if d.HasChange("name") || d.HasChange("description") {
|
||||||
|
fw, err := config.API.UpdateFirewallPolicy(d.Id(), d.Get("name").(string), d.Get("description").(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(fw, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("rules") {
|
||||||
|
oldR, newR := d.GetChange("rules")
|
||||||
|
oldValues := oldR.([]interface{})
|
||||||
|
newValues := newR.([]interface{})
|
||||||
|
if len(oldValues) > len(newValues) {
|
||||||
|
diff := difference(oldValues, newValues)
|
||||||
|
for _, old := range diff {
|
||||||
|
o := old.(map[string]interface{})
|
||||||
|
if o["id"] != nil {
|
||||||
|
old_id := o["id"].(string)
|
||||||
|
fw, err := config.API.DeleteFirewallPolicyRule(d.Id(), old_id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(fw, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var rules []oneandone.FirewallPolicyRule
|
||||||
|
|
||||||
|
for _, raw := range newValues {
|
||||||
|
rl := raw.(map[string]interface{})
|
||||||
|
|
||||||
|
if rl["id"].(string) == "" {
|
||||||
|
rule := oneandone.FirewallPolicyRule{
|
||||||
|
Protocol: rl["protocol"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl["port_from"] != nil {
|
||||||
|
rule.PortFrom = oneandone.Int2Pointer(rl["port_from"].(int))
|
||||||
|
}
|
||||||
|
if rl["port_to"] != nil {
|
||||||
|
rule.PortTo = oneandone.Int2Pointer(rl["port_to"].(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl["source_ip"] != nil {
|
||||||
|
rule.SourceIp = rl["source_ip"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rules) > 0 {
|
||||||
|
fw, err := config.API.AddFirewallPolicyRules(d.Id(), rules)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(fw, "ACTIVE", 10, config.Retries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneFirewallRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneFirewallRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
fw, err := config.API.GetFirewallPolicy(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("rules", readRules(d, fw.Rules))
|
||||||
|
d.Set("description", fw.Description)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneFirewallDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
fp, err := config.API.DeleteFirewallPolicy(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitUntilDeleted(fp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readRules(d *schema.ResourceData, rules []oneandone.FirewallPolicyRule) interface{} {
|
||||||
|
rawRules := d.Get("rules").([]interface{})
|
||||||
|
counter := 0
|
||||||
|
for _, rR := range rawRules {
|
||||||
|
if len(rules) > counter {
|
||||||
|
rawMap := rR.(map[string]interface{})
|
||||||
|
rawMap["id"] = rules[counter].Id
|
||||||
|
if rules[counter].SourceIp != "0.0.0.0" {
|
||||||
|
rawMap["source_ip"] = rules[counter].SourceIp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawRules
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRules(d *schema.ResourceData) []oneandone.FirewallPolicyRule {
|
||||||
|
var rules []oneandone.FirewallPolicyRule
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("rules"); ok {
|
||||||
|
rawRules := raw.([]interface{})
|
||||||
|
|
||||||
|
for _, raw := range rawRules {
|
||||||
|
rl := raw.(map[string]interface{})
|
||||||
|
rule := oneandone.FirewallPolicyRule{
|
||||||
|
Protocol: rl["protocol"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl["port_from"] != nil {
|
||||||
|
rule.PortFrom = oneandone.Int2Pointer(rl["port_from"].(int))
|
||||||
|
}
|
||||||
|
if rl["port_to"] != nil {
|
||||||
|
rule.PortTo = oneandone.Int2Pointer(rl["port_to"].(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl["source_ip"] != nil {
|
||||||
|
rule.SourceIp = rl["source_ip"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func difference(oldV, newV []interface{}) (toreturn []interface{}) {
|
||||||
|
var (
|
||||||
|
lenMin int
|
||||||
|
longest []interface{}
|
||||||
|
)
|
||||||
|
// Determine the shortest length and the longest slice
|
||||||
|
if len(oldV) < len(newV) {
|
||||||
|
lenMin = len(oldV)
|
||||||
|
longest = newV
|
||||||
|
} else {
|
||||||
|
lenMin = len(newV)
|
||||||
|
longest = oldV
|
||||||
|
}
|
||||||
|
// compare common indeces
|
||||||
|
for i := 0; i < lenMin; i++ {
|
||||||
|
if oldV[i] == nil || newV[i] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if oldV[i].(map[string]interface{})["id"] != newV[i].(map[string]interface{})["id"] {
|
||||||
|
toreturn = append(toreturn, newV) //out += fmt.Sprintf("=>\t%s\t%s\n", oldV[i], newV[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add indeces not in common
|
||||||
|
for _, v := range longest[lenMin:] {
|
||||||
|
//out += fmt.Sprintf("=>\t%s\n", v)
|
||||||
|
toreturn = append(toreturn, v)
|
||||||
|
}
|
||||||
|
return toreturn
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandoneFirewall_Basic(t *testing.T) {
|
||||||
|
var firewall oneandone.FirewallPolicy
|
||||||
|
|
||||||
|
name := "test"
|
||||||
|
name_updated := "test1"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandoneFirewallDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneFirewall_basic, name),
|
||||||
|
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneFirewallExists("oneandone_firewall_policy.fw", &firewall),
|
||||||
|
testAccCheckOneandoneFirewallAttributes("oneandone_firewall_policy.fw", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_firewall_policy.fw", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneFirewall_update, name_updated),
|
||||||
|
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneFirewallExists("oneandone_firewall_policy.fw", &firewall),
|
||||||
|
testAccCheckOneandoneFirewallAttributes("oneandone_firewall_policy.fw", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_firewall_policy.fw", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandoneFirewallDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_firewall_policy.fw" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetFirewallPolicy(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Firewall Policy still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandoneFirewallAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandoneFirewallExists(n string, fw_p *oneandone.FirewallPolicy) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_fw, err := api.GetFirewallPolicy(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching Firewall Policy: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_fw.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
fw_p = found_fw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandoneFirewall_basic = `
|
||||||
|
resource "oneandone_firewall_policy" "fw" {
|
||||||
|
name = "%s"
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 80
|
||||||
|
"port_to" = 80
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "ICMP"
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 43
|
||||||
|
"port_to" = 43
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 22
|
||||||
|
"port_to" = 22
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
const testAccCheckOneandoneFirewall_update = `
|
||||||
|
resource "oneandone_firewall_policy" "fw" {
|
||||||
|
name = "%s"
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 80
|
||||||
|
"port_to" = 80
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "ICMP"
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 43
|
||||||
|
"port_to" = 43
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 22
|
||||||
|
"port_to" = 22
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 88
|
||||||
|
"port_to" = 88
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}`
|
|
@ -0,0 +1,370 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/helper/validation"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOneLoadbalancer() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceOneandOneLoadbalancerCreate,
|
||||||
|
Read: resourceOneandOneLoadbalancerRead,
|
||||||
|
Update: resourceOneandOneLoadbalancerUpdate,
|
||||||
|
Delete: resourceOneandOneLoadbalancerDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validateMethod,
|
||||||
|
},
|
||||||
|
"datacenter": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"persistence": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"persistence_time": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"health_check_test": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"health_check_interval": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"health_check_path": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"health_check_path_parser": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"protocol": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"port_balancer": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validation.IntBetween(1, 65535),
|
||||||
|
},
|
||||||
|
"port_server": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validation.IntBetween(1, 65535),
|
||||||
|
},
|
||||||
|
"source_ip": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneLoadbalancerCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
req := oneandone.LoadBalancerRequest{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Rules: getLBRules(d),
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("description"); ok {
|
||||||
|
req.Description = raw.(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) {
|
||||||
|
req.DatacenterId = dc.Id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("method"); ok {
|
||||||
|
req.Method = raw.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("persistence"); ok {
|
||||||
|
req.Persistence = oneandone.Bool2Pointer(raw.(bool))
|
||||||
|
}
|
||||||
|
if raw, ok := d.GetOk("persistence_time"); ok {
|
||||||
|
req.PersistenceTime = oneandone.Int2Pointer(raw.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("health_check_test"); ok {
|
||||||
|
req.HealthCheckTest = raw.(string)
|
||||||
|
}
|
||||||
|
if raw, ok := d.GetOk("health_check_interval"); ok {
|
||||||
|
req.HealthCheckInterval = oneandone.Int2Pointer(raw.(int))
|
||||||
|
}
|
||||||
|
if raw, ok := d.GetOk("health_check_path"); ok {
|
||||||
|
req.HealthCheckPath = raw.(string)
|
||||||
|
}
|
||||||
|
if raw, ok := d.GetOk("health_check_path_parser"); ok {
|
||||||
|
req.HealthCheckPathParser = raw.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
lb_id, lb, err := config.API.CreateLoadBalancer(&req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(lb, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(lb_id)
|
||||||
|
|
||||||
|
return resourceOneandOneLoadbalancerRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLBRules(d *schema.ResourceData) []oneandone.LoadBalancerRule {
|
||||||
|
var rules []oneandone.LoadBalancerRule
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("rules"); ok {
|
||||||
|
rawRules := raw.([]interface{})
|
||||||
|
log.Println("[DEBUG] raw rules:", raw)
|
||||||
|
for _, raw := range rawRules {
|
||||||
|
rl := raw.(map[string]interface{})
|
||||||
|
rule := oneandone.LoadBalancerRule{
|
||||||
|
Protocol: rl["protocol"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl["port_balancer"] != nil {
|
||||||
|
rule.PortBalancer = uint16(rl["port_balancer"].(int))
|
||||||
|
}
|
||||||
|
if rl["port_server"] != nil {
|
||||||
|
rule.PortServer = uint16(rl["port_server"].(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl["source_ip"] != nil {
|
||||||
|
rule.Source = rl["source_ip"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneLoadbalancerUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
if d.HasChange("name") || d.HasChange("description") || d.HasChange("method") || d.HasChange("persistence") || d.HasChange("persistence_time") || d.HasChange("health_check_test") || d.HasChange("health_check_interval") {
|
||||||
|
lb := oneandone.LoadBalancerRequest{}
|
||||||
|
if d.HasChange("name") {
|
||||||
|
_, n := d.GetChange("name")
|
||||||
|
lb.Name = n.(string)
|
||||||
|
}
|
||||||
|
if d.HasChange("description") {
|
||||||
|
_, n := d.GetChange("description")
|
||||||
|
lb.Description = n.(string)
|
||||||
|
}
|
||||||
|
if d.HasChange("method") {
|
||||||
|
_, n := d.GetChange("method")
|
||||||
|
lb.Method = (n.(string))
|
||||||
|
}
|
||||||
|
if d.HasChange("persistence") {
|
||||||
|
_, n := d.GetChange("persistence")
|
||||||
|
lb.Persistence = oneandone.Bool2Pointer(n.(bool))
|
||||||
|
}
|
||||||
|
if d.HasChange("persistence_time") {
|
||||||
|
_, n := d.GetChange("persistence_time")
|
||||||
|
lb.PersistenceTime = oneandone.Int2Pointer(n.(int))
|
||||||
|
}
|
||||||
|
if d.HasChange("health_check_test") {
|
||||||
|
_, n := d.GetChange("health_check_test")
|
||||||
|
lb.HealthCheckTest = n.(string)
|
||||||
|
}
|
||||||
|
if d.HasChange("health_check_path") {
|
||||||
|
_, n := d.GetChange("health_check_path")
|
||||||
|
lb.HealthCheckPath = n.(string)
|
||||||
|
}
|
||||||
|
if d.HasChange("health_check_path_parser") {
|
||||||
|
_, n := d.GetChange("health_check_path_parser")
|
||||||
|
lb.HealthCheckPathParser = n.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
ss, err := config.API.UpdateLoadBalancer(d.Id(), &lb)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(ss, "ACTIVE", 10, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("rules") {
|
||||||
|
oldR, newR := d.GetChange("rules")
|
||||||
|
oldValues := oldR.([]interface{})
|
||||||
|
newValues := newR.([]interface{})
|
||||||
|
if len(oldValues) > len(newValues) {
|
||||||
|
diff := difference(oldValues, newValues)
|
||||||
|
for _, old := range diff {
|
||||||
|
o := old.(map[string]interface{})
|
||||||
|
if o["id"] != nil {
|
||||||
|
old_id := o["id"].(string)
|
||||||
|
fw, err := config.API.DeleteLoadBalancerRule(d.Id(), old_id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(fw, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var rules []oneandone.LoadBalancerRule
|
||||||
|
log.Println("[DEBUG] new values:", newValues)
|
||||||
|
|
||||||
|
for _, raw := range newValues {
|
||||||
|
rl := raw.(map[string]interface{})
|
||||||
|
log.Println("[DEBUG] rl:", rl)
|
||||||
|
|
||||||
|
if rl["id"].(string) == "" {
|
||||||
|
rule := oneandone.LoadBalancerRule{
|
||||||
|
Protocol: rl["protocol"].(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.PortServer = uint16(rl["port_server"].(int))
|
||||||
|
rule.PortBalancer = uint16(rl["port_balancer"].(int))
|
||||||
|
|
||||||
|
rule.Source = rl["source_ip"].(string)
|
||||||
|
|
||||||
|
log.Println("[DEBUG] adding to list", rl["protocol"], rl["source_ip"], rl["port_balancer"], rl["port_server"])
|
||||||
|
log.Println("[DEBUG] adding to list", rule)
|
||||||
|
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("[DEBUG] new rules:", rules)
|
||||||
|
|
||||||
|
if len(rules) > 0 {
|
||||||
|
fw, err := config.API.AddLoadBalancerRules(d.Id(), rules)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(fw, "ACTIVE", 10, config.Retries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneLoadbalancerRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneLoadbalancerRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
ss, err := config.API.GetLoadBalancer(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", ss.Name)
|
||||||
|
d.Set("description", ss.Description)
|
||||||
|
d.Set("datacenter", ss.Datacenter.CountryCode)
|
||||||
|
d.Set("method", ss.Method)
|
||||||
|
d.Set("persistence", ss.Persistence)
|
||||||
|
d.Set("persistence_time", ss.PersistenceTime)
|
||||||
|
d.Set("health_check_test", ss.HealthCheckTest)
|
||||||
|
d.Set("health_check_interval", ss.HealthCheckInterval)
|
||||||
|
d.Set("rules", getLoadbalancerRules(ss.Rules))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLoadbalancerRules(rules []oneandone.LoadBalancerRule) []map[string]interface{} {
|
||||||
|
raw := make([]map[string]interface{}, 0, len(rules))
|
||||||
|
|
||||||
|
for _, rule := range rules {
|
||||||
|
|
||||||
|
toadd := map[string]interface{}{
|
||||||
|
"id": rule.Id,
|
||||||
|
"port_balancer": rule.PortBalancer,
|
||||||
|
"port_server": rule.PortServer,
|
||||||
|
"protocol": rule.Protocol,
|
||||||
|
"source_ip": rule.Source,
|
||||||
|
}
|
||||||
|
|
||||||
|
raw = append(raw, toadd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneLoadbalancerDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
lb, err := config.API.DeleteLoadBalancer(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitUntilDeleted(lb)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateMethod(v interface{}, k string) (ws []string, errors []error) {
|
||||||
|
value := v.(string)
|
||||||
|
|
||||||
|
if value != "ROUND_ROBIN" && value != "LEAST_CONNECTIONS" {
|
||||||
|
errors = append(errors, fmt.Errorf("%q value sholud be either 'ROUND_ROBIN' or 'LEAST_CONNECTIONS' not %q", k, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandoneLoadbalancer_Basic(t *testing.T) {
|
||||||
|
var lb oneandone.LoadBalancer
|
||||||
|
|
||||||
|
name := "test_loadbalancer"
|
||||||
|
name_updated := "test_loadbalancer_renamed"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandoneLoadbalancerDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneLoadbalancer_basic, name),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneLoadbalancerExists("oneandone_loadbalancer.lb", &lb),
|
||||||
|
testAccCheckOneandoneLoadbalancerAttributes("oneandone_loadbalancer.lb", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_loadbalancer.lb", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneLoadbalancer_update, name_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneLoadbalancerExists("oneandone_loadbalancer.lb", &lb),
|
||||||
|
testAccCheckOneandoneLoadbalancerAttributes("oneandone_loadbalancer.lb", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_loadbalancer.lb", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandoneLoadbalancerDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_loadbalancer.lb" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetLoadBalancer(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Loadbalancer still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandoneLoadbalancerAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandoneLoadbalancerExists(n string, fw_p *oneandone.LoadBalancer) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_fw, err := api.GetLoadBalancer(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching Loadbalancer: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_fw.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
fw_p = found_fw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandoneLoadbalancer_basic = `
|
||||||
|
resource "oneandone_loadbalancer" "lb" {
|
||||||
|
name = "%s"
|
||||||
|
method = "ROUND_ROBIN"
|
||||||
|
persistence = true
|
||||||
|
persistence_time = 60
|
||||||
|
health_check_test = "TCP"
|
||||||
|
health_check_interval = 300
|
||||||
|
datacenter = "US"
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
protocol = "TCP"
|
||||||
|
port_balancer = 8080
|
||||||
|
port_server = 8089
|
||||||
|
source_ip = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
protocol = "TCP"
|
||||||
|
port_balancer = 9090
|
||||||
|
port_server = 9099
|
||||||
|
source_ip = "0.0.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
const testAccCheckOneandoneLoadbalancer_update = `
|
||||||
|
resource "oneandone_loadbalancer" "lb" {
|
||||||
|
name = "%s"
|
||||||
|
method = "ROUND_ROBIN"
|
||||||
|
persistence = true
|
||||||
|
persistence_time = 60
|
||||||
|
health_check_test = "TCP"
|
||||||
|
health_check_interval = 300
|
||||||
|
datacenter = "US"
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
protocol = "TCP"
|
||||||
|
port_balancer = 8080
|
||||||
|
port_server = 8089
|
||||||
|
source_ip = "0.0.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
|
@ -0,0 +1,706 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOneMonitoringPolicy() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceOneandOneMonitoringPolicyCreate,
|
||||||
|
Read: resourceOneandOneMonitoringPolicyRead,
|
||||||
|
Update: resourceOneandOneMonitoringPolicyUpdate,
|
||||||
|
Delete: resourceOneandOneMonitoringPolicyDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"agent": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"thresholds": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cpu": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"warning": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"critical": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"ram": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"warning": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"critical": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"disk": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"warning": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"critical": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"transfer": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"warning": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"critical": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"internal_ping": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"warning": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"critical": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"value": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"ports": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"email_notification": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"protocol": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"alert_if": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"processes": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
|
||||||
|
"email_notification": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"process": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"alert_if": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneMonitoringPolicyCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
mp_request := oneandone.MonitoringPolicy{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Agent: d.Get("agent").(bool),
|
||||||
|
Thresholds: getThresholds(d.Get("thresholds")),
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("ports"); ok {
|
||||||
|
mp_request.Ports = getPorts(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("processes"); ok {
|
||||||
|
mp_request.Processes = getProcesses(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_id, mp, err := config.API.CreateMonitoringPolicy(&mp_request)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(mp_id)
|
||||||
|
|
||||||
|
return resourceOneandOneMonitoringPolicyRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneMonitoringPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
req := oneandone.MonitoringPolicy{}
|
||||||
|
if d.HasChange("name") {
|
||||||
|
_, n := d.GetChange("name")
|
||||||
|
req.Name = n.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("description") {
|
||||||
|
_, n := d.GetChange("description")
|
||||||
|
req.Description = n.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("email") {
|
||||||
|
_, n := d.GetChange("email")
|
||||||
|
req.Email = n.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("agent") {
|
||||||
|
_, n := d.GetChange("agent")
|
||||||
|
req.Agent = n.(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("thresholds") {
|
||||||
|
_, n := d.GetChange("thresholds")
|
||||||
|
req.Thresholds = getThresholds(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
mp, err := config.API.UpdateMonitoringPolicy(d.Id(), &req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("ports") {
|
||||||
|
o, n := d.GetChange("ports")
|
||||||
|
oldValues := o.([]interface{})
|
||||||
|
newValues := n.([]interface{})
|
||||||
|
|
||||||
|
if len(newValues) > len(oldValues) {
|
||||||
|
ports := getPorts(newValues)
|
||||||
|
|
||||||
|
newports := []oneandone.MonitoringPort{}
|
||||||
|
|
||||||
|
for _, p := range ports {
|
||||||
|
if p.Id == "" {
|
||||||
|
newports = append(newports, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp, err := config.API.AddMonitoringPolicyPorts(d.Id(), newports)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if len(oldValues) > len(newValues) {
|
||||||
|
diff := difference(oldValues, newValues)
|
||||||
|
ports := getPorts(diff)
|
||||||
|
|
||||||
|
for _, port := range ports {
|
||||||
|
if port.Id == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mp, err := config.API.DeleteMonitoringPolicyPort(d.Id(), port.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if len(oldValues) == len(newValues) {
|
||||||
|
ports := getPorts(newValues)
|
||||||
|
|
||||||
|
for _, port := range ports {
|
||||||
|
mp, err := config.API.ModifyMonitoringPolicyPort(d.Id(), port.Id, &port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("processes") {
|
||||||
|
o, n := d.GetChange("processes")
|
||||||
|
oldValues := o.([]interface{})
|
||||||
|
newValues := n.([]interface{})
|
||||||
|
if len(newValues) > len(oldValues) {
|
||||||
|
processes := getProcesses(newValues)
|
||||||
|
|
||||||
|
newprocesses := []oneandone.MonitoringProcess{}
|
||||||
|
|
||||||
|
for _, p := range processes {
|
||||||
|
if p.Id == "" {
|
||||||
|
newprocesses = append(newprocesses, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp, err := config.API.AddMonitoringPolicyProcesses(d.Id(), newprocesses)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if len(oldValues) > len(newValues) {
|
||||||
|
diff := difference(oldValues, newValues)
|
||||||
|
processes := getProcesses(diff)
|
||||||
|
for _, process := range processes {
|
||||||
|
if process.Id == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mp, err := config.API.DeleteMonitoringPolicyProcess(d.Id(), process.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if len(oldValues) == len(newValues) {
|
||||||
|
processes := getProcesses(newValues)
|
||||||
|
|
||||||
|
for _, process := range processes {
|
||||||
|
mp, err := config.API.ModifyMonitoringPolicyProcess(d.Id(), process.Id, &process)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneMonitoringPolicyRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneMonitoringPolicyRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
mp, err := config.API.GetMonitoringPolicy(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mp.Servers) > 0 {
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mp.Ports) > 0 {
|
||||||
|
pports := d.Get("ports").([]interface{})
|
||||||
|
for i, raw_ports := range pports {
|
||||||
|
port := raw_ports.(map[string]interface{})
|
||||||
|
port["id"] = mp.Ports[i].Id
|
||||||
|
}
|
||||||
|
d.Set("ports", pports)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mp.Processes) > 0 {
|
||||||
|
pprocesses := d.Get("processes").([]interface{})
|
||||||
|
for i, raw_processes := range pprocesses {
|
||||||
|
process := raw_processes.(map[string]interface{})
|
||||||
|
process["id"] = mp.Processes[i].Id
|
||||||
|
}
|
||||||
|
d.Set("processes", pprocesses)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneMonitoringPolicyDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
mp, err := config.API.DeleteMonitoringPolicy(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitUntilDeleted(mp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getThresholds(d interface{}) *oneandone.MonitoringThreshold {
|
||||||
|
raw_thresholds := d.(*schema.Set).List()
|
||||||
|
|
||||||
|
toReturn := &oneandone.MonitoringThreshold{}
|
||||||
|
|
||||||
|
for _, thresholds := range raw_thresholds {
|
||||||
|
th_set := thresholds.(map[string]interface{})
|
||||||
|
|
||||||
|
//CPU
|
||||||
|
cpu_raw := th_set["cpu"].(*schema.Set)
|
||||||
|
toReturn.Cpu = &oneandone.MonitoringLevel{}
|
||||||
|
for _, c := range cpu_raw.List() {
|
||||||
|
int_k := c.(map[string]interface{})
|
||||||
|
for _, w := range int_k["warning"].(*schema.Set).List() {
|
||||||
|
toReturn.Cpu.Warning = &oneandone.MonitoringValue{
|
||||||
|
Value: w.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: w.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range int_k["critical"].(*schema.Set).List() {
|
||||||
|
toReturn.Cpu.Critical = &oneandone.MonitoringValue{
|
||||||
|
Value: c.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: c.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//RAM
|
||||||
|
ram_raw := th_set["ram"].(*schema.Set)
|
||||||
|
toReturn.Ram = &oneandone.MonitoringLevel{}
|
||||||
|
for _, c := range ram_raw.List() {
|
||||||
|
int_k := c.(map[string]interface{})
|
||||||
|
for _, w := range int_k["warning"].(*schema.Set).List() {
|
||||||
|
toReturn.Ram.Warning = &oneandone.MonitoringValue{
|
||||||
|
Value: w.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: w.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range int_k["critical"].(*schema.Set).List() {
|
||||||
|
toReturn.Ram.Critical = &oneandone.MonitoringValue{
|
||||||
|
Value: c.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: c.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//DISK
|
||||||
|
disk_raw := th_set["disk"].(*schema.Set)
|
||||||
|
toReturn.Disk = &oneandone.MonitoringLevel{}
|
||||||
|
for _, c := range disk_raw.List() {
|
||||||
|
int_k := c.(map[string]interface{})
|
||||||
|
for _, w := range int_k["warning"].(*schema.Set).List() {
|
||||||
|
toReturn.Disk.Warning = &oneandone.MonitoringValue{
|
||||||
|
Value: w.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: w.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range int_k["critical"].(*schema.Set).List() {
|
||||||
|
toReturn.Disk.Critical = &oneandone.MonitoringValue{
|
||||||
|
Value: c.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: c.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TRANSFER
|
||||||
|
transfer_raw := th_set["transfer"].(*schema.Set)
|
||||||
|
toReturn.Transfer = &oneandone.MonitoringLevel{}
|
||||||
|
for _, c := range transfer_raw.List() {
|
||||||
|
int_k := c.(map[string]interface{})
|
||||||
|
for _, w := range int_k["warning"].(*schema.Set).List() {
|
||||||
|
toReturn.Transfer.Warning = &oneandone.MonitoringValue{
|
||||||
|
Value: w.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: w.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range int_k["critical"].(*schema.Set).List() {
|
||||||
|
toReturn.Transfer.Critical = &oneandone.MonitoringValue{
|
||||||
|
Value: c.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: c.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//internal ping
|
||||||
|
ping_raw := th_set["internal_ping"].(*schema.Set)
|
||||||
|
toReturn.InternalPing = &oneandone.MonitoringLevel{}
|
||||||
|
for _, c := range ping_raw.List() {
|
||||||
|
int_k := c.(map[string]interface{})
|
||||||
|
for _, w := range int_k["warning"].(*schema.Set).List() {
|
||||||
|
toReturn.InternalPing.Warning = &oneandone.MonitoringValue{
|
||||||
|
Value: w.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: w.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range int_k["critical"].(*schema.Set).List() {
|
||||||
|
toReturn.InternalPing.Critical = &oneandone.MonitoringValue{
|
||||||
|
Value: c.(map[string]interface{})["value"].(int),
|
||||||
|
Alert: c.(map[string]interface{})["alert"].(bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProcesses(d interface{}) []oneandone.MonitoringProcess {
|
||||||
|
toReturn := []oneandone.MonitoringProcess{}
|
||||||
|
|
||||||
|
for _, raw := range d.([]interface{}) {
|
||||||
|
port := raw.(map[string]interface{})
|
||||||
|
m_port := oneandone.MonitoringProcess{
|
||||||
|
EmailNotification: port["email_notification"].(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
if port["id"] != nil {
|
||||||
|
m_port.Id = port["id"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if port["process"] != nil {
|
||||||
|
m_port.Process = port["process"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if port["alert_if"] != nil {
|
||||||
|
m_port.AlertIf = port["alert_if"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
toReturn = append(toReturn, m_port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPorts(d interface{}) []oneandone.MonitoringPort {
|
||||||
|
toReturn := []oneandone.MonitoringPort{}
|
||||||
|
|
||||||
|
for _, raw := range d.([]interface{}) {
|
||||||
|
port := raw.(map[string]interface{})
|
||||||
|
m_port := oneandone.MonitoringPort{
|
||||||
|
EmailNotification: port["email_notification"].(bool),
|
||||||
|
Port: port["port"].(int),
|
||||||
|
}
|
||||||
|
|
||||||
|
if port["id"] != nil {
|
||||||
|
m_port.Id = port["id"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if port["protocol"] != nil {
|
||||||
|
m_port.Protocol = port["protocol"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if port["alert_if"] != nil {
|
||||||
|
m_port.AlertIf = port["alert_if"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
toReturn = append(toReturn, m_port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn
|
||||||
|
}
|
|
@ -0,0 +1,212 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandoneMonitoringPolicy_Basic(t *testing.T) {
|
||||||
|
var mp oneandone.MonitoringPolicy
|
||||||
|
|
||||||
|
name := "test"
|
||||||
|
name_updated := "test1"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandoneMonitoringPolicyDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneMonitoringPolicy_basic, name),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneMonitoringPolicyExists("oneandone_monitoring_policy.mp", &mp),
|
||||||
|
testAccCheckOneandoneMonitoringPolicyAttributes("oneandone_monitoring_policy.mp", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_monitoring_policy.mp", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneMonitoringPolicy_basic, name_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneMonitoringPolicyExists("oneandone_monitoring_policy.mp", &mp),
|
||||||
|
testAccCheckOneandoneMonitoringPolicyAttributes("oneandone_monitoring_policy.mp", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_monitoring_policy.mp", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandoneMonitoringPolicyDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_monitoring_policy.mp" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetMonitoringPolicy(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("MonitoringPolicy still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandoneMonitoringPolicyAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandoneMonitoringPolicyExists(n string, fw_p *oneandone.MonitoringPolicy) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_fw, err := api.GetMonitoringPolicy(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching MonitoringPolicy: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_fw.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
fw_p = found_fw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandoneMonitoringPolicy_basic = `
|
||||||
|
resource "oneandone_monitoring_policy" "mp" {
|
||||||
|
name = "%s"
|
||||||
|
agent = true
|
||||||
|
email = "email@address.com"
|
||||||
|
thresholds = {
|
||||||
|
cpu = {
|
||||||
|
warning = {
|
||||||
|
value = 50,
|
||||||
|
alert = false
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 66,
|
||||||
|
alert = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ram = {
|
||||||
|
warning = {
|
||||||
|
value = 70,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 80,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ram = {
|
||||||
|
warning = {
|
||||||
|
value = 85,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 95,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disk = {
|
||||||
|
warning = {
|
||||||
|
value = 84,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 94,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transfer = {
|
||||||
|
warning = {
|
||||||
|
value = 1000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 2000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
internal_ping = {
|
||||||
|
warning = {
|
||||||
|
value = 3000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 4000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ports = [
|
||||||
|
{
|
||||||
|
email_notification = true
|
||||||
|
port = 443
|
||||||
|
protocol = "TCP"
|
||||||
|
alert_if = "NOT_RESPONDING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email_notification = false
|
||||||
|
port = 80
|
||||||
|
protocol = "TCP"
|
||||||
|
alert_if = "NOT_RESPONDING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email_notification = true
|
||||||
|
port = 21
|
||||||
|
protocol = "TCP"
|
||||||
|
alert_if = "NOT_RESPONDING"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
processes = [
|
||||||
|
{
|
||||||
|
email_notification = false
|
||||||
|
process = "httpdeamon"
|
||||||
|
alert_if = "RUNNING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
process = "iexplorer",
|
||||||
|
alert_if = "NOT_RUNNING"
|
||||||
|
email_notification = true
|
||||||
|
}]
|
||||||
|
}`
|
|
@ -0,0 +1,291 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOnePrivateNetwork() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
|
||||||
|
Create: resourceOneandOnePrivateNetworkCreate,
|
||||||
|
Read: resourceOneandOnePrivateNetworkRead,
|
||||||
|
Update: resourceOneandOnePrivateNetworkUpdate,
|
||||||
|
Delete: resourceOneandOnePrivateNetworkDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"datacenter": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"network_address": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"subnet_mask": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"server_ids": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePrivateNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
req := oneandone.PrivateNetworkRequest{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("description"); ok {
|
||||||
|
req.Description = raw.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("network_address"); ok {
|
||||||
|
req.NetworkAddress = raw.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("subnet_mask"); ok {
|
||||||
|
req.SubnetMask = raw.(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) {
|
||||||
|
req.DatacenterId = dc.Id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prn_id, prn, err := config.API.CreatePrivateNetwork(&req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(prn, "ACTIVE", 30, config.Retries)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(prn_id)
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
if raw, ok := d.GetOk("server_ids"); ok {
|
||||||
|
|
||||||
|
rawIps := raw.(*schema.Set).List()
|
||||||
|
|
||||||
|
for _, raw := range rawIps {
|
||||||
|
ids = append(ids, raw.(string))
|
||||||
|
server, err := config.API.ShutdownServer(raw.(string), false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(server, "POWERED_OFF", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prn, err = config.API.AttachPrivateNetworkServers(d.Id(), ids)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(prn, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range ids {
|
||||||
|
server, err := config.API.StartServer(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(server, "POWERED_ON", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOnePrivateNetworkRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePrivateNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
if d.HasChange("name") || d.HasChange("description") || d.HasChange("network_address") || d.HasChange("subnet_mask") {
|
||||||
|
pnset := oneandone.PrivateNetworkRequest{}
|
||||||
|
|
||||||
|
pnset.Name = d.Get("name").(string)
|
||||||
|
|
||||||
|
pnset.Description = d.Get("description").(string)
|
||||||
|
pnset.NetworkAddress = d.Get("network_address").(string)
|
||||||
|
pnset.SubnetMask = d.Get("subnet_mask").(string)
|
||||||
|
|
||||||
|
prn, err := config.API.UpdatePrivateNetwork(d.Id(), &pnset)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(prn, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("server_ids") {
|
||||||
|
o, n := d.GetChange("server_ids")
|
||||||
|
|
||||||
|
newValues := n.(*schema.Set).List()
|
||||||
|
oldValues := o.(*schema.Set).List()
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
for _, newV := range oldValues {
|
||||||
|
ids = append(ids, newV.(string))
|
||||||
|
}
|
||||||
|
for _, id := range ids {
|
||||||
|
server, err := config.API.ShutdownServer(id, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(server, "POWERED_OFF", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = config.API.RemoveServerPrivateNetwork(id, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
prn, _ := config.API.GetPrivateNetwork(d.Id())
|
||||||
|
|
||||||
|
err = config.API.WaitForState(prn, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var newids []string
|
||||||
|
|
||||||
|
for _, newV := range newValues {
|
||||||
|
newids = append(newids, newV.(string))
|
||||||
|
}
|
||||||
|
pn, err := config.API.AttachPrivateNetworkServers(d.Id(), newids)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(pn, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range newids {
|
||||||
|
server, err := config.API.StartServer(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(server, "POWERED_ON", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOnePrivateNetworkRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePrivateNetworkRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
pn, err := config.API.GetPrivateNetwork(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", pn.Name)
|
||||||
|
d.Set("description", pn.Description)
|
||||||
|
d.Set("network_address", pn.NetworkAddress)
|
||||||
|
d.Set("subnet_mask", pn.SubnetMask)
|
||||||
|
d.Set("datacenter", pn.Datacenter.CountryCode)
|
||||||
|
|
||||||
|
var toAdd []string
|
||||||
|
for _, s := range pn.Servers {
|
||||||
|
toAdd = append(toAdd, s.Id)
|
||||||
|
}
|
||||||
|
d.Set("server_ids", toAdd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePrivateNetworkDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
pn, err := config.API.GetPrivateNetwork(d.Id())
|
||||||
|
|
||||||
|
for _, server := range pn.Servers {
|
||||||
|
srv, err := config.API.ShutdownServer(server.Id, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(srv, "POWERED_OFF", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pn, err = config.API.DeletePrivateNetwork(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitUntilDeleted(pn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, server := range pn.Servers {
|
||||||
|
srv, err := config.API.StartServer(server.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(srv, "POWERED_ON", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandonePrivateNetwork_Basic(t *testing.T) {
|
||||||
|
var net oneandone.PrivateNetwork
|
||||||
|
|
||||||
|
name := "test"
|
||||||
|
name_updated := "test1"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckOneandonePrivateNetworkDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandonePrivateNetwork_basic, name),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandonePrivateNetworkExists("oneandone_private_network.pn", &net),
|
||||||
|
testAccCheckOneandonePrivateNetworkAttributes("oneandone_private_network.pn", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_private_network.pn", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandonePrivateNetwork_basic, name_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandonePrivateNetworkExists("oneandone_private_network.pn", &net),
|
||||||
|
testAccCheckOneandonePrivateNetworkAttributes("oneandone_private_network.pn", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_private_network.pn", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandonePrivateNetworkDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_private_network" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetPrivateNetwork(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("PrivateNetwork still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandonePrivateNetworkAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandonePrivateNetworkExists(n string, server *oneandone.PrivateNetwork) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_server, err := api.GetPrivateNetwork(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching PrivateNetwork: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_server.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
server = found_server
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandonePrivateNetwork_basic = `
|
||||||
|
resource "oneandone_server" "server1" {
|
||||||
|
name = "server_private_net_01"
|
||||||
|
description = "ttt"
|
||||||
|
image = "CoreOS_Stable_64std"
|
||||||
|
datacenter = "US"
|
||||||
|
vcores = 1
|
||||||
|
cores_per_processor = 1
|
||||||
|
ram = 2
|
||||||
|
password = "Kv40kd8PQb"
|
||||||
|
hdds = [
|
||||||
|
{
|
||||||
|
disk_size = 60
|
||||||
|
is_main = true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oneandone_server" "server2" {
|
||||||
|
name = "server_private_net_02"
|
||||||
|
description = "ttt"
|
||||||
|
image = "CoreOS_Stable_64std"
|
||||||
|
datacenter = "US"
|
||||||
|
vcores = 1
|
||||||
|
cores_per_processor = 1
|
||||||
|
ram = 2
|
||||||
|
password = "${oneandone_server.server1.password}"
|
||||||
|
hdds = [
|
||||||
|
{
|
||||||
|
disk_size = 60
|
||||||
|
is_main = true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oneandone_private_network" "pn" {
|
||||||
|
name = "%s",
|
||||||
|
description = "new private net"
|
||||||
|
datacenter = "US"
|
||||||
|
network_address = "192.168.7.0"
|
||||||
|
subnet_mask = "255.255.255.0"
|
||||||
|
server_ids = [
|
||||||
|
"${oneandone_server.server1.id}",
|
||||||
|
"${oneandone_server.server2.id}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,133 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOnePublicIp() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
|
||||||
|
Create: resourceOneandOnePublicIpCreate,
|
||||||
|
Read: resourceOneandOnePublicIpRead,
|
||||||
|
Update: resourceOneandOnePublicIpUpdate,
|
||||||
|
Delete: resourceOneandOnePublicIpDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"ip_type": { //IPV4 or IPV6
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"reverse_dns": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"datacenter": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"ip_address": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePublicIpCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
var reverse_dns string
|
||||||
|
var datacenter_id string
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("reverse_dns"); ok {
|
||||||
|
reverse_dns = raw.(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_id = dc.Id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_id, ip, err := config.API.CreatePublicIp(d.Get("ip_type").(string), reverse_dns, datacenter_id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(ip, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.SetId(ip_id)
|
||||||
|
|
||||||
|
return resourceOneandOnePublicIpRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePublicIpRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
ip, err := config.API.GetPublicIp(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("ip_address", ip.IpAddress)
|
||||||
|
d.Set("revers_dns", ip.ReverseDns)
|
||||||
|
d.Set("datacenter", ip.Datacenter.CountryCode)
|
||||||
|
d.Set("ip_type", ip.Type)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePublicIpUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
if d.HasChange("reverse_dns") {
|
||||||
|
_, n := d.GetChange("reverse_dns")
|
||||||
|
ip, err := config.API.UpdatePublicIp(d.Id(), n.(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(ip, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOnePublicIpRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOnePublicIpDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
ip, err := config.API.DeletePublicIp(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitUntilDeleted(ip)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandonePublicIp_Basic(t *testing.T) {
|
||||||
|
var public_ip oneandone.PublicIp
|
||||||
|
|
||||||
|
reverse_dns := "example.de"
|
||||||
|
reverse_dns_updated := "example.ba"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandonePublicIpDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandonePublicIp_basic, reverse_dns),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandonePublicIpExists("oneandone_public_ip.ip", &public_ip),
|
||||||
|
testAccCheckOneandonePublicIpAttributes("oneandone_public_ip.ip", reverse_dns),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_public_ip.ip", "reverse_dns", reverse_dns),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandonePublicIp_basic, reverse_dns_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandonePublicIpExists("oneandone_public_ip.ip", &public_ip),
|
||||||
|
testAccCheckOneandonePublicIpAttributes("oneandone_public_ip.ip", reverse_dns_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_public_ip.ip", "reverse_dns", reverse_dns_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandonePublicIpDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_public_ip" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetPublicIp(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Public IP still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandonePublicIpAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["reverse_dns"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandonePublicIpExists(n string, public_ip *oneandone.PublicIp) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_public_ip, err := api.GetPublicIp(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching public IP: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_public_ip.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
public_ip = found_public_ip
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandonePublicIp_basic = `
|
||||||
|
resource "oneandone_public_ip" "ip" {
|
||||||
|
"ip_type" = "IPV4"
|
||||||
|
"reverse_dns" = "%s"
|
||||||
|
"datacenter" = "GB"
|
||||||
|
}`
|
|
@ -0,0 +1,562 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOneServer() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceOneandOneServerCreate,
|
||||||
|
Read: resourceOneandOneServerRead,
|
||||||
|
Update: resourceOneandOneServerUpdate,
|
||||||
|
Delete: resourceOneandOneServerDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"vcores": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"cores_per_processor": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"ram": {
|
||||||
|
Type: schema.TypeFloat,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"ssh_key_path": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
"datacenter": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"ips": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"firewall_policy_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"hdds": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"disk_size": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"is_main": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"firewall_policy_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"monitoring_policy_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"loadbalancer_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneServerCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
saps, _ := config.API.ListServerAppliances()
|
||||||
|
|
||||||
|
var sa oneandone.ServerAppliance
|
||||||
|
for _, a := range saps {
|
||||||
|
|
||||||
|
if a.Type == "IMAGE" && strings.Contains(strings.ToLower(a.Name), strings.ToLower(d.Get("image").(string))) {
|
||||||
|
sa = a
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hdds []oneandone.Hdd
|
||||||
|
if raw, ok := d.GetOk("hdds"); ok {
|
||||||
|
rawhdds := raw.([]interface{})
|
||||||
|
|
||||||
|
var istheremain bool
|
||||||
|
for _, raw := range rawhdds {
|
||||||
|
hd := raw.(map[string]interface{})
|
||||||
|
hdd := oneandone.Hdd{
|
||||||
|
Size: hd["disk_size"].(int),
|
||||||
|
IsMain: hd["is_main"].(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
if hdd.IsMain {
|
||||||
|
if hdd.Size < sa.MinHddSize {
|
||||||
|
return fmt.Errorf(fmt.Sprintf("Minimum required disk size %d", sa.MinHddSize))
|
||||||
|
}
|
||||||
|
istheremain = true
|
||||||
|
}
|
||||||
|
|
||||||
|
hdds = append(hdds, hdd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !istheremain {
|
||||||
|
return fmt.Errorf("At least one HDD has to be %s", "`is_main`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req := oneandone.ServerRequest{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Description: d.Get("description").(string),
|
||||||
|
ApplianceId: sa.Id,
|
||||||
|
PowerOn: true,
|
||||||
|
Hardware: oneandone.Hardware{
|
||||||
|
Vcores: d.Get("vcores").(int),
|
||||||
|
CoresPerProcessor: d.Get("cores_per_processor").(int),
|
||||||
|
Ram: float32(d.Get("ram").(float64)),
|
||||||
|
Hdds: hdds,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("ip"); ok {
|
||||||
|
|
||||||
|
new_ip := raw.(string)
|
||||||
|
|
||||||
|
ips, err := config.API.ListPublicIps()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ip := range ips {
|
||||||
|
if ip.IpAddress == new_ip {
|
||||||
|
req.IpId = ip.Id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("[DEBUG] req.IP", req.IpId)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
req.DatacenterId = dc.Id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fwp_id, ok := d.GetOk("firewall_policy_id"); ok {
|
||||||
|
req.FirewallPolicyId = fwp_id.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mp_id, ok := d.GetOk("monitoring_policy_id"); ok {
|
||||||
|
req.MonitoringPolicyId = mp_id.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mp_id, ok := d.GetOk("loadbalancer_id"); ok {
|
||||||
|
req.LoadBalancerId = mp_id.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
var privateKey string
|
||||||
|
if raw, ok := d.GetOk("ssh_key_path"); ok {
|
||||||
|
rawpath := raw.(string)
|
||||||
|
|
||||||
|
priv, publicKey, err := getSshKey(rawpath)
|
||||||
|
privateKey = priv
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SSHKey = publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
var password string
|
||||||
|
if raw, ok := d.GetOk("password"); ok {
|
||||||
|
req.Password = raw.(string)
|
||||||
|
password = req.Password
|
||||||
|
}
|
||||||
|
|
||||||
|
server_id, server, err := config.API.CreateServer(&req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(server, "POWERED_ON", 10, config.Retries)
|
||||||
|
|
||||||
|
d.SetId(server_id)
|
||||||
|
server, err = config.API.GetServer(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if password == "" {
|
||||||
|
password = server.FirstPassword
|
||||||
|
}
|
||||||
|
d.SetConnInfo(map[string]string{
|
||||||
|
"type": "ssh",
|
||||||
|
"host": server.Ips[0].Ip,
|
||||||
|
"password": password,
|
||||||
|
"private_key": privateKey,
|
||||||
|
})
|
||||||
|
|
||||||
|
return resourceOneandOneServerRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneServerRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
server, err := config.API.GetServer(d.Id())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", server.Name)
|
||||||
|
d.Set("datacenter", server.Datacenter.CountryCode)
|
||||||
|
|
||||||
|
d.Set("hdds", readHdds(server.Hardware))
|
||||||
|
|
||||||
|
d.Set("ips", readIps(server.Ips))
|
||||||
|
|
||||||
|
if len(server.FirstPassword) > 0 {
|
||||||
|
d.Set("password", server.FirstPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneServerUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
if d.HasChange("name") || d.HasChange("description") {
|
||||||
|
_, name := d.GetChange("name")
|
||||||
|
_, description := d.GetChange("description")
|
||||||
|
server, err := config.API.RenameServer(d.Id(), name.(string), description.(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(server, "POWERED_ON", 10, config.Retries)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("hdds") {
|
||||||
|
oldV, newV := d.GetChange("hdds")
|
||||||
|
newValues := newV.([]interface{})
|
||||||
|
oldValues := oldV.([]interface{})
|
||||||
|
|
||||||
|
if len(oldValues) > len(newValues) {
|
||||||
|
diff := difference(oldValues, newValues)
|
||||||
|
for _, old := range diff {
|
||||||
|
o := old.(map[string]interface{})
|
||||||
|
old_id := o["id"].(string)
|
||||||
|
server, err := config.API.DeleteServerHdd(d.Id(), old_id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(server, "POWERED_ON", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, newHdd := range newValues {
|
||||||
|
n := newHdd.(map[string]interface{})
|
||||||
|
//old := oldHdd.(map[string]interface{})
|
||||||
|
|
||||||
|
if n["id"].(string) == "" {
|
||||||
|
hdds := oneandone.ServerHdds{
|
||||||
|
Hdds: []oneandone.Hdd{
|
||||||
|
{
|
||||||
|
Size: n["disk_size"].(int),
|
||||||
|
IsMain: n["is_main"].(bool),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := config.API.AddServerHdds(d.Id(), &hdds)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(server, "POWERED_ON", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
id := n["id"].(string)
|
||||||
|
isMain := n["is_main"].(bool)
|
||||||
|
|
||||||
|
if id != "" && !isMain {
|
||||||
|
log.Println("[DEBUG] Resizing existing HDD")
|
||||||
|
config.API.ResizeServerHdd(d.Id(), id, n["disk_size"].(int))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("monitoring_policy_id") {
|
||||||
|
o, n := d.GetChange("monitoring_policy_id")
|
||||||
|
|
||||||
|
if n == nil {
|
||||||
|
mp, err := config.API.RemoveMonitoringPolicyServer(o.(string), d.Id())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mp, err := config.API.AttachMonitoringPolicyServers(n.(string), []string{d.Id()})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("loadbalancer_id") {
|
||||||
|
o, n := d.GetChange("loadbalancer_id")
|
||||||
|
server, err := config.API.GetServer(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == nil || n.(string) == "" {
|
||||||
|
log.Println("[DEBUG] Removing")
|
||||||
|
log.Println("[DEBUG] IPS:", server.Ips)
|
||||||
|
|
||||||
|
for _, ip := range server.Ips {
|
||||||
|
mp, err := config.API.DeleteLoadBalancerServerIp(o.(string), ip.Id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("[DEBUG] Adding")
|
||||||
|
ip_ids := []string{}
|
||||||
|
for _, ip := range server.Ips {
|
||||||
|
ip_ids = append(ip_ids, ip.Id)
|
||||||
|
}
|
||||||
|
mp, err := config.API.AddLoadBalancerServerIps(n.(string), ip_ids)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("firewall_policy_id") {
|
||||||
|
server, err := config.API.GetServer(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
o, n := d.GetChange("firewall_policy_id")
|
||||||
|
if n == nil {
|
||||||
|
for _, ip := range server.Ips {
|
||||||
|
mp, err := config.API.DeleteFirewallPolicyServerIp(o.(string), ip.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ip_ids := []string{}
|
||||||
|
for _, ip := range server.Ips {
|
||||||
|
ip_ids = append(ip_ids, ip.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
mp, err := config.API.AddFirewallPolicyServerIps(n.(string), ip_ids)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(mp, "ACTIVE", 30, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneServerRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneServerDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
_, ok := d.GetOk("ip")
|
||||||
|
|
||||||
|
server, err := config.API.DeleteServer(d.Id(), ok)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitUntilDeleted(server)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[DEBUG] ************ ERROR While waiting ************")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readHdds(hardware *oneandone.Hardware) []map[string]interface{} {
|
||||||
|
hdds := make([]map[string]interface{}, 0, len(hardware.Hdds))
|
||||||
|
|
||||||
|
for _, hd := range hardware.Hdds {
|
||||||
|
hdds = append(hdds, map[string]interface{}{
|
||||||
|
"id": hd.Id,
|
||||||
|
"disk_size": hd.Size,
|
||||||
|
"is_main": hd.IsMain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return hdds
|
||||||
|
}
|
||||||
|
|
||||||
|
func readIps(ips []oneandone.ServerIp) []map[string]interface{} {
|
||||||
|
raw := make([]map[string]interface{}, 0, len(ips))
|
||||||
|
for _, ip := range ips {
|
||||||
|
|
||||||
|
toadd := map[string]interface{}{
|
||||||
|
"ip": ip.Ip,
|
||||||
|
"id": ip.Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip.Firewall != nil {
|
||||||
|
toadd["firewall_policy_id"] = ip.Firewall.Id
|
||||||
|
}
|
||||||
|
raw = append(raw, toadd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSshKey(path string) (privatekey string, publickey string, err error) {
|
||||||
|
pemBytes, err := ioutil.ReadFile(path)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
block, _ := pem.Decode(pemBytes)
|
||||||
|
|
||||||
|
if block == nil {
|
||||||
|
return "", "", errors.New("File " + path + " contains nothing")
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
priv_blk := pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Headers: nil,
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(priv),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := ssh.NewPublicKey(&priv.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
publickey = string(ssh.MarshalAuthorizedKey(pub))
|
||||||
|
privatekey = string(pem.EncodeToMemory(&priv_blk))
|
||||||
|
|
||||||
|
return privatekey, publickey, nil
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandoneServer_Basic(t *testing.T) {
|
||||||
|
var server oneandone.Server
|
||||||
|
|
||||||
|
name := "test_server"
|
||||||
|
name_updated := "test_server_renamed"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandoneServerDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneServer_basic, name, name),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneServerExists("oneandone_server.server", &server),
|
||||||
|
testAccCheckOneandoneServerAttributes("oneandone_server.server", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_server.server", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneServer_basic, name_updated, name_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneServerExists("oneandone_server.server", &server),
|
||||||
|
testAccCheckOneandoneServerAttributes("oneandone_server.server", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_server.server", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandoneServerDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_server" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetServer(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Server still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandoneServerAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandoneServerExists(n string, server *oneandone.Server) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_server, err := api.GetServer(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching Server: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_server.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
server = found_server
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandoneServer_basic = `
|
||||||
|
resource "oneandone_server" "server" {
|
||||||
|
name = "%s"
|
||||||
|
description = "%s"
|
||||||
|
image = "ubuntu"
|
||||||
|
datacenter = "GB"
|
||||||
|
vcores = 1
|
||||||
|
cores_per_processor = 1
|
||||||
|
ram = 2
|
||||||
|
password = "Kv40kd8PQb"
|
||||||
|
hdds = [
|
||||||
|
{
|
||||||
|
disk_size = 20
|
||||||
|
is_main = true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
|
@ -0,0 +1,217 @@
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandoneVpn_Basic(t *testing.T) {
|
||||||
|
var server oneandone.VPN
|
||||||
|
|
||||||
|
name := "test"
|
||||||
|
name_updated := "test1"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandoneVPNDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneVPN_basic, name),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneVPNExists("oneandone_vpn.vpn", &server),
|
||||||
|
testAccCheckOneandoneVPNAttributes("oneandone_vpn.vpn", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_vpn.vpn", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneVPN_basic, name_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneVPNExists("oneandone_vpn.vpn", &server),
|
||||||
|
testAccCheckOneandoneVPNAttributes("oneandone_vpn.vpn", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_vpn.vpn", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandoneVPNDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_server" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetVPN(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("VPN still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandoneVPNAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandoneVPNExists(n string, server *oneandone.VPN) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_server, err := api.GetVPN(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching VPN: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_server.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
server = found_server
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandoneVPN_basic = `
|
||||||
|
resource "oneandone_vpn" "vpn" {
|
||||||
|
datacenter = "GB"
|
||||||
|
name = "%s"
|
||||||
|
description = "ttest descr"
|
||||||
|
}`
|
|
@ -0,0 +1,256 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceOneandOneSharedStorage() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceOneandOneSharedStorageCreate,
|
||||||
|
Read: resourceOneandOneSharedStorageRead,
|
||||||
|
Update: resourceOneandOneSharedStorageUpdate,
|
||||||
|
Delete: resourceOneandOneSharedStorageDelete,
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"datacenter": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"storage_servers": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"rights": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneSharedStorageCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
req := oneandone.SharedStorageRequest{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Size: oneandone.Int2Pointer(d.Get("size").(int)),
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("description"); ok {
|
||||||
|
req.Description = raw.(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) {
|
||||||
|
req.DatacenterId = dc.Id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_id, ss, err := config.API.CreateSharedStorage(&req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(ss, "ACTIVE", 10, config.Retries)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.SetId(ss_id)
|
||||||
|
|
||||||
|
if raw, ok := d.GetOk("storage_servers"); ok {
|
||||||
|
|
||||||
|
storage_servers := []oneandone.SharedStorageServer{}
|
||||||
|
|
||||||
|
rawRights := raw.([]interface{})
|
||||||
|
for _, raws_ss := range rawRights {
|
||||||
|
ss := raws_ss.(map[string]interface{})
|
||||||
|
storage_server := oneandone.SharedStorageServer{
|
||||||
|
Id: ss["id"].(string),
|
||||||
|
Rights: ss["rights"].(string),
|
||||||
|
}
|
||||||
|
storage_servers = append(storage_servers, storage_server)
|
||||||
|
}
|
||||||
|
|
||||||
|
ss, err := config.API.AddSharedStorageServers(ss_id, storage_servers)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(ss, "ACTIVE", 10, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneSharedStorageRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneSharedStorageUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
if d.HasChange("name") || d.HasChange("description") || d.HasChange("size") {
|
||||||
|
ssu := oneandone.SharedStorageRequest{}
|
||||||
|
if d.HasChange("name") {
|
||||||
|
_, n := d.GetChange("name")
|
||||||
|
ssu.Name = n.(string)
|
||||||
|
}
|
||||||
|
if d.HasChange("description") {
|
||||||
|
_, n := d.GetChange("description")
|
||||||
|
ssu.Description = n.(string)
|
||||||
|
}
|
||||||
|
if d.HasChange("size") {
|
||||||
|
_, n := d.GetChange("size")
|
||||||
|
ssu.Size = oneandone.Int2Pointer(n.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
ss, err := config.API.UpdateSharedStorage(d.Id(), &ssu)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitForState(ss, "ACTIVE", 10, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("storage_servers") {
|
||||||
|
|
||||||
|
o, n := d.GetChange("storage_servers")
|
||||||
|
|
||||||
|
oldV := o.([]interface{})
|
||||||
|
|
||||||
|
for _, old := range oldV {
|
||||||
|
ol := old.(map[string]interface{})
|
||||||
|
|
||||||
|
ss, err := config.API.DeleteSharedStorageServer(d.Id(), ol["id"].(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(ss, "ACTIVE", 10, config.Retries)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
newV := n.([]interface{})
|
||||||
|
|
||||||
|
ids := []oneandone.SharedStorageServer{}
|
||||||
|
for _, newValue := range newV {
|
||||||
|
nn := newValue.(map[string]interface{})
|
||||||
|
ids = append(ids, oneandone.SharedStorageServer{
|
||||||
|
Id: nn["id"].(string),
|
||||||
|
Rights: nn["rights"].(string),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ids) > 0 {
|
||||||
|
ss, err := config.API.AddSharedStorageServers(d.Id(), ids)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.API.WaitForState(ss, "ACTIVE", 10, config.Retries)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//DeleteSharedStorageServer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceOneandOneSharedStorageRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceOneandOneSharedStorageRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
ss, err := config.API.GetSharedStorage(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "404") {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", ss.Name)
|
||||||
|
d.Set("description", ss.Description)
|
||||||
|
d.Set("size", ss.Size)
|
||||||
|
d.Set("datacenter", ss.Datacenter.CountryCode)
|
||||||
|
d.Set("storage_servers", getStorageServers(ss.Servers))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStorageServers(servers []oneandone.SharedStorageServer) []map[string]interface{} {
|
||||||
|
raw := make([]map[string]interface{}, 0, len(servers))
|
||||||
|
|
||||||
|
for _, server := range servers {
|
||||||
|
|
||||||
|
toadd := map[string]interface{}{
|
||||||
|
"id": server.Id,
|
||||||
|
"rights": server.Rights,
|
||||||
|
}
|
||||||
|
|
||||||
|
raw = append(raw, toadd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw
|
||||||
|
|
||||||
|
}
|
||||||
|
func resourceOneandOneSharedStorageDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
ss, err := config.API.DeleteSharedStorage(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = config.API.WaitUntilDeleted(ss)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/1and1/oneandone-cloudserver-sdk-go"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccOneandoneSharedStorage_Basic(t *testing.T) {
|
||||||
|
var storage oneandone.SharedStorage
|
||||||
|
|
||||||
|
name := "test_storage"
|
||||||
|
name_updated := "test1"
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckDOneandoneSharedStorageDestroyCheck,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneSharedStorage_basic, name),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneSharedStorageExists("oneandone_shared_storage.storage", &storage),
|
||||||
|
testAccCheckOneandoneSharedStorageAttributes("oneandone_shared_storage.storage", name),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_shared_storage.storage", "name", name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: fmt.Sprintf(testAccCheckOneandoneSharedStorage_basic, name_updated),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
func(*terraform.State) error {
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
testAccCheckOneandoneSharedStorageExists("oneandone_shared_storage.storage", &storage),
|
||||||
|
testAccCheckOneandoneSharedStorageAttributes("oneandone_shared_storage.storage", name_updated),
|
||||||
|
resource.TestCheckResourceAttr("oneandone_shared_storage.storage", "name", name_updated),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckDOneandoneSharedStorageDestroyCheck(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "oneandone_shared_storage" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
_, err := api.GetVPN(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("VPN still exists %s %s", rs.Primary.ID, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func testAccCheckOneandoneSharedStorageAttributes(n string, reverse_dns string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.Attributes["name"] != reverse_dns {
|
||||||
|
return fmt.Errorf("Bad name: expected %s : found %s ", reverse_dns, rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckOneandoneSharedStorageExists(n string, storage *oneandone.SharedStorage) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No Record ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
api := oneandone.New(os.Getenv("ONEANDONE_TOKEN"), oneandone.BaseUrl)
|
||||||
|
|
||||||
|
found_storage, err := api.GetSharedStorage(rs.Primary.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error occured while fetching SharedStorage: %s", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
if found_storage.Id != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found")
|
||||||
|
}
|
||||||
|
storage = found_storage
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccCheckOneandoneSharedStorage_basic = `
|
||||||
|
resource "oneandone_shared_storage" "storage" {
|
||||||
|
name = "%s"
|
||||||
|
description = "ttt"
|
||||||
|
size = 50
|
||||||
|
datacenter = "GB"
|
||||||
|
}`
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=countHookAction hook_count_action.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=countHookAction hook_count_action.go"; DO NOT EDIT
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ import (
|
||||||
nomadprovider "github.com/hashicorp/terraform/builtin/providers/nomad"
|
nomadprovider "github.com/hashicorp/terraform/builtin/providers/nomad"
|
||||||
ns1provider "github.com/hashicorp/terraform/builtin/providers/ns1"
|
ns1provider "github.com/hashicorp/terraform/builtin/providers/ns1"
|
||||||
nullprovider "github.com/hashicorp/terraform/builtin/providers/null"
|
nullprovider "github.com/hashicorp/terraform/builtin/providers/null"
|
||||||
|
oneandoneprovider "github.com/hashicorp/terraform/builtin/providers/oneandone"
|
||||||
opcprovider "github.com/hashicorp/terraform/builtin/providers/opc"
|
opcprovider "github.com/hashicorp/terraform/builtin/providers/opc"
|
||||||
openstackprovider "github.com/hashicorp/terraform/builtin/providers/openstack"
|
openstackprovider "github.com/hashicorp/terraform/builtin/providers/openstack"
|
||||||
opsgenieprovider "github.com/hashicorp/terraform/builtin/providers/opsgenie"
|
opsgenieprovider "github.com/hashicorp/terraform/builtin/providers/opsgenie"
|
||||||
|
@ -126,6 +127,7 @@ var InternalProviders = map[string]plugin.ProviderFunc{
|
||||||
"ns1": ns1provider.Provider,
|
"ns1": ns1provider.Provider,
|
||||||
"null": nullprovider.Provider,
|
"null": nullprovider.Provider,
|
||||||
"opc": opcprovider.Provider,
|
"opc": opcprovider.Provider,
|
||||||
|
"oneandone": oneandoneprovider.Provider,
|
||||||
"openstack": openstackprovider.Provider,
|
"openstack": openstackprovider.Provider,
|
||||||
"opsgenie": opsgenieprovider.Provider,
|
"opsgenie": opsgenieprovider.Provider,
|
||||||
"packet": packetprovider.Provider,
|
"packet": packetprovider.Provider,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=ResourceMode -output=resource_mode_string.go resource_mode.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=ResourceMode -output=resource_mode_string.go resource_mode.go"; DO NOT EDIT
|
||||||
|
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=getSource resource_data_get_source.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=getSource resource_data_get_source.go"; DO NOT EDIT
|
||||||
|
|
||||||
package schema
|
package schema
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=ValueType valuetype.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=ValueType valuetype.go"; DO NOT EDIT
|
||||||
|
|
||||||
package schema
|
package schema
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=GraphType context_graph_type.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=GraphType context_graph_type.go"; DO NOT EDIT
|
||||||
|
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=InstanceType instancetype.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=InstanceType instancetype.go"; DO NOT EDIT
|
||||||
|
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "stringer -type=walkOperation graph_walk_operation.go"; DO NOT EDIT.
|
// Code generated by "stringer -type=walkOperation graph_walk_operation.go"; DO NOT EDIT
|
||||||
|
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright (c) 2016 1&1 Internet SE
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
36
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/datacenters.go
generated
vendored
Normal file
36
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/datacenters.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type Datacenter struct {
|
||||||
|
idField
|
||||||
|
CountryCode string `json:"country_code,omitempty"`
|
||||||
|
Location string `json:"location,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /datacenters
|
||||||
|
func (api *API) ListDatacenters(args ...interface{}) ([]Datacenter, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, datacenterPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []Datacenter{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /datacenters/{datacenter_id}
|
||||||
|
func (api *API) GetDatacenter(dc_id string) (*Datacenter, error) {
|
||||||
|
result := new(Datacenter)
|
||||||
|
url := createUrl(api, datacenterPathSegment, dc_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// Struct to describe a ISO image that can be used to boot a server.
|
||||||
|
//
|
||||||
|
// Values of this type describe ISO images that can be inserted into the servers virtual DVD drive.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
type DvdIso struct {
|
||||||
|
Identity
|
||||||
|
OsFamily string `json:"os_family,omitempty"`
|
||||||
|
Os string `json:"os,omitempty"`
|
||||||
|
OsVersion string `json:"os_version,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
AvailableDatacenters []string `json:"available_datacenters,omitempty"`
|
||||||
|
Architecture interface{} `json:"os_architecture,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /dvd_isos
|
||||||
|
func (api *API) ListDvdIsos(args ...interface{}) ([]DvdIso, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, dvdIsoPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []DvdIso{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /dvd_isos/{id}
|
||||||
|
func (api *API) GetDvdIso(dvd_id string) (*DvdIso, error) {
|
||||||
|
result := new(DvdIso)
|
||||||
|
url := createUrl(api, dvdIsoPathSegment, dvd_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type errorResponse struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type apiError struct {
|
||||||
|
httpStatusCode int
|
||||||
|
message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e apiError) Error() string {
|
||||||
|
return fmt.Sprintf("%d - %s", e.httpStatusCode, e.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *apiError) HttpStatusCode() int {
|
||||||
|
return e.httpStatusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *apiError) Message() string {
|
||||||
|
return e.message
|
||||||
|
}
|
208
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/firewallpolicies.go
generated
vendored
Normal file
208
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/firewallpolicies.go
generated
vendored
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FirewallPolicy struct {
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
DefaultPolicy uint8 `json:"default"`
|
||||||
|
CloudpanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
Rules []FirewallPolicyRule `json:"rules,omitempty"`
|
||||||
|
ServerIps []ServerIpInfo `json:"server_ips,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type FirewallPolicyRule struct {
|
||||||
|
idField
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
PortFrom *int `json:"port_from,omitempty"`
|
||||||
|
PortTo *int `json:"port_to,omitempty"`
|
||||||
|
SourceIp string `json:"source,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FirewallPolicyRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Rules []FirewallPolicyRule `json:"rules,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /firewall_policies
|
||||||
|
func (api *API) ListFirewallPolicies(args ...interface{}) ([]FirewallPolicy, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, firewallPolicyPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []FirewallPolicy{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /firewall_policies
|
||||||
|
func (api *API) CreateFirewallPolicy(fp_data *FirewallPolicyRequest) (string, *FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment)
|
||||||
|
err := api.Client.Post(url, &fp_data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /firewall_policies/{id}
|
||||||
|
func (api *API) GetFirewallPolicy(fp_id string) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /firewall_policies/{id}
|
||||||
|
func (api *API) DeleteFirewallPolicy(fp_id string) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /firewall_policies/{id}
|
||||||
|
func (api *API) UpdateFirewallPolicy(fp_id string, fp_new_name string, fp_new_desc string) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
data := FirewallPolicyRequest{
|
||||||
|
Name: fp_new_name,
|
||||||
|
Description: fp_new_desc,
|
||||||
|
}
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id)
|
||||||
|
err := api.Client.Put(url, &data, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /firewall_policies/{id}/server_ips
|
||||||
|
func (api *API) ListFirewallPolicyServerIps(fp_id string) ([]ServerIpInfo, error) {
|
||||||
|
result := []ServerIpInfo{}
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /firewall_policies/{id}/server_ips/{id}
|
||||||
|
func (api *API) GetFirewallPolicyServerIp(fp_id string, ip_id string) (*ServerIpInfo, error) {
|
||||||
|
result := new(ServerIpInfo)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips", ip_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /firewall_policies/{id}/server_ips
|
||||||
|
func (api *API) AddFirewallPolicyServerIps(fp_id string, ip_ids []string) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
request := serverIps{
|
||||||
|
ServerIps: ip_ids,
|
||||||
|
}
|
||||||
|
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips")
|
||||||
|
err := api.Client.Post(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /firewall_policies/{id}/server_ips/{id}
|
||||||
|
func (api *API) DeleteFirewallPolicyServerIp(fp_id string, ip_id string) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "server_ips", ip_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /firewall_policies/{id}/rules
|
||||||
|
func (api *API) ListFirewallPolicyRules(fp_id string) ([]FirewallPolicyRule, error) {
|
||||||
|
result := []FirewallPolicyRule{}
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /firewall_policies/{id}/rules
|
||||||
|
func (api *API) AddFirewallPolicyRules(fp_id string, fp_rules []FirewallPolicyRule) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
data := struct {
|
||||||
|
Rules []FirewallPolicyRule `json:"rules"`
|
||||||
|
}{fp_rules}
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules")
|
||||||
|
err := api.Client.Post(url, &data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /firewall_policies/{id}/rules/{id}
|
||||||
|
func (api *API) GetFirewallPolicyRule(fp_id string, rule_id string) (*FirewallPolicyRule, error) {
|
||||||
|
result := new(FirewallPolicyRule)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules", rule_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /firewall_policies/{id}/rules/{id}
|
||||||
|
func (api *API) DeleteFirewallPolicyRule(fp_id string, rule_id string) (*FirewallPolicy, error) {
|
||||||
|
result := new(FirewallPolicy)
|
||||||
|
url := createUrl(api, firewallPolicyPathSegment, fp_id, "rules", rule_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fp *FirewallPolicy) GetState() (string, error) {
|
||||||
|
in, err := fp.api.GetFirewallPolicy(fp.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
idField
|
||||||
|
ImageConfig
|
||||||
|
MinHddSize int `json:"min_hdd_size"`
|
||||||
|
Architecture *int `json:"os_architecture"`
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
OsImageType string `json:"os_image_type,omitempty"`
|
||||||
|
OsFamily string `json:"os_family,omitempty"`
|
||||||
|
Os string `json:"os,omitempty"`
|
||||||
|
OsVersion string `json:"os_version,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Licenses []License `json:"licenses,omitempty"`
|
||||||
|
Hdds []Hdd `json:"hdds,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageConfig struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Frequency string `json:"frequency,omitempty"`
|
||||||
|
ServerId string `json:"server_id,omitempty"`
|
||||||
|
NumImages int `json:"num_images"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /images
|
||||||
|
func (api *API) ListImages(args ...interface{}) ([]Image, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, imagePathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []Image{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /images
|
||||||
|
func (api *API) CreateImage(request *ImageConfig) (string, *Image, error) {
|
||||||
|
res := new(Image)
|
||||||
|
url := createUrl(api, imagePathSegment)
|
||||||
|
err := api.Client.Post(url, &request, &res, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
res.api = api
|
||||||
|
return res.Id, res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /images/{id}
|
||||||
|
func (api *API) GetImage(img_id string) (*Image, error) {
|
||||||
|
result := new(Image)
|
||||||
|
url := createUrl(api, imagePathSegment, img_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /images/{id}
|
||||||
|
func (api *API) DeleteImage(img_id string) (*Image, error) {
|
||||||
|
result := new(Image)
|
||||||
|
url := createUrl(api, imagePathSegment, img_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /images/{id}
|
||||||
|
func (api *API) UpdateImage(img_id string, new_name string, new_desc string, new_freq string) (*Image, error) {
|
||||||
|
result := new(Image)
|
||||||
|
req := struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Frequency string `json:"frequency,omitempty"`
|
||||||
|
}{Name: new_name, Description: new_desc, Frequency: new_freq}
|
||||||
|
url := createUrl(api, imagePathSegment, img_id)
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (im *Image) GetState() (string, error) {
|
||||||
|
in, err := im.api.GetImage(im.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
219
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/loadbalancers.go
generated
vendored
Normal file
219
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/loadbalancers.go
generated
vendored
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoadBalancer struct {
|
||||||
|
ApiPtr
|
||||||
|
idField
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
Ip string `json:"ip,omitempty"`
|
||||||
|
HealthCheckTest string `json:"health_check_test,omitempty"`
|
||||||
|
HealthCheckInterval int `json:"health_check_interval"`
|
||||||
|
HealthCheckPath string `json:"health_check_path,omitempty"`
|
||||||
|
HealthCheckPathParser string `json:"health_check_path_parser,omitempty"`
|
||||||
|
Persistence bool `json:"persistence"`
|
||||||
|
PersistenceTime int `json:"persistence_time"`
|
||||||
|
Method string `json:"method,omitempty"`
|
||||||
|
Rules []LoadBalancerRule `json:"rules,omitempty"`
|
||||||
|
ServerIps []ServerIpInfo `json:"server_ips,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerRule struct {
|
||||||
|
idField
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
PortBalancer uint16 `json:"port_balancer"`
|
||||||
|
PortServer uint16 `json:"port_server"`
|
||||||
|
Source string `json:"source,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
HealthCheckTest string `json:"health_check_test,omitempty"`
|
||||||
|
HealthCheckInterval *int `json:"health_check_interval"`
|
||||||
|
HealthCheckPath string `json:"health_check_path,omitempty"`
|
||||||
|
HealthCheckPathParser string `json:"health_check_path_parser,omitempty"`
|
||||||
|
Persistence *bool `json:"persistence"`
|
||||||
|
PersistenceTime *int `json:"persistence_time"`
|
||||||
|
Method string `json:"method,omitempty"`
|
||||||
|
Rules []LoadBalancerRule `json:"rules,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /load_balancers
|
||||||
|
func (api *API) ListLoadBalancers(args ...interface{}) ([]LoadBalancer, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, loadBalancerPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []LoadBalancer{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /load_balancers
|
||||||
|
func (api *API) CreateLoadBalancer(request *LoadBalancerRequest) (string, *LoadBalancer, error) {
|
||||||
|
url := createUrl(api, loadBalancerPathSegment)
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
err := api.Client.Post(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /load_balancers/{id}
|
||||||
|
func (api *API) GetLoadBalancer(lb_id string) (*LoadBalancer, error) {
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id)
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /load_balancers/{id}
|
||||||
|
func (api *API) DeleteLoadBalancer(lb_id string) (*LoadBalancer, error) {
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id)
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /load_balancers/{id}
|
||||||
|
func (api *API) UpdateLoadBalancer(lb_id string, request *LoadBalancerRequest) (*LoadBalancer, error) {
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id)
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /load_balancers/{id}/server_ips
|
||||||
|
func (api *API) ListLoadBalancerServerIps(lb_id string) ([]ServerIpInfo, error) {
|
||||||
|
result := []ServerIpInfo{}
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /load_balancers/{id}/server_ips/{id}
|
||||||
|
func (api *API) GetLoadBalancerServerIp(lb_id string, ip_id string) (*ServerIpInfo, error) {
|
||||||
|
result := new(ServerIpInfo)
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips", ip_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /load_balancers/{id}/server_ips
|
||||||
|
func (api *API) AddLoadBalancerServerIps(lb_id string, ip_ids []string) (*LoadBalancer, error) {
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
request := serverIps{
|
||||||
|
ServerIps: ip_ids,
|
||||||
|
}
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips")
|
||||||
|
err := api.Client.Post(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /load_balancers/{id}/server_ips/{id}
|
||||||
|
func (api *API) DeleteLoadBalancerServerIp(lb_id string, ip_id string) (*LoadBalancer, error) {
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "server_ips", ip_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /load_balancers/{load_balancer_id}/rules
|
||||||
|
func (api *API) ListLoadBalancerRules(lb_id string) ([]LoadBalancerRule, error) {
|
||||||
|
result := []LoadBalancerRule{}
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "rules")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /load_balancers/{load_balancer_id}/rules
|
||||||
|
func (api *API) AddLoadBalancerRules(lb_id string, lb_rules []LoadBalancerRule) (*LoadBalancer, error) {
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
data := struct {
|
||||||
|
Rules []LoadBalancerRule `json:"rules"`
|
||||||
|
}{lb_rules}
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "rules")
|
||||||
|
err := api.Client.Post(url, &data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /load_balancers/{load_balancer_id}/rules/{rule_id}
|
||||||
|
func (api *API) GetLoadBalancerRule(lb_id string, rule_id string) (*LoadBalancerRule, error) {
|
||||||
|
result := new(LoadBalancerRule)
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "rules", rule_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /load_balancers/{load_balancer_id}/rules/{rule_id}
|
||||||
|
func (api *API) DeleteLoadBalancerRule(lb_id string, rule_id string) (*LoadBalancer, error) {
|
||||||
|
result := new(LoadBalancer)
|
||||||
|
url := createUrl(api, loadBalancerPathSegment, lb_id, "rules", rule_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *LoadBalancer) GetState() (string, error) {
|
||||||
|
in, err := lb.api.GetLoadBalancer(lb.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Log struct {
|
||||||
|
ApiPtr
|
||||||
|
idField
|
||||||
|
typeField
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
SiteId string `json:"site_id,omitempty"`
|
||||||
|
StartDate string `json:"start_date,omitempty"`
|
||||||
|
EndDate string `json:"end_date,omitempty"`
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
Status *Status `json:"Status,omitempty"`
|
||||||
|
Resource *Identity `json:"resource,omitempty"`
|
||||||
|
User *Identity `json:"user,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /logs
|
||||||
|
func (api *API) ListLogs(period string, sd *time.Time, ed *time.Time, args ...interface{}) ([]Log, error) {
|
||||||
|
result := []Log{}
|
||||||
|
url, err := processQueryParamsExt(createUrl(api, logPathSegment), period, sd, ed, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /logs/{id}
|
||||||
|
func (api *API) GetLog(log_id string) (*Log, error) {
|
||||||
|
result := new(Log)
|
||||||
|
url := createUrl(api, logPathSegment, log_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
158
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringcenter.go
generated
vendored
Normal file
158
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringcenter.go
generated
vendored
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MonServerUsageSummary struct {
|
||||||
|
Identity
|
||||||
|
Agent *monitoringAgent `json:"agent,omitempty"`
|
||||||
|
Alerts *monitoringAlerts `json:"alerts,omitempty"`
|
||||||
|
Status *monitoringStatus `json:"status,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonServerUsageDetails struct {
|
||||||
|
Identity
|
||||||
|
Status *statusState `json:"status,omitempty"`
|
||||||
|
Agent *monitoringAgent `json:"agent,omitempty"`
|
||||||
|
Alerts *monitoringAlerts `json:"alerts,omitempty"`
|
||||||
|
CpuStatus *utilizationStatus `json:"cpu,omitempty"`
|
||||||
|
DiskStatus *utilizationStatus `json:"disk,omitempty"`
|
||||||
|
RamStatus *utilizationStatus `json:"ram,omitempty"`
|
||||||
|
PingStatus *pingStatus `json:"internal_ping,omitempty"`
|
||||||
|
TransferStatus *transferStatus `json:"transfer,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type monitoringStatus struct {
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
Cpu *statusState `json:"cpu,omitempty"`
|
||||||
|
Disk *statusState `json:"disk,omitempty"`
|
||||||
|
InternalPing *statusState `json:"internal_ping,omitempty"`
|
||||||
|
Ram *statusState `json:"ram,omitempty"`
|
||||||
|
Transfer *statusState `json:"transfer,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type utilizationStatus struct {
|
||||||
|
CriticalThreshold int `json:"critical,omitempty"`
|
||||||
|
WarningThreshold int `json:"warning,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Data []usageData `json:"data,omitempty"`
|
||||||
|
Unit *usageUnit `json:"unit,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type pingStatus struct {
|
||||||
|
CriticalThreshold int `json:"critical,omitempty"`
|
||||||
|
WarningThreshold int `json:"warning,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Data []pingData `json:"data,omitempty"`
|
||||||
|
Unit *pingUnit `json:"unit,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type transferStatus struct {
|
||||||
|
CriticalThreshold int `json:"critical,omitempty"`
|
||||||
|
WarningThreshold int `json:"warning,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Data []transferData `json:"data,omitempty"`
|
||||||
|
Unit *transferUnit `json:"unit,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type monitoringAgent struct {
|
||||||
|
AgentInstalled bool `json:"agent_installed"`
|
||||||
|
MissingAgentAlert bool `json:"missing_agent_alert"`
|
||||||
|
MonitoringNeedsAgent bool `json:"monitoring_needs_agent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type monitoringAlerts struct {
|
||||||
|
Ports *monitoringAlertInfo `json:"ports,omitempty"`
|
||||||
|
Process *monitoringAlertInfo `json:"process,omitempty"`
|
||||||
|
Resources *monitoringAlertInfo `json:"resources,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type monitoringAlertInfo struct {
|
||||||
|
Ok int `json:"ok"`
|
||||||
|
Warning int `json:"warning"`
|
||||||
|
Critical int `json:"critical"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type usageData struct {
|
||||||
|
Date string `json:"date,omitempty"`
|
||||||
|
UsedPercent float32 `json:"used_percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type usageUnit struct {
|
||||||
|
UsedPercent string `json:"used_percent,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type pingUnit struct {
|
||||||
|
PackagesLost string `json:"pl,omitempty"`
|
||||||
|
AccessTime string `json:"rta,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type pingData struct {
|
||||||
|
Date string `json:"date,omitempty"`
|
||||||
|
PackagesLost int `json:"pl"`
|
||||||
|
AccessTime float32 `json:"rta"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type transferUnit struct {
|
||||||
|
Downstream string `json:"downstream,omitempty"`
|
||||||
|
Upstream string `json:"upstream,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type transferData struct {
|
||||||
|
Date string `json:"date,omitempty"`
|
||||||
|
Downstream int `json:"downstream"`
|
||||||
|
Upstream int `json:"upstream"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_center
|
||||||
|
func (api *API) ListMonitoringServersUsages(args ...interface{}) ([]MonServerUsageSummary, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, monitorCenterPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []MonServerUsageSummary{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_center/{server_id}
|
||||||
|
func (api *API) GetMonitoringServerUsage(ser_id string, period string, dates ...time.Time) (*MonServerUsageDetails, error) {
|
||||||
|
if period == "" {
|
||||||
|
return nil, errors.New("Time period must be provided.")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := make(map[string]interface{}, len(dates)+1)
|
||||||
|
params["period"] = period
|
||||||
|
|
||||||
|
if len(dates) == 2 {
|
||||||
|
if dates[0].After(dates[1]) {
|
||||||
|
return nil, errors.New("Start date cannot be after end date.")
|
||||||
|
}
|
||||||
|
|
||||||
|
params["start_date"] = dates[0].Format(time.RFC3339)
|
||||||
|
params["end_date"] = dates[1].Format(time.RFC3339)
|
||||||
|
|
||||||
|
} else if len(dates) > 0 {
|
||||||
|
return nil, errors.New("Start and end dates must be provided.")
|
||||||
|
}
|
||||||
|
url := createUrl(api, monitorCenterPathSegment, ser_id)
|
||||||
|
url = appendQueryParams(url, params)
|
||||||
|
result := new(MonServerUsageDetails)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
305
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringpolicies.go
generated
vendored
Normal file
305
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/monitoringpolicies.go
generated
vendored
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MonitoringPolicy struct {
|
||||||
|
ApiPtr
|
||||||
|
idField
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
Default *int `json:"default,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
Agent bool `json:"agent"`
|
||||||
|
Servers []Identity `json:"servers,omitempty"`
|
||||||
|
Thresholds *MonitoringThreshold `json:"thresholds,omitempty"`
|
||||||
|
Ports []MonitoringPort `json:"ports,omitempty"`
|
||||||
|
Processes []MonitoringProcess `json:"processes,omitempty"`
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitoringThreshold struct {
|
||||||
|
Cpu *MonitoringLevel `json:"cpu,omitempty"`
|
||||||
|
Ram *MonitoringLevel `json:"ram,omitempty"`
|
||||||
|
Disk *MonitoringLevel `json:"disk,omitempty"`
|
||||||
|
Transfer *MonitoringLevel `json:"transfer,omitempty"`
|
||||||
|
InternalPing *MonitoringLevel `json:"internal_ping,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitoringLevel struct {
|
||||||
|
Warning *MonitoringValue `json:"warning,omitempty"`
|
||||||
|
Critical *MonitoringValue `json:"critical,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitoringValue struct {
|
||||||
|
Value int `json:"value"`
|
||||||
|
Alert bool `json:"alert"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitoringPort struct {
|
||||||
|
idField
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
AlertIf string `json:"alert_if,omitempty"`
|
||||||
|
EmailNotification bool `json:"email_notification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitoringProcess struct {
|
||||||
|
idField
|
||||||
|
Process string `json:"process,omitempty"`
|
||||||
|
AlertIf string `json:"alert_if,omitempty"`
|
||||||
|
EmailNotification bool `json:"email_notification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies
|
||||||
|
func (api *API) ListMonitoringPolicies(args ...interface{}) ([]MonitoringPolicy, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, monitorPolicyPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []MonitoringPolicy{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /monitoring_policies
|
||||||
|
func (api *API) CreateMonitoringPolicy(mp *MonitoringPolicy) (string, *MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment)
|
||||||
|
err := api.Client.Post(url, &mp, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}
|
||||||
|
func (api *API) GetMonitoringPolicy(mp_id string) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /monitoring_policies/{id}
|
||||||
|
func (api *API) DeleteMonitoringPolicy(mp_id string) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /monitoring_policies/{id}
|
||||||
|
func (api *API) UpdateMonitoringPolicy(mp_id string, mp *MonitoringPolicy) (*MonitoringPolicy, error) {
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id)
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
err := api.Client.Put(url, &mp, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}/ports
|
||||||
|
func (api *API) ListMonitoringPolicyPorts(mp_id string) ([]MonitoringPort, error) {
|
||||||
|
result := []MonitoringPort{}
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /monitoring_policies/{id}/ports
|
||||||
|
func (api *API) AddMonitoringPolicyPorts(mp_id string, mp_ports []MonitoringPort) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
data := struct {
|
||||||
|
Ports []MonitoringPort `json:"ports"`
|
||||||
|
}{mp_ports}
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports")
|
||||||
|
err := api.Client.Post(url, &data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}/ports/{id}
|
||||||
|
func (api *API) GetMonitoringPolicyPort(mp_id string, port_id string) (*MonitoringPort, error) {
|
||||||
|
result := new(MonitoringPort)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports", port_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /monitoring_policies/{id}/ports/{id}
|
||||||
|
func (api *API) DeleteMonitoringPolicyPort(mp_id string, port_id string) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports", port_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /monitoring_policies/{id}/ports/{id}
|
||||||
|
func (api *API) ModifyMonitoringPolicyPort(mp_id string, port_id string, mp_port *MonitoringPort) (*MonitoringPolicy, error) {
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "ports", port_id)
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
req := struct {
|
||||||
|
Ports *MonitoringPort `json:"ports"`
|
||||||
|
}{mp_port}
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}/processes
|
||||||
|
func (api *API) ListMonitoringPolicyProcesses(mp_id string) ([]MonitoringProcess, error) {
|
||||||
|
result := []MonitoringProcess{}
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /monitoring_policies/{id}/processes
|
||||||
|
func (api *API) AddMonitoringPolicyProcesses(mp_id string, mp_procs []MonitoringProcess) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
request := struct {
|
||||||
|
Processes []MonitoringProcess `json:"processes"`
|
||||||
|
}{mp_procs}
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes")
|
||||||
|
err := api.Client.Post(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}/processes/{id}
|
||||||
|
func (api *API) GetMonitoringPolicyProcess(mp_id string, proc_id string) (*MonitoringProcess, error) {
|
||||||
|
result := new(MonitoringProcess)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes", proc_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /monitoring_policies/{id}/processes/{id}
|
||||||
|
func (api *API) DeleteMonitoringPolicyProcess(mp_id string, proc_id string) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes", proc_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /monitoring_policies/{id}/processes/{id}
|
||||||
|
func (api *API) ModifyMonitoringPolicyProcess(mp_id string, proc_id string, mp_proc *MonitoringProcess) (*MonitoringPolicy, error) {
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "processes", proc_id)
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
req := struct {
|
||||||
|
Processes *MonitoringProcess `json:"processes"`
|
||||||
|
}{mp_proc}
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}/servers
|
||||||
|
func (api *API) ListMonitoringPolicyServers(mp_id string) ([]Identity, error) {
|
||||||
|
result := []Identity{}
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /monitoring_policies/{id}/servers
|
||||||
|
func (api *API) AttachMonitoringPolicyServers(mp_id string, sids []string) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
request := servers{
|
||||||
|
Servers: sids,
|
||||||
|
}
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers")
|
||||||
|
err := api.Client.Post(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /monitoring_policies/{id}/servers/{id}
|
||||||
|
func (api *API) GetMonitoringPolicyServer(mp_id string, ser_id string) (*Identity, error) {
|
||||||
|
result := new(Identity)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers", ser_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /monitoring_policies/{id}/servers/{id}
|
||||||
|
func (api *API) RemoveMonitoringPolicyServer(mp_id string, ser_id string) (*MonitoringPolicy, error) {
|
||||||
|
result := new(MonitoringPolicy)
|
||||||
|
url := createUrl(api, monitorPolicyPathSegment, mp_id, "servers", ser_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mp *MonitoringPolicy) GetState() (string, error) {
|
||||||
|
in, err := mp.api.GetMonitoringPolicy(mp.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
163
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/oneandone.go
generated
vendored
Normal file
163
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/oneandone.go
generated
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct to hold the required information for accessing the API.
|
||||||
|
//
|
||||||
|
// Instances of this type contain the URL of the endpoint to access the API as well as the API access token to be used.
|
||||||
|
// They offer also all methods that allow to access the various objects that are returned by top level resources of
|
||||||
|
// the API.
|
||||||
|
type API struct {
|
||||||
|
Endpoint string
|
||||||
|
Client *restClient
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiPtr struct {
|
||||||
|
api *API
|
||||||
|
}
|
||||||
|
|
||||||
|
type idField struct {
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type typeField struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type nameField struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type descField struct {
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type countField struct {
|
||||||
|
Count int `json:"count,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverIps struct {
|
||||||
|
ServerIps []string `json:"server_ips"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type servers struct {
|
||||||
|
Servers []string `json:"servers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiInstance interface {
|
||||||
|
GetState() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
datacenterPathSegment = "datacenters"
|
||||||
|
dvdIsoPathSegment = "dvd_isos"
|
||||||
|
firewallPolicyPathSegment = "firewall_policies"
|
||||||
|
imagePathSegment = "images"
|
||||||
|
loadBalancerPathSegment = "load_balancers"
|
||||||
|
logPathSegment = "logs"
|
||||||
|
monitorCenterPathSegment = "monitoring_center"
|
||||||
|
monitorPolicyPathSegment = "monitoring_policies"
|
||||||
|
pingPathSegment = "ping"
|
||||||
|
pingAuthPathSegment = "ping_auth"
|
||||||
|
pricingPathSegment = "pricing"
|
||||||
|
privateNetworkPathSegment = "private_networks"
|
||||||
|
publicIpPathSegment = "public_ips"
|
||||||
|
rolePathSegment = "roles"
|
||||||
|
serverPathSegment = "servers"
|
||||||
|
serverAppliancePathSegment = "server_appliances"
|
||||||
|
sharedStoragePathSegment = "shared_storages"
|
||||||
|
usagePathSegment = "usages"
|
||||||
|
userPathSegment = "users"
|
||||||
|
vpnPathSegment = "vpns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct to hold the status of an API object.
|
||||||
|
//
|
||||||
|
// Values of this type are used to represent the status of API objects like servers, firewall policies and the like.
|
||||||
|
//
|
||||||
|
// The value of the "State" field can represent fixed states like "ACTIVE" or "POWERED_ON" but also transitional
|
||||||
|
// states like "POWERING_ON" or "CONFIGURING".
|
||||||
|
//
|
||||||
|
// For fixed states the "Percent" field is empty where as for transitional states it contains the progress of the
|
||||||
|
// transition in percent.
|
||||||
|
type Status struct {
|
||||||
|
State string `json:"state"`
|
||||||
|
Percent int `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type statusState struct {
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Identity struct {
|
||||||
|
idField
|
||||||
|
nameField
|
||||||
|
}
|
||||||
|
|
||||||
|
type License struct {
|
||||||
|
nameField
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new API instance.
|
||||||
|
//
|
||||||
|
// Explanations about given token and url information can be found online under the following url TODO add url!
|
||||||
|
func New(token string, url string) *API {
|
||||||
|
api := new(API)
|
||||||
|
api.Endpoint = url
|
||||||
|
api.Client = newRestClient(token)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a given integer value into a pointer of the same type.
|
||||||
|
func Int2Pointer(input int) *int {
|
||||||
|
result := new(int)
|
||||||
|
*result = input
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a given boolean value into a pointer of the same type.
|
||||||
|
func Bool2Pointer(input bool) *bool {
|
||||||
|
result := new(bool)
|
||||||
|
*result = input
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs busy-waiting for types that implement ApiInstance interface.
|
||||||
|
func (api *API) WaitForState(in ApiInstance, state string, sec time.Duration, count int) error {
|
||||||
|
if in != nil {
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
s, err := in.GetState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if s == state {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
time.Sleep(sec * time.Second)
|
||||||
|
}
|
||||||
|
return errors.New(reflect.ValueOf(in).Type().String() + " operation timeout.")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Waits until instance is deleted for types that implement ApiInstance interface.
|
||||||
|
func (api *API) WaitUntilDeleted(in ApiInstance) error {
|
||||||
|
var err error
|
||||||
|
for in != nil {
|
||||||
|
_, err = in.GetState()
|
||||||
|
if err != nil {
|
||||||
|
if apiError, ok := err.(apiError); ok && apiError.httpStatusCode == http.StatusNotFound {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// GET /ping
|
||||||
|
// Returns "PONG" if API is running
|
||||||
|
func (api *API) Ping() ([]string, error) {
|
||||||
|
url := createUrl(api, pingPathSegment)
|
||||||
|
result := []string{}
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /ping_auth
|
||||||
|
// Returns "PONG" if the API is running and the authentication token is valid
|
||||||
|
func (api *API) PingAuth() ([]string, error) {
|
||||||
|
url := createUrl(api, pingAuthPathSegment)
|
||||||
|
result := []string{}
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type Pricing struct {
|
||||||
|
Currency string `json:"currency,omitempty"`
|
||||||
|
Plan *pricingPlan `json:"pricing_plans,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type pricingPlan struct {
|
||||||
|
Image *pricingItem `json:"image,omitempty"`
|
||||||
|
PublicIPs []pricingItem `json:"public_ips,omitempty"`
|
||||||
|
Servers *serverPricing `json:"servers,omitempty"`
|
||||||
|
SharedStorage *pricingItem `json:"shared_storage,omitempty"`
|
||||||
|
SoftwareLicenses []pricingItem `json:"software_licences,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverPricing struct {
|
||||||
|
FixedServers []pricingItem `json:"fixed_servers,omitempty"`
|
||||||
|
FlexServers []pricingItem `json:"flexible_server,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type pricingItem struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
GrossPrice string `json:"price_gross,omitempty"`
|
||||||
|
NetPrice string `json:"price_net,omitempty"`
|
||||||
|
Unit string `json:"unit,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /pricing
|
||||||
|
func (api *API) GetPricing() (*Pricing, error) {
|
||||||
|
result := new(Pricing)
|
||||||
|
url := createUrl(api, pricingPathSegment)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
149
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/privatenetworks.go
generated
vendored
Normal file
149
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/privatenetworks.go
generated
vendored
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PrivateNetwork struct {
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
CloudpanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
NetworkAddress string `json:"network_address,omitempty"`
|
||||||
|
SubnetMask string `json:"subnet_mask,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
SiteId string `json:"site_id,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
Servers []Identity `json:"servers,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrivateNetworkRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
NetworkAddress string `json:"network_address,omitempty"`
|
||||||
|
SubnetMask string `json:"subnet_mask,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /private_networks
|
||||||
|
func (api *API) ListPrivateNetworks(args ...interface{}) ([]PrivateNetwork, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, privateNetworkPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []PrivateNetwork{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /private_networks
|
||||||
|
func (api *API) CreatePrivateNetwork(request *PrivateNetworkRequest) (string, *PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
url := createUrl(api, privateNetworkPathSegment)
|
||||||
|
err := api.Client.Post(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /private_networks/{id}
|
||||||
|
func (api *API) GetPrivateNetwork(pn_id string) (*PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /private_networks/{id}
|
||||||
|
func (api *API) UpdatePrivateNetwork(pn_id string, request *PrivateNetworkRequest) (*PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id)
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /private_networks/{id}
|
||||||
|
func (api *API) DeletePrivateNetwork(pn_id string) (*PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /private_networks/{id}/servers
|
||||||
|
func (api *API) ListPrivateNetworkServers(pn_id string) ([]Identity, error) {
|
||||||
|
result := []Identity{}
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id, "servers")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /private_networks/{id}/servers
|
||||||
|
func (api *API) AttachPrivateNetworkServers(pn_id string, sids []string) (*PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
req := servers{
|
||||||
|
Servers: sids,
|
||||||
|
}
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id, "servers")
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /private_networks/{id}/servers/{id}
|
||||||
|
func (api *API) GetPrivateNetworkServer(pn_id string, server_id string) (*Identity, error) {
|
||||||
|
result := new(Identity)
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id, "servers", server_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /private_networks/{id}/servers/{id}
|
||||||
|
func (api *API) DetachPrivateNetworkServer(pn_id string, pns_id string) (*PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
url := createUrl(api, privateNetworkPathSegment, pn_id, "servers", pns_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pn *PrivateNetwork) GetState() (string, error) {
|
||||||
|
in, err := pn.api.GetPrivateNetwork(pn.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
108
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/publicips.go
generated
vendored
Normal file
108
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/publicips.go
generated
vendored
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type PublicIp struct {
|
||||||
|
idField
|
||||||
|
typeField
|
||||||
|
IpAddress string `json:"ip,omitempty"`
|
||||||
|
AssignedTo *assignedTo `json:"assigned_to,omitempty"`
|
||||||
|
ReverseDns string `json:"reverse_dns,omitempty"`
|
||||||
|
IsDhcp *bool `json:"is_dhcp,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
SiteId string `json:"site_id,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type assignedTo struct {
|
||||||
|
Identity
|
||||||
|
typeField
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
IpTypeV4 = "IPV4"
|
||||||
|
IpTypeV6 = "IPV6"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GET /public_ips
|
||||||
|
func (api *API) ListPublicIps(args ...interface{}) ([]PublicIp, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, publicIpPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []PublicIp{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /public_ips
|
||||||
|
func (api *API) CreatePublicIp(ip_type string, reverse_dns string, datacenter_id string) (string, *PublicIp, error) {
|
||||||
|
res := new(PublicIp)
|
||||||
|
url := createUrl(api, publicIpPathSegment)
|
||||||
|
req := struct {
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
ReverseDns string `json:"reverse_dns,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}{DatacenterId: datacenter_id, ReverseDns: reverse_dns, Type: ip_type}
|
||||||
|
err := api.Client.Post(url, &req, &res, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
res.api = api
|
||||||
|
return res.Id, res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /public_ips/{id}
|
||||||
|
func (api *API) GetPublicIp(ip_id string) (*PublicIp, error) {
|
||||||
|
result := new(PublicIp)
|
||||||
|
url := createUrl(api, publicIpPathSegment, ip_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /public_ips/{id}
|
||||||
|
func (api *API) DeletePublicIp(ip_id string) (*PublicIp, error) {
|
||||||
|
result := new(PublicIp)
|
||||||
|
url := createUrl(api, publicIpPathSegment, ip_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /public_ips/{id}
|
||||||
|
func (api *API) UpdatePublicIp(ip_id string, reverse_dns string) (*PublicIp, error) {
|
||||||
|
result := new(PublicIp)
|
||||||
|
url := createUrl(api, publicIpPathSegment, ip_id)
|
||||||
|
req := struct {
|
||||||
|
ReverseDns string `json:"reverse_dns,omitempty"`
|
||||||
|
}{reverse_dns}
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ip *PublicIp) GetState() (string, error) {
|
||||||
|
in, err := ip.api.GetPublicIp(ip.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
213
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/restclient.go
generated
vendored
Normal file
213
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/restclient.go
generated
vendored
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
p_url "net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type restClient struct {
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRestClient(token string) *restClient {
|
||||||
|
restClient := new(restClient)
|
||||||
|
restClient.token = token
|
||||||
|
return restClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *restClient) Get(url string, result interface{}, expectedStatus int) error {
|
||||||
|
return c.doRequest(url, "GET", nil, result, expectedStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *restClient) Delete(url string, requestBody interface{}, result interface{}, expectedStatus int) error {
|
||||||
|
return c.doRequest(url, "DELETE", requestBody, result, expectedStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *restClient) Post(url string, requestBody interface{}, result interface{}, expectedStatus int) error {
|
||||||
|
return c.doRequest(url, "POST", requestBody, result, expectedStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *restClient) Put(url string, requestBody interface{}, result interface{}, expectedStatus int) error {
|
||||||
|
return c.doRequest(url, "PUT", requestBody, result, expectedStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *restClient) doRequest(url string, method string, requestBody interface{}, result interface{}, expectedStatus int) error {
|
||||||
|
var bodyData io.Reader
|
||||||
|
if requestBody != nil {
|
||||||
|
data, _ := json.Marshal(requestBody)
|
||||||
|
bodyData = bytes.NewBuffer(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
request, err := http.NewRequest(method, url, bodyData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Header.Add("X-Token", c.token)
|
||||||
|
request.Header.Add("Content-Type", "application/json")
|
||||||
|
client := http.Client{}
|
||||||
|
response, err := client.Do(request)
|
||||||
|
if err = isError(response, expectedStatus, err); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer response.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.unmarshal(body, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *restClient) unmarshal(data []byte, result interface{}) error {
|
||||||
|
err := json.Unmarshal(data, result)
|
||||||
|
if err != nil {
|
||||||
|
// handle the case when the result is an empty array instead of an object
|
||||||
|
switch err.(type) {
|
||||||
|
case *json.UnmarshalTypeError:
|
||||||
|
var ra []interface{}
|
||||||
|
e := json.Unmarshal(data, &ra)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
} else if len(ra) > 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isError(response *http.Response, expectedStatus int, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if response != nil {
|
||||||
|
if response.StatusCode == expectedStatus {
|
||||||
|
// we got a response with the expected HTTP status code, hence no error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
body, _ := ioutil.ReadAll(response.Body)
|
||||||
|
// extract the API's error message to be returned later
|
||||||
|
er_resp := new(errorResponse)
|
||||||
|
err = json.Unmarshal(body, er_resp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiError{response.StatusCode, fmt.Sprintf("Type: %s; Message: %s", er_resp.Type, er_resp.Message)}
|
||||||
|
}
|
||||||
|
return errors.New("Generic error - no response from the REST API service.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createUrl(api *API, sections ...interface{}) string {
|
||||||
|
url := api.Endpoint
|
||||||
|
for _, section := range sections {
|
||||||
|
url += "/" + fmt.Sprint(section)
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeParameterMap(args ...interface{}) (map[string]interface{}, error) {
|
||||||
|
qps := make(map[string]interface{}, len(args))
|
||||||
|
var is_true bool
|
||||||
|
var page, per_page int
|
||||||
|
var sort, query, fields string
|
||||||
|
|
||||||
|
for i, p := range args {
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
page, is_true = p.(int)
|
||||||
|
if !is_true {
|
||||||
|
return nil, errors.New("1st parameter must be a page number (integer).")
|
||||||
|
} else if page > 0 {
|
||||||
|
qps["page"] = page
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
per_page, is_true = p.(int)
|
||||||
|
if !is_true {
|
||||||
|
return nil, errors.New("2nd parameter must be a per_page number (integer).")
|
||||||
|
} else if per_page > 0 {
|
||||||
|
qps["per_page"] = per_page
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
sort, is_true = p.(string)
|
||||||
|
if !is_true {
|
||||||
|
return nil, errors.New("3rd parameter must be a sorting property string (e.g. 'name' or '-name').")
|
||||||
|
} else if sort != "" {
|
||||||
|
qps["sort"] = sort
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
query, is_true = p.(string)
|
||||||
|
if !is_true {
|
||||||
|
return nil, errors.New("4th parameter must be a query string to look for the response.")
|
||||||
|
} else if query != "" {
|
||||||
|
qps["q"] = query
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
fields, is_true = p.(string)
|
||||||
|
if !is_true {
|
||||||
|
return nil, errors.New("5th parameter must be fields properties string (e.g. 'id,name').")
|
||||||
|
} else if fields != "" {
|
||||||
|
qps["fields"] = fields
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("Wrong number of parameters.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return qps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processQueryParams(url string, args ...interface{}) (string, error) {
|
||||||
|
if len(args) > 0 {
|
||||||
|
params, err := makeParameterMap(args...)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
url = appendQueryParams(url, params)
|
||||||
|
}
|
||||||
|
return url, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processQueryParamsExt(url string, period string, sd *time.Time, ed *time.Time, args ...interface{}) (string, error) {
|
||||||
|
var qm map[string]interface{}
|
||||||
|
var err error
|
||||||
|
if len(args) > 0 {
|
||||||
|
qm, err = makeParameterMap(args...)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qm = make(map[string]interface{}, 3)
|
||||||
|
}
|
||||||
|
qm["period"] = period
|
||||||
|
if sd != nil && ed != nil {
|
||||||
|
if sd.After(*ed) {
|
||||||
|
return "", errors.New("Start date cannot be after end date.")
|
||||||
|
}
|
||||||
|
qm["start_date"] = sd.Format(time.RFC3339)
|
||||||
|
qm["end_date"] = ed.Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
url = appendQueryParams(url, qm)
|
||||||
|
return url, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendQueryParams(url string, params map[string]interface{}) string {
|
||||||
|
queryUrl, _ := p_url.Parse(url)
|
||||||
|
parameters := p_url.Values{}
|
||||||
|
for key, value := range params {
|
||||||
|
parameters.Add(key, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
queryUrl.RawQuery = parameters.Encode()
|
||||||
|
return queryUrl.String()
|
||||||
|
}
|
|
@ -0,0 +1,595 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type Role struct {
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
Default *int `json:"default,omitempty"`
|
||||||
|
Permissions *Permissions `json:"permissions,omitempty"`
|
||||||
|
Users []Identity `json:"users,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type Permissions struct {
|
||||||
|
Backups *BackupPerm `json:"backups,omitempty"`
|
||||||
|
Firewalls *FirewallPerm `json:"firewall_policies,omitempty"`
|
||||||
|
Images *ImagePerm `json:"images,omitempty"`
|
||||||
|
Invoice *InvoicePerm `json:"interactive_invoices,omitempty"`
|
||||||
|
IPs *IPPerm `json:"public_ips,omitempty"`
|
||||||
|
LoadBalancers *LoadBalancerPerm `json:"load_balancers,omitempty"`
|
||||||
|
Logs *LogPerm `json:"logs,omitempty"`
|
||||||
|
MonitorCenter *MonitorCenterPerm `json:"monitoring_center,omitempty"`
|
||||||
|
MonitorPolicies *MonitorPolicyPerm `json:"monitoring_policies,omitempty"`
|
||||||
|
PrivateNetworks *PrivateNetworkPerm `json:"private_networks,omitempty"`
|
||||||
|
Roles *RolePerm `json:"roles,omitempty"`
|
||||||
|
Servers *ServerPerm `json:"servers,omitempty"`
|
||||||
|
SharedStorage *SharedStoragePerm `json:"shared_storages,omitempty"`
|
||||||
|
Usages *UsagePerm `json:"usages,omitempty"`
|
||||||
|
Users *UserPerm `json:"users,omitempty"`
|
||||||
|
VPNs *VPNPerm `json:"vpn,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackupPerm struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FirewallPerm struct {
|
||||||
|
Clone bool `json:"clone"`
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageAttachedServerIPs bool `json:"manage_attached_server_ips"`
|
||||||
|
ManageRules bool `json:"manage_rules"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImagePerm struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
DisableAutoCreate bool `json:"disable_automatic_creation"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvoicePerm struct {
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPPerm struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
Release bool `json:"release"`
|
||||||
|
SetReverseDNS bool `json:"set_reverse_dns"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerPerm struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageAttachedServerIPs bool `json:"manage_attached_server_ips"`
|
||||||
|
ManageRules bool `json:"manage_rules"`
|
||||||
|
Modify bool `json:"modify"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogPerm struct {
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitorCenterPerm struct {
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MonitorPolicyPerm struct {
|
||||||
|
Clone bool `json:"clone"`
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageAttachedServers bool `json:"manage_attached_servers"`
|
||||||
|
ManagePorts bool `json:"manage_ports"`
|
||||||
|
ManageProcesses bool `json:"manage_processes"`
|
||||||
|
ModifyResources bool `json:"modify_resources"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetEmail bool `json:"set_email"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrivateNetworkPerm struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageAttachedServers bool `json:"manage_attached_servers"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
SetNetworkInfo bool `json:"set_network_info"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RolePerm struct {
|
||||||
|
Clone bool `json:"clone"`
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageUsers bool `json:"manage_users"`
|
||||||
|
Modify bool `json:"modify"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerPerm struct {
|
||||||
|
AccessKVMConsole bool `json:"access_kvm_console"`
|
||||||
|
AssignIP bool `json:"assign_ip"`
|
||||||
|
Clone bool `json:"clone"`
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageDVD bool `json:"manage_dvd"`
|
||||||
|
ManageSnapshot bool `json:"manage_snapshot"`
|
||||||
|
Reinstall bool `json:"reinstall"`
|
||||||
|
Resize bool `json:"resize"`
|
||||||
|
Restart bool `json:"restart"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
Shutdown bool `json:"shutdown"`
|
||||||
|
Start bool `json:"start"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SharedStoragePerm struct {
|
||||||
|
Access bool `json:"access"`
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
ManageAttachedServers bool `json:"manage_attached_servers"`
|
||||||
|
Resize bool `json:"resize"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UsagePerm struct {
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserPerm struct {
|
||||||
|
ChangeRole bool `json:"change_role"`
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
Disable bool `json:"disable"`
|
||||||
|
Enable bool `json:"enable"`
|
||||||
|
ManageAPI bool `json:"manage_api"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetEmail bool `json:"set_email"`
|
||||||
|
SetPassword bool `json:"set_password"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VPNPerm struct {
|
||||||
|
Create bool `json:"create"`
|
||||||
|
Delete bool `json:"delete"`
|
||||||
|
DownloadFile bool `json:"download_file"`
|
||||||
|
SetDescription bool `json:"set_description"`
|
||||||
|
SetName bool `json:"set_name"`
|
||||||
|
Show bool `json:"show"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /roles
|
||||||
|
func (api *API) ListRoles(args ...interface{}) ([]Role, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, rolePathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []Role{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, role := range result {
|
||||||
|
role.api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /roles
|
||||||
|
func (api *API) CreateRole(name string) (string, *Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment)
|
||||||
|
req := struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}{name}
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /roles/{role_id}
|
||||||
|
func (api *API) GetRole(role_id string) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /roles/{role_id}
|
||||||
|
func (api *API) ModifyRole(role_id string, name string, description string, state string) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id)
|
||||||
|
req := struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
}{Name: name, Description: description, State: state}
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /roles/{role_id}
|
||||||
|
func (api *API) DeleteRole(role_id string) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /roles/{role_id}/permissions
|
||||||
|
func (api *API) GetRolePermissions(role_id string) (*Permissions, error) {
|
||||||
|
result := new(Permissions)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "permissions")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /roles/{role_id}/permissions
|
||||||
|
func (api *API) ModifyRolePermissions(role_id string, perm *Permissions) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "permissions")
|
||||||
|
err := api.Client.Put(url, &perm, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /roles/{role_id}/users
|
||||||
|
func (api *API) ListRoleUsers(role_id string) ([]Identity, error) {
|
||||||
|
result := []Identity{}
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "users")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /roles/{role_id}/users
|
||||||
|
func (api *API) AssignRoleUsers(role_id string, user_ids []string) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "users")
|
||||||
|
req := struct {
|
||||||
|
Users []string `json:"users"`
|
||||||
|
}{user_ids}
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /roles/{role_id}/users/{user_id}
|
||||||
|
func (api *API) GetRoleUser(role_id string, user_id string) (*Identity, error) {
|
||||||
|
result := new(Identity)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "users", user_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /roles/{role_id}/users/{user_id}
|
||||||
|
func (api *API) RemoveRoleUser(role_id string, user_id string) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "users", user_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /roles/{role_id}/clone
|
||||||
|
func (api *API) CloneRole(role_id string, name string) (*Role, error) {
|
||||||
|
result := new(Role)
|
||||||
|
url := createUrl(api, rolePathSegment, role_id, "clone")
|
||||||
|
req := struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}{name}
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role *Role) GetState() (string, error) {
|
||||||
|
in, err := role.api.GetRole(role.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all backups' permissions
|
||||||
|
func (bp *BackupPerm) SetAll(value bool) {
|
||||||
|
bp.Create = value
|
||||||
|
bp.Delete = value
|
||||||
|
bp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all firewall policies' permissions
|
||||||
|
func (fp *FirewallPerm) SetAll(value bool) {
|
||||||
|
fp.Clone = value
|
||||||
|
fp.Create = value
|
||||||
|
fp.Delete = value
|
||||||
|
fp.ManageAttachedServerIPs = value
|
||||||
|
fp.ManageRules = value
|
||||||
|
fp.SetDescription = value
|
||||||
|
fp.SetName = value
|
||||||
|
fp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all images' permissions
|
||||||
|
func (imp *ImagePerm) SetAll(value bool) {
|
||||||
|
imp.Create = value
|
||||||
|
imp.Delete = value
|
||||||
|
imp.DisableAutoCreate = value
|
||||||
|
imp.SetDescription = value
|
||||||
|
imp.SetName = value
|
||||||
|
imp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all invoice's permissions
|
||||||
|
func (inp *InvoicePerm) SetAll(value bool) {
|
||||||
|
inp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all IPs' permissions
|
||||||
|
func (ipp *IPPerm) SetAll(value bool) {
|
||||||
|
ipp.Create = value
|
||||||
|
ipp.Delete = value
|
||||||
|
ipp.Release = value
|
||||||
|
ipp.SetReverseDNS = value
|
||||||
|
ipp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all load balancers' permissions
|
||||||
|
func (lbp *LoadBalancerPerm) SetAll(value bool) {
|
||||||
|
lbp.Create = value
|
||||||
|
lbp.Delete = value
|
||||||
|
lbp.ManageAttachedServerIPs = value
|
||||||
|
lbp.ManageRules = value
|
||||||
|
lbp.Modify = value
|
||||||
|
lbp.SetDescription = value
|
||||||
|
lbp.SetName = value
|
||||||
|
lbp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all logs' permissions
|
||||||
|
func (lp *LogPerm) SetAll(value bool) {
|
||||||
|
lp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all monitoring center's permissions
|
||||||
|
func (mcp *MonitorCenterPerm) SetAll(value bool) {
|
||||||
|
mcp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all monitoring policies' permissions
|
||||||
|
func (mpp *MonitorPolicyPerm) SetAll(value bool) {
|
||||||
|
mpp.Clone = value
|
||||||
|
mpp.Create = value
|
||||||
|
mpp.Delete = value
|
||||||
|
mpp.ManageAttachedServers = value
|
||||||
|
mpp.ManagePorts = value
|
||||||
|
mpp.ManageProcesses = value
|
||||||
|
mpp.ModifyResources = value
|
||||||
|
mpp.SetDescription = value
|
||||||
|
mpp.SetEmail = value
|
||||||
|
mpp.SetName = value
|
||||||
|
mpp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all private networks' permissions
|
||||||
|
func (pnp *PrivateNetworkPerm) SetAll(value bool) {
|
||||||
|
pnp.Create = value
|
||||||
|
pnp.Delete = value
|
||||||
|
pnp.ManageAttachedServers = value
|
||||||
|
pnp.SetDescription = value
|
||||||
|
pnp.SetName = value
|
||||||
|
pnp.SetNetworkInfo = value
|
||||||
|
pnp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all roles' permissions
|
||||||
|
func (rp *RolePerm) SetAll(value bool) {
|
||||||
|
rp.Clone = value
|
||||||
|
rp.Create = value
|
||||||
|
rp.Delete = value
|
||||||
|
rp.ManageUsers = value
|
||||||
|
rp.Modify = value
|
||||||
|
rp.SetDescription = value
|
||||||
|
rp.SetName = value
|
||||||
|
rp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all servers' permissions
|
||||||
|
func (sp *ServerPerm) SetAll(value bool) {
|
||||||
|
sp.AccessKVMConsole = value
|
||||||
|
sp.AssignIP = value
|
||||||
|
sp.Clone = value
|
||||||
|
sp.Create = value
|
||||||
|
sp.Delete = value
|
||||||
|
sp.ManageDVD = value
|
||||||
|
sp.ManageSnapshot = value
|
||||||
|
sp.Reinstall = value
|
||||||
|
sp.Resize = value
|
||||||
|
sp.Restart = value
|
||||||
|
sp.SetDescription = value
|
||||||
|
sp.SetName = value
|
||||||
|
sp.Show = value
|
||||||
|
sp.Shutdown = value
|
||||||
|
sp.Start = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all shared storages' permissions
|
||||||
|
func (ssp *SharedStoragePerm) SetAll(value bool) {
|
||||||
|
ssp.Access = value
|
||||||
|
ssp.Create = value
|
||||||
|
ssp.Delete = value
|
||||||
|
ssp.ManageAttachedServers = value
|
||||||
|
ssp.Resize = value
|
||||||
|
ssp.SetDescription = value
|
||||||
|
ssp.SetName = value
|
||||||
|
ssp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all usages' permissions
|
||||||
|
func (up *UsagePerm) SetAll(value bool) {
|
||||||
|
up.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all users' permissions
|
||||||
|
func (up *UserPerm) SetAll(value bool) {
|
||||||
|
up.ChangeRole = value
|
||||||
|
up.Create = value
|
||||||
|
up.Delete = value
|
||||||
|
up.Disable = value
|
||||||
|
up.Enable = value
|
||||||
|
up.ManageAPI = value
|
||||||
|
up.SetDescription = value
|
||||||
|
up.SetEmail = value
|
||||||
|
up.SetPassword = value
|
||||||
|
up.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all VPNs' permissions
|
||||||
|
func (vpnp *VPNPerm) SetAll(value bool) {
|
||||||
|
vpnp.Create = value
|
||||||
|
vpnp.Delete = value
|
||||||
|
vpnp.DownloadFile = value
|
||||||
|
vpnp.SetDescription = value
|
||||||
|
vpnp.SetName = value
|
||||||
|
vpnp.Show = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets all available permissions
|
||||||
|
func (p *Permissions) SetAll(v bool) {
|
||||||
|
if p.Backups == nil {
|
||||||
|
p.Backups = &BackupPerm{v, v, v}
|
||||||
|
} else {
|
||||||
|
p.Backups.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Firewalls == nil {
|
||||||
|
p.Firewalls = &FirewallPerm{v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.Firewalls.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Images == nil {
|
||||||
|
p.Images = &ImagePerm{v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.Images.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Invoice == nil {
|
||||||
|
p.Invoice = &InvoicePerm{v}
|
||||||
|
} else {
|
||||||
|
p.Invoice.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.IPs == nil {
|
||||||
|
p.IPs = &IPPerm{v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.IPs.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.LoadBalancers == nil {
|
||||||
|
p.LoadBalancers = &LoadBalancerPerm{v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.LoadBalancers.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Logs == nil {
|
||||||
|
p.Logs = &LogPerm{v}
|
||||||
|
} else {
|
||||||
|
p.Logs.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.MonitorCenter == nil {
|
||||||
|
p.MonitorCenter = &MonitorCenterPerm{v}
|
||||||
|
} else {
|
||||||
|
p.MonitorCenter.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.MonitorPolicies == nil {
|
||||||
|
p.MonitorPolicies = &MonitorPolicyPerm{v, v, v, v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.MonitorPolicies.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.PrivateNetworks == nil {
|
||||||
|
p.PrivateNetworks = &PrivateNetworkPerm{v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.PrivateNetworks.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Roles == nil {
|
||||||
|
p.Roles = &RolePerm{v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.Roles.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Servers == nil {
|
||||||
|
p.Servers = &ServerPerm{v, v, v, v, v, v, v, v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.Servers.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.SharedStorage == nil {
|
||||||
|
p.SharedStorage = &SharedStoragePerm{v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.SharedStorage.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Usages == nil {
|
||||||
|
p.Usages = &UsagePerm{v}
|
||||||
|
} else {
|
||||||
|
p.Usages.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.Users == nil {
|
||||||
|
p.Users = &UserPerm{v, v, v, v, v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.Users.SetAll(v)
|
||||||
|
}
|
||||||
|
if p.VPNs == nil {
|
||||||
|
p.VPNs = &VPNPerm{v, v, v, v, v, v}
|
||||||
|
} else {
|
||||||
|
p.VPNs.SetAll(v)
|
||||||
|
}
|
||||||
|
}
|
48
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/serverappliances.go
generated
vendored
Normal file
48
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/serverappliances.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type ServerAppliance struct {
|
||||||
|
Identity
|
||||||
|
typeField
|
||||||
|
OsInstallBase string `json:"os_installation_base,omitempty"`
|
||||||
|
OsFamily string `json:"os_family,omitempty"`
|
||||||
|
Os string `json:"os,omitempty"`
|
||||||
|
OsVersion string `json:"os_version,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
MinHddSize int `json:"min_hdd_size"`
|
||||||
|
Architecture interface{} `json:"os_architecture"`
|
||||||
|
Licenses interface{} `json:"licenses,omitempty"`
|
||||||
|
Categories []string `json:"categories,omitempty"`
|
||||||
|
// AvailableDatacenters []string `json:"available_datacenters,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /server_appliances
|
||||||
|
func (api *API) ListServerAppliances(args ...interface{}) ([]ServerAppliance, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, serverAppliancePathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := []ServerAppliance{}
|
||||||
|
err = api.Client.Get(url, &res, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range res {
|
||||||
|
res[index].api = api
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /server_appliances/{id}
|
||||||
|
func (api *API) GetServerAppliance(sa_id string) (*ServerAppliance, error) {
|
||||||
|
res := new(ServerAppliance)
|
||||||
|
url := createUrl(api, serverAppliancePathSegment, sa_id)
|
||||||
|
err := api.Client.Get(url, &res, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// res.api = api
|
||||||
|
return res, nil
|
||||||
|
}
|
|
@ -0,0 +1,808 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
ApiPtr
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
FirstPassword string `json:"first_password,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
Status *Status `json:"status,omitempty"`
|
||||||
|
Hardware *Hardware `json:"hardware,omitempty"`
|
||||||
|
Image *Identity `json:"image,omitempty"`
|
||||||
|
Dvd *Identity `json:"dvd,omitempty"`
|
||||||
|
MonPolicy *Identity `json:"monitoring_policy,omitempty"`
|
||||||
|
Snapshot *ServerSnapshot `json:"snapshot,omitempty"`
|
||||||
|
Ips []ServerIp `json:"ips,omitempty"`
|
||||||
|
PrivateNets []Identity `json:"private_networks,omitempty"`
|
||||||
|
Alerts *ServerAlerts `json:"-"`
|
||||||
|
AlertsRaw *json.RawMessage `json:"alerts,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Hardware struct {
|
||||||
|
Vcores int `json:"vcore,omitempty"`
|
||||||
|
CoresPerProcessor int `json:"cores_per_processor"`
|
||||||
|
Ram float32 `json:"ram"`
|
||||||
|
Hdds []Hdd `json:"hdds,omitempty"`
|
||||||
|
FixedInsSizeId string `json:"fixed_instance_size_id,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerHdds struct {
|
||||||
|
Hdds []Hdd `json:"hdds,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Hdd struct {
|
||||||
|
idField
|
||||||
|
Size int `json:"size,omitempty"`
|
||||||
|
IsMain bool `json:"is_main,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverDeployImage struct {
|
||||||
|
idField
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Firewall *Identity `json:"firewall_policy,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerIp struct {
|
||||||
|
idField
|
||||||
|
typeField
|
||||||
|
Ip string `json:"ip,omitempty"`
|
||||||
|
ReverseDns string `json:"reverse_dns,omitempty"`
|
||||||
|
Firewall *Identity `json:"firewall_policy,omitempty"`
|
||||||
|
LoadBalancers []Identity `json:"load_balancers,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerIpInfo struct {
|
||||||
|
idField // IP id
|
||||||
|
Ip string `json:"ip,omitempty"`
|
||||||
|
ServerName string `json:"server_name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerSnapshot struct {
|
||||||
|
idField
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
DeletionDate string `json:"deletion_date,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerAlerts struct {
|
||||||
|
AlertSummary []serverAlertSummary
|
||||||
|
AlertDetails *serverAlertDetails
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverAlertSummary struct {
|
||||||
|
countField
|
||||||
|
typeField
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverAlertDetails struct {
|
||||||
|
Criticals []ServerAlert `json:"critical,omitempty"`
|
||||||
|
Warnings []ServerAlert `json:"warning,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerAlert struct {
|
||||||
|
typeField
|
||||||
|
descField
|
||||||
|
Date string `json:"date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Hardware Hardware `json:"hardware"`
|
||||||
|
ApplianceId string `json:"appliance_id,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
PowerOn bool `json:"power_on"`
|
||||||
|
FirewallPolicyId string `json:"firewall_policy_id,omitempty"`
|
||||||
|
IpId string `json:"ip_id,omitempty"`
|
||||||
|
LoadBalancerId string `json:"load_balancer_id,omitempty"`
|
||||||
|
MonitoringPolicyId string `json:"monitoring_policy_id,omitempty"`
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
SSHKey string `json:"rsa_key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerAction struct {
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
Method string `json:"method,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FixedInstanceInfo struct {
|
||||||
|
Identity
|
||||||
|
Hardware *Hardware `json:"hardware,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers
|
||||||
|
func (api *API) ListServers(args ...interface{}) ([]Server, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, serverPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []Server{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, s := range result {
|
||||||
|
s.api = api
|
||||||
|
s.decodeRaws()
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers
|
||||||
|
func (api *API) CreateServer(request *ServerRequest) (string, *Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment)
|
||||||
|
insert2map := func(hasht map[string]interface{}, key string, value string) {
|
||||||
|
if key != "" && value != "" {
|
||||||
|
hasht[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
req := make(map[string]interface{})
|
||||||
|
hw := make(map[string]interface{})
|
||||||
|
req["name"] = request.Name
|
||||||
|
req["description"] = request.Description
|
||||||
|
req["appliance_id"] = request.ApplianceId
|
||||||
|
req["power_on"] = request.PowerOn
|
||||||
|
insert2map(req, "password", request.Password)
|
||||||
|
insert2map(req, "firewall_policy_id", request.FirewallPolicyId)
|
||||||
|
insert2map(req, "ip_id", request.IpId)
|
||||||
|
insert2map(req, "load_balancer_id", request.LoadBalancerId)
|
||||||
|
insert2map(req, "monitoring_policy_id", request.MonitoringPolicyId)
|
||||||
|
insert2map(req, "datacenter_id", request.DatacenterId)
|
||||||
|
insert2map(req, "rsa_key", request.SSHKey)
|
||||||
|
req["hardware"] = hw
|
||||||
|
if request.Hardware.FixedInsSizeId != "" {
|
||||||
|
hw["fixed_instance_size_id"] = request.Hardware.FixedInsSizeId
|
||||||
|
} else {
|
||||||
|
hw["vcore"] = request.Hardware.Vcores
|
||||||
|
hw["cores_per_processor"] = request.Hardware.CoresPerProcessor
|
||||||
|
hw["ram"] = request.Hardware.Ram
|
||||||
|
hw["hdds"] = request.Hardware.Hdds
|
||||||
|
}
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a wraper function for `CreateServer` that returns the server's IP address and first password.
|
||||||
|
// The function waits at most `timeout` seconds for the server to be created.
|
||||||
|
// The initial `POST /servers` response does not contain the IP address, so we need to wait
|
||||||
|
// until the server is created.
|
||||||
|
func (api *API) CreateServerEx(request *ServerRequest, timeout int) (string, string, error) {
|
||||||
|
id, server, err := api.CreateServer(request)
|
||||||
|
if server != nil && err == nil {
|
||||||
|
count := timeout / 5
|
||||||
|
if request.PowerOn {
|
||||||
|
err = api.WaitForState(server, "POWERED_ON", 5, count)
|
||||||
|
} else {
|
||||||
|
err = api.WaitForState(server, "POWERED_OFF", 5, count)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
server, err := api.GetServer(id)
|
||||||
|
if server != nil && err == nil && server.Ips[0].Ip != "" {
|
||||||
|
if server.FirstPassword != "" {
|
||||||
|
return server.Ips[0].Ip, server.FirstPassword, nil
|
||||||
|
}
|
||||||
|
if request.Password != "" {
|
||||||
|
return server.Ips[0].Ip, request.Password, nil
|
||||||
|
}
|
||||||
|
// should never reach here
|
||||||
|
return "", "", errors.New("No server's password was found.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}
|
||||||
|
func (api *API) GetServer(server_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/fixed_instance_sizes
|
||||||
|
func (api *API) ListFixedInstanceSizes() ([]FixedInstanceInfo, error) {
|
||||||
|
result := []FixedInstanceInfo{}
|
||||||
|
url := createUrl(api, serverPathSegment, "fixed_instance_sizes")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/fixed_instance_sizes/{fixed_instance_size_id}
|
||||||
|
func (api *API) GetFixedInstanceSize(fis_id string) (*FixedInstanceInfo, error) {
|
||||||
|
result := new(FixedInstanceInfo)
|
||||||
|
url := createUrl(api, serverPathSegment, "fixed_instance_sizes", fis_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{id}
|
||||||
|
func (api *API) DeleteServer(server_id string, keep_ips bool) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id)
|
||||||
|
pm := make(map[string]interface{}, 1)
|
||||||
|
pm["keep_ips"] = keep_ips
|
||||||
|
url = appendQueryParams(url, pm)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}
|
||||||
|
func (api *API) RenameServer(server_id string, new_name string, new_desc string) (*Server, error) {
|
||||||
|
data := struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
}{Name: new_name, Description: new_desc}
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id)
|
||||||
|
err := api.Client.Put(url, &data, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{server_id}/hardware
|
||||||
|
func (api *API) GetServerHardware(server_id string) (*Hardware, error) {
|
||||||
|
result := new(Hardware)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{server_id}/hardware
|
||||||
|
func (api *API) UpdateServerHardware(server_id string, hardware *Hardware) (*Server, error) {
|
||||||
|
var vc, cpp *int
|
||||||
|
var ram *float32
|
||||||
|
if hardware.Vcores > 0 {
|
||||||
|
vc = new(int)
|
||||||
|
*vc = hardware.Vcores
|
||||||
|
}
|
||||||
|
if hardware.CoresPerProcessor > 0 {
|
||||||
|
cpp = new(int)
|
||||||
|
*cpp = hardware.CoresPerProcessor
|
||||||
|
}
|
||||||
|
if big.NewFloat(float64(hardware.Ram)).Cmp(big.NewFloat(0)) != 0 {
|
||||||
|
ram = new(float32)
|
||||||
|
*ram = hardware.Ram
|
||||||
|
}
|
||||||
|
req := struct {
|
||||||
|
VCores *int `json:"vcore,omitempty"`
|
||||||
|
Cpp *int `json:"cores_per_processor,omitempty"`
|
||||||
|
Ram *float32 `json:"ram,omitempty"`
|
||||||
|
Flavor string `json:"fixed_instance_size_id,omitempty"`
|
||||||
|
}{VCores: vc, Cpp: cpp, Ram: ram, Flavor: hardware.FixedInsSizeId}
|
||||||
|
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware")
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/hardware/hdds
|
||||||
|
func (api *API) ListServerHdds(server_id string) ([]Hdd, error) {
|
||||||
|
result := []Hdd{}
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware/hdds")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers/{id}/hardware/hdds
|
||||||
|
func (api *API) AddServerHdds(server_id string, hdds *ServerHdds) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware/hdds")
|
||||||
|
err := api.Client.Post(url, &hdds, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/hardware/hdds/{id}
|
||||||
|
func (api *API) GetServerHdd(server_id string, hdd_id string) (*Hdd, error) {
|
||||||
|
result := new(Hdd)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{id}/hardware/hdds/{id}
|
||||||
|
func (api *API) DeleteServerHdd(server_id string, hdd_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}/hardware/hdds/{id}
|
||||||
|
func (api *API) ResizeServerHdd(server_id string, hdd_id string, new_size int) (*Server, error) {
|
||||||
|
data := Hdd{Size: new_size}
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "hardware/hdds", hdd_id)
|
||||||
|
err := api.Client.Put(url, &data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/image
|
||||||
|
func (api *API) GetServerImage(server_id string) (*Identity, error) {
|
||||||
|
result := new(Identity)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "image")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}/image
|
||||||
|
func (api *API) ReinstallServerImage(server_id string, image_id string, password string, fp_id string) (*Server, error) {
|
||||||
|
data := new(serverDeployImage)
|
||||||
|
data.Id = image_id
|
||||||
|
data.Password = password
|
||||||
|
if fp_id != "" {
|
||||||
|
fp := new(Identity)
|
||||||
|
fp.Id = fp_id
|
||||||
|
data.Firewall = fp
|
||||||
|
}
|
||||||
|
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "image")
|
||||||
|
err := api.Client.Put(url, &data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/ips
|
||||||
|
func (api *API) ListServerIps(server_id string) ([]ServerIp, error) {
|
||||||
|
result := []ServerIp{}
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers/{id}/ips
|
||||||
|
func (api *API) AssignServerIp(server_id string, ip_type string) (*Server, error) {
|
||||||
|
data := typeField{Type: ip_type}
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips")
|
||||||
|
err := api.Client.Post(url, &data, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/ips/{id}
|
||||||
|
func (api *API) GetServerIp(server_id string, ip_id string) (*ServerIp, error) {
|
||||||
|
result := new(ServerIp)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{id}/ips/{id}
|
||||||
|
func (api *API) DeleteServerIp(server_id string, ip_id string, keep_ip bool) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id)
|
||||||
|
qm := make(map[string]interface{}, 1)
|
||||||
|
qm["keep_ip"] = keep_ip
|
||||||
|
url = appendQueryParams(url, qm)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/status
|
||||||
|
func (api *API) GetServerStatus(server_id string) (*Status, error) {
|
||||||
|
result := new(Status)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "status")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}/status/action (action = REBOOT)
|
||||||
|
func (api *API) RebootServer(server_id string, is_hardware bool) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
request := ServerAction{}
|
||||||
|
request.Action = "REBOOT"
|
||||||
|
if is_hardware {
|
||||||
|
request.Method = "HARDWARE"
|
||||||
|
} else {
|
||||||
|
request.Method = "SOFTWARE"
|
||||||
|
}
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "status", "action")
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}/status/action (action = POWER_OFF)
|
||||||
|
func (api *API) ShutdownServer(server_id string, is_hardware bool) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
request := ServerAction{}
|
||||||
|
request.Action = "POWER_OFF"
|
||||||
|
if is_hardware {
|
||||||
|
request.Method = "HARDWARE"
|
||||||
|
} else {
|
||||||
|
request.Method = "SOFTWARE"
|
||||||
|
}
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "status", "action")
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}/status/action (action = POWER_ON)
|
||||||
|
func (api *API) StartServer(server_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
request := ServerAction{}
|
||||||
|
request.Action = "POWER_ON"
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "status", "action")
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/dvd
|
||||||
|
func (api *API) GetServerDvd(server_id string) (*Identity, error) {
|
||||||
|
result := new(Identity)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "dvd")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{id}/dvd
|
||||||
|
func (api *API) EjectServerDvd(server_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "dvd")
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{id}/dvd
|
||||||
|
func (api *API) LoadServerDvd(server_id string, dvd_id string) (*Server, error) {
|
||||||
|
request := Identity{}
|
||||||
|
request.Id = dvd_id
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "dvd")
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/private_networks
|
||||||
|
func (api *API) ListServerPrivateNetworks(server_id string) ([]Identity, error) {
|
||||||
|
result := []Identity{}
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "private_networks")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers/{id}/private_networks
|
||||||
|
func (api *API) AssignServerPrivateNetwork(server_id string, pn_id string) (*Server, error) {
|
||||||
|
req := new(Identity)
|
||||||
|
req.Id = pn_id
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "private_networks")
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/private_networks/{id}
|
||||||
|
func (api *API) GetServerPrivateNetwork(server_id string, pn_id string) (*PrivateNetwork, error) {
|
||||||
|
result := new(PrivateNetwork)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "private_networks", pn_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{id}/private_networks/{id}
|
||||||
|
func (api *API) RemoveServerPrivateNetwork(server_id string, pn_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "private_networks", pn_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{server_id}/ips/{ip_id}/load_balancers
|
||||||
|
func (api *API) ListServerIpLoadBalancers(server_id string, ip_id string) ([]Identity, error) {
|
||||||
|
result := []Identity{}
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers/{server_id}/ips/{ip_id}/load_balancers
|
||||||
|
func (api *API) AssignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error) {
|
||||||
|
req := struct {
|
||||||
|
LbId string `json:"load_balancer_id"`
|
||||||
|
}{lb_id}
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers")
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{server_id}/ips/{ip_id}/load_balancers
|
||||||
|
func (api *API) UnassignServerIpLoadBalancer(server_id string, ip_id string, lb_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "load_balancers", lb_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{server_id}/ips/{ip_id}/firewall_policy
|
||||||
|
func (api *API) GetServerIpFirewallPolicy(server_id string, ip_id string) (*Identity, error) {
|
||||||
|
result := new(Identity)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{server_id}/ips/{ip_id}/firewall_policy
|
||||||
|
func (api *API) AssignServerIpFirewallPolicy(server_id string, ip_id string, fp_id string) (*Server, error) {
|
||||||
|
req := idField{fp_id}
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{server_id}/ips/{ip_id}/firewall_policy
|
||||||
|
func (api *API) UnassignServerIpFirewallPolicy(server_id string, ip_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "ips", ip_id, "firewall_policy")
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /servers/{id}/snapshots
|
||||||
|
func (api *API) GetServerSnapshot(server_id string) (*ServerSnapshot, error) {
|
||||||
|
result := new(ServerSnapshot)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "snapshots")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers/{id}/snapshots
|
||||||
|
func (api *API) CreateServerSnapshot(server_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "snapshots")
|
||||||
|
err := api.Client.Post(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /servers/{server_id}/snapshots/{snapshot_id}
|
||||||
|
func (api *API) RestoreServerSnapshot(server_id string, snapshot_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "snapshots", snapshot_id)
|
||||||
|
err := api.Client.Put(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /servers/{server_id}/snapshots/{snapshot_id}
|
||||||
|
func (api *API) DeleteServerSnapshot(server_id string, snapshot_id string) (*Server, error) {
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "snapshots", snapshot_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /servers/{server_id}/clone
|
||||||
|
func (api *API) CloneServer(server_id string, new_name string, datacenter_id string) (*Server, error) {
|
||||||
|
data := struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
}{Name: new_name, DatacenterId: datacenter_id}
|
||||||
|
result := new(Server)
|
||||||
|
url := createUrl(api, serverPathSegment, server_id, "clone")
|
||||||
|
err := api.Client.Post(url, &data, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
result.decodeRaws()
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetState() (string, error) {
|
||||||
|
st, err := s.api.GetServerStatus(s.Id)
|
||||||
|
if st == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return st.State, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) decodeRaws() {
|
||||||
|
if server.AlertsRaw != nil {
|
||||||
|
server.Alerts = new(ServerAlerts)
|
||||||
|
var sad serverAlertDetails
|
||||||
|
if err := json.Unmarshal(*server.AlertsRaw, &sad); err == nil {
|
||||||
|
server.Alerts.AlertDetails = &sad
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var sams []serverAlertSummary
|
||||||
|
if err := json.Unmarshal(*server.AlertsRaw, &sams); err == nil {
|
||||||
|
server.Alerts.AlertSummary = sams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
// The base url for 1&1 Cloud Server REST API.
|
||||||
|
var BaseUrl = "https://cloudpanel-api.1and1.com/v1"
|
||||||
|
|
||||||
|
// Authentication token
|
||||||
|
var Token string
|
||||||
|
|
||||||
|
// SetBaseUrl is intended to set the REST base url. BaseUrl is declared in setup.go
|
||||||
|
func SetBaseUrl(newbaseurl string) string {
|
||||||
|
BaseUrl = newbaseurl
|
||||||
|
return BaseUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToken is used to set authentication Token for the REST service. Token is declared in setup.go
|
||||||
|
func SetToken(newtoken string) string {
|
||||||
|
Token = newtoken
|
||||||
|
return Token
|
||||||
|
}
|
190
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/sharedstorages.go
generated
vendored
Normal file
190
vendor/github.com/1and1/oneandone-cloudserver-sdk-go/sharedstorages.go
generated
vendored
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SharedStorage struct {
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
Size int `json:"size"`
|
||||||
|
MinSizeAllowed int `json:"minimum_size_allowed"`
|
||||||
|
SizeUsed string `json:"size_used,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
SiteId string `json:"site_id,omitempty"`
|
||||||
|
CifsPath string `json:"cifs_path,omitempty"`
|
||||||
|
NfsPath string `json:"nfs_path,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
Servers []SharedStorageServer `json:"servers,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type SharedStorageServer struct {
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Rights string `json:"rights,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SharedStorageRequest struct {
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Size *int `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SharedStorageAccess struct {
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
KerberosContentFile string `json:"kerberos_content_file,omitempty"`
|
||||||
|
UserDomain string `json:"user_domain,omitempty"`
|
||||||
|
SiteId string `json:"site_id,omitempty"`
|
||||||
|
NeedsPasswordReset int `json:"needs_password_reset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /shared_storages
|
||||||
|
func (api *API) ListSharedStorages(args ...interface{}) ([]SharedStorage, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, sharedStoragePathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []SharedStorage{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /shared_storages
|
||||||
|
func (api *API) CreateSharedStorage(request *SharedStorageRequest) (string, *SharedStorage, error) {
|
||||||
|
result := new(SharedStorage)
|
||||||
|
url := createUrl(api, sharedStoragePathSegment)
|
||||||
|
err := api.Client.Post(url, request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /shared_storages/{id}
|
||||||
|
func (api *API) GetSharedStorage(ss_id string) (*SharedStorage, error) {
|
||||||
|
result := new(SharedStorage)
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, ss_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /shared_storages/{id}
|
||||||
|
func (api *API) DeleteSharedStorage(ss_id string) (*SharedStorage, error) {
|
||||||
|
result := new(SharedStorage)
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, ss_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /shared_storages/{id}
|
||||||
|
func (api *API) UpdateSharedStorage(ss_id string, request *SharedStorageRequest) (*SharedStorage, error) {
|
||||||
|
result := new(SharedStorage)
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, ss_id)
|
||||||
|
err := api.Client.Put(url, &request, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /shared_storages/{id}/servers
|
||||||
|
func (api *API) ListSharedStorageServers(st_id string) ([]SharedStorageServer, error) {
|
||||||
|
result := []SharedStorageServer{}
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, st_id, "servers")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /shared_storages/{id}/servers
|
||||||
|
func (api *API) AddSharedStorageServers(st_id string, servers []SharedStorageServer) (*SharedStorage, error) {
|
||||||
|
result := new(SharedStorage)
|
||||||
|
req := struct {
|
||||||
|
Servers []SharedStorageServer `json:"servers"`
|
||||||
|
}{servers}
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, st_id, "servers")
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /shared_storages/{id}/servers/{id}
|
||||||
|
func (api *API) GetSharedStorageServer(st_id string, ser_id string) (*SharedStorageServer, error) {
|
||||||
|
result := new(SharedStorageServer)
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, st_id, "servers", ser_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /shared_storages/{id}/servers/{id}
|
||||||
|
func (api *API) DeleteSharedStorageServer(st_id string, ser_id string) (*SharedStorage, error) {
|
||||||
|
result := new(SharedStorage)
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, st_id, "servers", ser_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /shared_storages/access
|
||||||
|
func (api *API) GetSharedStorageCredentials() ([]SharedStorageAccess, error) {
|
||||||
|
result := []SharedStorageAccess{}
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, "access")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /shared_storages/access
|
||||||
|
func (api *API) UpdateSharedStorageCredentials(new_pass string) ([]SharedStorageAccess, error) {
|
||||||
|
result := []SharedStorageAccess{}
|
||||||
|
req := struct {
|
||||||
|
Password string `json:"password"`
|
||||||
|
}{new_pass}
|
||||||
|
url := createUrl(api, sharedStoragePathSegment, "access")
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *SharedStorage) GetState() (string, error) {
|
||||||
|
in, err := ss.api.GetSharedStorage(ss.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Usages struct {
|
||||||
|
Images []usage `json:"IMAGES,omitempty"`
|
||||||
|
LoadBalancers []usage `json:"LOAD BALANCERS,omitempty"`
|
||||||
|
PublicIPs []usage `json:"PUBLIC IP,omitempty"`
|
||||||
|
Servers []usage `json:"SERVERS,omitempty"`
|
||||||
|
SharedStorages []usage `json:"SHARED STORAGE,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type usage struct {
|
||||||
|
Identity
|
||||||
|
Site int `json:"site"`
|
||||||
|
Services []usageService `json:"services,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type usageService struct {
|
||||||
|
AverageAmmount string `json:"avg_amount,omitempty"`
|
||||||
|
Unit string `json:"unit,omitempty"`
|
||||||
|
Usage int `json:"usage"`
|
||||||
|
Details []usageDetails `json:"detail,omitempty"`
|
||||||
|
typeField
|
||||||
|
}
|
||||||
|
|
||||||
|
type usageDetails struct {
|
||||||
|
AverageAmmount string `json:"avg_amount,omitempty"`
|
||||||
|
StartDate string `json:"start_date,omitempty"`
|
||||||
|
EndDate string `json:"end_date,omitempty"`
|
||||||
|
Unit string `json:"unit,omitempty"`
|
||||||
|
Usage int `json:"usage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /usages
|
||||||
|
func (api *API) ListUsages(period string, sd *time.Time, ed *time.Time, args ...interface{}) (*Usages, error) {
|
||||||
|
result := new(Usages)
|
||||||
|
url, err := processQueryParamsExt(createUrl(api, usagePathSegment), period, sd, ed, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
Role *Identity `json:"role,omitempty"`
|
||||||
|
Api *UserApi `json:"api,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserApi struct {
|
||||||
|
Active bool `json:"active"`
|
||||||
|
AllowedIps []string `json:"allowed_ips,omitempty"`
|
||||||
|
UserApiKey
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserApiKey struct {
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserRequest struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /users
|
||||||
|
func (api *API) ListUsers(args ...interface{}) ([]User, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, userPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []User{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for index, _ := range result {
|
||||||
|
result[index].api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /users
|
||||||
|
func (api *API) CreateUser(user *UserRequest) (string, *User, error) {
|
||||||
|
result := new(User)
|
||||||
|
url := createUrl(api, userPathSegment)
|
||||||
|
err := api.Client.Post(url, &user, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result.Id, result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /users/{id}
|
||||||
|
func (api *API) GetUser(user_id string) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
url := createUrl(api, userPathSegment, user_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /users/{id}
|
||||||
|
func (api *API) DeleteUser(user_id string) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
url := createUrl(api, userPathSegment, user_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /users/{id}
|
||||||
|
func (api *API) ModifyUser(user_id string, user *UserRequest) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
url := createUrl(api, userPathSegment, user_id)
|
||||||
|
err := api.Client.Put(url, &user, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /users/{id}/api
|
||||||
|
func (api *API) GetUserApi(user_id string) (*UserApi, error) {
|
||||||
|
result := new(UserApi)
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /users/{id}/api
|
||||||
|
func (api *API) ModifyUserApi(user_id string, active bool) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
req := struct {
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}{active}
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api")
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /users/{id}/api/key
|
||||||
|
func (api *API) GetUserApiKey(user_id string) (*UserApiKey, error) {
|
||||||
|
result := new(UserApiKey)
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api/key")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /users/{id}/api/key
|
||||||
|
func (api *API) RenewUserApiKey(user_id string) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api/key")
|
||||||
|
err := api.Client.Put(url, nil, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /users/{id}/api/ips
|
||||||
|
func (api *API) ListUserApiAllowedIps(user_id string) ([]string, error) {
|
||||||
|
result := []string{}
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api/ips")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /users/{id}/api/ips
|
||||||
|
func (api *API) AddUserApiAlowedIps(user_id string, ips []string) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
req := struct {
|
||||||
|
Ips []string `json:"ips"`
|
||||||
|
}{ips}
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api/ips")
|
||||||
|
err := api.Client.Post(url, &req, &result, http.StatusCreated)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /users/{id}/api/ips/{ip}
|
||||||
|
func (api *API) RemoveUserApiAllowedIp(user_id string, ip string) (*User, error) {
|
||||||
|
result := new(User)
|
||||||
|
url := createUrl(api, userPathSegment, user_id, "api/ips", ip)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /users/{id}/api/ips
|
||||||
|
func (api *API) GetCurrentUserPermissions() (*Permissions, error) {
|
||||||
|
result := new(Permissions)
|
||||||
|
url := createUrl(api, userPathSegment, "current_user_permissions")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) GetState() (string, error) {
|
||||||
|
in, err := u.api.GetUser(u.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
package oneandone
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type VPN struct {
|
||||||
|
Identity
|
||||||
|
descField
|
||||||
|
typeField
|
||||||
|
CloudPanelId string `json:"cloudpanel_id,omitempty"`
|
||||||
|
CreationDate string `json:"creation_date,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
IPs []string `json:"ips,omitempty"`
|
||||||
|
Datacenter *Datacenter `json:"datacenter,omitempty"`
|
||||||
|
ApiPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
type configZipFile struct {
|
||||||
|
Base64String string `json:"config_zip_file"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /vpns
|
||||||
|
func (api *API) ListVPNs(args ...interface{}) ([]VPN, error) {
|
||||||
|
url, err := processQueryParams(createUrl(api, vpnPathSegment), args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []VPN{}
|
||||||
|
err = api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, vpn := range result {
|
||||||
|
vpn.api = api
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /vpns
|
||||||
|
func (api *API) CreateVPN(name string, description string, datacenter_id string) (string, *VPN, error) {
|
||||||
|
res := new(VPN)
|
||||||
|
url := createUrl(api, vpnPathSegment)
|
||||||
|
req := struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
DatacenterId string `json:"datacenter_id,omitempty"`
|
||||||
|
}{Name: name, Description: description, DatacenterId: datacenter_id}
|
||||||
|
err := api.Client.Post(url, &req, &res, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
res.api = api
|
||||||
|
return res.Id, res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /vpns/{vpn_id}
|
||||||
|
func (api *API) GetVPN(vpn_id string) (*VPN, error) {
|
||||||
|
result := new(VPN)
|
||||||
|
url := createUrl(api, vpnPathSegment, vpn_id)
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /vpns/{vpn_id}
|
||||||
|
func (api *API) ModifyVPN(vpn_id string, name string, description string) (*VPN, error) {
|
||||||
|
result := new(VPN)
|
||||||
|
url := createUrl(api, vpnPathSegment, vpn_id)
|
||||||
|
req := struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
}{Name: name, Description: description}
|
||||||
|
err := api.Client.Put(url, &req, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /vpns/{vpn_id}
|
||||||
|
func (api *API) DeleteVPN(vpn_id string) (*VPN, error) {
|
||||||
|
result := new(VPN)
|
||||||
|
url := createUrl(api, vpnPathSegment, vpn_id)
|
||||||
|
err := api.Client.Delete(url, nil, &result, http.StatusAccepted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.api = api
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /vpns/{vpn_id}/configuration_file
|
||||||
|
// Returns VPN configuration files (in a zip arhive) as a base64 encoded string
|
||||||
|
func (api *API) GetVPNConfigFile(vpn_id string) (string, error) {
|
||||||
|
result := new(configZipFile)
|
||||||
|
url := createUrl(api, vpnPathSegment, vpn_id, "configuration_file")
|
||||||
|
err := api.Client.Get(url, &result, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Base64String, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vpn *VPN) GetState() (string, error) {
|
||||||
|
in, err := vpn.api.GetVPN(vpn.Id)
|
||||||
|
if in == nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return in.State, err
|
||||||
|
}
|
|
@ -14,6 +14,12 @@
|
||||||
"revision": "81b7822b1e798e8f17bf64b59512a5be4097e966",
|
"revision": "81b7822b1e798e8f17bf64b59512a5be4097e966",
|
||||||
"revisionTime": "2017-01-18T16:13:56Z"
|
"revisionTime": "2017-01-18T16:13:56Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "aABATU51PlDHfGeSe5cc9udwSXg=",
|
||||||
|
"path": "github.com/1and1/oneandone-cloudserver-sdk-go",
|
||||||
|
"revision": "5678f03fc801525df794f953aa82f5ad7555a2ef",
|
||||||
|
"revisionTime": "2016-08-11T22:04:02Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "N92Zji40JkCHAnsCNHTP4iKPz88=",
|
"checksumSHA1": "N92Zji40JkCHAnsCNHTP4iKPz88=",
|
||||||
"comment": "v2.1.1-beta-8-gca4d906",
|
"comment": "v2.1.1-beta-8-gca4d906",
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "Provider: 1&1"
|
||||||
|
sidebar_current: "docs-oneandone-index"
|
||||||
|
description: |-
|
||||||
|
A provider for 1&1.
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1&1 Provider
|
||||||
|
|
||||||
|
The 1&1 provider gives the ability to deploy and configure resources using the 1&1 Cloud Server API.
|
||||||
|
|
||||||
|
Use the navigation to the left to read about the available resources.
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The provider needs to be configured with proper credentials before it can be used.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
$ export ONEANDONE_TOKEN="oneandone_token"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can provide your credentials like this:
|
||||||
|
|
||||||
|
|
||||||
|
The credentials provided in `.tf` file will override credentials in the environment variables.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
provider "oneandone"{
|
||||||
|
token = "oneandone_token"
|
||||||
|
endpoint = "oneandone_endpoint"
|
||||||
|
retries = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "oneandone_server" "server" {
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `token` - (Required) If omitted, the `ONEANDONE_TOKEN` environment variable is used.
|
||||||
|
|
||||||
|
* `endpoint` - (Optional)
|
||||||
|
|
||||||
|
* `retries` - (Optional) Number of retries while waiting for a resource to be provisioned. Default value is 50.
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_firewall_policy"
|
||||||
|
sidebar_current: "docs-oneandone-resource-firwall-policy"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Firewall Policy.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_server
|
||||||
|
|
||||||
|
Manages a Firewall Policy on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_firewall_policy" "fw" {
|
||||||
|
name = "test_fw_011"
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 80
|
||||||
|
"port_to" = 80
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "ICMP"
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 43
|
||||||
|
"port_to" = 43
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"protocol" = "TCP"
|
||||||
|
"port_from" = 22
|
||||||
|
"port_to" = 22
|
||||||
|
"source_ip" = "0.0.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `description` - (Optional) [string] Description for the VPN
|
||||||
|
* `name` - (Required) [string] The name of the VPN.
|
||||||
|
|
||||||
|
Firewall Policy Rules (`rules`) support the follwing:
|
||||||
|
|
||||||
|
* `protocol` - (Required) [String] The protocol for the rule ["TCP", "UDP", "TCP/UDP", "ICMP", "IPSEC"]
|
||||||
|
* `port_from` - (Optional) [String] Defines the start range of the allowed port
|
||||||
|
* `port_to` - (Optional) [String] Defines the end range of the allowed port
|
||||||
|
* `source_ip` - (Optional) [String] Only traffic directed to the respective IP address
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_loadbalancer"
|
||||||
|
sidebar_current: "docs-oneandone-resource-loadbalancer"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Load Balancer.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_server
|
||||||
|
|
||||||
|
Manages a Load Balancer on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_loadbalancer" "lb" {
|
||||||
|
name = "test_lb"
|
||||||
|
method = "ROUND_ROBIN"
|
||||||
|
persistence = true
|
||||||
|
persistence_time = 60
|
||||||
|
health_check_test = "TCP"
|
||||||
|
health_check_interval = 300
|
||||||
|
datacenter = "GB"
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
protocol = "TCP"
|
||||||
|
port_balancer = 8080
|
||||||
|
port_server = 8089
|
||||||
|
source_ip = "0.0.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
protocol = "TCP"
|
||||||
|
port_balancer = 9090
|
||||||
|
port_server = 9099
|
||||||
|
source_ip = "0.0.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) [String] The name of the load balancer.
|
||||||
|
* `description` - (Optional) [String] Description for the load balancer
|
||||||
|
* `method` - (Required) [String] Balancing procedure ["ROUND_ROBIN", "LEAST_CONNECTIONS"]
|
||||||
|
* `datacenter` - (Optional) [String] Location of desired 1and1 datacenter ["DE", "GB", "US", "ES" ]
|
||||||
|
* `persistence` - (Optional) [Boolean] True/false defines whether persistence should be turned on/off
|
||||||
|
* `persistence_time` - (Optional) [Integer] Persistance duration in seconds
|
||||||
|
* `health_check_test` - (Optional) [String] ["TCP", "ICMP"]
|
||||||
|
* `health_check_test_interval` - (Optional) [String]
|
||||||
|
* `health_check_test_path` - (Optional) [String]
|
||||||
|
* `health_check_test_parser` - (Optional) [String]
|
||||||
|
|
||||||
|
Loadbalancer rules (`rules`) support the following
|
||||||
|
|
||||||
|
* `protocol` - (Required) [String] The protocol for the rule ["TCP", "UDP", "TCP/UDP", "ICMP", "IPSEC"]
|
||||||
|
* `port_balancer` - (Required) [String]
|
||||||
|
* `port_server` - (Required) [String]
|
||||||
|
* `source_ip` - (Required) [String]
|
|
@ -0,0 +1,177 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_monitoring_policy"
|
||||||
|
sidebar_current: "docs-oneandone-resource-monitoring-policy"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Monitoring Policy.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_server
|
||||||
|
|
||||||
|
Manages a Monitoring Policy on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_monitoring_policy" "mp" {
|
||||||
|
name = "test_mp"
|
||||||
|
agent = true
|
||||||
|
email = "jasmin@stackpointcloud.com"
|
||||||
|
|
||||||
|
thresholds = {
|
||||||
|
cpu = {
|
||||||
|
warning = {
|
||||||
|
value = 50,
|
||||||
|
alert = false
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 66,
|
||||||
|
alert = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ram = {
|
||||||
|
warning = {
|
||||||
|
value = 70,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 80,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ram = {
|
||||||
|
warning = {
|
||||||
|
value = 85,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 95,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disk = {
|
||||||
|
warning = {
|
||||||
|
value = 84,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 94,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transfer = {
|
||||||
|
warning = {
|
||||||
|
value = 1000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 2000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
internal_ping = {
|
||||||
|
warning = {
|
||||||
|
value = 3000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
critical = {
|
||||||
|
value = 4000,
|
||||||
|
alert = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ports = [
|
||||||
|
{
|
||||||
|
email_notification = true
|
||||||
|
port = 443
|
||||||
|
protocol = "TCP"
|
||||||
|
alert_if = "NOT_RESPONDING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email_notification = false
|
||||||
|
port = 80
|
||||||
|
protocol = "TCP"
|
||||||
|
alert_if = "NOT_RESPONDING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email_notification = true
|
||||||
|
port = 21
|
||||||
|
protocol = "TCP"
|
||||||
|
alert_if = "NOT_RESPONDING"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
processes = [
|
||||||
|
{
|
||||||
|
email_notification = false
|
||||||
|
process = "httpdeamon"
|
||||||
|
alert_if = "RUNNING"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
process = "iexplorer",
|
||||||
|
alert_if = "NOT_RUNNING"
|
||||||
|
email_notification = true
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) [string] The name of the VPN.
|
||||||
|
* `description` - (Optional) [string] Description for the VPN
|
||||||
|
* `email` - (Optional) [String] Email address to which notifications monitoring system will send
|
||||||
|
* `agent- (Required)[Boolean] Indicates which monitoring type will be used. True: To use this monitoring type, you must install an agent on the server. False: Monitor a server without installing an agent. Note: If you do not install an agent, you cannot retrieve information such as free hard disk space or ongoing processes.
|
||||||
|
|
||||||
|
Monitoring Policy Thresholds (`thresholds`) support the following:
|
||||||
|
|
||||||
|
* `cpu - (Required)[Type] CPU thresholds
|
||||||
|
* `warning - (Required)[Type] Warning alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `critical - (Required)[Type] Critical alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `ram - (Required)[Type] RAM threshold
|
||||||
|
* `warning - (Required)[Type] Warning alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `critical - (Required)[Type] Critical alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `disk - (Required)[Type] Hard Disk threshold
|
||||||
|
* `warning - (Required)[Type] Warning alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `critical - (Required)[Type] Critical alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `transfer - (Required)[Type] Data transfer threshold
|
||||||
|
* `warning - (Required)[Type] Warning alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `critical - (Required)[Type] Critical alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `internal_ping - (Required)[type] Ping threshold
|
||||||
|
* `warning - (Required)[Type] Warning alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
* `critical - (Required)[Type] Critical alert
|
||||||
|
* `value - (Required)[Integer] Warning to be issued when the threshold is reached. from 1 to 100
|
||||||
|
* `alert - (Required)[Boolean] If set true warning will be issued.
|
||||||
|
|
||||||
|
Monitoring Policy Ports (`ports`) support the following:
|
||||||
|
|
||||||
|
* `email_notification - (Required)[boolean] If set true email will be sent.
|
||||||
|
* `port - (Required)[Integer] Port number.
|
||||||
|
* `protocol - (Required)[String] The protocol of the port ["TCP", "UDP", "TCP/UDP", "ICMP", "IPSEC"]
|
||||||
|
* `alert_if - (Required)[String] Condition for the alert to be issued.
|
||||||
|
|
||||||
|
Monitoring Policy Ports (`processes`) support the following:
|
||||||
|
|
||||||
|
* `email_notification - (Required)[Boolean] If set true email will be sent.
|
||||||
|
* `process - (Required)[Integer] Process name.
|
||||||
|
* `alert_if - (Required)[String] Condition for the alert to be issued.
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_private_network"
|
||||||
|
sidebar_current: "docs-oneandone-resource-private-network"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Private Network.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_server
|
||||||
|
|
||||||
|
Manages a Private Network on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_private_network" "pn" {
|
||||||
|
name = "pn_test",
|
||||||
|
description = "new stuff001"
|
||||||
|
datacenter = "GB"
|
||||||
|
network_address = "192.168.7.0"
|
||||||
|
subnet_mask = "255.255.255.0"
|
||||||
|
server_ids = [
|
||||||
|
"${oneandone_server.server.id}",
|
||||||
|
"${oneandone_server.server02.id}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `datacenter` - (Optional)[string] Location of desired 1and1 datacenter ["DE", "GB", "US", "ES" ]
|
||||||
|
* `description` - (Optional)[string] Description for the shared storage
|
||||||
|
* `name` - (Required)[string] The name of the private network
|
||||||
|
* `network_address` - (Optional)[string] Network address for the private network
|
||||||
|
* `subnet_mask` - (Optional)[string] Subnet mask for the private network
|
||||||
|
* `server_ids` (Optional)[Collection] List of servers that are to be associated with the private network
|
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_public_ip"
|
||||||
|
sidebar_current: "docs-oneandone-resource-public-ip"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Public IP.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_vpn
|
||||||
|
|
||||||
|
Manages a Public IP on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_vpn" "vpn" {
|
||||||
|
datacenter = "GB"
|
||||||
|
name = "test_vpn_01"
|
||||||
|
description = "ttest descr"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `datacenter` - (Optional)[string] Location of desired 1and1 datacenter ["DE", "GB", "US", "ES" ]
|
||||||
|
* `description` - (Optional)[string] Description of the VPN
|
||||||
|
* `name` -(Required)[string] The name of the VPN.
|
|
@ -0,0 +1,60 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_server"
|
||||||
|
sidebar_current: "docs-oneandone-resource-server"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Server.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_server
|
||||||
|
|
||||||
|
Manages a Server on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_server" "server" {
|
||||||
|
name = "Example"
|
||||||
|
description = "Terraform 1and1 tutorial"
|
||||||
|
image = "ubuntu"
|
||||||
|
datacenter = "GB"
|
||||||
|
vcores = 1
|
||||||
|
cores_per_processor = 1
|
||||||
|
ram = 2
|
||||||
|
ssh_key_path = "/path/to/prvate/ssh_key"
|
||||||
|
hdds = [
|
||||||
|
{
|
||||||
|
disk_size = 60
|
||||||
|
is_main = true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
inline = [
|
||||||
|
"apt-get update",
|
||||||
|
"apt-get -y install nginx",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `cores_per_processor` -(Required)[integer] Number of cores per processor
|
||||||
|
* `datacenter` - (Optional)[string] Location of desired 1and1 datacenter ["DE", "GB", "US", "ES" ]
|
||||||
|
* `description` - (Optional)[string] Description of the server
|
||||||
|
* `firewall_policy_id` - (Optional)[string] ID of firewall policy
|
||||||
|
* `hdds` - (Required)[collection] List of HDDs. One HDD must be main.
|
||||||
|
* `*disk_size` -(Required)[integer] The size of HDD
|
||||||
|
* `*is_main` - (Optional)[boolean] Indicates if HDD is to be used as main hard disk of the server
|
||||||
|
* `image` -(Required)[string] The name of a desired image to be provisioned with the server
|
||||||
|
* `ip` - (Optional)[string] IP address for the server
|
||||||
|
* `loadbalancer_id` - (Optional)[string] ID of the load balancer
|
||||||
|
* `monitoring_policy_id` - (Optional)[string] ID of monitoring policy
|
||||||
|
* `name` -(Required)[string] The name of the server.
|
||||||
|
* `password` - (Optional)[string] Desired password.
|
||||||
|
* `ram` -(Required)[float] Size of ram.
|
||||||
|
* `ssh_key_path` - (Optional)[string] Path to private ssh key
|
||||||
|
* `vcores` -(Required)[integer] Number of virtual cores.
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_shared_storage"
|
||||||
|
sidebar_current: "docs-oneandone-resource-shared-storage"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 Shared Storage.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_server
|
||||||
|
|
||||||
|
Manages a Shared Storage on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_shared_storage" "storage" {
|
||||||
|
name = "test_storage1"
|
||||||
|
description = "1234"
|
||||||
|
size = 50
|
||||||
|
|
||||||
|
storage_servers = [
|
||||||
|
{
|
||||||
|
id = "${oneandone_server.server.id}"
|
||||||
|
rights = "RW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = "${oneandone_server.server02.id}"
|
||||||
|
rights = "RW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `datacenter` - (Optional)[string] Location of desired 1and1 datacenter ["DE", "GB", "US", "ES" ]
|
||||||
|
* `description` - (Optional)[string] Description for the shared storage
|
||||||
|
* `size` - (Required)[string] Size of the shared storage
|
||||||
|
* `storage_servers` (Optional)[Collection] List of servers that will have access to the stored storage
|
||||||
|
* `id` - (Required) [string] ID of the server
|
||||||
|
* `rights` - (Required)[string] Access rights to be assigned to the server ["RW","R"]
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
layout: "oneandone"
|
||||||
|
page_title: "1&1: oneandone_vpn"
|
||||||
|
sidebar_current: "docs-oneandone-resource-vpn"
|
||||||
|
description: |-
|
||||||
|
Creates and manages 1&1 VPN.
|
||||||
|
---
|
||||||
|
|
||||||
|
# oneandone\_vpn
|
||||||
|
|
||||||
|
Manages a VPN on 1&1
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "oneandone_public_ip" "ip" {
|
||||||
|
"ip_type" = "IPV4"
|
||||||
|
"reverse_dns" = "test.1and1.com"
|
||||||
|
"datacenter" = "GB"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `datacenter` - (Optional)[string] Location of desired 1and1 datacenter ["DE", "GB", "US", "ES" ]
|
||||||
|
* `ip_type` - (Required)[string] IPV4 or IPV6
|
||||||
|
* `reverese_dns` - [Optional](string)
|
||||||
|
|
Loading…
Reference in New Issue