1package vultr
2
3import (
4	"errors"
5	"fmt"
6	"log"
7	"strings"
8
9	"github.com/JamesClonk/vultr/lib"
10	"github.com/hashicorp/terraform/helper/schema"
11)
12
13func resourceIPV4() *schema.Resource {
14	return &schema.Resource{
15		Create: resourceIPV4Create,
16		Read:   resourceIPV4Read,
17		Update: resourceIPV4Update,
18		Delete: resourceIPV4Delete,
19		Importer: &schema.ResourceImporter{
20			State: schema.ImportStatePassthrough,
21		},
22
23		Schema: map[string]*schema.Schema{
24			"gateway": {
25				Type:     schema.TypeString,
26				Computed: true,
27			},
28
29			"ipv4_address": {
30				Type:     schema.TypeString,
31				Computed: true,
32			},
33
34			"instance_id": {
35				Type:     schema.TypeString,
36				Required: true,
37				ForceNew: true,
38			},
39
40			"netmask": {
41				Type:     schema.TypeString,
42				Computed: true,
43			},
44
45			"reboot": {
46				Type:     schema.TypeBool,
47				Optional: true,
48				Default:  true,
49			},
50
51			"reverse_dns": {
52				Type:     schema.TypeString,
53				Computed: true,
54			},
55		},
56	}
57}
58
59func resourceIPV4Create(d *schema.ResourceData, meta interface{}) error {
60	client := meta.(*Client)
61
62	instance := d.Get("instance_id").(string)
63	reboot := d.Get("reboot").(bool)
64
65	log.Printf("[INFO] Creating new IPv4 address")
66
67	vultrMutexKV.Lock(instance)
68	ips, err := client.ListIPv4(instance)
69	if err != nil {
70		return fmt.Errorf("Error listing IPv4 addresses: %v", err)
71	}
72	if err := client.CreateIPv4(instance, reboot); err != nil {
73		return fmt.Errorf("Error creating IPv4 address: %v", err)
74	}
75	newIPs, err := client.ListIPv4(instance)
76	if err != nil {
77		return fmt.Errorf("Error re-listing IPv4 addresses: %v", err)
78	}
79	vultrMutexKV.Unlock(instance)
80
81	var ip *lib.IPv4
82	for i := range newIPs {
83		var found bool
84		for j := range ips {
85			if newIPs[i] == ips[j] {
86				found = true
87				break
88			}
89		}
90		if !found {
91			ip = &newIPs[i]
92			break
93		}
94	}
95	if ip == nil {
96		return errors.New("Error finding created IPv4 address")
97	}
98
99	d.SetId(fmt.Sprintf("%s/%s", instance, ip.IP))
100
101	return resourceIPV4Read(d, meta)
102}
103
104func resourceIPV4Read(d *schema.ResourceData, meta interface{}) error {
105	client := meta.(*Client)
106
107	instance, id, err := parseStringSlashString(d.Id(), "IPv4 ID", "instance-id", "ip-address")
108	if err != nil {
109		return err
110	}
111
112	ips, err := client.ListIPv4(instance)
113	if err != nil {
114		if strings.HasPrefix(err.Error(), "Invalid server") {
115			log.Printf("[WARN] Removing IPv4 address (%s) because the attached instance (%s) is gone", d.Id(), instance)
116			d.SetId("")
117			return nil
118		}
119		return fmt.Errorf("Error getting IPv4 addresses: %v", err)
120	}
121	var ip *lib.IPv4
122	for i := range ips {
123		if ips[i].IP == id {
124			ip = &ips[i]
125			break
126		}
127	}
128	if ip == nil {
129		log.Printf("[WARN] Removing IPv4 address (%s) because it is gone", d.Id())
130		d.SetId("")
131		return nil
132	}
133
134	d.Set("gateway", ip.Gateway)
135	d.Set("ipv4_address", ip.IP)
136	d.Set("netmask", ip.Netmask)
137	d.Set("reverse_dns", ip.ReverseDNS)
138
139	return nil
140}
141
142func resourceIPV4Update(d *schema.ResourceData, meta interface{}) error {
143	return resourceIPV4Read(d, meta)
144}
145
146func resourceIPV4Delete(d *schema.ResourceData, meta interface{}) error {
147	client := meta.(*Client)
148
149	instance, id, err := parseStringSlashString(d.Id(), "IPv4 ID", "instance-id", "ip-address")
150	if err != nil {
151		return err
152	}
153
154	log.Printf("[INFO] Destroying IPv4 address (%s)", d.Id())
155
156	if err := client.DeleteIPv4(instance, id); err != nil {
157		return fmt.Errorf("Error destroying IPv4 address (%s): %v", d.Id(), err)
158	}
159
160	return nil
161}
162