open-nomad/vendor/github.com/packethost/packngo/devices.go

258 lines
9.2 KiB
Go

package packngo
import (
"fmt"
"strings"
)
const deviceBasePath = "/devices"
// DeviceService interface defines available device methods
type DeviceService interface {
List(ProjectID string, listOpt *ListOptions) ([]Device, *Response, error)
Get(string) (*Device, *Response, error)
GetExtra(deviceID string, includes, excludes []string) (*Device, *Response, error)
Create(*DeviceCreateRequest) (*Device, *Response, error)
Update(string, *DeviceUpdateRequest) (*Device, *Response, error)
Delete(string) (*Response, error)
Reboot(string) (*Response, error)
PowerOff(string) (*Response, error)
PowerOn(string) (*Response, error)
Lock(string) (*Response, error)
Unlock(string) (*Response, error)
}
type devicesRoot struct {
Devices []Device `json:"devices"`
Meta meta `json:"meta"`
}
// Device represents a Packet device
type Device struct {
ID string `json:"id"`
Href string `json:"href,omitempty"`
Hostname string `json:"hostname,omitempty"`
State string `json:"state,omitempty"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
Locked bool `json:"locked,omitempty"`
BillingCycle string `json:"billing_cycle,omitempty"`
Storage map[string]interface{} `json:"storage,omitempty"`
Tags []string `json:"tags,omitempty"`
Network []*IPAddressAssignment `json:"ip_addresses"`
Volumes []*Volume `json:"volumes"`
OS *OS `json:"operating_system,omitempty"`
Plan *Plan `json:"plan,omitempty"`
Facility *Facility `json:"facility,omitempty"`
Project *Project `json:"project,omitempty"`
ProvisionEvents []*ProvisionEvent `json:"provisioning_events,omitempty"`
ProvisionPer float32 `json:"provisioning_percentage,omitempty"`
UserData string `json:"userdata,omitempty"`
RootPassword string `json:"root_password,omitempty"`
IPXEScriptURL string `json:"ipxe_script_url,omitempty"`
AlwaysPXE bool `json:"always_pxe,omitempty"`
HardwareReservation Href `json:"hardware_reservation,omitempty"`
SpotInstance bool `json:"spot_instance,omitempty"`
SpotPriceMax float64 `json:"spot_price_max,omitempty"`
TerminationTime *Timestamp `json:"termination_time,omitempty"`
NetworkPorts []Port `json:"network_ports,omitempty"`
CustomData map[string]interface{} `json:"customdata,omitempty"`
}
type ProvisionEvent struct {
ID string `json:"id"`
Body string `json:"body"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Href string `json:"href"`
Interpolated string `json:"interpolated"`
Relationships []Href `json:"relationships"`
State string `json:"state"`
Type string `json:"type"`
}
func (d Device) String() string {
return Stringify(d)
}
// DeviceCreateRequest type used to create a Packet device
type DeviceCreateRequest struct {
Hostname string `json:"hostname"`
Plan string `json:"plan"`
Facility string `json:"facility"`
OS string `json:"operating_system"`
BillingCycle string `json:"billing_cycle"`
ProjectID string `json:"project_id"`
UserData string `json:"userdata"`
Storage string `json:"storage,omitempty"`
Tags []string `json:"tags"`
IPXEScriptURL string `json:"ipxe_script_url,omitempty"`
PublicIPv4SubnetSize int `json:"public_ipv4_subnet_size,omitempty"`
AlwaysPXE bool `json:"always_pxe,omitempty"`
HardwareReservationID string `json:"hardware_reservation_id,omitempty"`
SpotInstance bool `json:"spot_instance,omitempty"`
SpotPriceMax float64 `json:"spot_price_max,omitempty,string"`
TerminationTime *Timestamp `json:"termination_time,omitempty"`
CustomData string `json:"customdata,omitempty"`
}
// DeviceUpdateRequest type used to update a Packet device
type DeviceUpdateRequest struct {
Hostname *string `json:"hostname,omitempty"`
Description *string `json:"description,omitempty"`
UserData *string `json:"userdata,omitempty"`
Locked *bool `json:"locked,omitempty"`
Tags *[]string `json:"tags,omitempty"`
AlwaysPXE *bool `json:"always_pxe,omitempty"`
IPXEScriptURL *string `json:"ipxe_script_url,omitempty"`
CustomData *string `json:"customdata,omitempty"`
}
func (d DeviceCreateRequest) String() string {
return Stringify(d)
}
// DeviceActionRequest type used to execute actions on devices
type DeviceActionRequest struct {
Type string `json:"type"`
}
func (d DeviceActionRequest) String() string {
return Stringify(d)
}
// DeviceServiceOp implements DeviceService
type DeviceServiceOp struct {
client *Client
}
// List returns devices on a project
func (s *DeviceServiceOp) List(projectID string, listOpt *ListOptions) (devices []Device, resp *Response, err error) {
params := "include=facility"
if listOpt != nil {
params = listOpt.createURL()
}
path := fmt.Sprintf("%s/%s%s?%s", projectBasePath, projectID, deviceBasePath, params)
for {
subset := new(devicesRoot)
resp, err = s.client.DoRequest("GET", path, nil, subset)
if err != nil {
return nil, resp, err
}
devices = append(devices, subset.Devices...)
if subset.Meta.Next != nil && (listOpt == nil || listOpt.Page == 0) {
path = subset.Meta.Next.Href
if params != "" {
path = fmt.Sprintf("%s&%s", path, params)
}
continue
}
return
}
}
// Get returns a device by id
func (s *DeviceServiceOp) Get(deviceID string) (*Device, *Response, error) {
return s.GetExtra(deviceID, []string{"facility"}, nil)
}
// GetExtra returns a device by id. Specifying either includes/excludes provides more or less desired
// detailed information about resources which would otherwise be represented with an href link
func (s *DeviceServiceOp) GetExtra(deviceID string, includes, excludes []string) (*Device, *Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
if includes != nil {
path += fmt.Sprintf("?include=%s", strings.Join(includes, ","))
} else if excludes != nil {
path += fmt.Sprintf("?exclude=%s", strings.Join(excludes, ","))
}
device := new(Device)
resp, err := s.client.DoRequest("GET", path, nil, device)
if err != nil {
return nil, resp, err
}
return device, resp, err
}
// Create creates a new device
func (s *DeviceServiceOp) Create(createRequest *DeviceCreateRequest) (*Device, *Response, error) {
path := fmt.Sprintf("%s/%s%s", projectBasePath, createRequest.ProjectID, deviceBasePath)
device := new(Device)
resp, err := s.client.DoRequest("POST", path, createRequest, device)
if err != nil {
return nil, resp, err
}
return device, resp, err
}
// Update updates an existing device
func (s *DeviceServiceOp) Update(deviceID string, updateRequest *DeviceUpdateRequest) (*Device, *Response, error) {
path := fmt.Sprintf("%s/%s?include=facility", deviceBasePath, deviceID)
device := new(Device)
resp, err := s.client.DoRequest("PUT", path, updateRequest, device)
if err != nil {
return nil, resp, err
}
return device, resp, err
}
// Delete deletes a device
func (s *DeviceServiceOp) Delete(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
return s.client.DoRequest("DELETE", path, nil, nil)
}
// Reboot reboots on a device
func (s *DeviceServiceOp) Reboot(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s/actions", deviceBasePath, deviceID)
action := &DeviceActionRequest{Type: "reboot"}
return s.client.DoRequest("POST", path, action, nil)
}
// PowerOff powers on a device
func (s *DeviceServiceOp) PowerOff(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s/actions", deviceBasePath, deviceID)
action := &DeviceActionRequest{Type: "power_off"}
return s.client.DoRequest("POST", path, action, nil)
}
// PowerOn powers on a device
func (s *DeviceServiceOp) PowerOn(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s/actions", deviceBasePath, deviceID)
action := &DeviceActionRequest{Type: "power_on"}
return s.client.DoRequest("POST", path, action, nil)
}
type lockType struct {
Locked bool `json:"locked"`
}
// Lock sets a device to "locked"
func (s *DeviceServiceOp) Lock(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
action := lockType{Locked: true}
return s.client.DoRequest("PATCH", path, action, nil)
}
// Unlock sets a device to "unlocked"
func (s *DeviceServiceOp) Unlock(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
action := lockType{Locked: false}
return s.client.DoRequest("PATCH", path, action, nil)
}