add volume
This commit is contained in:
parent
3481d1bf6e
commit
3099fc7b1c
|
@ -21,6 +21,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"packet_device": resourcePacketDevice(),
|
"packet_device": resourcePacketDevice(),
|
||||||
"packet_ssh_key": resourcePacketSSHKey(),
|
"packet_ssh_key": resourcePacketSSHKey(),
|
||||||
"packet_project": resourcePacketProject(),
|
"packet_project": resourcePacketProject(),
|
||||||
|
"packet_volume": resourcePacketVolume(),
|
||||||
},
|
},
|
||||||
|
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
|
|
|
@ -208,13 +208,13 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
network := map[string]interface{}{
|
network := map[string]interface{}{
|
||||||
"address": ip.Address,
|
"address": ip.Address,
|
||||||
"gateway": ip.Gateway,
|
"gateway": ip.Gateway,
|
||||||
"family": ip.Family,
|
"family": ip.AddressFamily,
|
||||||
"cidr": ip.Cidr,
|
"cidr": ip.Cidr,
|
||||||
"public": ip.Public,
|
"public": ip.Public,
|
||||||
}
|
}
|
||||||
networks = append(networks, network)
|
networks = append(networks, network)
|
||||||
|
|
||||||
if ip.Family == 4 && ip.Public == true {
|
if ip.AddressFamily == 4 && ip.Public == true {
|
||||||
host = ip.Address
|
host = ip.Address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
package packet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/packethost/packngo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourcePacketVolume() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourcePacketVolumeCreate,
|
||||||
|
Read: resourcePacketVolumeRead,
|
||||||
|
Update: resourcePacketVolumeUpdate,
|
||||||
|
Delete: resourcePacketVolumeDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"project_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"description": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: false,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"size": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: false,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"facility": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"plan": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"billing_cycle": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"state": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"locked": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"snapshot_policies": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"snapshot_frequency": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"snapshot_count": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"attachments": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"href": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"created": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"updated": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourcePacketVolumeCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
|
createRequest := &packngo.VolumeCreateRequest{
|
||||||
|
PlanID: d.Get("plan").(string),
|
||||||
|
FacilityID: d.Get("facility").(string),
|
||||||
|
BillingCycle: d.Get("billing_cycle").(string),
|
||||||
|
ProjectID: d.Get("project_id").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr, ok := d.GetOk("description"); ok {
|
||||||
|
createRequest.Description = attr.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr, ok := d.GetOk("size"); ok {
|
||||||
|
createRequest.Size = attr.(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot_policies := d.Get("snapshot_policies.#").(int)
|
||||||
|
if snapshot_policies > 0 {
|
||||||
|
createRequest.SnapshotPolicies = make([]*packngo.SnapshotPolicy, 0, snapshot_policies)
|
||||||
|
for i := 0; i < snapshot_policies; i++ {
|
||||||
|
key := fmt.Sprintf("snapshot_policies.%d", i)
|
||||||
|
createRequest.SnapshotPolicies = append(createRequest.SnapshotPolicies, d.Get(key).(*packngo.SnapshotPolicy))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newVolume, _, err := client.Volumes.Create(createRequest)
|
||||||
|
if err != nil {
|
||||||
|
return friendlyError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(newVolume.ID)
|
||||||
|
|
||||||
|
return resourcePacketVolumeRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourcePacketVolumeRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
|
device, _, err := client.Volumes.Get(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
err = friendlyError(err)
|
||||||
|
|
||||||
|
// If the volume somehow already destroyed, mark as succesfully gone.
|
||||||
|
if isNotFound(err) {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", device.Name)
|
||||||
|
d.Set("description", device.Description)
|
||||||
|
d.Set("size", device.Size)
|
||||||
|
d.Set("plan", device.Plan.Slug)
|
||||||
|
d.Set("facility", device.Facility.Code)
|
||||||
|
d.Set("state", device.State)
|
||||||
|
d.Set("billing_cycle", device.BillingCycle)
|
||||||
|
d.Set("locked", device.Locked)
|
||||||
|
d.Set("created", device.Created)
|
||||||
|
d.Set("updated", device.Updated)
|
||||||
|
|
||||||
|
snapshot_policies := make([]*packngo.SnapshotPolicy, 0, len(device.SnapshotPolicies))
|
||||||
|
for _, snapshot_policy := range device.SnapshotPolicies {
|
||||||
|
snapshot_policies = append(snapshot_policies, snapshot_policy)
|
||||||
|
}
|
||||||
|
d.Set("snapshot_policies", snapshot_policies)
|
||||||
|
|
||||||
|
attachments := make([]*packngo.Attachment, 0, len(device.Attachments))
|
||||||
|
for _, attachment := range device.Attachments {
|
||||||
|
attachments = append(attachments, attachment)
|
||||||
|
}
|
||||||
|
d.Set("attachments", attachments)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourcePacketVolumeUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
|
updateRequest := &packngo.VolumeUpdateRequest{
|
||||||
|
ID: d.Get("id").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr, ok := d.GetOk("description"); ok {
|
||||||
|
updateRequest.Description = attr.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr, ok := d.GetOk("plan"); ok {
|
||||||
|
updateRequest.Plan = attr.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := client.Volumes.Update(updateRequest)
|
||||||
|
if err != nil {
|
||||||
|
return friendlyError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourcePacketVolumeRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourcePacketVolumeDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*packngo.Client)
|
||||||
|
|
||||||
|
if _, err := client.Volumes.Delete(d.Id()); err != nil {
|
||||||
|
return friendlyError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -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 TestAccPacketVolume_Basic(t *testing.T) {
|
||||||
|
var volume packngo.Volume
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckPacketVolumeDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccCheckPacketVolumeConfig_basic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckPacketVolumeExists("packet_volume.foobar", &volume),
|
||||||
|
testAccCheckPacketVolumeAttributes(&volume),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"packet_volume.foobar", "name", "foobar"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckPacketVolumeDestroy(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*packngo.Client)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "packet_volume" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, _, err := client.Volumes.Get(rs.Primary.ID); err == nil {
|
||||||
|
return fmt.Errorf("Volume cstill exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckPacketVolumeAttributes(volume *packngo.Volume) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if volume.Name != "foobar" {
|
||||||
|
return fmt.Errorf("Bad name: %s", volume.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckPacketVolumeExists(n string, volume *packngo.Volume) 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)
|
||||||
|
|
||||||
|
foundVolume, _, err := client.Volumes.Get(rs.Primary.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if foundVolume.ID != rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Record not found: %v - %v", rs.Primary.ID, foundVolume)
|
||||||
|
}
|
||||||
|
|
||||||
|
*volume = *foundVolume
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testAccCheckPacketVolumeConfig_basic = fmt.Sprintf(`
|
||||||
|
resource "packet_volume" "foobar" {
|
||||||
|
name = "foobar"
|
||||||
|
}`)
|
|
@ -0,0 +1,9 @@
|
||||||
|
# packngo
|
||||||
|
Packet Go Api Client
|
||||||
|
|
||||||
|
![](https://www.packet.net/media/labs/images/1679091c5a880faf6fb5e6087eb1b2dc/ULY7-hero.png)
|
||||||
|
|
||||||
|
Committing
|
||||||
|
----------
|
||||||
|
|
||||||
|
Before committing, it's a good idea to run `gofmt -w *.go`. ([gofmt](https://golang.org/cmd/gofmt/))
|
|
@ -69,19 +69,6 @@ func (d DeviceActionRequest) String() string {
|
||||||
return Stringify(d)
|
return Stringify(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPAddress used to execute actions on devices
|
|
||||||
type IPAddress struct {
|
|
||||||
Family int `json:"address_family"`
|
|
||||||
Cidr int `json:"cidr"`
|
|
||||||
Address string `json:"address"`
|
|
||||||
Gateway string `json:"gateway"`
|
|
||||||
Public bool `json:"public"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IPAddress) String() string {
|
|
||||||
return Stringify(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeviceServiceOp implements DeviceService
|
// DeviceServiceOp implements DeviceService
|
||||||
type DeviceServiceOp struct {
|
type DeviceServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
|
|
|
@ -9,11 +9,12 @@ type EmailService interface {
|
||||||
|
|
||||||
// Email represents a user's email address
|
// Email represents a user's email address
|
||||||
type Email struct {
|
type Email struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Default bool `json:"default,omitempty"`
|
Default bool `json:"default,omitempty"`
|
||||||
URL string `json:"href,omitempty"`
|
URL string `json:"href,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Email) String() string {
|
func (e Email) String() string {
|
||||||
return Stringify(e)
|
return Stringify(e)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +24,7 @@ type EmailServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get retrieves an email by id
|
// Get retrieves an email by id
|
||||||
func (s *EmailServiceOp) Get(emailID string) (*Email, *Response, error) {
|
func (s *EmailServiceOp) Get(emailID string) (*Email, *Response, error) {
|
||||||
req, err := s.client.NewRequest("GET", emailBasePath, nil)
|
req, err := s.client.NewRequest("GET", emailBasePath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package packngo
|
package packngo
|
||||||
|
|
||||||
const facilityBasePath = "/facilities"
|
const facilityBasePath = "/facilities"
|
||||||
|
|
||||||
|
@ -13,13 +13,14 @@ type facilityRoot struct {
|
||||||
|
|
||||||
// Facility represents a Packet facility
|
// Facility represents a Packet facility
|
||||||
type Facility struct {
|
type Facility struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Code string `json:"code,omitempty"`
|
Code string `json:"code,omitempty"`
|
||||||
Features []string `json:"features,omitempty"`
|
Features []string `json:"features,omitempty"`
|
||||||
Address *Address `json:"address,omitempty"`
|
Address *Address `json:"address,omitempty"`
|
||||||
URL string `json:"href,omitempty"`
|
URL string `json:"href,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Facility) String() string {
|
func (f Facility) String() string {
|
||||||
return Stringify(f)
|
return Stringify(f)
|
||||||
}
|
}
|
||||||
|
@ -28,11 +29,11 @@ func (f Facility) String() string {
|
||||||
type Address struct {
|
type Address struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Address) String() string {
|
func (a Address) String() string {
|
||||||
return Stringify(a)
|
return Stringify(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FacilityServiceOp implements FacilityService
|
// FacilityServiceOp implements FacilityService
|
||||||
type FacilityServiceOp struct {
|
type FacilityServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
package packngo
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const ipBasePath = "/ips"
|
||||||
|
|
||||||
|
// IPService interface defines available IP methods
|
||||||
|
type IPService interface {
|
||||||
|
Assign(deviceID string, assignRequest *IPAddressAssignRequest) (*IPAddress, *Response, error)
|
||||||
|
Unassign(ipAddressID string) (*Response, error)
|
||||||
|
Get(ipAddressID string) (*IPAddress, *Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress represents a ip address
|
||||||
|
type IPAddress struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Gateway string `json:"gateway"`
|
||||||
|
Network string `json:"network"`
|
||||||
|
AddressFamily int `json:"address_family"`
|
||||||
|
Netmask string `json:"netmask"`
|
||||||
|
Public bool `json:"public"`
|
||||||
|
Cidr int `json:"cidr"`
|
||||||
|
AssignedTo map[string]string `json:"assigned_to"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddressAssignRequest represents the body if a ip assign request
|
||||||
|
type IPAddressAssignRequest struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IPAddress) String() string {
|
||||||
|
return Stringify(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPServiceOp implements IPService
|
||||||
|
type IPServiceOp struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns IpAddress by ID
|
||||||
|
func (i *IPServiceOp) Get(ipAddressID string) (*IPAddress, *Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", ipBasePath, ipAddressID)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := new(IPAddress)
|
||||||
|
resp, err := i.client.Do(req, ip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unassign unassigns an IP address record. This will remove the relationship between an IP
|
||||||
|
// and the device and will make the IP address available to be assigned to another device.
|
||||||
|
func (i *IPServiceOp) Unassign(ipAddressID string) (*Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", ipBasePath, ipAddressID)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := i.client.Do(req, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign assigns an IP address to a device. The IP address must be in one of the IP ranges assigned to the device’s project.
|
||||||
|
func (i *IPServiceOp) Assign(deviceID string, assignRequest *IPAddressAssignRequest) (*IPAddress, *Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s%s", deviceBasePath, deviceID, ipBasePath)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("POST", path, assignRequest)
|
||||||
|
|
||||||
|
ip := new(IPAddress)
|
||||||
|
resp, err := i.client.Do(req, ip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP RESERVATIONS API
|
||||||
|
|
||||||
|
// IPReservationService interface defines available IPReservation methods
|
||||||
|
type IPReservationService interface {
|
||||||
|
List(projectID string) ([]IPReservation, *Response, error)
|
||||||
|
RequestMore(projectID string, ipReservationReq *IPReservationRequest) (*Response, error)
|
||||||
|
Get(ipReservationID string) (*IPReservation, *Response, error)
|
||||||
|
Remove(ipReservationID string) (*Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPReservationServiceOp implements the IPReservationService interface
|
||||||
|
type IPReservationServiceOp struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPReservationRequest represents the body of a reservation request
|
||||||
|
type IPReservationRequest struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
Comments string `json:"comments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPReservation represent an IP reservation for a single project
|
||||||
|
type IPReservation struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Network string `json:"network"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
AddressFamily int `json:"address_family"`
|
||||||
|
Netmask string `json:"netmask"`
|
||||||
|
Public bool `json:"public"`
|
||||||
|
Cidr int `json:"cidr"`
|
||||||
|
Management bool `json:"management"`
|
||||||
|
Manageable bool `json:"manageable"`
|
||||||
|
Addon bool `json:"addon"`
|
||||||
|
Bill bool `json:"bill"`
|
||||||
|
Assignments []map[string]string `json:"assignments"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ipReservationRoot struct {
|
||||||
|
IPReservations []IPReservation `json:"ip_addresses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List provides a list of IP resevations for a single project.
|
||||||
|
func (i *IPReservationServiceOp) List(projectID string) ([]IPReservation, *Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, ipBasePath)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reservations := new(ipReservationRoot)
|
||||||
|
resp, err := i.client.Do(req, reservations)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return reservations.IPReservations, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
path := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, ipBasePath)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("POST", path, &ipReservationReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := i.client.Do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns a single IP reservation object
|
||||||
|
func (i *IPReservationServiceOp) Get(ipReservationID string) (*IPReservation, *Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", ipBasePath, ipReservationID)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reservation := new(IPReservation)
|
||||||
|
resp, err := i.client.Do(req, reservation)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reservation, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes an IP reservation from the project.
|
||||||
|
func (i *IPReservationServiceOp) Remove(ipReservationID string) (*Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", ipBasePath, ipReservationID)
|
||||||
|
|
||||||
|
req, err := i.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := i.client.Do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
|
@ -18,16 +18,17 @@ type OS struct {
|
||||||
Distro string `json:"distro"`
|
Distro string `json:"distro"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o OS) String() string {
|
func (o OS) String() string {
|
||||||
return Stringify(o)
|
return Stringify(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSServiceOp implements OSService
|
// OSServiceOp implements OSService
|
||||||
type OSServiceOp struct {
|
type OSServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// List returns all available operating systems
|
// List returns all available operating systems
|
||||||
func (s *OSServiceOp) List() ([]OS, *Response, error) {
|
func (s *OSServiceOp) List() ([]OS, *Response, error) {
|
||||||
req, err := s.client.NewRequest("GET", osBasePath, nil)
|
req, err := s.client.NewRequest("GET", osBasePath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -89,6 +89,9 @@ type Client struct {
|
||||||
Projects ProjectService
|
Projects ProjectService
|
||||||
Facilities FacilityService
|
Facilities FacilityService
|
||||||
OperatingSystems OSService
|
OperatingSystems OSService
|
||||||
|
Ips IPService
|
||||||
|
IpReservations IPReservationService
|
||||||
|
Volumes VolumeService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRequest inits a new http request with the proper headers
|
// NewRequest inits a new http request with the proper headers
|
||||||
|
@ -165,6 +168,10 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
|
||||||
// an older version of Go, pass in a custom http.Client with a custom TLS configuration
|
// an older version of Go, pass in a custom http.Client with a custom TLS configuration
|
||||||
// that sets "InsecureSkipVerify" to "true"
|
// that sets "InsecureSkipVerify" to "true"
|
||||||
func NewClient(consumerToken string, apiKey string, httpClient *http.Client) *Client {
|
func NewClient(consumerToken string, apiKey string, httpClient *http.Client) *Client {
|
||||||
|
client, _ := NewClientWithBaseURL(consumerToken, apiKey, httpClient, baseURL)
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
func NewClientWithBaseURL(consumerToken string, apiKey string, httpClient *http.Client, apiBaseURL string) (*Client, error) {
|
||||||
if httpClient == nil {
|
if httpClient == nil {
|
||||||
// Don't fall back on http.DefaultClient as it's not nice to adjust state
|
// Don't fall back on http.DefaultClient as it's not nice to adjust state
|
||||||
// implicitly. If the client wants to use http.DefaultClient, they can
|
// implicitly. If the client wants to use http.DefaultClient, they can
|
||||||
|
@ -172,9 +179,12 @@ func NewClient(consumerToken string, apiKey string, httpClient *http.Client) *Cl
|
||||||
httpClient = &http.Client{}
|
httpClient = &http.Client{}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseURL, _ := url.Parse(baseURL)
|
u, err := url.Parse(apiBaseURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
c := &Client{client: httpClient, BaseURL: BaseURL, UserAgent: userAgent, ConsumerToken: consumerToken, APIKey: apiKey}
|
c := &Client{client: httpClient, BaseURL: u, UserAgent: userAgent, ConsumerToken: consumerToken, APIKey: apiKey}
|
||||||
c.Plans = &PlanServiceOp{client: c}
|
c.Plans = &PlanServiceOp{client: c}
|
||||||
c.Users = &UserServiceOp{client: c}
|
c.Users = &UserServiceOp{client: c}
|
||||||
c.Emails = &EmailServiceOp{client: c}
|
c.Emails = &EmailServiceOp{client: c}
|
||||||
|
@ -183,8 +193,11 @@ func NewClient(consumerToken string, apiKey string, httpClient *http.Client) *Cl
|
||||||
c.Projects = &ProjectServiceOp{client: c}
|
c.Projects = &ProjectServiceOp{client: c}
|
||||||
c.Facilities = &FacilityServiceOp{client: c}
|
c.Facilities = &FacilityServiceOp{client: c}
|
||||||
c.OperatingSystems = &OSServiceOp{client: c}
|
c.OperatingSystems = &OSServiceOp{client: c}
|
||||||
|
c.Ips = &IPServiceOp{client: c}
|
||||||
|
c.IpReservations = &IPReservationServiceOp{client: c}
|
||||||
|
c.Volumes = &VolumeServiceOp{client: c}
|
||||||
|
|
||||||
return c
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkResponse(r *http.Response) error {
|
func checkResponse(r *http.Response) error {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package packngo
|
package packngo
|
||||||
|
|
||||||
const planBasePath = "/plans"
|
const planBasePath = "/plans"
|
||||||
|
|
||||||
|
@ -21,18 +21,20 @@ type Plan struct {
|
||||||
Specs *Specs `json:"specs,omitempty"`
|
Specs *Specs `json:"specs,omitempty"`
|
||||||
Pricing *Pricing `json:"pricing,omitempty"`
|
Pricing *Pricing `json:"pricing,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Plan) String() string {
|
func (p Plan) String() string {
|
||||||
return Stringify(p)
|
return Stringify(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specs - the server specs for a plan
|
// Specs - the server specs for a plan
|
||||||
type Specs struct {
|
type Specs struct {
|
||||||
Cpus []*Cpus `json:"cpus,omitempty"`
|
Cpus []*Cpus `json:"cpus,omitempty"`
|
||||||
Memory *Memory `json:"memory,omitempty"`
|
Memory *Memory `json:"memory,omitempty"`
|
||||||
Drives []*Drives `json:"drives,omitempty"`
|
Drives []*Drives `json:"drives,omitempty"`
|
||||||
Nics []*Nics `json:"nics,omitempty"`
|
Nics []*Nics `json:"nics,omitempty"`
|
||||||
Features *Features `json:"features,omitempty"`
|
Features *Features `json:"features,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Specs) String() string {
|
func (s Specs) String() string {
|
||||||
return Stringify(s)
|
return Stringify(s)
|
||||||
}
|
}
|
||||||
|
@ -42,6 +44,7 @@ type Cpus struct {
|
||||||
Count int `json:"count,omitempty"`
|
Count int `json:"count,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Cpus) String() string {
|
func (c Cpus) String() string {
|
||||||
return Stringify(c)
|
return Stringify(c)
|
||||||
}
|
}
|
||||||
|
@ -50,6 +53,7 @@ func (c Cpus) String() string {
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
Total string `json:"total,omitempty"`
|
Total string `json:"total,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Memory) String() string {
|
func (m Memory) String() string {
|
||||||
return Stringify(m)
|
return Stringify(m)
|
||||||
}
|
}
|
||||||
|
@ -60,6 +64,7 @@ type Drives struct {
|
||||||
Size string `json:"size,omitempty"`
|
Size string `json:"size,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d Drives) String() string {
|
func (d Drives) String() string {
|
||||||
return Stringify(d)
|
return Stringify(d)
|
||||||
}
|
}
|
||||||
|
@ -69,6 +74,7 @@ type Nics struct {
|
||||||
Count int `json:"count,omitempty"`
|
Count int `json:"count,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n Nics) String() string {
|
func (n Nics) String() string {
|
||||||
return Stringify(n)
|
return Stringify(n)
|
||||||
}
|
}
|
||||||
|
@ -78,6 +84,7 @@ type Features struct {
|
||||||
Raid bool `json:"raid,omitempty"`
|
Raid bool `json:"raid,omitempty"`
|
||||||
Txt bool `json:"txt,omitempty"`
|
Txt bool `json:"txt,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Features) String() string {
|
func (f Features) String() string {
|
||||||
return Stringify(f)
|
return Stringify(f)
|
||||||
}
|
}
|
||||||
|
@ -87,6 +94,7 @@ type Pricing struct {
|
||||||
Hourly float32 `json:"hourly,omitempty"`
|
Hourly float32 `json:"hourly,omitempty"`
|
||||||
Monthly float32 `json:"monthly,omitempty"`
|
Monthly float32 `json:"monthly,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Pricing) String() string {
|
func (p Pricing) String() string {
|
||||||
return Stringify(p)
|
return Stringify(p)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,22 @@ type ProjectService interface {
|
||||||
Create(*ProjectCreateRequest) (*Project, *Response, error)
|
Create(*ProjectCreateRequest) (*Project, *Response, error)
|
||||||
Update(*ProjectUpdateRequest) (*Project, *Response, error)
|
Update(*ProjectUpdateRequest) (*Project, *Response, error)
|
||||||
Delete(string) (*Response, error)
|
Delete(string) (*Response, error)
|
||||||
|
ListIPAddresses(string) ([]IPAddress, *Response, error)
|
||||||
|
ListVolumes(string) ([]Volume, *Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ipsRoot struct {
|
||||||
|
IPAddresses []IPAddress `json:"ip_addresses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type volumesRoot struct {
|
||||||
|
Volumes []Volume `json:"volumes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type projectsRoot struct {
|
type projectsRoot struct {
|
||||||
Projects []Project `json:"projects"`
|
Projects []Project `json:"projects"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Project represents a Packet project
|
// Project represents a Packet project
|
||||||
type Project struct {
|
type Project struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
@ -27,6 +38,7 @@ type Project struct {
|
||||||
SSHKeys []SSHKey `json:"ssh_keys,omitempty"`
|
SSHKeys []SSHKey `json:"ssh_keys,omitempty"`
|
||||||
URL string `json:"href,omitempty"`
|
URL string `json:"href,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Project) String() string {
|
func (p Project) String() string {
|
||||||
return Stringify(p)
|
return Stringify(p)
|
||||||
}
|
}
|
||||||
|
@ -36,6 +48,7 @@ type ProjectCreateRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
PaymentMethod string `json:"payment_method,omitempty"`
|
PaymentMethod string `json:"payment_method,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ProjectCreateRequest) String() string {
|
func (p ProjectCreateRequest) String() string {
|
||||||
return Stringify(p)
|
return Stringify(p)
|
||||||
}
|
}
|
||||||
|
@ -46,6 +59,7 @@ type ProjectUpdateRequest struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
PaymentMethod string `json:"payment_method,omitempty"`
|
PaymentMethod string `json:"payment_method,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ProjectUpdateRequest) String() string {
|
func (p ProjectUpdateRequest) String() string {
|
||||||
return Stringify(p)
|
return Stringify(p)
|
||||||
}
|
}
|
||||||
|
@ -55,6 +69,22 @@ type ProjectServiceOp struct {
|
||||||
client *Client
|
client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ProjectServiceOp) ListIPAddresses(projectID string) ([]IPAddress, *Response, error) {
|
||||||
|
url := fmt.Sprintf("%s/%s/ips", projectBasePath, projectID)
|
||||||
|
req, err := s.client.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := new(ipsRoot)
|
||||||
|
resp, err := s.client.Do(req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.IPAddresses, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
// List returns the user's projects
|
// List returns the user's projects
|
||||||
func (s *ProjectServiceOp) List() ([]Project, *Response, error) {
|
func (s *ProjectServiceOp) List() ([]Project, *Response, error) {
|
||||||
req, err := s.client.NewRequest("GET", projectBasePath, nil)
|
req, err := s.client.NewRequest("GET", projectBasePath, nil)
|
||||||
|
@ -134,3 +164,20 @@ func (s *ProjectServiceOp) Delete(projectID string) (*Response, error) {
|
||||||
|
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List returns Volumes for a project
|
||||||
|
func (s *ProjectServiceOp) ListVolumes(projectID string) ([]Volume, *Response, error) {
|
||||||
|
url := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, volumeBasePath)
|
||||||
|
req, err := s.client.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := new(volumesRoot)
|
||||||
|
resp, err := s.client.Do(req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.Volumes, resp, err
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@ package packngo
|
||||||
|
|
||||||
// Rate provides the API request rate limit details
|
// Rate provides the API request rate limit details
|
||||||
type Rate struct {
|
type Rate struct {
|
||||||
RequestLimit int `json:"request_limit"`
|
RequestLimit int `json:"request_limit"`
|
||||||
RequestsRemaining int `json:"requests_remaining"`
|
RequestsRemaining int `json:"requests_remaining"`
|
||||||
Reset Timestamp `json:"rate_reset"`
|
Reset Timestamp `json:"rate_reset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Rate) String() string {
|
func (r Rate) String() string {
|
||||||
return Stringify(r)
|
return Stringify(r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,34 +19,37 @@ type sshKeyRoot struct {
|
||||||
|
|
||||||
// SSHKey represents a user's ssh key
|
// SSHKey represents a user's ssh key
|
||||||
type SSHKey struct {
|
type SSHKey struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
FingerPrint string `json:"fingerprint"`
|
FingerPrint string `json:"fingerprint"`
|
||||||
Created string `json:"created_at"`
|
Created string `json:"created_at"`
|
||||||
Updated string `json:"updated_at"`
|
Updated string `json:"updated_at"`
|
||||||
User User `json:"user,omitempty"`
|
User User `json:"user,omitempty"`
|
||||||
URL string `json:"href,omitempty"`
|
URL string `json:"href,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SSHKey) String() string {
|
func (s SSHKey) String() string {
|
||||||
return Stringify(s)
|
return Stringify(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSHKeyCreateRequest type used to create an ssh key
|
// SSHKeyCreateRequest type used to create an ssh key
|
||||||
type SSHKeyCreateRequest struct {
|
type SSHKeyCreateRequest struct {
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SSHKeyCreateRequest) String() string {
|
func (s SSHKeyCreateRequest) String() string {
|
||||||
return Stringify(s)
|
return Stringify(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSHKeyUpdateRequest type used to update an ssh key
|
// SSHKeyUpdateRequest type used to update an ssh key
|
||||||
type SSHKeyUpdateRequest struct {
|
type SSHKeyUpdateRequest struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SSHKeyUpdateRequest) String() string {
|
func (s SSHKeyUpdateRequest) String() string {
|
||||||
return Stringify(s)
|
return Stringify(s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,23 +9,24 @@ type UserService interface {
|
||||||
|
|
||||||
// User represents a Packet user
|
// User represents a Packet user
|
||||||
type User struct {
|
type User struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
FirstName string `json:"first_name,omitempty"`
|
FirstName string `json:"first_name,omitempty"`
|
||||||
LastName string `json:"last_name,omitempty"`
|
LastName string `json:"last_name,omitempty"`
|
||||||
FullName string `json:"full_name,omitempty"`
|
FullName string `json:"full_name,omitempty"`
|
||||||
Email string `json:"email,omitempty"`
|
Email string `json:"email,omitempty"`
|
||||||
TwoFactor string `json:"two_factor_auth,omitempty"`
|
TwoFactor string `json:"two_factor_auth,omitempty"`
|
||||||
AvatarURL string `json:"avatar_url,omitempty"`
|
AvatarURL string `json:"avatar_url,omitempty"`
|
||||||
Facebook string `json:"twitter,omitempty"`
|
Facebook string `json:"twitter,omitempty"`
|
||||||
Twitter string `json:"facebook,omitempty"`
|
Twitter string `json:"facebook,omitempty"`
|
||||||
LinkedIn string `json:"linkedin,omitempty"`
|
LinkedIn string `json:"linkedin,omitempty"`
|
||||||
Created string `json:"created_at,omitempty"`
|
Created string `json:"created_at,omitempty"`
|
||||||
Updated string `json:"updated_at,omitempty"`
|
Updated string `json:"updated_at,omitempty"`
|
||||||
TimeZone string `json:"timezone,omitempty"`
|
TimeZone string `json:"timezone,omitempty"`
|
||||||
Emails []Email `json:"email,omitempty"`
|
Emails []Email `json:"email,omitempty"`
|
||||||
PhoneNumber string `json:"phone_number,omitempty"`
|
PhoneNumber string `json:"phone_number,omitempty"`
|
||||||
URL string `json:"href,omitempty"`
|
URL string `json:"href,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u User) String() string {
|
func (u User) String() string {
|
||||||
return Stringify(u)
|
return Stringify(u)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
package packngo
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const volumeBasePath = "/storage"
|
||||||
|
|
||||||
|
// VolumeService interface defines available Volume methods
|
||||||
|
type VolumeService interface {
|
||||||
|
Get(string) (*Volume, *Response, error)
|
||||||
|
Update(*VolumeUpdateRequest) (*Volume, *Response, error)
|
||||||
|
Delete(string) (*Response, error)
|
||||||
|
Create(*VolumeCreateRequest) (*Volume, *Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SnapshotPolicy used to execute actions on volume
|
||||||
|
type SnapshotPolicy struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
SnapshotFrequency string `json:"snapshot_frequency,omitempty"`
|
||||||
|
snapshot_count int `json:"snapshot_count,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attachment used to execute actions on volume
|
||||||
|
type Attachment struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Href string `json:"href"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Volume) String() string {
|
||||||
|
return Stringify(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
SnapshotPolicies []*SnapshotPolicy `json:"snapshot_policies,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v VolumeCreateRequest) String() string {
|
||||||
|
return Stringify(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VolumeUpdateRequest type used to update a Packet volume
|
||||||
|
type VolumeUpdateRequest struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Plan string `json:"plan,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v VolumeUpdateRequest) String() string {
|
||||||
|
return Stringify(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VolumeServiceOp implements VolumeService
|
||||||
|
type VolumeServiceOp struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns a volume by id
|
||||||
|
func (v *VolumeServiceOp) Get(volumeID string) (*Volume, *Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", volumeBasePath, volumeID)
|
||||||
|
req, err := v.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
volume := new(Volume)
|
||||||
|
resp, err := v.client.Do(req, volume)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return volume, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates a volume
|
||||||
|
func (v *VolumeServiceOp) Update(updateRequest *VolumeUpdateRequest) (*Volume, *Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", volumeBasePath, updateRequest.ID)
|
||||||
|
req, err := v.client.NewRequest("PATCH", path, updateRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
volume := new(Volume)
|
||||||
|
resp, err := v.client.Do(req, volume)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return volume, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes a volume
|
||||||
|
func (v *VolumeServiceOp) Delete(volumeID string) (*Response, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", volumeBasePath, volumeID)
|
||||||
|
|
||||||
|
req, err := v.client.NewRequest("DELETE", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := v.client.Do(req, nil)
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates a new volume for a project
|
||||||
|
func (v *VolumeServiceOp) Create(createRequest *VolumeCreateRequest) (*Volume, *Response, error) {
|
||||||
|
url := fmt.Sprintf("%s/%s%s", projectBasePath, createRequest.ProjectID, volumeBasePath)
|
||||||
|
req, err := v.client.NewRequest("POST", url, createRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
volume := new(Volume)
|
||||||
|
resp, err := v.client.Do(req, volume)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return volume, resp, err
|
||||||
|
}
|
|
@ -1464,8 +1464,10 @@
|
||||||
"revision": "3d184cea22ee1c41ec1697e0d830ff0c78f7ea97"
|
"revision": "3d184cea22ee1c41ec1697e0d830ff0c78f7ea97"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"checksumSHA1": "yHIFvxXMD3q3ZvQZFLw+EJBhTq8=",
|
||||||
"path": "github.com/packethost/packngo",
|
"path": "github.com/packethost/packngo",
|
||||||
"revision": "f03d7dc788a8b57b62d301ccb98c950c325756f8"
|
"revision": "a596b01fbf1afdf90188ec02aa61fe7cc9703945",
|
||||||
|
"revisionTime": "2016-07-21T21:43:59Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "github.com/pborman/uuid",
|
"path": "github.com/pborman/uuid",
|
||||||
|
|
Loading…
Reference in New Issue