Skip to content

Commit df2a192

Browse files
committed
triton: add fabric resource
1 parent 7332b0e commit df2a192

3 files changed

Lines changed: 283 additions & 0 deletions

File tree

builtin/providers/triton/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func Provider() terraform.ResourceProvider {
4747
"triton_machine": resourceMachine(),
4848
"triton_key": resourceKey(),
4949
"triton_vlan": resourceVLAN(),
50+
"triton_fabric": resourceFabric(),
5051
},
5152
ConfigureFunc: providerConfigure,
5253
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package triton
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/terraform/helper/schema"
7+
"github.com/joyent/gosdc/cloudapi"
8+
)
9+
10+
func resourceFabric() *schema.Resource {
11+
return &schema.Resource{
12+
Create: resourceFabricCreate,
13+
Exists: resourceFabricExists,
14+
Read: resourceFabricRead,
15+
Delete: resourceFabricDelete,
16+
17+
Schema: map[string]*schema.Schema{
18+
"name": {
19+
Description: "network name",
20+
Required: true,
21+
ForceNew: true,
22+
Type: schema.TypeString,
23+
},
24+
"public": {
25+
Description: "whether or not this is an RFC1918 network",
26+
Computed: true,
27+
Type: schema.TypeBool,
28+
},
29+
"fabric": {
30+
Description: "whether or not this network is on a fabric",
31+
Computed: true,
32+
Type: schema.TypeBool,
33+
},
34+
"description": {
35+
Description: "optional description of network",
36+
Optional: true,
37+
ForceNew: true,
38+
Type: schema.TypeString,
39+
},
40+
"subnet": {
41+
Description: "CIDR formatted string describing network",
42+
Required: true,
43+
ForceNew: true,
44+
Type: schema.TypeString,
45+
},
46+
"provision_start_ip": {
47+
Description: "first IP on the network that can be assigned",
48+
Required: true,
49+
ForceNew: true,
50+
Type: schema.TypeString,
51+
},
52+
"provision_end_ip": {
53+
Description: "last assignable IP on the network",
54+
Required: true,
55+
ForceNew: true,
56+
Type: schema.TypeString,
57+
},
58+
"gateway": {
59+
Description: "optional gateway IP",
60+
Optional: true,
61+
ForceNew: true,
62+
Type: schema.TypeString,
63+
},
64+
"resolvers": {
65+
Description: "array of IP addresses for resolvers",
66+
Optional: true,
67+
Computed: true,
68+
Type: schema.TypeList,
69+
Elem: &schema.Schema{Type: schema.TypeString},
70+
},
71+
"routes": {
72+
Description: "map of CIDR block to Gateway IP address",
73+
Computed: true,
74+
Optional: true,
75+
ForceNew: true,
76+
Type: schema.TypeMap,
77+
},
78+
"internet_nat": {
79+
Description: "if a NAT zone is provisioned at Gateway IP address",
80+
Computed: true,
81+
Optional: true,
82+
ForceNew: true,
83+
Type: schema.TypeBool,
84+
},
85+
"vlan_id": {
86+
Description: "VLAN network is on",
87+
Required: true,
88+
ForceNew: true,
89+
Type: schema.TypeInt,
90+
},
91+
},
92+
}
93+
}
94+
95+
func resourceFabricCreate(d *schema.ResourceData, meta interface{}) error {
96+
client := meta.(*cloudapi.Client)
97+
98+
var resolvers []string
99+
for _, resolver := range d.Get("resolvers").([]interface{}) {
100+
resolvers = append(resolvers, resolver.(string))
101+
}
102+
103+
routes := map[string]string{}
104+
for cidr, v := range d.Get("routes").(map[string]interface{}) {
105+
ip, ok := v.(string)
106+
if !ok {
107+
return fmt.Errorf(`cannot use "%v" as an IP address`, v)
108+
}
109+
routes[cidr] = ip
110+
}
111+
112+
fabric, err := client.CreateFabricNetwork(
113+
int16(d.Get("vlan_id").(int)),
114+
cloudapi.CreateFabricNetworkOpts{
115+
Name: d.Get("name").(string),
116+
Description: d.Get("description").(string),
117+
Subnet: d.Get("subnet").(string),
118+
ProvisionStartIp: d.Get("provision_start_ip").(string),
119+
ProvisionEndIp: d.Get("provision_end_ip").(string),
120+
Gateway: d.Get("gateway").(string),
121+
Resolvers: resolvers,
122+
Routes: routes,
123+
InternetNAT: d.Get("internet_nat").(bool),
124+
},
125+
)
126+
if err != nil {
127+
return err
128+
}
129+
130+
d.SetId(fabric.Id)
131+
132+
err = resourceFabricRead(d, meta)
133+
if err != nil {
134+
return err
135+
}
136+
137+
return nil
138+
}
139+
140+
func resourceFabricExists(d *schema.ResourceData, meta interface{}) (bool, error) {
141+
client := meta.(*cloudapi.Client)
142+
143+
fabric, err := client.GetFabricNetwork(int16(d.Get("vlan_id").(int)), d.Id())
144+
145+
return fabric != nil && err == nil, err
146+
}
147+
148+
func resourceFabricRead(d *schema.ResourceData, meta interface{}) error {
149+
client := meta.(*cloudapi.Client)
150+
151+
fabric, err := client.GetFabricNetwork(int16(d.Get("vlan_id").(int)), d.Id())
152+
if err != nil {
153+
return err
154+
}
155+
156+
d.SetId(fabric.Id)
157+
d.Set("name", fabric.Name)
158+
d.Set("public", fabric.Public)
159+
d.Set("public", fabric.Public)
160+
d.Set("fabric", fabric.Fabric)
161+
d.Set("description", fabric.Description)
162+
d.Set("subnet", fabric.Subnet)
163+
d.Set("provision_start_ip", fabric.ProvisionStartIp)
164+
d.Set("provision_end_ip", fabric.ProvisionEndIp)
165+
d.Set("gateway", fabric.Gateway)
166+
d.Set("resolvers", fabric.Resolvers)
167+
d.Set("routes", fabric.Routes)
168+
d.Set("internet_nat", fabric.InternetNAT)
169+
d.Set("vlan_id", fabric.VLANId)
170+
171+
return nil
172+
}
173+
174+
func resourceFabricDelete(d *schema.ResourceData, meta interface{}) error {
175+
client := meta.(*cloudapi.Client)
176+
177+
return client.DeleteFabricNetwork(int16(d.Get("vlan_id").(int)), d.Id())
178+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package triton
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"testing"
7+
"time"
8+
9+
"github.com/hashicorp/terraform/helper/acctest"
10+
"github.com/hashicorp/terraform/helper/resource"
11+
"github.com/hashicorp/terraform/terraform"
12+
"github.com/joyent/gosdc/cloudapi"
13+
)
14+
15+
func TestAccTritonFabric_basic(t *testing.T) {
16+
fabricName := fmt.Sprintf("acctest-%d", acctest.RandInt())
17+
config := fmt.Sprintf(testAccTritonFabric_basic, fabricName)
18+
19+
resource.Test(t, resource.TestCase{
20+
PreCheck: func() { testAccPreCheck(t) },
21+
Providers: testAccProviders,
22+
CheckDestroy: testCheckTritonFabricDestroy,
23+
Steps: []resource.TestStep{
24+
resource.TestStep{
25+
Config: config,
26+
Check: resource.ComposeTestCheckFunc(
27+
testCheckTritonFabricExists("triton_fabric.test"),
28+
func(*terraform.State) error {
29+
time.Sleep(10 * time.Second)
30+
return nil
31+
},
32+
),
33+
},
34+
},
35+
})
36+
}
37+
38+
func testCheckTritonFabricExists(name string) resource.TestCheckFunc {
39+
return func(s *terraform.State) error {
40+
// Ensure we have enough information in state to look up in API
41+
rs, ok := s.RootModule().Resources[name]
42+
if !ok {
43+
return fmt.Errorf("Not found: %s", name)
44+
}
45+
conn := testAccProvider.Meta().(*cloudapi.Client)
46+
47+
id, err := strconv.ParseInt(rs.Primary.Attributes["vlan_id"], 10, 16)
48+
if err != nil {
49+
return err
50+
}
51+
52+
fabric, err := conn.GetFabricNetwork(int16(id), rs.Primary.ID)
53+
if err != nil {
54+
return fmt.Errorf("Bad: Check Fabric Exists: %s", err)
55+
}
56+
57+
if fabric == nil {
58+
return fmt.Errorf("Bad: Fabric %q does not exist", rs.Primary.ID)
59+
}
60+
61+
return nil
62+
}
63+
}
64+
65+
func testCheckTritonFabricDestroy(s *terraform.State) error {
66+
conn := testAccProvider.Meta().(*cloudapi.Client)
67+
68+
for _, rs := range s.RootModule().Resources {
69+
if rs.Type != "triton_fabric" {
70+
continue
71+
}
72+
73+
id, err := strconv.ParseInt(rs.Primary.Attributes["vlan_id"], 10, 16)
74+
if err != nil {
75+
return err
76+
}
77+
78+
fabric, err := conn.GetFabricNetwork(int16(id), rs.Primary.ID)
79+
if err != nil {
80+
return nil
81+
}
82+
83+
if fabric != nil {
84+
return fmt.Errorf("Bad: Fabric %q still exists", rs.Primary.ID)
85+
}
86+
}
87+
88+
return nil
89+
}
90+
91+
var testAccTritonFabric_basic = `
92+
resource "triton_fabric" "test" {
93+
name = "%s"
94+
description = "test network"
95+
vlan_id = 2 # every DC seems to have a vlan 2 available
96+
97+
subnet = "10.0.0.0/22"
98+
gateway = "10.0.0.1"
99+
provision_start_ip = "10.0.0.5"
100+
provision_end_ip = "10.0.3.250"
101+
102+
resolvers = ["8.8.8.8", "8.8.4.4"]
103+
}
104+
`

0 commit comments

Comments
 (0)