From be3df2e54794331e906667c06445438a93f49ef1 Mon Sep 17 00:00:00 2001 From: Ayu Demura Date: Fri, 22 Jul 2016 11:55:49 -0400 Subject: [PATCH] Add ip reservation --- .../packet/resource_packet_ip_address.go | 2 +- .../packet/resource_packet_ip_reservation.go | 135 ++++++++++++++++++ .../resource_packet_ip_reservation_test.go | 86 +++++++++++ vendor/github.com/packethost/packngo/ip.go | 15 +- .../github.com/packethost/packngo/volumes.go | 38 ++--- vendor/vendor.json | 6 +- 6 files changed, 253 insertions(+), 29 deletions(-) create mode 100644 builtin/providers/packet/resource_packet_ip_reservation.go create mode 100644 builtin/providers/packet/resource_packet_ip_reservation_test.go diff --git a/builtin/providers/packet/resource_packet_ip_address.go b/builtin/providers/packet/resource_packet_ip_address.go index c3d2c9815..502e378b3 100644 --- a/builtin/providers/packet/resource_packet_ip_address.go +++ b/builtin/providers/packet/resource_packet_ip_address.go @@ -96,7 +96,7 @@ func resourcePacketIPAddressRead(d *schema.ResourceData, meta interface{}) error if err != nil { err = friendlyError(err) - // If the volume somehow already destroyed, mark as succesfully gone. + // If the ip_address somehow already destroyed, mark as succesfully gone. if isNotFound(err) { d.SetId("") return nil diff --git a/builtin/providers/packet/resource_packet_ip_reservation.go b/builtin/providers/packet/resource_packet_ip_reservation.go new file mode 100644 index 000000000..80547f3c0 --- /dev/null +++ b/builtin/providers/packet/resource_packet_ip_reservation.go @@ -0,0 +1,135 @@ +package packet + +import ( + "github.com/hashicorp/terraform/helper/schema" + "github.com/packethost/packngo" +) + +func resourcePacketIPReservation() *schema.Resource { + return &schema.Resource{ + Create: resourcePacketIPReservationCreate, + Read: resourcePacketIPReservationRead, + Delete: resourcePacketIPReservationDelete, + + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Optional: true, + Computed: true, + }, + + "gateway": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "network": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "family": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + + "netmask": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + + "cidr": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + + "public": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + }, + + "assigned_to": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + }, + + "created": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "updated": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourcePacketIPReservationCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*packngo.Client) + + createRequest := &packngo.IPReservationRequest{ + Type: d.Get("type").(string), + Quantity: d.Get("quantity").(int), + Comments: d.Get("comments").(string), + } + + project_id := "" + if attr, ok := d.GetOk("project_id"); ok { + project_id = attr.(string) + } + + newIPReservation, _, err := client.IpReservations.RequestMore(project_id, createRequest) + if err != nil { + return friendlyError(err) + } + + d.SetId(newIPReservation.ID) + + return resourcePacketIPReservationRead(d, meta) +} + +func resourcePacketIPReservationRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*packngo.Client) + + ip_reservation, _, err := client.IpReservations.Get(d.Id()) + if err != nil { + err = friendlyError(err) + + // If the ip_reservation somehow already destroyed, mark as succesfully gone. + if isNotFound(err) { + d.SetId("") + return nil + } + + return err + } + + d.Set("address", ip_reservation.Address) + d.Set("network", ip_reservation.Network) + d.Set("family", ip_reservation.AddressFamily) + d.Set("netmask", ip_reservation.Netmask) + d.Set("public", ip_reservation.Public) + d.Set("cidr", ip_reservation.Cidr) + d.Set("management", ip_reservation.Management) + d.Set("manageable", ip_reservation.Manageable) + d.Set("addon", ip_reservation.Addon) + d.Set("bill", ip_reservation.Bill) + d.Set("assignments", ip_reservation.Assignments) + d.Set("created", ip_reservation.Created) + d.Set("updated", ip_reservation.Updated) + + return nil +} + +func resourcePacketIPReservationDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*packngo.Client) + + if _, err := client.IpReservations.Remove(d.Id()); err != nil { + return friendlyError(err) + } + + return nil +} diff --git a/builtin/providers/packet/resource_packet_ip_reservation_test.go b/builtin/providers/packet/resource_packet_ip_reservation_test.go new file mode 100644 index 000000000..954e7c3c5 --- /dev/null +++ b/builtin/providers/packet/resource_packet_ip_reservation_test.go @@ -0,0 +1,86 @@ +package packet + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/packethost/packngo" +) + +func TestAccPacketIPReservation_Basic(t *testing.T) { + var ip_reservation packngo.IPReservation + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPacketIPReservationDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckPacketIPReservationConfig_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckPacketIPReservationExists("packet_ip_reservation.foobar", &ip_reservation), + testAccCheckPacketIPReservationAttributes(&ip_reservation), + resource.TestCheckResourceAttr( + "packet_ip_reservation.foobar", "address", "foobar"), + ), + }, + }, + }) +} + +func testAccCheckPacketIPReservationDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*packngo.Client) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "packet_ip_reservation" { + continue + } + if _, _, err := client.IpReservations.Get(rs.Primary.ID); err == nil { + return fmt.Errorf("IPReservation cstill exists") + } + } + + return nil +} + +func testAccCheckPacketIPReservationAttributes(ip_reservation *packngo.IPReservation) resource.TestCheckFunc { + return func(s *terraform.State) error { + if ip_reservation.Address != "foobar" { + return fmt.Errorf("Bad address: %s", ip_reservation.Address) + } + return nil + } +} + +func testAccCheckPacketIPReservationExists(n string, ip_reservation *packngo.IPReservation) 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") + } + + client := testAccProvider.Meta().(*packngo.Client) + + foundIPReservation, _, err := client.IpReservations.Get(rs.Primary.ID) + if err != nil { + return err + } + if foundIPReservation.ID != rs.Primary.ID { + return fmt.Errorf("Record not found: %v - %v", rs.Primary.ID, foundIPReservation) + } + + *ip_reservation = *foundIPReservation + + return nil + } +} + +var testAccCheckPacketIPReservationConfig_basic = fmt.Sprintf(` +resource "packet_ip_reservation" "foobar" { + address = "foobar" +}`) diff --git a/vendor/github.com/packethost/packngo/ip.go b/vendor/github.com/packethost/packngo/ip.go index c95147a9a..e65be7745 100644 --- a/vendor/github.com/packethost/packngo/ip.go +++ b/vendor/github.com/packethost/packngo/ip.go @@ -93,7 +93,7 @@ func (i *IPServiceOp) Assign(deviceID string, assignRequest *IPAddressAssignRequ // IPReservationService interface defines available IPReservation methods type IPReservationService interface { List(projectID string) ([]IPReservation, *Response, error) - RequestMore(projectID string, ipReservationReq *IPReservationRequest) (*Response, error) + RequestMore(projectID string, ipReservationReq *IPReservationRequest) (*IPReservation, *Response, error) Get(ipReservationID string) (*IPReservation, *Response, error) Remove(ipReservationID string) (*Response, error) } @@ -124,6 +124,8 @@ type IPReservation struct { Addon bool `json:"addon"` Bill bool `json:"bill"` Assignments []map[string]string `json:"assignments"` + Created string `json:"created_at,omitempty"` + Updated string `json:"updated_at,omitempty"` Href string `json:"href"` } @@ -149,19 +151,20 @@ func (i *IPReservationServiceOp) List(projectID string) ([]IPReservation, *Respo } // RequestMore requests more IP space for a project in order to have additional IP addresses to assign to devices -func (i *IPReservationServiceOp) RequestMore(projectID string, ipReservationReq *IPReservationRequest) (*Response, error) { +func (i *IPReservationServiceOp) RequestMore(projectID string, ipReservationReq *IPReservationRequest) (*IPReservation, *Response, error) { path := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, ipBasePath) req, err := i.client.NewRequest("POST", path, &ipReservationReq) if err != nil { - return nil, err + return nil, nil, err } - resp, err := i.client.Do(req, nil) + ip := new(IPReservation) + resp, err := i.client.Do(req, ip) if err != nil { - return nil, err + return nil, resp, err } - return resp, err + return ip, resp, err } // Get returns a single IP reservation object diff --git a/vendor/github.com/packethost/packngo/volumes.go b/vendor/github.com/packethost/packngo/volumes.go index e0b7eeacc..6b6171f95 100644 --- a/vendor/github.com/packethost/packngo/volumes.go +++ b/vendor/github.com/packethost/packngo/volumes.go @@ -14,21 +14,21 @@ type VolumeService interface { // Volume represents a volume type Volume struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Size int `json:"size,omitempty"` - State string `json:"state,omitempty"` - Locked bool `json:"locked,omitempty"` - BillingCycle string `json:"billing_cycle,omitempty"` - Created string `json:"created_at,omitempty"` - Updated string `json:"updated_at,omitempty"` - Href string `json:"href,omitempty"` + ID string `json:"id"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Size int `json:"size,omitempty"` + State string `json:"state,omitempty"` + Locked bool `json:"locked,omitempty"` + BillingCycle string `json:"billing_cycle,omitempty"` + Created string `json:"created_at,omitempty"` + Updated string `json:"updated_at,omitempty"` + Href string `json:"href,omitempty"` SnapshotPolicies []*SnapshotPolicy `json:"snapshot_policies,omitempty"` Attachments []*Attachment `json:"attachments,omitempty"` - Plan *Plan `json:"plan,omitempty"` - Facility *Facility `json:"facility,omitempty"` - Project *Project `json:"project,omitempty"` + Plan *Plan `json:"plan,omitempty"` + Facility *Facility `json:"facility,omitempty"` + Project *Project `json:"project,omitempty"` } // SnapshotPolicy used to execute actions on volume @@ -51,12 +51,12 @@ func (v Volume) String() string { // VolumeCreateRequest type used to create a Packet volume type VolumeCreateRequest struct { - Size int `json:"size"` - BillingCycle string `json:"billing_cycle"` - ProjectID string `json:"project_id"` - PlanID string `json:"plan_id"` - FacilityID string `json:"facility_id"` - Description string `json:"Description,omitempty"` + Size int `json:"size"` + BillingCycle string `json:"billing_cycle"` + ProjectID string `json:"project_id"` + PlanID string `json:"plan_id"` + FacilityID string `json:"facility_id"` + Description string `json:"Description,omitempty"` SnapshotPolicies []*SnapshotPolicy `json:"snapshot_policies,omitempty"` } diff --git a/vendor/vendor.json b/vendor/vendor.json index 07197c307..c55457f68 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1464,10 +1464,10 @@ "revision": "3d184cea22ee1c41ec1697e0d830ff0c78f7ea97" }, { - "checksumSHA1": "yHIFvxXMD3q3ZvQZFLw+EJBhTq8=", + "checksumSHA1": "/r0HjrIkynh4Gj0EIAKirEKP/Rk=", "path": "github.com/packethost/packngo", - "revision": "a596b01fbf1afdf90188ec02aa61fe7cc9703945", - "revisionTime": "2016-07-21T21:43:59Z" + "revision": "1bf5adfc4f590757da03407f576c46569a9c04b0", + "revisionTime": "2016-07-22T15:57:43Z" }, { "path": "github.com/pborman/uuid",