435c0d9fc8
This PR switches the Nomad repository from using govendor to Go modules for managing dependencies. Aspects of the Nomad workflow remain pretty much the same. The usual Makefile targets should continue to work as they always did. The API submodule simply defers to the parent Nomad version on the repository, keeping the semantics of API versioning that currently exists.
240 lines
7.3 KiB
Go
240 lines
7.3 KiB
Go
package packngo
|
|
|
|
import "fmt"
|
|
|
|
const (
|
|
volumeBasePath = "/storage"
|
|
attachmentsBasePath = "/attachments"
|
|
)
|
|
|
|
// VolumeService interface defines available Volume methods
|
|
type VolumeService interface {
|
|
List(string, *ListOptions) ([]Volume, *Response, error)
|
|
Get(string) (*Volume, *Response, error)
|
|
Update(string, *VolumeUpdateRequest) (*Volume, *Response, error)
|
|
Delete(string) (*Response, error)
|
|
Create(*VolumeCreateRequest, string) (*Volume, *Response, error)
|
|
Lock(string) (*Response, error)
|
|
Unlock(string) (*Response, error)
|
|
}
|
|
|
|
// VolumeAttachmentService defines attachment methdods
|
|
type VolumeAttachmentService interface {
|
|
Get(string) (*VolumeAttachment, *Response, error)
|
|
Create(string, string) (*VolumeAttachment, *Response, error)
|
|
Delete(string) (*Response, error)
|
|
}
|
|
|
|
type volumesRoot struct {
|
|
Volumes []Volume `json:"volumes"`
|
|
Meta meta `json:"meta"`
|
|
}
|
|
|
|
// Volume represents a volume
|
|
type Volume struct {
|
|
Attachments []*VolumeAttachment `json:"attachments,omitempty"`
|
|
BillingCycle string `json:"billing_cycle,omitempty"`
|
|
Created string `json:"created_at,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
Facility *Facility `json:"facility,omitempty"`
|
|
Href string `json:"href,omitempty"`
|
|
ID string `json:"id"`
|
|
Locked bool `json:"locked,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Plan *Plan `json:"plan,omitempty"`
|
|
Project *Project `json:"project,omitempty"`
|
|
Size int `json:"size,omitempty"`
|
|
SnapshotPolicies []*SnapshotPolicy `json:"snapshot_policies,omitempty"`
|
|
State string `json:"state,omitempty"`
|
|
Updated string `json:"updated_at,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"`
|
|
SnapshotCount int `json:"snapshot_count,omitempty"`
|
|
}
|
|
|
|
func (v Volume) String() string {
|
|
return Stringify(v)
|
|
}
|
|
|
|
// VolumeCreateRequest type used to create a Packet volume
|
|
type VolumeCreateRequest struct {
|
|
BillingCycle string `json:"billing_cycle"`
|
|
Description string `json:"description,omitempty"`
|
|
Locked bool `json:"locked,omitempty"`
|
|
Size int `json:"size"`
|
|
PlanID string `json:"plan_id"`
|
|
FacilityID string `json:"facility_id"`
|
|
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 {
|
|
Description *string `json:"description,omitempty"`
|
|
PlanID *string `json:"plan_id,omitempty"`
|
|
Size *int `json:"size,omitempty"`
|
|
BillingCycle *string `json:"billing_cycle,omitempty"`
|
|
}
|
|
|
|
// VolumeAttachment is a type from Packet API
|
|
type VolumeAttachment struct {
|
|
Href string `json:"href"`
|
|
ID string `json:"id"`
|
|
Volume Volume `json:"volume"`
|
|
Device Device `json:"device"`
|
|
}
|
|
|
|
func (v VolumeUpdateRequest) String() string {
|
|
return Stringify(v)
|
|
}
|
|
|
|
// VolumeAttachmentServiceOp implements VolumeService
|
|
type VolumeAttachmentServiceOp struct {
|
|
client *Client
|
|
}
|
|
|
|
// VolumeServiceOp implements VolumeService
|
|
type VolumeServiceOp struct {
|
|
client *Client
|
|
}
|
|
|
|
// List returns the volumes for a project
|
|
func (v *VolumeServiceOp) List(projectID string, listOpt *ListOptions) (volumes []Volume, resp *Response, err error) {
|
|
url := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, volumeBasePath)
|
|
var params string
|
|
if listOpt != nil {
|
|
params = listOpt.createURL()
|
|
if params != "" {
|
|
url = fmt.Sprintf("%s?%s", url, params)
|
|
}
|
|
}
|
|
|
|
for {
|
|
subset := new(volumesRoot)
|
|
|
|
resp, err = v.client.DoRequest("GET", url, nil, subset)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
volumes = append(volumes, subset.Volumes...)
|
|
|
|
if subset.Meta.Next != nil && (listOpt == nil || listOpt.Page == 0) {
|
|
url = subset.Meta.Next.Href
|
|
if params != "" {
|
|
url = fmt.Sprintf("%s&%s", url, params)
|
|
}
|
|
continue
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
// Get returns a volume by id
|
|
func (v *VolumeServiceOp) Get(volumeID string) (*Volume, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s?include=facility,snapshot_policies,attachments.device", volumeBasePath, volumeID)
|
|
volume := new(Volume)
|
|
|
|
resp, err := v.client.DoRequest("GET", path, nil, volume)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
return volume, resp, err
|
|
}
|
|
|
|
// Update updates a volume
|
|
func (v *VolumeServiceOp) Update(id string, updateRequest *VolumeUpdateRequest) (*Volume, *Response, error) {
|
|
path := fmt.Sprintf("%s/%s", volumeBasePath, id)
|
|
volume := new(Volume)
|
|
|
|
resp, err := v.client.DoRequest("PATCH", path, updateRequest, 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)
|
|
|
|
return v.client.DoRequest("DELETE", path, nil, nil)
|
|
}
|
|
|
|
// Create creates a new volume for a project
|
|
func (v *VolumeServiceOp) Create(createRequest *VolumeCreateRequest, projectID string) (*Volume, *Response, error) {
|
|
url := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, volumeBasePath)
|
|
volume := new(Volume)
|
|
|
|
resp, err := v.client.DoRequest("POST", url, createRequest, volume)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
return volume, resp, err
|
|
}
|
|
|
|
// Attachments
|
|
|
|
// Create Attachment, i.e. attach volume to a device
|
|
func (v *VolumeAttachmentServiceOp) Create(volumeID, deviceID string) (*VolumeAttachment, *Response, error) {
|
|
url := fmt.Sprintf("%s/%s%s", volumeBasePath, volumeID, attachmentsBasePath)
|
|
volAttachParam := map[string]string{
|
|
"device_id": deviceID,
|
|
}
|
|
volumeAttachment := new(VolumeAttachment)
|
|
|
|
resp, err := v.client.DoRequest("POST", url, volAttachParam, volumeAttachment)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
return volumeAttachment, resp, nil
|
|
}
|
|
|
|
// Get gets attachment by id
|
|
func (v *VolumeAttachmentServiceOp) Get(attachmentID string) (*VolumeAttachment, *Response, error) {
|
|
path := fmt.Sprintf("%s%s/%s", volumeBasePath, attachmentsBasePath, attachmentID)
|
|
volumeAttachment := new(VolumeAttachment)
|
|
|
|
resp, err := v.client.DoRequest("GET", path, nil, volumeAttachment)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
return volumeAttachment, resp, nil
|
|
}
|
|
|
|
// Delete deletes attachment by id
|
|
func (v *VolumeAttachmentServiceOp) Delete(attachmentID string) (*Response, error) {
|
|
path := fmt.Sprintf("%s%s/%s", volumeBasePath, attachmentsBasePath, attachmentID)
|
|
|
|
return v.client.DoRequest("DELETE", path, nil, nil)
|
|
}
|
|
|
|
// Lock sets a volume to "locked"
|
|
func (s *VolumeServiceOp) Lock(id string) (*Response, error) {
|
|
path := fmt.Sprintf("%s/%s", volumeBasePath, id)
|
|
action := lockType{Locked: true}
|
|
|
|
return s.client.DoRequest("PATCH", path, action, nil)
|
|
}
|
|
|
|
// Unlock sets a volume to "unlocked"
|
|
func (s *VolumeServiceOp) Unlock(id string) (*Response, error) {
|
|
path := fmt.Sprintf("%s/%s", volumeBasePath, id)
|
|
action := lockType{Locked: false}
|
|
|
|
return s.client.DoRequest("PATCH", path, action, nil)
|
|
}
|