1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

Switch to official Vultr API library (#529)

* vultr: Switched to official API library (closes #528)

* vultr: Renamed vultr.VultrApi to vultr.Provider

* vendor: Updated govultr
This commit is contained in:
Patrick Gaskin
2019-07-15 10:31:55 -04:00
committed by Craig Peterson
parent a138b12ec2
commit 44a7ba5711
46 changed files with 5719 additions and 2502 deletions

View File

@ -1,71 +0,0 @@
package lib
import (
"encoding/json"
"fmt"
"strconv"
)
// AccountInfo of Vultr account
type AccountInfo struct {
Balance float64 `json:"balance"`
PendingCharges float64 `json:"pending_charges"`
LastPaymentDate string `json:"last_payment_date"`
LastPaymentAmount float64 `json:"last_payment_amount"`
}
// GetAccountInfo retrieves the Vultr account information about current balance, pending charges, etc..
func (c *Client) GetAccountInfo() (info AccountInfo, err error) {
if err := c.get(`account/info`, &info); err != nil {
return AccountInfo{}, err
}
return
}
// UnmarshalJSON implements json.Unmarshaller on AccountInfo.
// This is needed because the Vultr API is inconsistent in it's JSON responses for account info.
// Some fields can change type, from JSON number to JSON string and vice-versa.
func (a *AccountInfo) UnmarshalJSON(data []byte) (err error) {
if a == nil {
*a = AccountInfo{}
}
var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
value := fmt.Sprintf("%v", fields["balance"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
b, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
a.Balance = b
value = fmt.Sprintf("%v", fields["pending_charges"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
pc, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
a.PendingCharges = pc
value = fmt.Sprintf("%v", fields["last_payment_amount"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
lpa, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
a.LastPaymentAmount = lpa
a.LastPaymentDate = fmt.Sprintf("%v", fields["last_payment_date"])
return
}

View File

@ -1,38 +0,0 @@
package lib
import (
"sort"
"strings"
)
// Application on Vultr
type Application struct {
ID string `json:"APPID"`
Name string `json:"name"`
ShortName string `json:"short_name"`
DeployName string `json:"deploy_name"`
Surcharge float64 `json:"surcharge"`
}
type applications []Application
func (s applications) Len() int { return len(s) }
func (s applications) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s applications) Less(i, j int) bool {
return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name)
}
// GetApplications returns a list of all available applications on Vultr
func (c *Client) GetApplications() ([]Application, error) {
var appMap map[string]Application
if err := c.get(`app/list`, &appMap); err != nil {
return nil, err
}
var appList []Application
for _, app := range appMap {
appList = append(appList, app)
}
sort.Sort(applications(appList))
return appList, nil
}

View File

@ -1,210 +0,0 @@
package lib
import (
"encoding/json"
"fmt"
"net/url"
"sort"
"strconv"
"strings"
)
// BlockStorage on Vultr account
type BlockStorage struct {
ID string `json:"SUBID,string"`
Name string `json:"label"`
RegionID int `json:"DCID,string"`
SizeGB int `json:"size_gb,string"`
Created string `json:"date_created"`
Cost string `json:"cost_per_month"`
Status string `json:"status"`
AttachedTo string `json:"attached_to_SUBID"`
}
type blockstorages []BlockStorage
func (b blockstorages) Len() int { return len(b) }
func (b blockstorages) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b blockstorages) Less(i, j int) bool {
// sort order: name, size, status
if strings.ToLower(b[i].Name) < strings.ToLower(b[j].Name) {
return true
} else if strings.ToLower(b[i].Name) > strings.ToLower(b[j].Name) {
return false
}
if b[i].SizeGB < b[j].SizeGB {
return true
} else if b[i].SizeGB > b[j].SizeGB {
return false
}
return b[i].Status < b[j].Status
}
// UnmarshalJSON implements json.Unmarshaller on BlockStorage.
// This is needed because the Vultr API is inconsistent in it's JSON responses.
// Some fields can change type, from JSON number to JSON string and vice-versa.
func (b *BlockStorage) UnmarshalJSON(data []byte) (err error) {
if b == nil {
*b = BlockStorage{}
}
var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
value := fmt.Sprintf("%v", fields["SUBID"])
if len(value) == 0 || value == "<nil>" || value == "0" {
b.ID = ""
} else {
id, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
b.ID = strconv.FormatFloat(id, 'f', -1, 64)
}
value = fmt.Sprintf("%v", fields["DCID"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
region, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
b.RegionID = int(region)
value = fmt.Sprintf("%v", fields["size_gb"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
size, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
b.SizeGB = int(size)
value = fmt.Sprintf("%v", fields["attached_to_SUBID"])
if len(value) == 0 || value == "<nil>" || value == "0" {
b.AttachedTo = ""
} else {
attached, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
b.AttachedTo = strconv.FormatFloat(attached, 'f', -1, 64)
}
b.Name = fmt.Sprintf("%v", fields["label"])
b.Created = fmt.Sprintf("%v", fields["date_created"])
b.Status = fmt.Sprintf("%v", fields["status"])
b.Cost = fmt.Sprintf("%v", fields["cost_per_month"])
return
}
// GetBlockStorages returns a list of all active block storages on Vultr account
func (c *Client) GetBlockStorages() (storages []BlockStorage, err error) {
if err := c.get(`block/list`, &storages); err != nil {
return nil, err
}
sort.Sort(blockstorages(storages))
return storages, nil
}
// GetBlockStorage returns block storage with given ID
func (c *Client) GetBlockStorage(id string) (BlockStorage, error) {
storages, err := c.GetBlockStorages()
if err != nil {
return BlockStorage{}, err
}
for _, s := range storages {
if s.ID == id {
return s, nil
}
}
return BlockStorage{}, fmt.Errorf("BlockStorage with ID %v not found", id)
}
// CreateBlockStorage creates a new block storage on Vultr account
func (c *Client) CreateBlockStorage(name string, regionID, size int) (BlockStorage, error) {
values := url.Values{
"label": {name},
"DCID": {fmt.Sprintf("%v", regionID)},
"size_gb": {fmt.Sprintf("%v", size)},
}
var storage BlockStorage
if err := c.post(`block/create`, values, &storage); err != nil {
return BlockStorage{}, err
}
storage.RegionID = regionID
storage.Name = name
storage.SizeGB = size
return storage, nil
}
// ResizeBlockStorage resizes an existing block storage
func (c *Client) ResizeBlockStorage(id string, size int) error {
values := url.Values{
"SUBID": {id},
"size_gb": {fmt.Sprintf("%v", size)},
}
if err := c.post(`block/resize`, values, nil); err != nil {
return err
}
return nil
}
// LabelBlockStorage changes the label on an existing block storage
func (c *Client) LabelBlockStorage(id, name string) error {
values := url.Values{
"SUBID": {id},
"label": {name},
}
if err := c.post(`block/label_set`, values, nil); err != nil {
return err
}
return nil
}
// AttachBlockStorage attaches block storage to an existing virtual machine
func (c *Client) AttachBlockStorage(id, serverID string) error {
values := url.Values{
"SUBID": {id},
"attach_to_SUBID": {serverID},
}
if err := c.post(`block/attach`, values, nil); err != nil {
return err
}
return nil
}
// DetachBlockStorage detaches block storage from virtual machine
func (c *Client) DetachBlockStorage(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`block/detach`, values, nil); err != nil {
return err
}
return nil
}
// DeleteBlockStorage deletes an existing block storage
func (c *Client) DeleteBlockStorage(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`block/delete`, values, nil); err != nil {
return err
}
return nil
}

View File

@ -1,249 +0,0 @@
package lib
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"strings"
"time"
"github.com/juju/ratelimit"
)
const (
// Version of this libary
Version = "1.13.0"
// APIVersion of Vultr
APIVersion = "v1"
// DefaultEndpoint to be used
DefaultEndpoint = "https://api.vultr.com/"
mediaType = "application/json"
)
// retryableStatusCodes are API response status codes that indicate that
// the failed request can be retried without further actions.
var retryableStatusCodes = map[int]struct{}{
503: {}, // Rate limit hit
500: {}, // Internal server error. Try again at a later time.
}
// Client represents the Vultr API client
type Client struct {
// HTTP client for communication with the Vultr API
client *http.Client
// User agent for HTTP client
UserAgent string
// Endpoint URL for API requests
Endpoint *url.URL
// API key for accessing the Vultr API
APIKey string
// Max. number of request attempts
MaxAttempts int
// Throttling struct
bucket *ratelimit.Bucket
}
// Options represents optional settings and flags that can be passed to NewClient
type Options struct {
// HTTP client for communication with the Vultr API
HTTPClient *http.Client
// User agent for HTTP client
UserAgent string
// Endpoint URL for API requests
Endpoint string
// API rate limitation, calls per duration
RateLimitation time.Duration
// Max. number of times to retry API calls
MaxRetries int
}
// NewClient creates new Vultr API client. Options are optional and can be nil.
func NewClient(apiKey string, options *Options) *Client {
userAgent := "vultr-go/" + Version
transport := &http.Transport{
TLSNextProto: make(map[string]func(string, *tls.Conn) http.RoundTripper),
}
client := http.DefaultClient
client.Transport = transport
endpoint, _ := url.Parse(DefaultEndpoint)
rate := 505 * time.Millisecond
attempts := 1
if options != nil {
if options.HTTPClient != nil {
client = options.HTTPClient
}
if options.UserAgent != "" {
userAgent = options.UserAgent
}
if options.Endpoint != "" {
endpoint, _ = url.Parse(options.Endpoint)
}
if options.RateLimitation != 0 {
rate = options.RateLimitation
}
if options.MaxRetries != 0 {
attempts = options.MaxRetries + 1
}
}
return &Client{
UserAgent: userAgent,
client: client,
Endpoint: endpoint,
APIKey: apiKey,
MaxAttempts: attempts,
bucket: ratelimit.NewBucket(rate, 1),
}
}
func apiPath(path string) string {
return fmt.Sprintf("/%s/%s", APIVersion, path)
}
func apiKeyPath(path, apiKey string) string {
if strings.Contains(path, "?") {
return path + "&api_key=" + apiKey
}
return path + "?api_key=" + apiKey
}
func (c *Client) get(path string, data interface{}) error {
req, err := c.newRequest("GET", apiPath(path), nil)
if err != nil {
return err
}
return c.do(req, data)
}
func (c *Client) post(path string, values url.Values, data interface{}) error {
req, err := c.newRequest("POST", apiPath(path), strings.NewReader(values.Encode()))
if err != nil {
return err
}
return c.do(req, data)
}
func (c *Client) newRequest(method string, path string, body io.Reader) (*http.Request, error) {
relPath, err := url.Parse(apiKeyPath(path, c.APIKey))
if err != nil {
return nil, err
}
url := c.Endpoint.ResolveReference(relPath)
req, err := http.NewRequest(method, url.String(), body)
if err != nil {
return nil, err
}
req.Header.Add("User-Agent", c.UserAgent)
req.Header.Add("Accept", mediaType)
if req.Method == "POST" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
return req, nil
}
func (c *Client) do(req *http.Request, data interface{}) error {
// Throttle http requests to avoid hitting Vultr's API rate-limit
c.bucket.Wait(1)
// Request body gets drained on each read so we
// need to save it's content for retrying requests
var err error
var requestBody []byte
if req.Body != nil {
requestBody, err = ioutil.ReadAll(req.Body)
if err != nil {
return fmt.Errorf("Error reading request body: %v", err)
}
req.Body.Close()
}
var apiError error
for tryCount := 1; tryCount <= c.MaxAttempts; tryCount++ {
// Restore request body to the original state
if requestBody != nil {
req.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
}
resp, err := c.client.Do(req)
if err != nil {
return err
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return err
}
if resp.StatusCode == http.StatusOK {
if data != nil {
// avoid unmarshalling problem because Vultr API returns
// empty array instead of empty map when it shouldn't!
if string(body) == `[]` {
data = nil
} else {
if err := json.Unmarshal(body, data); err != nil {
return err
}
}
}
return nil
}
apiError = errors.New(string(body))
if !isCodeRetryable(resp.StatusCode) {
break
}
delay := backoffDuration(tryCount)
time.Sleep(delay)
}
return apiError
}
// backoffDuration returns the duration to wait before retrying the request.
// Duration is an exponential function of the retry count with a jitter of ~0-30%.
func backoffDuration(retryCount int) time.Duration {
// Upper limit of delay at ~1 minute
if retryCount > 7 {
retryCount = 7
}
rand.Seed(time.Now().UnixNano())
delay := (1 << uint(retryCount)) * (rand.Intn(150) + 500)
return time.Duration(delay) * time.Millisecond
}
// isCodeRetryable returns true if the given status code means that we should retry.
func isCodeRetryable(statusCode int) bool {
if _, ok := retryableStatusCodes[statusCode]; ok {
return true
}
return false
}

View File

@ -1,150 +0,0 @@
package lib
import (
"fmt"
"net/url"
"sort"
"strings"
)
// DNSDomain represents a DNS domain on Vultr
type DNSDomain struct {
Domain string `json:"domain"`
Created string `json:"date_created"`
}
type dnsdomains []DNSDomain
func (d dnsdomains) Len() int { return len(d) }
func (d dnsdomains) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d dnsdomains) Less(i, j int) bool {
return strings.ToLower(d[i].Domain) < strings.ToLower(d[j].Domain)
}
// DNSRecord represents a DNS record on Vultr
type DNSRecord struct {
RecordID int `json:"RECORDID"`
Type string `json:"type"`
Name string `json:"name"`
Data string `json:"data"`
Priority int `json:"priority"`
TTL int `json:"ttl"`
}
type dnsrecords []DNSRecord
func (d dnsrecords) Len() int { return len(d) }
func (d dnsrecords) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d dnsrecords) Less(i, j int) bool {
// sort order: type, data, name
if d[i].Type < d[j].Type {
return true
} else if d[i].Type > d[j].Type {
return false
}
if d[i].Data < d[j].Data {
return true
} else if d[i].Data > d[j].Data {
return false
}
return strings.ToLower(d[i].Name) < strings.ToLower(d[j].Name)
}
// GetDNSDomains returns a list of available domains on Vultr account
func (c *Client) GetDNSDomains() (domains []DNSDomain, err error) {
if err := c.get(`dns/list`, &domains); err != nil {
return nil, err
}
sort.Sort(dnsdomains(domains))
return domains, nil
}
// GetDNSRecords returns a list of all DNS records of a particular domain
func (c *Client) GetDNSRecords(domain string) (records []DNSRecord, err error) {
if err := c.get(`dns/records?domain=`+domain, &records); err != nil {
return nil, err
}
sort.Sort(dnsrecords(records))
return records, nil
}
// CreateDNSDomain creates a new DNS domain name on Vultr
func (c *Client) CreateDNSDomain(domain, serverIP string) error {
values := url.Values{
"domain": {domain},
"serverip": {serverIP},
}
if err := c.post(`dns/create_domain`, values, nil); err != nil {
return err
}
return nil
}
// DeleteDNSDomain deletes an existing DNS domain name
func (c *Client) DeleteDNSDomain(domain string) error {
values := url.Values{
"domain": {domain},
}
if err := c.post(`dns/delete_domain`, values, nil); err != nil {
return err
}
return nil
}
// CreateDNSRecord creates a new DNS record
func (c *Client) CreateDNSRecord(domain, name, rtype, data string, priority, ttl int) error {
values := url.Values{
"domain": {domain},
"name": {name},
"type": {rtype},
"data": {data},
"priority": {fmt.Sprintf("%v", priority)},
"ttl": {fmt.Sprintf("%v", ttl)},
}
if err := c.post(`dns/create_record`, values, nil); err != nil {
return err
}
return nil
}
// UpdateDNSRecord updates an existing DNS record
func (c *Client) UpdateDNSRecord(domain string, dnsrecord DNSRecord) error {
values := url.Values{
"domain": {domain},
"RECORDID": {fmt.Sprintf("%v", dnsrecord.RecordID)},
}
if dnsrecord.Name != "" {
values.Add("name", dnsrecord.Name)
}
if dnsrecord.Data != "" {
values.Add("data", dnsrecord.Data)
}
if dnsrecord.Priority != 0 {
values.Add("priority", fmt.Sprintf("%v", dnsrecord.Priority))
}
if dnsrecord.TTL != 0 {
values.Add("ttl", fmt.Sprintf("%v", dnsrecord.TTL))
}
if err := c.post(`dns/update_record`, values, nil); err != nil {
return err
}
return nil
}
// DeleteDNSRecord deletes an existing DNS record
func (c *Client) DeleteDNSRecord(domain string, recordID int) error {
values := url.Values{
"domain": {domain},
"RECORDID": {fmt.Sprintf("%v", recordID)},
}
if err := c.post(`dns/delete_record`, values, nil); err != nil {
return err
}
return nil
}

View File

@ -1,248 +0,0 @@
package lib
import (
"encoding/json"
"fmt"
"net"
"net/url"
"sort"
"strconv"
"strings"
)
// FirewallGroup represents a firewall group on Vultr
type FirewallGroup struct {
ID string `json:"FIREWALLGROUPID"`
Description string `json:"description"`
Created string `json:"date_created"`
Modified string `json:"date_modified"`
InstanceCount int `json:"instance_count"`
RuleCount int `json:"rule_count"`
MaxRuleCount int `json:"max_rule_count"`
}
// FirewallRule represents a firewall rule on Vultr
type FirewallRule struct {
RuleNumber int `json:"rulenumber"`
Action string `json:"action"`
Protocol string `json:"protocol"`
Port string `json:"port"`
Network *net.IPNet
}
type firewallGroups []FirewallGroup
func (f firewallGroups) Len() int { return len(f) }
func (f firewallGroups) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
func (f firewallGroups) Less(i, j int) bool {
// sort order: description
return strings.ToLower(f[i].Description) < strings.ToLower(f[j].Description)
}
type firewallRules []FirewallRule
func (r firewallRules) Len() int { return len(r) }
func (r firewallRules) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r firewallRules) Less(i, j int) bool {
// sort order: rule number
return r[i].RuleNumber < r[j].RuleNumber
}
// UnmarshalJSON implements json.Unmarshaller on FirewallRule.
// This is needed because the Vultr API is inconsistent in it's JSON responses.
// Some fields can change type, from JSON number to JSON string and vice-versa.
func (r *FirewallRule) UnmarshalJSON(data []byte) (err error) {
if r == nil {
*r = FirewallRule{}
}
var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
value := fmt.Sprintf("%v", fields["rulenumber"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
number, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
r.RuleNumber = int(number)
value = fmt.Sprintf("%v", fields["subnet_size"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
subnetSize, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
r.Action = fmt.Sprintf("%v", fields["action"])
r.Protocol = fmt.Sprintf("%v", fields["protocol"])
r.Port = fmt.Sprintf("%v", fields["port"])
subnet := fmt.Sprintf("%v", fields["subnet"])
if subnetSize > 0 && len(subnet) > 0 {
_, r.Network, err = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet, subnetSize))
if err != nil {
return fmt.Errorf("Failed to parse subnet from Vultr API")
}
} else {
_, r.Network, _ = net.ParseCIDR("0.0.0.0/0")
}
return
}
// GetFirewallGroups returns a list of all available firewall groups on Vultr
func (c *Client) GetFirewallGroups() ([]FirewallGroup, error) {
var groupMap map[string]FirewallGroup
if err := c.get(`firewall/group_list`, &groupMap); err != nil {
return nil, err
}
var groupList []FirewallGroup
for _, g := range groupMap {
groupList = append(groupList, g)
}
sort.Sort(firewallGroups(groupList))
return groupList, nil
}
// GetFirewallGroup returns the firewall group with given ID
func (c *Client) GetFirewallGroup(id string) (FirewallGroup, error) {
groups, err := c.GetFirewallGroups()
if err != nil {
return FirewallGroup{}, err
}
for _, g := range groups {
if g.ID == id {
return g, nil
}
}
return FirewallGroup{}, fmt.Errorf("Firewall group with ID %v not found", id)
}
// CreateFirewallGroup creates a new firewall group in Vultr account
func (c *Client) CreateFirewallGroup(description string) (string, error) {
values := url.Values{}
// Optional description
if len(description) > 0 {
values.Add("description", description)
}
var result FirewallGroup
err := c.post(`firewall/group_create`, values, &result)
if err != nil {
return "", err
}
return result.ID, nil
}
// DeleteFirewallGroup deletes an existing firewall group
func (c *Client) DeleteFirewallGroup(groupID string) error {
values := url.Values{
"FIREWALLGROUPID": {groupID},
}
if err := c.post(`firewall/group_delete`, values, nil); err != nil {
return err
}
return nil
}
// SetFirewallGroupDescription sets the description of an existing firewall group
func (c *Client) SetFirewallGroupDescription(groupID, description string) error {
values := url.Values{
"FIREWALLGROUPID": {groupID},
"description": {description},
}
if err := c.post(`firewall/group_set_description`, values, nil); err != nil {
return err
}
return nil
}
// GetFirewallRules returns a list of rules for the given firewall group
func (c *Client) GetFirewallRules(groupID string) ([]FirewallRule, error) {
var ruleMap map[string]FirewallRule
ipTypes := []string{"v4", "v6"}
for _, ipType := range ipTypes {
args := fmt.Sprintf("direction=in&FIREWALLGROUPID=%s&ip_type=%s",
groupID, ipType)
if err := c.get(`firewall/rule_list?`+args, &ruleMap); err != nil {
return nil, err
}
}
var ruleList []FirewallRule
for _, r := range ruleMap {
ruleList = append(ruleList, r)
}
sort.Sort(firewallRules(ruleList))
return ruleList, nil
}
// CreateFirewallRule creates a new firewall rule in Vultr account.
// groupID is the ID of the firewall group to create the rule in
// protocol must be one of: "icmp", "tcp", "udp", "gre"
// port can be a port number or colon separated port range (TCP/UDP only)
func (c *Client) CreateFirewallRule(groupID, protocol, port string,
network *net.IPNet) (int, error) {
ip := network.IP.String()
maskBits, _ := network.Mask.Size()
if ip == "<nil>" {
return 0, fmt.Errorf("Invalid network")
}
var ipType string
if network.IP.To4() != nil {
ipType = "v4"
} else {
ipType = "v6"
}
values := url.Values{
"FIREWALLGROUPID": {groupID},
// possible values: "in"
"direction": {"in"},
// possible values: "icmp", "tcp", "udp", "gre"
"protocol": {protocol},
// possible values: "v4", "v6"
"ip_type": {ipType},
// IP address representing a subnet
"subnet": {ip},
// IP prefix size in bits
"subnet_size": {fmt.Sprintf("%v", maskBits)},
}
if len(port) > 0 {
values.Add("port", port)
}
var result FirewallRule
err := c.post(`firewall/rule_create`, values, &result)
if err != nil {
return 0, err
}
return result.RuleNumber, nil
}
// DeleteFirewallRule deletes an existing firewall rule
func (c *Client) DeleteFirewallRule(ruleNumber int, groupID string) error {
values := url.Values{
"FIREWALLGROUPID": {groupID},
"rulenumber": {fmt.Sprintf("%v", ruleNumber)},
}
if err := c.post(`firewall/rule_delete`, values, nil); err != nil {
return err
}
return nil
}

View File

@ -1,192 +0,0 @@
package lib
import (
"fmt"
"net/url"
"sort"
)
// IPv4 information of a virtual machine
type IPv4 struct {
IP string `json:"ip"`
Netmask string `json:"netmask"`
Gateway string `json:"gateway"`
Type string `json:"type"`
ReverseDNS string `json:"reverse"`
}
type ipv4s []IPv4
func (s ipv4s) Len() int { return len(s) }
func (s ipv4s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ipv4s) Less(i, j int) bool {
// sort order: type, ip
if s[i].Type < s[j].Type {
return true
} else if s[i].Type > s[j].Type {
return false
}
return s[i].IP < s[j].IP
}
// IPv6 information of a virtual machine
type IPv6 struct {
IP string `json:"ip"`
Network string `json:"network"`
NetworkSize string `json:"network_size"`
Type string `json:"type"`
}
type ipv6s []IPv6
func (s ipv6s) Len() int { return len(s) }
func (s ipv6s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ipv6s) Less(i, j int) bool {
// sort order: type, ip
if s[i].Type < s[j].Type {
return true
} else if s[i].Type > s[j].Type {
return false
}
return s[i].IP < s[j].IP
}
// ReverseDNSIPv6 information of a virtual machine
type ReverseDNSIPv6 struct {
IP string `json:"ip"`
ReverseDNS string `json:"reverse"`
}
type reverseDNSIPv6s []ReverseDNSIPv6
func (s reverseDNSIPv6s) Len() int { return len(s) }
func (s reverseDNSIPv6s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s reverseDNSIPv6s) Less(i, j int) bool { return s[i].IP < s[j].IP }
// ListIPv4 lists the IPv4 information of a virtual machine
func (c *Client) ListIPv4(id string) (list []IPv4, err error) {
var ipMap map[string][]IPv4
if err := c.get(`server/list_ipv4?SUBID=`+id, &ipMap); err != nil {
return nil, err
}
for _, iplist := range ipMap {
for _, ip := range iplist {
list = append(list, ip)
}
}
sort.Sort(ipv4s(list))
return list, nil
}
// CreateIPv4 creates an IPv4 address and attaches it to a virtual machine
func (c *Client) CreateIPv4(id string, reboot bool) error {
values := url.Values{
"SUBID": {id},
"reboot": {fmt.Sprintf("%t", reboot)},
}
if err := c.post(`server/create_ipv4`, values, nil); err != nil {
return err
}
return nil
}
// DeleteIPv4 deletes an IPv4 address and detaches it from a virtual machine
func (c *Client) DeleteIPv4(id, ip string) error {
values := url.Values{
"SUBID": {id},
"ip": {ip},
}
if err := c.post(`server/destroy_ipv4`, values, nil); err != nil {
return err
}
return nil
}
// ListIPv6 lists the IPv4 information of a virtual machine
func (c *Client) ListIPv6(id string) (list []IPv6, err error) {
var ipMap map[string][]IPv6
if err := c.get(`server/list_ipv6?SUBID=`+id, &ipMap); err != nil {
return nil, err
}
for _, iplist := range ipMap {
for _, ip := range iplist {
list = append(list, ip)
}
}
sort.Sort(ipv6s(list))
return list, nil
}
// ListIPv6ReverseDNS lists the IPv6 reverse DNS entries of a virtual machine
func (c *Client) ListIPv6ReverseDNS(id string) (list []ReverseDNSIPv6, err error) {
var ipMap map[string][]ReverseDNSIPv6
if err := c.get(`server/reverse_list_ipv6?SUBID=`+id, &ipMap); err != nil {
return nil, err
}
for _, iplist := range ipMap {
for _, ip := range iplist {
list = append(list, ip)
}
}
sort.Sort(reverseDNSIPv6s(list))
return list, nil
}
// DeleteIPv6ReverseDNS removes a reverse DNS entry for an IPv6 address of a virtual machine
func (c *Client) DeleteIPv6ReverseDNS(id string, ip string) error {
values := url.Values{
"SUBID": {id},
"ip": {ip},
}
if err := c.post(`server/reverse_delete_ipv6`, values, nil); err != nil {
return err
}
return nil
}
// SetIPv6ReverseDNS sets a reverse DNS entry for an IPv6 address of a virtual machine
func (c *Client) SetIPv6ReverseDNS(id, ip, entry string) error {
values := url.Values{
"SUBID": {id},
"ip": {ip},
"entry": {entry},
}
if err := c.post(`server/reverse_set_ipv6`, values, nil); err != nil {
return err
}
return nil
}
// DefaultIPv4ReverseDNS sets a reverse DNS entry for an IPv4 address of a virtual machine to the original setting
func (c *Client) DefaultIPv4ReverseDNS(id, ip string) error {
values := url.Values{
"SUBID": {id},
"ip": {ip},
}
if err := c.post(`server/reverse_default_ipv4`, values, nil); err != nil {
return err
}
return nil
}
// SetIPv4ReverseDNS sets a reverse DNS entry for an IPv4 address of a virtual machine
func (c *Client) SetIPv4ReverseDNS(id, ip, entry string) error {
values := url.Values{
"SUBID": {id},
"ip": {ip},
"entry": {entry},
}
if err := c.post(`server/reverse_set_ipv4`, values, nil); err != nil {
return err
}
return nil
}

View File

@ -1,44 +0,0 @@
package lib
import (
"sort"
"strings"
)
// ISO image on Vultr
type ISO struct {
ID int `json:"ISOID"`
Created string `json:"date_created"`
Filename string `json:"filename"`
Size int `json:"size"`
MD5sum string `json:"md5sum"`
}
type isos []ISO
func (s isos) Len() int { return len(s) }
func (s isos) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s isos) Less(i, j int) bool {
// sort order: filename, created
if strings.ToLower(s[i].Filename) < strings.ToLower(s[j].Filename) {
return true
} else if strings.ToLower(s[i].Filename) > strings.ToLower(s[j].Filename) {
return false
}
return s[i].Created < s[j].Created
}
// GetISO returns a list of all ISO images on Vultr account
func (c *Client) GetISO() ([]ISO, error) {
var isoMap map[string]ISO
if err := c.get(`iso/list`, &isoMap); err != nil {
return nil, err
}
var isoList []ISO
for _, iso := range isoMap {
isoList = append(isoList, iso)
}
sort.Sort(isos(isoList))
return isoList, nil
}

View File

@ -1,37 +0,0 @@
package lib
import (
"sort"
"strings"
)
// OS image on Vultr
type OS struct {
ID int `json:"OSID"`
Name string `json:"name"`
Arch string `json:"arch"`
Family string `json:"family"`
Windows bool `json:"windows"`
Surcharge string `json:"surcharge"`
}
type oses []OS
func (s oses) Len() int { return len(s) }
func (s oses) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s oses) Less(i, j int) bool { return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name) }
// GetOS returns a list of all available operating systems on Vultr
func (c *Client) GetOS() ([]OS, error) {
var osMap map[string]OS
if err := c.get(`os/list`, &osMap); err != nil {
return nil, err
}
var osList []OS
for _, os := range osMap {
osList = append(osList, os)
}
sort.Sort(oses(osList))
return osList, nil
}

View File

@ -1,78 +0,0 @@
package lib
import (
"fmt"
"sort"
"strconv"
"strings"
)
// Plan on Vultr
type Plan struct {
ID int `json:"VPSPLANID,string"`
Name string `json:"name"`
VCpus int `json:"vcpu_count,string"`
RAM string `json:"ram"`
Disk string `json:"disk"`
Bandwidth string `json:"bandwidth"`
Price string `json:"price_per_month"`
Regions []int `json:"available_locations"`
}
type plans []Plan
func (p plans) Len() int { return len(p) }
func (p plans) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p plans) Less(i, j int) bool {
pa, _ := strconv.ParseFloat(strings.TrimSpace(p[i].Price), 64)
pb, _ := strconv.ParseFloat(strings.TrimSpace(p[j].Price), 64)
ra, _ := strconv.ParseInt(strings.TrimSpace(p[i].RAM), 10, 64)
rb, _ := strconv.ParseInt(strings.TrimSpace(p[j].RAM), 10, 64)
da, _ := strconv.ParseInt(strings.TrimSpace(p[i].Disk), 10, 64)
db, _ := strconv.ParseInt(strings.TrimSpace(p[j].Disk), 10, 64)
// sort order: price, vcpu, ram, disk
if pa < pb {
return true
} else if pa > pb {
return false
}
if p[i].VCpus < p[j].VCpus {
return true
} else if p[i].VCpus > p[j].VCpus {
return false
}
if ra < rb {
return true
} else if ra > rb {
return false
}
return da < db
}
// GetPlans returns a list of all available plans on Vultr account
func (c *Client) GetPlans() ([]Plan, error) {
var planMap map[string]Plan
if err := c.get(`plans/list`, &planMap); err != nil {
return nil, err
}
var p plans
for _, plan := range planMap {
p = append(p, plan)
}
sort.Sort(plans(p))
return p, nil
}
// GetAvailablePlansForRegion returns available plans for specified region
func (c *Client) GetAvailablePlansForRegion(id int) (planIDs []int, err error) {
if err := c.get(fmt.Sprintf(`regions/availability?DCID=%v`, id), &planIDs); err != nil {
return nil, err
}
return
}

View File

@ -1,44 +0,0 @@
package lib
import "sort"
// Region on Vultr
type Region struct {
ID int `json:"DCID,string"`
Name string `json:"name"`
Country string `json:"country"`
Continent string `json:"continent"`
State string `json:"state"`
Ddos bool `json:"ddos_protection"`
BlockStorage bool `json:"block_storage"`
Code string `json:"regioncode"`
}
type regions []Region
func (s regions) Len() int { return len(s) }
func (s regions) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s regions) Less(i, j int) bool {
// sort order: continent, name
if s[i].Continent < s[j].Continent {
return true
} else if s[i].Continent > s[j].Continent {
return false
}
return s[i].Name < s[j].Name
}
// GetRegions returns a list of all available Vultr regions
func (c *Client) GetRegions() ([]Region, error) {
var regionMap map[string]Region
if err := c.get(`regions/list`, &regionMap); err != nil {
return nil, err
}
var regionList []Region
for _, os := range regionMap {
regionList = append(regionList, os)
}
sort.Sort(regions(regionList))
return regionList, nil
}

View File

@ -1,192 +0,0 @@
package lib
import (
"encoding/json"
"fmt"
"net/url"
"sort"
"strconv"
"strings"
)
// IP on Vultr
type IP struct {
ID string `json:"SUBID,string"`
RegionID int `json:"DCID,string"`
IPType string `json:"ip_type"`
Subnet string `json:"subnet"`
SubnetSize int `json:"subnet_size"`
Label string `json:"label"`
AttachedTo string `json:"attached_SUBID,string"`
}
type ips []IP
func (s ips) Len() int { return len(s) }
func (s ips) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ips) Less(i, j int) bool {
// sort order: label, iptype, subnet
if strings.ToLower(s[i].Label) < strings.ToLower(s[j].Label) {
return true
} else if strings.ToLower(s[i].Label) > strings.ToLower(s[j].Label) {
return false
}
if s[i].IPType < s[j].IPType {
return true
} else if s[i].IPType > s[j].IPType {
return false
}
return s[i].Subnet < s[j].Subnet
}
// UnmarshalJSON implements json.Unmarshaller on IP.
// This is needed because the Vultr API is inconsistent in it's JSON responses.
// Some fields can change type, from JSON number to JSON string and vice-versa.
func (i *IP) UnmarshalJSON(data []byte) (err error) {
if i == nil {
*i = IP{}
}
var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
value := fmt.Sprintf("%v", fields["SUBID"])
if len(value) == 0 || value == "<nil>" || value == "0" {
i.ID = ""
} else {
id, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
i.ID = strconv.FormatFloat(id, 'f', -1, 64)
}
value = fmt.Sprintf("%v", fields["DCID"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
region, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
i.RegionID = int(region)
value = fmt.Sprintf("%v", fields["attached_SUBID"])
if len(value) == 0 || value == "<nil>" || value == "0" || value == "false" {
i.AttachedTo = ""
} else {
attached, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
i.AttachedTo = strconv.FormatFloat(attached, 'f', -1, 64)
}
value = fmt.Sprintf("%v", fields["subnet_size"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
size, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
i.SubnetSize = int(size)
i.IPType = fmt.Sprintf("%v", fields["ip_type"])
i.Subnet = fmt.Sprintf("%v", fields["subnet"])
i.Label = fmt.Sprintf("%v", fields["label"])
return
}
// ListReservedIP returns a list of all available reserved IPs on Vultr account
func (c *Client) ListReservedIP() ([]IP, error) {
var ipMap map[string]IP
err := c.get(`reservedip/list`, &ipMap)
if err != nil {
return nil, err
}
ipList := make([]IP, 0)
for _, ip := range ipMap {
ipList = append(ipList, ip)
}
sort.Sort(ips(ipList))
return ipList, nil
}
// GetReservedIP returns reserved IP with given ID
func (c *Client) GetReservedIP(id string) (IP, error) {
var ipMap map[string]IP
err := c.get(`reservedip/list`, &ipMap)
if err != nil {
return IP{}, err
}
if ip, ok := ipMap[id]; ok {
return ip, nil
}
return IP{}, fmt.Errorf("IP with ID %v not found", id)
}
// CreateReservedIP creates a new reserved IP on Vultr account
func (c *Client) CreateReservedIP(regionID int, ipType string, label string) (string, error) {
values := url.Values{
"DCID": {fmt.Sprintf("%v", regionID)},
"ip_type": {ipType},
}
if len(label) > 0 {
values.Add("label", label)
}
result := IP{}
err := c.post(`reservedip/create`, values, &result)
if err != nil {
return "", err
}
return result.ID, nil
}
// DestroyReservedIP deletes an existing reserved IP
func (c *Client) DestroyReservedIP(id string) error {
values := url.Values{
"SUBID": {id},
}
return c.post(`reservedip/destroy`, values, nil)
}
// AttachReservedIP attaches a reserved IP to a virtual machine
func (c *Client) AttachReservedIP(ip string, serverID string) error {
values := url.Values{
"ip_address": {ip},
"attach_SUBID": {serverID},
}
return c.post(`reservedip/attach`, values, nil)
}
// DetachReservedIP detaches a reserved IP from an existing virtual machine
func (c *Client) DetachReservedIP(serverID string, ip string) error {
values := url.Values{
"ip_address": {ip},
"detach_SUBID": {serverID},
}
return c.post(`reservedip/detach`, values, nil)
}
// ConvertReservedIP converts an existing virtual machines IP to a reserved IP
func (c *Client) ConvertReservedIP(serverID string, ip string) (string, error) {
values := url.Values{
"SUBID": {serverID},
"ip_address": {ip},
}
result := IP{}
err := c.post(`reservedip/convert`, values, &result)
if err != nil {
return "", err
}
return result.ID, err
}

View File

@ -1,126 +0,0 @@
package lib
import (
"encoding/json"
"fmt"
"net/url"
"sort"
"strings"
)
// StartupScript on Vultr account
type StartupScript struct {
ID string `json:"SCRIPTID"`
Name string `json:"name"`
Type string `json:"type"`
Content string `json:"script"`
}
type startupscripts []StartupScript
func (s startupscripts) Len() int { return len(s) }
func (s startupscripts) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s startupscripts) Less(i, j int) bool {
return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name)
}
// UnmarshalJSON implements json.Unmarshaller on StartupScript.
// Necessary because the SCRIPTID field has inconsistent types.
func (s *StartupScript) UnmarshalJSON(data []byte) (err error) {
if s == nil {
*s = StartupScript{}
}
var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
s.ID = fmt.Sprintf("%v", fields["SCRIPTID"])
s.Name = fmt.Sprintf("%v", fields["name"])
s.Type = fmt.Sprintf("%v", fields["type"])
s.Content = fmt.Sprintf("%v", fields["script"])
return
}
// GetStartupScripts returns a list of all startup scripts on the current Vultr account
func (c *Client) GetStartupScripts() (scripts []StartupScript, err error) {
var scriptMap map[string]StartupScript
if err := c.get(`startupscript/list`, &scriptMap); err != nil {
return nil, err
}
for _, script := range scriptMap {
if script.Type == "" {
script.Type = "boot" // set default script type
}
scripts = append(scripts, script)
}
sort.Sort(startupscripts(scripts))
return scripts, nil
}
// GetStartupScript returns the startup script with the given ID
func (c *Client) GetStartupScript(id string) (StartupScript, error) {
scripts, err := c.GetStartupScripts()
if err != nil {
return StartupScript{}, err
}
for _, s := range scripts {
if s.ID == id {
return s, nil
}
}
return StartupScript{}, nil
}
// CreateStartupScript creates a new startup script
func (c *Client) CreateStartupScript(name, content, scriptType string) (StartupScript, error) {
values := url.Values{
"name": {name},
"script": {content},
"type": {scriptType},
}
var script StartupScript
if err := c.post(`startupscript/create`, values, &script); err != nil {
return StartupScript{}, err
}
script.Name = name
script.Content = content
script.Type = scriptType
return script, nil
}
// UpdateStartupScript updates an existing startup script
func (c *Client) UpdateStartupScript(script StartupScript) error {
values := url.Values{
"SCRIPTID": {script.ID},
}
if script.Name != "" {
values.Add("name", script.Name)
}
if script.Content != "" {
values.Add("script", script.Content)
}
if err := c.post(`startupscript/update`, values, nil); err != nil {
return err
}
return nil
}
// DeleteStartupScript deletes an existing startup script from Vultr account
func (c *Client) DeleteStartupScript(id string) error {
values := url.Values{
"SCRIPTID": {id},
}
if err := c.post(`startupscript/destroy`, values, nil); err != nil {
return err
}
return nil
}

View File

@ -1,561 +0,0 @@
package lib
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"sort"
"strconv"
"strings"
)
// Server (virtual machine) on Vultr account
type Server struct {
ID string `json:"SUBID"`
Name string `json:"label"`
OS string `json:"os"`
RAM string `json:"ram"`
Disk string `json:"disk"`
MainIP string `json:"main_ip"`
VCpus int `json:"vcpu_count,string"`
Location string `json:"location"`
RegionID int `json:"DCID,string"`
DefaultPassword string `json:"default_password"`
Created string `json:"date_created"`
PendingCharges float64 `json:"pending_charges"`
Status string `json:"status"`
Cost string `json:"cost_per_month"`
CurrentBandwidth float64 `json:"current_bandwidth_gb"`
AllowedBandwidth float64 `json:"allowed_bandwidth_gb,string"`
NetmaskV4 string `json:"netmask_v4"`
GatewayV4 string `json:"gateway_v4"`
PowerStatus string `json:"power_status"`
ServerState string `json:"server_state"`
PlanID int `json:"VPSPLANID,string"`
V6Networks []V6Network `json:"v6_networks"`
InternalIP string `json:"internal_ip"`
KVMUrl string `json:"kvm_url"`
AutoBackups string `json:"auto_backups"`
Tag string `json:"tag"`
OSID string `json:"OSID"`
AppID string `json:"APPID"`
FirewallGroupID string `json:"FIREWALLGROUPID"`
}
// ServerOptions are optional parameters to be used during server creation
type ServerOptions struct {
IPXEChainURL string
ISO int
Script int
UserData string
Snapshot string
SSHKey string
ReservedIP string
IPV6 bool
PrivateNetworking bool
AutoBackups bool
DontNotifyOnActivate bool
Hostname string
Tag string
AppID string
FirewallGroupID string
}
type servers []Server
func (s servers) Len() int { return len(s) }
func (s servers) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s servers) Less(i, j int) bool {
// sort order: name, ip
if strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name) {
return true
} else if strings.ToLower(s[i].Name) > strings.ToLower(s[j].Name) {
return false
}
return s[i].MainIP < s[j].MainIP
}
// V6Network represents a IPv6 network of a Vultr server
type V6Network struct {
Network string `json:"v6_network"`
MainIP string `json:"v6_main_ip"`
NetworkSize string `json:"v6_network_size"`
}
// ISOStatus represents an ISO image attached to a Vultr server
type ISOStatus struct {
State string `json:"state"`
ISOID string `json:"ISOID"`
}
// UnmarshalJSON implements json.Unmarshaller on Server.
// This is needed because the Vultr API is inconsistent in it's JSON responses for servers.
// Some fields can change type, from JSON number to JSON string and vice-versa.
func (s *Server) UnmarshalJSON(data []byte) (err error) {
if s == nil {
*s = Server{}
}
var fields map[string]interface{}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
value := fmt.Sprintf("%v", fields["vcpu_count"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
vcpu, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
s.VCpus = int(vcpu)
value = fmt.Sprintf("%v", fields["DCID"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
region, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
s.RegionID = int(region)
value = fmt.Sprintf("%v", fields["VPSPLANID"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
plan, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
s.PlanID = int(plan)
value = fmt.Sprintf("%v", fields["pending_charges"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
pc, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
s.PendingCharges = pc
value = fmt.Sprintf("%v", fields["current_bandwidth_gb"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
cb, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
s.CurrentBandwidth = cb
value = fmt.Sprintf("%v", fields["allowed_bandwidth_gb"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
ab, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
s.AllowedBandwidth = ab
value = fmt.Sprintf("%v", fields["OSID"])
if value == "<nil>" {
value = ""
}
s.OSID = value
value = fmt.Sprintf("%v", fields["APPID"])
if value == "<nil>" || value == "0" {
value = ""
}
s.AppID = value
value = fmt.Sprintf("%v", fields["FIREWALLGROUPID"])
if value == "<nil>" || value == "0" {
value = ""
}
s.FirewallGroupID = value
s.ID = fmt.Sprintf("%v", fields["SUBID"])
s.Name = fmt.Sprintf("%v", fields["label"])
s.OS = fmt.Sprintf("%v", fields["os"])
s.RAM = fmt.Sprintf("%v", fields["ram"])
s.Disk = fmt.Sprintf("%v", fields["disk"])
s.MainIP = fmt.Sprintf("%v", fields["main_ip"])
s.Location = fmt.Sprintf("%v", fields["location"])
s.DefaultPassword = fmt.Sprintf("%v", fields["default_password"])
s.Created = fmt.Sprintf("%v", fields["date_created"])
s.Status = fmt.Sprintf("%v", fields["status"])
s.Cost = fmt.Sprintf("%v", fields["cost_per_month"])
s.NetmaskV4 = fmt.Sprintf("%v", fields["netmask_v4"])
s.GatewayV4 = fmt.Sprintf("%v", fields["gateway_v4"])
s.PowerStatus = fmt.Sprintf("%v", fields["power_status"])
s.ServerState = fmt.Sprintf("%v", fields["server_state"])
v6networks := make([]V6Network, 0)
if networks, ok := fields["v6_networks"].([]interface{}); ok {
for _, network := range networks {
if network, ok := network.(map[string]interface{}); ok {
v6network := V6Network{
Network: fmt.Sprintf("%v", network["v6_network"]),
MainIP: fmt.Sprintf("%v", network["v6_main_ip"]),
NetworkSize: fmt.Sprintf("%v", network["v6_network_size"]),
}
v6networks = append(v6networks, v6network)
}
}
s.V6Networks = v6networks
}
s.InternalIP = fmt.Sprintf("%v", fields["internal_ip"])
s.KVMUrl = fmt.Sprintf("%v", fields["kvm_url"])
s.AutoBackups = fmt.Sprintf("%v", fields["auto_backups"])
s.Tag = fmt.Sprintf("%v", fields["tag"])
return
}
// GetServers returns a list of current virtual machines on Vultr account
func (c *Client) GetServers() (serverList []Server, err error) {
var serverMap map[string]Server
if err := c.get(`server/list`, &serverMap); err != nil {
return nil, err
}
for _, server := range serverMap {
serverList = append(serverList, server)
}
sort.Sort(servers(serverList))
return serverList, nil
}
// GetServersByTag returns a list of all virtual machines matching by tag
func (c *Client) GetServersByTag(tag string) (serverList []Server, err error) {
var serverMap map[string]Server
if err := c.get(`server/list?tag=`+tag, &serverMap); err != nil {
return nil, err
}
for _, server := range serverMap {
serverList = append(serverList, server)
}
sort.Sort(servers(serverList))
return serverList, nil
}
// GetServer returns the virtual machine with the given ID
func (c *Client) GetServer(id string) (server Server, err error) {
if err := c.get(`server/list?SUBID=`+id, &server); err != nil {
return Server{}, err
}
return server, nil
}
// CreateServer creates a new virtual machine on Vultr. ServerOptions are optional settings.
func (c *Client) CreateServer(name string, regionID, planID, osID int, options *ServerOptions) (Server, error) {
values := url.Values{
"label": {name},
"DCID": {fmt.Sprintf("%v", regionID)},
"VPSPLANID": {fmt.Sprintf("%v", planID)},
"OSID": {fmt.Sprintf("%v", osID)},
}
if options != nil {
if options.IPXEChainURL != "" {
values.Add("ipxe_chain_url", options.IPXEChainURL)
}
if options.ISO != 0 {
values.Add("ISOID", fmt.Sprintf("%v", options.ISO))
}
if options.Script != 0 {
values.Add("SCRIPTID", fmt.Sprintf("%v", options.Script))
}
if options.UserData != "" {
values.Add("userdata", base64.StdEncoding.EncodeToString([]byte(options.UserData)))
}
if options.Snapshot != "" {
values.Add("SNAPSHOTID", options.Snapshot)
}
if options.SSHKey != "" {
values.Add("SSHKEYID", options.SSHKey)
}
if options.ReservedIP != "" {
values.Add("reserved_ip_v4", options.ReservedIP)
}
values.Add("enable_ipv6", "no")
if options.IPV6 {
values.Set("enable_ipv6", "yes")
}
values.Add("enable_private_network", "no")
if options.PrivateNetworking {
values.Set("enable_private_network", "yes")
}
values.Add("auto_backups", "no")
if options.AutoBackups {
values.Set("auto_backups", "yes")
}
values.Add("notify_activate", "yes")
if options.DontNotifyOnActivate {
values.Set("notify_activate", "no")
}
if options.Hostname != "" {
values.Add("hostname", options.Hostname)
}
if options.Tag != "" {
values.Add("tag", options.Tag)
}
if options.AppID != "" {
values.Add("APPID", options.AppID)
}
if options.FirewallGroupID != "" {
values.Add("FIREWALLGROUPID", options.FirewallGroupID)
}
}
var server Server
if err := c.post(`server/create`, values, &server); err != nil {
return Server{}, err
}
server.Name = name
server.RegionID = regionID
server.PlanID = planID
return server, nil
}
// RenameServer renames an existing virtual machine
func (c *Client) RenameServer(id, name string) error {
values := url.Values{
"SUBID": {id},
"label": {name},
}
if err := c.post(`server/label_set`, values, nil); err != nil {
return err
}
return nil
}
// TagServer replaces the tag on an existing virtual machine
func (c *Client) TagServer(id, tag string) error {
values := url.Values{
"SUBID": {id},
"tag": {tag},
}
if err := c.post(`server/tag_set`, values, nil); err != nil {
return err
}
return nil
}
// StartServer starts an existing virtual machine
func (c *Client) StartServer(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`server/start`, values, nil); err != nil {
return err
}
return nil
}
// HaltServer stops an existing virtual machine
func (c *Client) HaltServer(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`server/halt`, values, nil); err != nil {
return err
}
return nil
}
// RebootServer reboots an existing virtual machine
func (c *Client) RebootServer(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`server/reboot`, values, nil); err != nil {
return err
}
return nil
}
// ReinstallServer reinstalls the operating system on an existing virtual machine
func (c *Client) ReinstallServer(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`server/reinstall`, values, nil); err != nil {
return err
}
return nil
}
// ChangeOSofServer changes the virtual machine to a different operating system
func (c *Client) ChangeOSofServer(id string, osID int) error {
values := url.Values{
"SUBID": {id},
"OSID": {fmt.Sprintf("%v", osID)},
}
if err := c.post(`server/os_change`, values, nil); err != nil {
return err
}
return nil
}
// ListOSforServer lists all available operating systems to which an existing virtual machine can be changed
func (c *Client) ListOSforServer(id string) (os []OS, err error) {
var osMap map[string]OS
if err := c.get(`server/os_change_list?SUBID=`+id, &osMap); err != nil {
return nil, err
}
for _, o := range osMap {
os = append(os, o)
}
sort.Sort(oses(os))
return os, nil
}
// AttachISOtoServer attaches an ISO image to an existing virtual machine and reboots it
func (c *Client) AttachISOtoServer(id string, isoID int) error {
values := url.Values{
"SUBID": {id},
"ISOID": {fmt.Sprintf("%v", isoID)},
}
if err := c.post(`server/iso_attach`, values, nil); err != nil {
return err
}
return nil
}
// DetachISOfromServer detaches the currently mounted ISO image from the virtual machine and reboots it
func (c *Client) DetachISOfromServer(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`server/iso_detach`, values, nil); err != nil {
return err
}
return nil
}
// GetISOStatusofServer retrieves the current ISO image state of an existing virtual machine
func (c *Client) GetISOStatusofServer(id string) (isoStatus ISOStatus, err error) {
if err := c.get(`server/iso_status?SUBID=`+id, &isoStatus); err != nil {
return ISOStatus{}, err
}
return isoStatus, nil
}
// DeleteServer deletes an existing virtual machine
func (c *Client) DeleteServer(id string) error {
values := url.Values{
"SUBID": {id},
}
if err := c.post(`server/destroy`, values, nil); err != nil {
return err
}
return nil
}
// SetFirewallGroup adds a virtual machine to a firewall group
func (c *Client) SetFirewallGroup(id, firewallgroup string) error {
values := url.Values{
"SUBID": {id},
"FIREWALLGROUPID": {firewallgroup},
}
if err := c.post(`server/firewall_group_set`, values, nil); err != nil {
return err
}
return nil
}
// UnsetFirewallGroup removes a virtual machine from a firewall group
func (c *Client) UnsetFirewallGroup(id string) error {
return c.SetFirewallGroup(id, "0")
}
// BandwidthOfServer retrieves the bandwidth used by a virtual machine
func (c *Client) BandwidthOfServer(id string) (bandwidth []map[string]string, err error) {
var bandwidthMap map[string][][]string
if err := c.get(`server/bandwidth?SUBID=`+id, &bandwidthMap); err != nil {
return nil, err
}
// parse incoming bytes
for _, b := range bandwidthMap["incoming_bytes"] {
bMap := make(map[string]string)
bMap["date"] = b[0]
bMap["incoming"] = b[1]
bandwidth = append(bandwidth, bMap)
}
// parse outgoing bytes (we'll assume that incoming and outgoing dates are always a match)
for _, b := range bandwidthMap["outgoing_bytes"] {
for i := range bandwidth {
if bandwidth[i]["date"] == b[0] {
bandwidth[i]["outgoing"] = b[1]
break
}
}
}
return bandwidth, nil
}
// ChangeApplicationofServer changes the virtual machine to a different application
func (c *Client) ChangeApplicationofServer(id string, appID string) error {
values := url.Values{
"SUBID": {id},
"APPID": {appID},
}
if err := c.post(`server/app_change`, values, nil); err != nil {
return err
}
return nil
}
// ListApplicationsforServer lists all available operating systems to which an existing virtual machine can be changed
func (c *Client) ListApplicationsforServer(id string) (apps []Application, err error) {
var appMap map[string]Application
if err := c.get(`server/app_change_list?SUBID=`+id, &appMap); err != nil {
return nil, err
}
for _, app := range appMap {
apps = append(apps, app)
}
sort.Sort(applications(apps))
return apps, nil
}

View File

@ -1,72 +0,0 @@
package lib
import (
"net/url"
"sort"
"strings"
)
// Snapshot of a virtual machine on Vultr account
type Snapshot struct {
ID string `json:"SNAPSHOTID"`
Description string `json:"description"`
Size string `json:"size"`
Status string `json:"status"`
Created string `json:"date_created"`
}
type snapshots []Snapshot
func (s snapshots) Len() int { return len(s) }
func (s snapshots) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s snapshots) Less(i, j int) bool {
// sort order: description, created
if strings.ToLower(s[i].Description) < strings.ToLower(s[j].Description) {
return true
} else if strings.ToLower(s[i].Description) > strings.ToLower(s[j].Description) {
return false
}
return s[i].Created < s[j].Created
}
// GetSnapshots retrieves a list of all snapshots on Vultr account
func (c *Client) GetSnapshots() (snapshotList []Snapshot, err error) {
var snapshotMap map[string]Snapshot
if err := c.get(`snapshot/list`, &snapshotMap); err != nil {
return nil, err
}
for _, snapshot := range snapshotMap {
snapshotList = append(snapshotList, snapshot)
}
sort.Sort(snapshots(snapshotList))
return snapshotList, nil
}
// CreateSnapshot creates a new virtual machine snapshot
func (c *Client) CreateSnapshot(id, description string) (Snapshot, error) {
values := url.Values{
"SUBID": {id},
"description": {description},
}
var snapshot Snapshot
if err := c.post(`snapshot/create`, values, &snapshot); err != nil {
return Snapshot{}, err
}
snapshot.Description = description
return snapshot, nil
}
// DeleteSnapshot deletes an existing virtual machine snapshot
func (c *Client) DeleteSnapshot(id string) error {
values := url.Values{
"SNAPSHOTID": {id},
}
if err := c.post(`snapshot/destroy`, values, nil); err != nil {
return err
}
return nil
}

View File

@ -1,82 +0,0 @@
package lib
import (
"net/url"
"sort"
"strings"
)
// SSHKey on Vultr account
type SSHKey struct {
ID string `json:"SSHKEYID"`
Name string `json:"name"`
Key string `json:"ssh_key"`
Created string `json:"date_created"`
}
type sshkeys []SSHKey
func (s sshkeys) Len() int { return len(s) }
func (s sshkeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sshkeys) Less(i, j int) bool { return strings.ToLower(s[i].Name) < strings.ToLower(s[j].Name) }
// GetSSHKeys returns a list of SSHKeys from Vultr account
func (c *Client) GetSSHKeys() (keys []SSHKey, err error) {
var keyMap map[string]SSHKey
if err := c.get(`sshkey/list`, &keyMap); err != nil {
return nil, err
}
for _, key := range keyMap {
keys = append(keys, key)
}
sort.Sort(sshkeys(keys))
return keys, nil
}
// CreateSSHKey creates new SSHKey on Vultr
func (c *Client) CreateSSHKey(name, key string) (SSHKey, error) {
values := url.Values{
"name": {name},
"ssh_key": {key},
}
var sshKey SSHKey
if err := c.post(`sshkey/create`, values, &sshKey); err != nil {
return SSHKey{}, err
}
sshKey.Name = name
sshKey.Key = key
return sshKey, nil
}
// UpdateSSHKey updates an existing SSHKey entry
func (c *Client) UpdateSSHKey(key SSHKey) error {
values := url.Values{
"SSHKEYID": {key.ID},
}
if key.Name != "" {
values.Add("name", key.Name)
}
if key.Key != "" {
values.Add("ssh_key", key.Key)
}
if err := c.post(`sshkey/update`, values, nil); err != nil {
return err
}
return nil
}
// DeleteSSHKey deletes an existing SSHKey from Vultr account
func (c *Client) DeleteSSHKey(id string) error {
values := url.Values{
"SSHKEYID": {id},
}
if err := c.post(`sshkey/destroy`, values, nil); err != nil {
return err
}
return nil
}

53
vendor/github.com/vultr/govultr/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,53 @@
# Change Log
## [v0.1.3](https://github.com/vultr/govultr/compare/v0.1.2..v0.1.3) (2019-06-13)
### Features
* added `GetVc2zList` to Plans to retrieve `high-frequency compute` plans [#13](https://github.com/vultr/govultr/pull/13)
### Breaking Changes
* Renamed all variables named `vpsID` to `instanceID` [#14](https://github.com/vultr/govultr/pull/14)
* Server
* Renamed Server struct field `VpsID` to `InstanceID` [#14](https://github.com/vultr/govultr/pull/14)
* Plans
* Renamed Plan struct field `VpsID` to `PlanID` [#14](https://github.com/vultr/govultr/pull/14)
* Renamed BareMetalPlan struct field `BareMetalID` to `PlanID` [#14](https://github.com/vultr/govultr/pull/14)
* Renamed VCPlan struct field `VpsID` to `PlanID` [#14](https://github.com/vultr/govultr/pull/14)
* Renamed Plan struct field `VCPUCount` to `vCPUs` [#13](https://github.com/vultr/govultr/pull/13)
* Renamed BareMetalPlan struct field `CPUCount` to `CPUs` [#13](https://github.com/vultr/govultr/pull/13)
* Renamed VCPlan struct field `VCPUCount` to `vCPUs` [#13](https://github.com/vultr/govultr/pull/13)
* Renamed VCPlan struct field `Cost` to `Price` [#13](https://github.com/vultr/govultr/pull/13)
## [v0.1.2](https://github.com/vultr/govultr/compare/v0.1.1..v0.1.2) (2019-05-29)
### Fixes
* Fixed Server Option `NotifyActivate` bug that ignored a `false` value
* Fixed Bare Metal Server Option `UserData` to be based64encoded
### Breaking Changes
* Renamed all methods named `GetList` to `List`
* Renamed all methods named `Destroy` to `Delete`
* Server Service
* Renamed `GetListByLabel` to `ListByLabel`
* Renamed `GetListByMainIP` to `ListByMainIP`
* Renamed `GetListByTag` to `ListByTag`
* Bare Metal Server Service
* Renamed `GetListByLabel` to `ListByLabel`
* Renamed `GetListByMainIP` to `ListByMainIP`
* Renamed `GetListByTag` to `ListByTag`
## [v0.1.1](https://github.com/vultr/govultr/compare/v0.1.0..v0.1.1) (2019-05-20)
### Features
* add `SnapshotID` to ServerOptions as an option during server creation
* bumped default RateLimit from `.2` to `.6` seconds
### Breaking Changes
* Iso
* Renamed all instances of `Iso` to `ISO`.
* BlockStorage
* Renamed `Cost` to `CostPerMonth`
* Renamed `Size` to `SizeGB`
* BareMetal & Server
* Change `SSHKeyID` to `SSHKeyIDs` which are now `[]string` instead of `string`
* Renamed `OS` to `Os`
## v0.1.0 (2019-05-10)
### Features
* Initial release
* Supports all available API endpoints that Vultr has to offer

64
vendor/github.com/vultr/govultr/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,64 @@
# Contributing to `govultr`
We would love to get your feedback, thoughts, and overall improvements to `govultr`!
## Overview
- All code should run through `go fmt`
- All code **must be tested**
- All types, structs, and funcs **must be documented** for GoDocs
## Getting started
GoVultr supports `go modules` so you can pull down the repo outside of your `$GOPATH`.
You can also run:
`go get -u github.com/vultr/govultr`
## Testing
We aim to have as much code coverage as possible.
To run tests locally:
```sh
go test .
```
If you want to get more information on your local unit tests. You can run the following:
```sh
go test -v -coverprofile cover.out
go tool cover -html=cover.out
```
Upon opening a pull request we have CodeCov checks to make sure that code coverage meets a minimum requirement. In addition to CodeCov we have Travis CI that will run your unit tests on each pull request as well.
## Versioning
GoVultr follows [SemVer](http://semver.org/) for versioning. New functionality will result in a increment to the minor version and bug fixes will result in a increment to the patch version.
## Releases
Releases of new versions are done as independent pull requests and will be made by the maintainers.
To release a new version of `govultr` we must do the following:
- Update version number in `govultr.go` to reflect the new release version
- Make the appropriate updates to `CHANGELOG.md`. This should include the:
- Version,
- List of fix/features with accompanying pull request ID
- Description of each fix/feature
```
## v0.0.1 (2019-05-05)
### Fixes
* Fixed random bug #12
### Features
* BareMetalServer functionality #13
```
- Submit a pull request with the changes above.
- Once the pull request is merged in, create a new tag and publish.

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
MIT License
Copyright (c) 2015 Fabio Berchtold
Copyright (c) 2019 Vultr
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

94
vendor/github.com/vultr/govultr/README.md generated vendored Normal file
View File

@ -0,0 +1,94 @@
# GoVultr
[![Build Status](https://travis-ci.org/vultr/govultr.svg?branch=master)](https://travis-ci.org/vultr/govultr)
[![GoDoc](https://godoc.org/github.com/vultr/govultr?status.svg)](https://godoc.org/github.com/vultr/govultr)
[![codecov](https://codecov.io/gh/vultr/govultr/branch/master/graph/badge.svg?token=PDJXBc7Rci)](https://codecov.io/gh/vultr/govultr)
[![Go Report Card](https://goreportcard.com/badge/github.com/vultr/govultr)](https://goreportcard.com/report/github.com/vultr/govultr)
The official Vultr Go client - GoVultr allows you to interact with the Vultr V1 API.
## Installation
```sh
go get -u github.com/vultr/govultr
```
## Usage
Vultr uses a PAT (Personal Access token) to interact/authenticate with the APIs. An API Key can be generated and acquired from the API menu in [settings](https://my.vultr.com/settings/#settingsapi).
To instantiate a govultr client you invoke `NewClient()`.
This takes in two parameters:
- \*http.Client
- API Key
You can define your own `http.Client` however if you pass in `nil` then you will be defaulted to use `http.DefaultClient`. For the API key, we recommend you store this as a environment variable and not hard code it.
There are also three optional parameters you may change regarding the client:
- BaseUrl: allows you to override the base URL that Vultr defaults to
- UserAgent: allows you to override the UserAgent that Vultr defaults to
- RateLimit: Vultr currently rate limits how fast you can make calls back to back. This lets you configure if you want a delay in between calls
### Example Client Setup
```go
package main
import (
"github.com/vultr/govultr"
"os"
)
func main() {
apiKey := os.Getenv("VultrAPIKey")
vultrClient := govultr.NewClient(nil, apiKey)
// Optional changes
_ = vultrClient.SetBaseURL("https://api.vultr.com")
vultrClient.SetUserAgent("mycool-app")
vultrClient.SetRateLimit(500)
}
```
### Example Usage
Create a VPS
```go
vpsOptions := &govultr.ServerOptions{
Label: "awesome-go-app",
Hostname: "awesome-go.com",
EnablePrivateNetwork: true,
AutoBackups: true,
EnableIPV6: true,
}
// RegionId, VpsPlanID, OsID can be grabbed from their respective API calls
res, err := vultrClient.Server.Create(context.Background(), 1, 201, 1, vpsOptions)
if err != nil {
fmt.Println(err)
}
```
## Versioning
This project follows [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/vultr/govultr/tags).
## Documentation
For detailed information about our V1 API head over to our [API documentation](https://www.vultr.com/api/).
If you want more details about this client's functionality then check out our [GoDoc](https://godoc.org/github.com/vultr/govultr) documentation.
## Contributing
Feel free to send pull requests our way! Please see the [contributing guidelines](CONTRIBUTING.md).
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE) file for details.

45
vendor/github.com/vultr/govultr/account.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
package govultr
import (
"context"
"net/http"
)
// AccountService is the interface to interact with Accounts endpoint on the Vultr API
// Link: https://www.vultr.com/api/#account
type AccountService interface {
GetInfo(ctx context.Context) (*Account, error)
}
// AccountServiceHandler handles interaction with the account methods for the Vultr API
type AccountServiceHandler struct {
client *Client
}
// Account represents a Vultr account
type Account struct {
Balance string `json:"balance"`
PendingCharges string `json:"pending_charges"`
LastPaymentDate string `json:"last_payment_date"`
LastPaymentAmount string `json:"last_payment_amount"`
}
// GetInfo Vultr account info
func (a *AccountServiceHandler) GetInfo(ctx context.Context) (*Account, error) {
uri := "/v1/account/info"
req, err := a.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
account := new(Account)
err = a.client.DoWithContext(ctx, req, account)
if err != nil {
return nil, err
}
return account, nil
}

44
vendor/github.com/vultr/govultr/api.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
package govultr
import (
"context"
"net/http"
)
// APIService is the interface to interact with the API endpoint on the Vultr API
// Link: https://www.vultr.com/api/#auth
type APIService interface {
GetInfo(ctx context.Context) (*API, error)
}
// APIServiceHandler handles interaction with the API methods for the Vultr API
type APIServiceHandler struct {
client *Client
}
// API represents Vultr API information
type API struct {
ACL []string `json:"acls"`
Email string `json:"email"`
Name string `json:"name"`
}
// GetInfo Vultr API auth information
func (a *APIServiceHandler) GetInfo(ctx context.Context) (*API, error) {
uri := "/v1/auth/info"
req, err := a.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
api := new(API)
err = a.client.DoWithContext(ctx, req, api)
if err != nil {
return nil, err
}
return api, nil
}

51
vendor/github.com/vultr/govultr/application.go generated vendored Normal file
View File

@ -0,0 +1,51 @@
package govultr
import (
"context"
"net/http"
)
// ApplicationService is the interface to interact with the Application endpoint on the Vultr API
// Link: https://www.vultr.com/api/#app
type ApplicationService interface {
List(ctx context.Context) ([]Application, error)
}
// ApplicationServiceHandler handles interaction with the application methods for the Vultr API
type ApplicationServiceHandler struct {
client *Client
}
// Application represents a Vultr application
type Application struct {
AppID string `json:"APPID"`
Name string `json:"name"`
ShortName string `json:"short_name"`
DeployName string `json:"deploy_name"`
Surcharge float64 `json:"surcharge"`
}
// List retrieves a list of available applications that can be launched when creating a Vultr VPS
func (a *ApplicationServiceHandler) List(ctx context.Context) ([]Application, error) {
uri := "/v1/app/list"
req, err := a.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
appsMap := make(map[string]Application)
err = a.client.DoWithContext(ctx, req, &appsMap)
if err != nil {
return nil, err
}
var apps []Application
for _, app := range appsMap {
apps = append(apps, app)
}
return apps, nil
}

105
vendor/github.com/vultr/govultr/backup.go generated vendored Normal file
View File

@ -0,0 +1,105 @@
package govultr
import (
"context"
"net/http"
)
// BackupService is the interface to interact with the backup endpoint on the Vultr API
// Link: https://www.vultr.com/api/#backup
type BackupService interface {
List(ctx context.Context) ([]Backup, error)
Get(ctx context.Context, backupID string) (*Backup, error)
ListBySub(ctx context.Context, subID string) ([]Backup, error)
}
// BackupServiceHandler handles interaction with the backup methods for the Vultr API
type BackupServiceHandler struct {
client *Client
}
// Backup represents a Vultr backup
type Backup struct {
BackupID string `json:"BACKUPID"`
DateCreated string `json:"date_created"`
Description string `json:"description"`
Size string `json:"size"`
Status string `json:"status"`
}
// List retrieves a list of all backups on the current account
func (b *BackupServiceHandler) List(ctx context.Context) ([]Backup, error) {
uri := "/v1/backup/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
backupsMap := make(map[string]Backup)
err = b.client.DoWithContext(ctx, req, &backupsMap)
if err != nil {
return nil, err
}
var backups []Backup
for _, backup := range backupsMap {
backups = append(backups, backup)
}
return backups, nil
}
// Get retrieves a backup that matches the given backupID
func (b *BackupServiceHandler) Get(ctx context.Context, backupID string) (*Backup, error) {
uri := "/v1/backup/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("BACKUPID", backupID)
req.URL.RawQuery = q.Encode()
backupsMap := make(map[string]Backup)
err = b.client.DoWithContext(ctx, req, &backupsMap)
if err != nil {
return nil, err
}
backup := new(Backup)
for _, bk := range backupsMap {
backup = &bk
}
return backup, nil
}
// ListBySub retrieves a list of all backups on the current account that match the given subID
func (b *BackupServiceHandler) ListBySub(ctx context.Context, subID string) ([]Backup, error) {
uri := "/v1/backup/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", subID)
req.URL.RawQuery = q.Encode()
backupsMap := make(map[string]Backup)
err = b.client.DoWithContext(ctx, req, &backupsMap)
if err != nil {
return nil, err
}
var backups []Backup
for _, backup := range backupsMap {
backups = append(backups, backup)
}
return backups, nil
}

790
vendor/github.com/vultr/govultr/bare_metal_server.go generated vendored Normal file
View File

@ -0,0 +1,790 @@
package govultr
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
)
// BareMetalServerService is the interface to interact with the bare metal endpoints on the Vultr API
// Link: https://www.vultr.com/api/#baremetal
type BareMetalServerService interface {
AppInfo(ctx context.Context, serverID string) (*AppInfo, error)
Bandwidth(ctx context.Context, serverID string) ([]map[string]string, error)
ChangeApp(ctx context.Context, serverID, appID string) error
ChangeOS(ctx context.Context, serverID, osID string) error
Create(ctx context.Context, regionID, planID, osID string, options *BareMetalServerOptions) (*BareMetalServer, error)
Delete(ctx context.Context, serverID string) error
EnableIPV6(ctx context.Context, serverID string) error
List(ctx context.Context) ([]BareMetalServer, error)
ListByLabel(ctx context.Context, label string) ([]BareMetalServer, error)
ListByMainIP(ctx context.Context, mainIP string) ([]BareMetalServer, error)
ListByTag(ctx context.Context, tag string) ([]BareMetalServer, error)
GetServer(ctx context.Context, serverID string) (*BareMetalServer, error)
GetUserData(ctx context.Context, serverID string) (*UserData, error)
Halt(ctx context.Context, serverID string) error
IPV4Info(ctx context.Context, serverID string) ([]BareMetalServerIPV4, error)
IPV6Info(ctx context.Context, serverID string) ([]BareMetalServerIPV6, error)
ListApps(ctx context.Context, serverID string) ([]Application, error)
ListOS(ctx context.Context, serverID string) ([]OS, error)
Reboot(ctx context.Context, serverID string) error
Reinstall(ctx context.Context, serverID string) error
SetLabel(ctx context.Context, serverID, label string) error
SetTag(ctx context.Context, serverID, tag string) error
SetUserData(ctx context.Context, serverID, userData string) error
}
// BareMetalServerServiceHandler handles interaction with the bare metal methods for the Vultr API
type BareMetalServerServiceHandler struct {
client *Client
}
// BareMetalServer represents a bare metal server on Vultr
type BareMetalServer struct {
BareMetalServerID string `json:"SUBID"`
Os string `json:"os"`
RAM string `json:"ram"`
Disk string `json:"disk"`
MainIP string `json:"main_ip"`
CPUs int `json:"cpu_count"`
Location string `json:"location"`
RegionID int `json:"DCID"`
DefaultPassword string `json:"default_password"`
DateCreated string `json:"date_created"`
Status string `json:"status"`
NetmaskV4 string `json:"netmask_v4"`
GatewayV4 string `json:"gateway_v4"`
BareMetalPlanID int `json:"METALPLANID"`
V6Networks []V6Network `json:"v6_networks"`
Label string `json:"label"`
Tag string `json:"tag"`
OsID string `json:"OSID"`
AppID string `json:"APPID"`
}
// BareMetalServerOptions represents the optional parameters that can be set when creating a bare metal server
type BareMetalServerOptions struct {
StartupScriptID string
SnapshotID string
EnableIPV6 string
Label string
SSHKeyIDs []string
AppID string
UserData string
NotifyActivate string
Hostname string
Tag string
ReservedIPV4 string
}
// BareMetalServerIPV4 represents IPV4 information for a bare metal server
type BareMetalServerIPV4 struct {
IP string `json:"ip"`
Netmask string `json:"netmask"`
Gateway string `json:"gateway"`
Type string `json:"type"`
}
// BareMetalServerIPV6 represents IPV6 information for a bare metal server
type BareMetalServerIPV6 struct {
IP string `json:"ip"`
Network string `json:"network"`
NetworkSize int `json:"network_size"`
Type string `json:"type"`
}
// UnmarshalJSON implements a custom unmarshaler on BareMetalServer
// This is done to help reduce data inconsistency with V1 of the Vultr API
func (b *BareMetalServer) UnmarshalJSON(data []byte) error {
if b == nil {
*b = BareMetalServer{}
}
var v map[string]interface{}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
cpu, err := b.unmarshalInt(fmt.Sprintf("%v", v["cpu_count"]))
if err != nil {
return err
}
b.CPUs = cpu
region, err := b.unmarshalInt(fmt.Sprintf("%v", v["DCID"]))
if err != nil {
return err
}
b.RegionID = region
plan, err := b.unmarshalInt(fmt.Sprintf("%v", v["METALPLANID"]))
if err != nil {
return err
}
b.BareMetalPlanID = plan
b.BareMetalServerID = b.unmarshalStr(fmt.Sprintf("%v", v["SUBID"]))
b.Os = b.unmarshalStr(fmt.Sprintf("%v", v["os"]))
b.RAM = b.unmarshalStr(fmt.Sprintf("%v", v["ram"]))
b.Label = b.unmarshalStr(fmt.Sprintf("%v", v["label"]))
b.Disk = b.unmarshalStr(fmt.Sprintf("%v", v["disk"]))
b.MainIP = b.unmarshalStr(fmt.Sprintf("%v", v["main_ip"]))
b.Location = b.unmarshalStr(fmt.Sprintf("%v", v["location"]))
b.DefaultPassword = b.unmarshalStr(fmt.Sprintf("%v", v["default_password"]))
b.DateCreated = b.unmarshalStr(fmt.Sprintf("%v", v["date_created"]))
b.Status = b.unmarshalStr(fmt.Sprintf("%v", v["status"]))
b.NetmaskV4 = b.unmarshalStr(fmt.Sprintf("%v", v["netmask_v4"]))
b.GatewayV4 = b.unmarshalStr(fmt.Sprintf("%v", v["gateway_v4"]))
b.Tag = b.unmarshalStr(fmt.Sprintf("%v", v["tag"]))
b.OsID = b.unmarshalStr(fmt.Sprintf("%v", v["OSID"]))
b.AppID = b.unmarshalStr(fmt.Sprintf("%v", v["APPID"]))
v6networks := make([]V6Network, 0)
if networks, ok := v["v6_networks"].([]interface{}); ok {
for _, network := range networks {
if network, ok := network.(map[string]interface{}); ok {
v6network := V6Network{
Network: fmt.Sprintf("%v", network["v6_network"]),
MainIP: fmt.Sprintf("%v", network["v6_main_ip"]),
NetworkSize: fmt.Sprintf("%v", network["v6_network_size"]),
}
v6networks = append(v6networks, v6network)
}
}
b.V6Networks = v6networks
}
return nil
}
func (b *BareMetalServer) unmarshalInt(value string) (int, error) {
if len(value) == 0 || value == "<nil>" {
value = "0"
}
v, err := strconv.Atoi(value)
if err != nil {
return 0, err
}
return v, nil
}
func (b *BareMetalServer) unmarshalStr(value string) string {
if value == "<nil>" {
value = ""
}
return value
}
// AppInfo retrieves the application information for a given server ID
func (b *BareMetalServerServiceHandler) AppInfo(ctx context.Context, serverID string) (*AppInfo, error) {
uri := "/v1/baremetal/get_app_info"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
appInfo := new(AppInfo)
err = b.client.DoWithContext(ctx, req, appInfo)
if err != nil {
return nil, err
}
return appInfo, nil
}
// Bandwidth will get the bandwidth used by a bare metal server
func (b *BareMetalServerServiceHandler) Bandwidth(ctx context.Context, serverID string) ([]map[string]string, error) {
uri := "/v1/baremetal/bandwidth"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
var bandwidthMap map[string][][]interface{}
err = b.client.DoWithContext(ctx, req, &bandwidthMap)
if err != nil {
return nil, err
}
var bandwidth []map[string]string
for _, b := range bandwidthMap["incoming_bytes"] {
inMap := make(map[string]string)
inMap["date"] = fmt.Sprintf("%v", b[0])
var bytes int64
switch b[1].(type) {
case float64:
bytes = int64(b[1].(float64))
case int64:
bytes = b[1].(int64)
}
inMap["incoming"] = fmt.Sprintf("%v", bytes)
bandwidth = append(bandwidth, inMap)
}
for _, b := range bandwidthMap["outgoing_bytes"] {
for i := range bandwidth {
if bandwidth[i]["date"] == b[0] {
var bytes int64
switch b[1].(type) {
case float64:
bytes = int64(b[1].(float64))
case int64:
bytes = b[1].(int64)
}
bandwidth[i]["outgoing"] = fmt.Sprintf("%v", bytes)
break
}
}
}
return bandwidth, nil
}
// ChangeApp changes the bare metal server to a different application.
func (b *BareMetalServerServiceHandler) ChangeApp(ctx context.Context, serverID, appID string) error {
uri := "/v1/baremetal/app_change"
values := url.Values{
"SUBID": {serverID},
"APPID": {appID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// ChangeOS changes the bare metal server to a different operating system. All data will be permanently lost.
func (b *BareMetalServerServiceHandler) ChangeOS(ctx context.Context, serverID, osID string) error {
uri := "/v1/baremetal/os_change"
values := url.Values{
"SUBID": {serverID},
"OSID": {osID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Create a new bare metal server.
func (b *BareMetalServerServiceHandler) Create(ctx context.Context, regionID, planID, osID string, options *BareMetalServerOptions) (*BareMetalServer, error) {
uri := "/v1/baremetal/create"
values := url.Values{
"DCID": {regionID},
"METALPLANID": {planID},
"OSID": {osID},
}
if options != nil {
if options.StartupScriptID != "" {
values.Add("SCRIPTID", options.StartupScriptID)
}
if options.SnapshotID != "" {
values.Add("SNAPSHOTID", options.SnapshotID)
}
if options.EnableIPV6 != "" {
values.Add("enable_ipv6", options.EnableIPV6)
}
if options.Label != "" {
values.Add("label", options.Label)
}
if options.SSHKeyIDs != nil && len(options.SSHKeyIDs) != 0 {
values.Add("SSHKEYID", strings.Join(options.SSHKeyIDs, ","))
}
if options.AppID != "" {
values.Add("APPID", options.AppID)
}
if options.UserData != "" {
values.Add("userdata", base64.StdEncoding.EncodeToString([]byte(options.UserData)))
}
if options.NotifyActivate != "" {
values.Add("notify_activate", options.NotifyActivate)
}
if options.Hostname != "" {
values.Add("hostname", options.Hostname)
}
if options.Tag != "" {
values.Add("tag", options.Tag)
}
if options.ReservedIPV4 != "" {
values.Add("reserved_ip_v4", options.ReservedIPV4)
}
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
bm := new(BareMetalServer)
err = b.client.DoWithContext(ctx, req, bm)
if err != nil {
return nil, err
}
return bm, nil
}
// Delete a bare metal server.
// All data will be permanently lost, and the IP address will be released. There is no going back from this call.
func (b *BareMetalServerServiceHandler) Delete(ctx context.Context, serverID string) error {
uri := "/v1/baremetal/destroy"
values := url.Values{
"SUBID": {serverID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// EnableIPV6 enables IPv6 networking on a bare metal server by assigning an IPv6 subnet to it.
// The server will not be rebooted when the subnet is assigned.
func (b *BareMetalServerServiceHandler) EnableIPV6(ctx context.Context, serverID string) error {
uri := "/v1/baremetal/ipv6_enable"
values := url.Values{
"SUBID": {serverID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List lists all bare metal servers on the current account. This includes both pending and active servers.
func (b *BareMetalServerServiceHandler) List(ctx context.Context) ([]BareMetalServer, error) {
return b.list(ctx, "", "")
}
// ListByLabel lists all bare metal servers that match the given label on the current account. This includes both pending and active servers.
func (b *BareMetalServerServiceHandler) ListByLabel(ctx context.Context, label string) ([]BareMetalServer, error) {
return b.list(ctx, "label", label)
}
// ListByMainIP lists all bare metal servers that match the given IP address on the current account. This includes both pending and active servers.
func (b *BareMetalServerServiceHandler) ListByMainIP(ctx context.Context, mainIP string) ([]BareMetalServer, error) {
return b.list(ctx, "main_ip", mainIP)
}
// ListByTag lists all bare metal servers that match the given tag on the current account. This includes both pending and active servers.
func (b *BareMetalServerServiceHandler) ListByTag(ctx context.Context, tag string) ([]BareMetalServer, error) {
return b.list(ctx, "tag", tag)
}
func (b *BareMetalServerServiceHandler) list(ctx context.Context, key, value string) ([]BareMetalServer, error) {
uri := "/v1/baremetal/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
if key != "" {
q := req.URL.Query()
q.Add(key, value)
req.URL.RawQuery = q.Encode()
}
bmsMap := make(map[string]BareMetalServer)
err = b.client.DoWithContext(ctx, req, &bmsMap)
if err != nil {
return nil, err
}
var bms []BareMetalServer
for _, bm := range bmsMap {
bms = append(bms, bm)
}
return bms, nil
}
// GetServer gets the server with the given ID
func (b *BareMetalServerServiceHandler) GetServer(ctx context.Context, serverID string) (*BareMetalServer, error) {
uri := "/v1/baremetal/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
bms := new(BareMetalServer)
err = b.client.DoWithContext(ctx, req, bms)
if err != nil {
return nil, err
}
return bms, nil
}
// GetUserData retrieves the (base64 encoded) user-data for this bare metal server
func (b *BareMetalServerServiceHandler) GetUserData(ctx context.Context, serverID string) (*UserData, error) {
uri := "/v1/baremetal/get_user_data"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
userData := new(UserData)
err = b.client.DoWithContext(ctx, req, userData)
if err != nil {
return nil, err
}
return userData, nil
}
// Halt a bare metal server.
// This is a hard power off, meaning that the power to the machine is severed.
// The data on the machine will not be modified, and you will still be billed for the machine.
func (b *BareMetalServerServiceHandler) Halt(ctx context.Context, serverID string) error {
uri := "/v1/baremetal/halt"
values := url.Values{
"SUBID": {serverID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// IPV4Info will List the IPv4 information of a bare metal server.
// IP information is only available for bare metal servers in the "active" state.
func (b *BareMetalServerServiceHandler) IPV4Info(ctx context.Context, serverID string) ([]BareMetalServerIPV4, error) {
uri := "/v1/baremetal/list_ipv4"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
var ipMap map[string][]BareMetalServerIPV4
err = b.client.DoWithContext(ctx, req, &ipMap)
if err != nil {
return nil, err
}
var ipv4 []BareMetalServerIPV4
for _, i := range ipMap {
ipv4 = i
}
return ipv4, nil
}
// IPV6Info ists the IPv6 information of a bare metal server.
// IP information is only available for bare metal servers in the "active" state.
// If the bare metal server does not have IPv6 enabled, then an empty array is returned.
func (b *BareMetalServerServiceHandler) IPV6Info(ctx context.Context, serverID string) ([]BareMetalServerIPV6, error) {
uri := "/v1/baremetal/list_ipv6"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
var ipMap map[string][]BareMetalServerIPV6
err = b.client.DoWithContext(ctx, req, &ipMap)
if err != nil {
return nil, err
}
var ipv6 []BareMetalServerIPV6
for _, i := range ipMap {
ipv6 = i
}
return ipv6, nil
}
// ListApps retrieves a list of Vultr one-click applications to which a bare metal server can be changed.
// Always check against this list before trying to switch applications because it is not possible to switch between every application combination.
func (b *BareMetalServerServiceHandler) ListApps(ctx context.Context, serverID string) ([]Application, error) {
uri := "/v1/baremetal/app_change_list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
var appMap map[string]Application
err = b.client.DoWithContext(ctx, req, &appMap)
if err != nil {
return nil, err
}
var appList []Application
for _, a := range appMap {
appList = append(appList, a)
}
return appList, nil
}
// ListOS retrieves a list of operating systems to which a bare metal server can be changed.
// Always check against this list before trying to switch operating systems because it is not possible to switch between every operating system combination.
func (b *BareMetalServerServiceHandler) ListOS(ctx context.Context, serverID string) ([]OS, error) {
uri := "/v1/baremetal/os_change_list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", serverID)
req.URL.RawQuery = q.Encode()
var osMap map[string]OS
err = b.client.DoWithContext(ctx, req, &osMap)
if err != nil {
return nil, err
}
var os []OS
for _, o := range osMap {
os = append(os, o)
}
return os, nil
}
// Reboot a bare metal server. This is a hard reboot, which means that the server is powered off, then back on.
func (b *BareMetalServerServiceHandler) Reboot(ctx context.Context, serverID string) error {
uri := "/v1/baremetal/reboot"
values := url.Values{
"SUBID": {serverID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Reinstall the operating system on a bare metal server.
// All data will be permanently lost, but the IP address will remain the same. There is no going back from this call.
func (b *BareMetalServerServiceHandler) Reinstall(ctx context.Context, serverID string) error {
uri := "/v1/baremetal/reinstall"
values := url.Values{
"SUBID": {serverID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// SetLabel sets the label of a bare metal server.
func (b *BareMetalServerServiceHandler) SetLabel(ctx context.Context, serverID, label string) error {
uri := "/v1/baremetal/label_set"
values := url.Values{
"SUBID": {serverID},
"label": {label},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// SetTag sets the tag of a bare metal server.
func (b *BareMetalServerServiceHandler) SetTag(ctx context.Context, serverID, tag string) error {
uri := "/v1/baremetal/tag_set"
values := url.Values{
"SUBID": {serverID},
"tag": {tag},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// SetUserData sets the user-data for this server.
// User-data is a generic data store, which some provisioning tools and cloud operating systems use as a configuration file.
// It is generally consumed only once after an instance has been launched, but individual needs may vary.
func (b *BareMetalServerServiceHandler) SetUserData(ctx context.Context, serverID, userData string) error {
uri := "/v1/baremetal/set_user_data"
encodedUserData := base64.StdEncoding.EncodeToString([]byte(userData))
values := url.Values{
"SUBID": {serverID},
"userdata": {encodedUserData},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

319
vendor/github.com/vultr/govultr/block_storage.go generated vendored Normal file
View File

@ -0,0 +1,319 @@
package govultr
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
)
// BlockStorageService is the interface to interact with Block-Storage endpoint on the Vultr API
// Link: https://www.vultr.com/api/#block
type BlockStorageService interface {
Attach(ctx context.Context, blockID, InstanceID string) error
Create(ctx context.Context, regionID, size int, label string) (*BlockStorage, error)
Delete(ctx context.Context, blockID string) error
Detach(ctx context.Context, blockID string) error
SetLabel(ctx context.Context, blockID, label string) error
List(ctx context.Context) ([]BlockStorage, error)
Get(ctx context.Context, blockID string) (*BlockStorage, error)
Resize(ctx context.Context, blockID string, size int) error
}
// BlockStorageServiceHandler handles interaction with the block-storage methods for the Vultr API
type BlockStorageServiceHandler struct {
client *Client
}
// BlockStorage represents Vultr Block-Storage
type BlockStorage struct {
BlockStorageID string `json:"SUBID"`
DateCreated string `json:"date_created"`
CostPerMonth string `json:"cost_per_month"`
Status string `json:"status"`
SizeGB int `json:"size_gb"`
RegionID int `json:"DCID"`
InstanceID string `json:"attached_to_SUBID"`
Label string `json:"label"`
}
// UnmarshalJSON implements json.Unmarshaller on BlockStorage to handle the inconsistent types returned from the Vultr v1 API.
func (b *BlockStorage) UnmarshalJSON(data []byte) (err error) {
if b == nil {
*b = BlockStorage{}
}
var v map[string]interface{}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
b.BlockStorageID, err = b.unmarshalStr(fmt.Sprintf("%v", v["SUBID"]))
if err != nil {
return err
}
b.RegionID, err = b.unmarshalInt(fmt.Sprintf("%v", v["DCID"]))
if err != nil {
return err
}
b.SizeGB, err = b.unmarshalInt(fmt.Sprintf("%v", v["size_gb"]))
if err != nil {
return err
}
b.InstanceID, err = b.unmarshalStr(fmt.Sprintf("%v", v["attached_to_SUBID"]))
if err != nil {
return err
}
b.CostPerMonth, err = b.unmarshalStr(fmt.Sprintf("%v", v["cost_per_month"]))
if err != nil {
return err
}
date := fmt.Sprintf("%v", v["date_created"])
if date == "<nil>" {
date = ""
}
b.DateCreated = date
status := fmt.Sprintf("%v", v["status"])
if status == "<nil>" {
status = ""
}
b.Status = status
b.Label = fmt.Sprintf("%v", v["label"])
return nil
}
func (b *BlockStorage) unmarshalInt(value string) (int, error) {
if len(value) == 0 || value == "<nil>" {
value = "0"
}
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0, err
}
return int(i), nil
}
func (b *BlockStorage) unmarshalStr(value string) (string, error) {
if len(value) == 0 || value == "<nil>" || value == "0" || value == "false" {
return "", nil
}
f, err := strconv.ParseFloat(value, 64)
if err != nil {
return "", err
}
return strconv.FormatFloat(f, 'f', -1, 64), nil
}
// Attach will link a given block storage to a given Vultr vps
func (b *BlockStorageServiceHandler) Attach(ctx context.Context, blockID, InstanceID string) error {
uri := "/v1/block/attach"
values := url.Values{
"SUBID": {blockID},
"attach_to_SUBID": {InstanceID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Create builds out a block storage
func (b *BlockStorageServiceHandler) Create(ctx context.Context, regionID, sizeGB int, label string) (*BlockStorage, error) {
uri := "/v1/block/create"
values := url.Values{
"DCID": {strconv.Itoa(regionID)},
"size_gb": {strconv.Itoa(sizeGB)},
"label": {label},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
blockStorage := new(BlockStorage)
err = b.client.DoWithContext(ctx, req, blockStorage)
if err != nil {
return nil, err
}
blockStorage.RegionID = regionID
blockStorage.Label = label
blockStorage.SizeGB = sizeGB
return blockStorage, nil
}
// Delete will remove block storage instance from your Vultr account
func (b *BlockStorageServiceHandler) Delete(ctx context.Context, blockID string) error {
uri := "/v1/block/delete"
values := url.Values{
"SUBID": {blockID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Detach will de-link a given block storage to the Vultr vps it is attached to
func (b *BlockStorageServiceHandler) Detach(ctx context.Context, blockID string) error {
uri := "/v1/block/detach"
values := url.Values{
"SUBID": {blockID},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// SetLabel allows you to set/update the label on your Vultr Block storage
func (b *BlockStorageServiceHandler) SetLabel(ctx context.Context, blockID, label string) error {
uri := "/v1/block/label_set"
values := url.Values{
"SUBID": {blockID},
"label": {label},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List returns a list of all block storage instances on your Vultr Account
func (b *BlockStorageServiceHandler) List(ctx context.Context) ([]BlockStorage, error) {
uri := "/v1/block/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var blockStorage []BlockStorage
err = b.client.DoWithContext(ctx, req, &blockStorage)
if err != nil {
return nil, err
}
return blockStorage, nil
}
// Get returns a single block storage instance based ony our blockID you provide from your Vultr Account
func (b *BlockStorageServiceHandler) Get(ctx context.Context, blockID string) (*BlockStorage, error) {
uri := "/v1/block/list"
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("SUBID", blockID)
req.URL.RawQuery = q.Encode()
blockStorage := new(BlockStorage)
err = b.client.DoWithContext(ctx, req, blockStorage)
if err != nil {
return nil, err
}
return blockStorage, nil
}
// Resize allows you to resize your Vultr block storage instance
func (b *BlockStorageServiceHandler) Resize(ctx context.Context, blockID string, sizeGB int) error {
uri := "/v1/block/resize"
values := url.Values{
"SUBID": {blockID},
"size_gb": {strconv.Itoa(sizeGB)},
}
req, err := b.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = b.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

209
vendor/github.com/vultr/govultr/dns_domains.go generated vendored Normal file
View File

@ -0,0 +1,209 @@
package govultr
import (
"context"
"net/http"
"net/url"
)
// DNSDomainService is the interface to interact with the DNS endpoints on the Vultr API
// Link: https://www.vultr.com/api/#dns
type DNSDomainService interface {
Create(ctx context.Context, domain, InstanceIP string) error
Delete(ctx context.Context, domain string) error
ToggleDNSSec(ctx context.Context, domain string, enabled bool) error
DNSSecInfo(ctx context.Context, domain string) ([]string, error)
List(ctx context.Context) ([]DNSDomain, error)
GetSoa(ctx context.Context, domain string) (*Soa, error)
UpdateSoa(ctx context.Context, domain, nsPrimary, email string) error
}
// DNSDomainServiceHandler handles interaction with the DNS methods for the Vultr API
type DNSDomainServiceHandler struct {
client *Client
}
// DNSDomain represents a DNS Domain entry on Vultr
type DNSDomain struct {
Domain string `json:"domain"`
DateCreated string `json:"date_created"`
}
// Soa represents record information for a domain on Vultr
type Soa struct {
NsPrimary string `json:"nsprimary"`
Email string `json:"email"`
}
// Create will create a DNS Domain entry on Vultr
func (d *DNSDomainServiceHandler) Create(ctx context.Context, domain, InstanceIP string) error {
uri := "/v1/dns/create_domain"
values := url.Values{
"domain": {domain},
"serverip": {InstanceIP},
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
//Delete will delete a domain name and all associated records
func (d *DNSDomainServiceHandler) Delete(ctx context.Context, domain string) error {
uri := "/v1/dns/delete_domain"
values := url.Values{
"domain": {domain},
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// ToggleDNSSec will enable or disable DNSSEC for a domain on Vultr
func (d *DNSDomainServiceHandler) ToggleDNSSec(ctx context.Context, domain string, enabled bool) error {
uri := "/v1/dns/dnssec_enable"
enable := "no"
if enabled == true {
enable = "yes"
}
values := url.Values{
"domain": {domain},
"enable": {enable},
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// DNSSecInfo gets the DNSSec keys for a domain (if enabled)
func (d *DNSDomainServiceHandler) DNSSecInfo(ctx context.Context, domain string) ([]string, error) {
uri := "/v1/dns/dnssec_info"
req, err := d.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("domain", domain)
req.URL.RawQuery = q.Encode()
var DNSSec []string
err = d.client.DoWithContext(ctx, req, &DNSSec)
if err != nil {
return nil, err
}
return DNSSec, nil
}
// List gets all domains associated with the current Vultr account.
func (d *DNSDomainServiceHandler) List(ctx context.Context) ([]DNSDomain, error) {
uri := "/v1/dns/list"
req, err := d.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var dnsDomains []DNSDomain
err = d.client.DoWithContext(ctx, req, &dnsDomains)
if err != nil {
return nil, err
}
return dnsDomains, nil
}
// GetSoa gets the SOA record information for a domain
func (d *DNSDomainServiceHandler) GetSoa(ctx context.Context, domain string) (*Soa, error) {
uri := "/v1/dns/soa_info"
req, err := d.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("domain", domain)
req.URL.RawQuery = q.Encode()
soa := new(Soa)
err = d.client.DoWithContext(ctx, req, soa)
if err != nil {
return nil, err
}
return soa, nil
}
// UpdateSoa will update the SOA record information for a domain.
func (d *DNSDomainServiceHandler) UpdateSoa(ctx context.Context, domain, nsPrimary, email string) error {
uri := "/v1/dns/soa_update"
values := url.Values{
"domain": {domain},
"nsprimary": {nsPrimary},
"email": {email},
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

150
vendor/github.com/vultr/govultr/dns_records.go generated vendored Normal file
View File

@ -0,0 +1,150 @@
package govultr
import (
"context"
"net/http"
"net/url"
"strconv"
)
// DNSRecordService is the interface to interact with the DNS Records endpoints on the Vultr API
// Link: https://www.vultr.com/api/#dns
type DNSRecordService interface {
Create(ctx context.Context, domain, recordType, name, data string, ttl, priority int) error
Delete(ctx context.Context, domain, recordID string) error
List(ctx context.Context, domain string) ([]DNSRecord, error)
Update(ctx context.Context, domain string, dnsRecord *DNSRecord) error
}
// DNSRecordsServiceHandler handles interaction with the DNS Records methods for the Vultr API
type DNSRecordsServiceHandler struct {
client *Client
}
// DNSRecord represents a DNS record on Vultr
type DNSRecord struct {
RecordID int `json:"RECORDID"`
Type string `json:"type"`
Name string `json:"name"`
Data string `json:"data"`
Priority int `json:"priority"`
TTL int `json:"ttl"`
}
// Create will add a DNS record.
func (d *DNSRecordsServiceHandler) Create(ctx context.Context, domain, recordType, name, data string, ttl, priority int) error {
uri := "/v1/dns/create_record"
values := url.Values{
"domain": {domain},
"name": {name},
"type": {recordType},
"data": {data},
"ttl": {strconv.Itoa(ttl)},
"priority": {strconv.Itoa(priority)},
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Delete will delete a domain name and all associated records.
func (d *DNSRecordsServiceHandler) Delete(ctx context.Context, domain, recordID string) error {
uri := "/v1/dns/delete_record"
values := url.Values{
"domain": {domain},
"RECORDID": {recordID},
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will list all the records associated with a particular domain on Vultr
func (d *DNSRecordsServiceHandler) List(ctx context.Context, domain string) ([]DNSRecord, error) {
uri := "/v1/dns/records"
req, err := d.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("domain", domain)
req.URL.RawQuery = q.Encode()
var dnsRecord []DNSRecord
err = d.client.DoWithContext(ctx, req, &dnsRecord)
if err != nil {
return nil, err
}
return dnsRecord, nil
}
// Update will update a DNS record
func (d *DNSRecordsServiceHandler) Update(ctx context.Context, domain string, dnsRecord *DNSRecord) error {
uri := "/v1/dns/update_record"
values := url.Values{
"domain": {domain},
"RECORDID": {strconv.Itoa(dnsRecord.RecordID)},
}
// Optional
if dnsRecord.Name != "" {
values.Add("name", dnsRecord.Name)
}
if dnsRecord.Data != "" {
values.Add("data", dnsRecord.Data)
}
if dnsRecord.TTL != 0 {
values.Add("ttl", strconv.Itoa(dnsRecord.TTL))
}
if dnsRecord.Priority != 0 {
values.Add("priority", strconv.Itoa(dnsRecord.Priority))
}
req, err := d.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = d.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

163
vendor/github.com/vultr/govultr/firewall_group.go generated vendored Normal file
View File

@ -0,0 +1,163 @@
package govultr
import (
"context"
"net/http"
"net/url"
)
// FirewallGroupService is the interface to interact with the firewall group endpoints on the Vultr API
// Link: https://www.vultr.com/api/#firewall
type FirewallGroupService interface {
Create(ctx context.Context, description string) (*FirewallGroup, error)
Delete(ctx context.Context, groupID string) error
List(ctx context.Context) ([]FirewallGroup, error)
Get(ctx context.Context, groupID string) (*FirewallGroup, error)
ChangeDescription(ctx context.Context, groupID, description string) error
}
// FireWallGroupServiceHandler handles interaction with the firewall group methods for the Vultr API
type FireWallGroupServiceHandler struct {
client *Client
}
// FirewallGroup represents a Vultr firewall group
type FirewallGroup struct {
FirewallGroupID string `json:"FIREWALLGROUPID"`
Description string `json:"description"`
DateCreated string `json:"date_created"`
DateModified string `json:"date_modified"`
InstanceCount int `json:"instance_count"`
RuleCount int `json:"rule_count"`
MaxRuleCount int `json:"max_rule_count"`
}
// Create will create a new firewall group on your Vultr account
func (f *FireWallGroupServiceHandler) Create(ctx context.Context, description string) (*FirewallGroup, error) {
uri := "/v1/firewall/group_create"
values := url.Values{
"description": {description},
}
req, err := f.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
firewall := new(FirewallGroup)
err = f.client.DoWithContext(ctx, req, firewall)
if err != nil {
return nil, err
}
return firewall, nil
}
// Delete will delete a firewall group from your Vultr account
func (f *FireWallGroupServiceHandler) Delete(ctx context.Context, groupID string) error {
uri := "/v1/firewall/group_delete"
values := url.Values{
"FIREWALLGROUPID": {groupID},
}
req, err := f.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = f.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will return a list of all firewall groups on your Vultr account
func (f *FireWallGroupServiceHandler) List(ctx context.Context) ([]FirewallGroup, error) {
uri := "/v1/firewall/group_list"
req, err := f.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var firewallGroupMap map[string]FirewallGroup
err = f.client.DoWithContext(ctx, req, &firewallGroupMap)
if err != nil {
return nil, err
}
var firewallGroup []FirewallGroup
for _, f := range firewallGroupMap {
firewallGroup = append(firewallGroup, f)
}
return firewallGroup, nil
}
// Get will return a firewall group based on provided groupID from your Vultr account
func (f *FireWallGroupServiceHandler) Get(ctx context.Context, groupID string) (*FirewallGroup, error) {
uri := "/v1/firewall/group_list"
req, err := f.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("FIREWALLGROUPID", groupID)
req.URL.RawQuery = q.Encode()
var firewallGroupMap map[string]FirewallGroup
err = f.client.DoWithContext(ctx, req, &firewallGroupMap)
if err != nil {
return nil, err
}
firewallGroup := new(FirewallGroup)
for _, f := range firewallGroupMap {
firewallGroup = &f
}
return firewallGroup, nil
}
// ChangeDescription will change the description of a firewall group
func (f *FireWallGroupServiceHandler) ChangeDescription(ctx context.Context, groupID, description string) error {
uri := "/v1/firewall/group_set_description"
values := url.Values{
"FIREWALLGROUPID": {groupID},
"description": {description},
}
req, err := f.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = f.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

265
vendor/github.com/vultr/govultr/firewall_rule.go generated vendored Normal file
View File

@ -0,0 +1,265 @@
package govultr
import (
"context"
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"net/url"
"strconv"
)
// FireWallRuleService is the interface to interact with the firewall rule endpoints on the Vultr API
// Link: https://www.vultr.com/api/#firewall
type FireWallRuleService interface {
Create(ctx context.Context, groupID, protocol, port, network, notes string) (*FirewallRule, error)
Delete(ctx context.Context, groupID, ruleID string) error
ListByIPType(ctx context.Context, groupID, ipType string) ([]FirewallRule, error)
List(ctx context.Context, groupID string) ([]FirewallRule, error)
}
// FireWallRuleServiceHandler handles interaction with the firewall rule methods for the Vultr API
type FireWallRuleServiceHandler struct {
client *Client
}
// FirewallRule represents a Vultr firewall rule
type FirewallRule struct {
RuleNumber int `json:"rulenumber"`
Action string `json:"action"`
Protocol string `json:"protocol"`
Port string `json:"port"`
Network *net.IPNet `json:"network"`
Notes string `json:"notes"`
}
// UnmarshalJSON implements a custom unmarshaler on FirewallRule
// This is done to help reduce data inconsistency with V1 of the Vultr API
// It also merges the subnet & subnet_mask into a single type of *net.IPNet
func (f *FirewallRule) UnmarshalJSON(data []byte) (err error) {
if f == nil {
*f = FirewallRule{}
}
// Pull out all of the data that was given to us and put it into a map
var fields map[string]interface{}
err = json.Unmarshal(data, &fields)
if err != nil {
return err
}
// Unmarshal RuleNumber
value := fmt.Sprintf("%v", fields["rulenumber"])
number, _ := strconv.Atoi(value)
f.RuleNumber = number
// Unmarshal all other strings
action := fmt.Sprintf("%v", fields["action"])
if action == "<nil>" {
action = ""
}
f.Action = action
protocol := fmt.Sprintf("%v", fields["protocol"])
if protocol == "<nil>" {
protocol = ""
}
f.Protocol = protocol
port := fmt.Sprintf("%v", fields["port"])
if port == "<nil>" {
port = ""
}
f.Port = port
notes := fmt.Sprintf("%v", fields["notes"])
if notes == "<nil>" {
notes = ""
}
f.Notes = notes
// Unmarshal subnet_size & subnet and convert to *net.IP
value = fmt.Sprintf("%v", fields["subnet_size"])
if len(value) == 0 || value == "<nil>" {
value = "0"
}
subnetSize, _ := strconv.Atoi(value)
subnet := fmt.Sprintf("%v", fields["subnet"])
if subnet == "<nil>" {
subnet = ""
}
if len(subnet) > 0 {
_, ipNet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", subnet, subnetSize))
if err != nil {
return errors.New("an issue has occurred while parsing subnet")
}
f.Network = ipNet
}
return
}
// Create will create a rule in a firewall group.
func (f *FireWallRuleServiceHandler) Create(ctx context.Context, groupID, protocol, port, cdirBlock, notes string) (*FirewallRule, error) {
uri := "/v1/firewall/rule_create"
ip, ipNet, err := net.ParseCIDR(cdirBlock)
if err != nil {
return nil, err
}
values := url.Values{
"FIREWALLGROUPID": {groupID},
"direction": {"in"},
"protocol": {protocol},
"subnet": {ip.String()},
}
// mask
mask, _ := ipNet.Mask.Size()
values.Add("subnet_size", strconv.Itoa(mask))
// ip Type
if ipNet.IP.To4() != nil {
values.Add("ip_type", "v4")
} else {
values.Add("ip_type", "v6")
}
// Optional params
if port != "" {
values.Add("port", port)
}
if notes != "" {
values.Add("notes", notes)
}
req, err := f.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
firewallRule := new(FirewallRule)
err = f.client.DoWithContext(ctx, req, firewallRule)
if err != nil {
return nil, err
}
return firewallRule, nil
}
// Delete will delete a firewall rule on your Vultr account
func (f *FireWallRuleServiceHandler) Delete(ctx context.Context, groupID, ruleID string) error {
uri := "/v1/firewall/rule_delete"
values := url.Values{
"FIREWALLGROUPID": {groupID},
"rulenumber": {ruleID},
}
req, err := f.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = f.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will list the current firewall rules in a firewall group.
// ipType values that can be passed in are "v4", "v6"
func (f *FireWallRuleServiceHandler) ListByIPType(ctx context.Context, groupID, ipType string) ([]FirewallRule, error) {
uri := "/v1/firewall/rule_list"
req, err := f.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("FIREWALLGROUPID", groupID)
q.Add("direction", "in")
q.Add("ip_type", ipType)
req.URL.RawQuery = q.Encode()
var firewallRuleMap map[string]FirewallRule
err = f.client.DoWithContext(ctx, req, &firewallRuleMap)
if err != nil {
return nil, err
}
var firewallRule []FirewallRule
for _, f := range firewallRuleMap {
firewallRule = append(firewallRule, f)
}
return firewallRule, nil
}
// List will return both ipv4 an ipv6 firewall rules that are defined within a firewall group
func (f *FireWallRuleServiceHandler) List(ctx context.Context, groupID string) ([]FirewallRule, error) {
uri := "/v1/firewall/rule_list"
req, err := f.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("FIREWALLGROUPID", groupID)
q.Add("direction", "in")
q.Add("ip_type", "v4")
req.URL.RawQuery = q.Encode()
var firewallRuleMap map[string]FirewallRule
// V4 call
err = f.client.DoWithContext(ctx, req, &firewallRuleMap)
if err != nil {
return nil, err
}
// V6 call
q.Del("ip_type")
q.Add("ip_type", "v6")
req.URL.RawQuery = q.Encode()
err = f.client.DoWithContext(ctx, req, &firewallRuleMap)
if err != nil {
return nil, err
}
var firewallRule []FirewallRule
for _, f := range firewallRuleMap {
firewallRule = append(firewallRule, f)
}
return firewallRule, nil
}

3
vendor/github.com/vultr/govultr/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/vultr/govultr
go 1.12

222
vendor/github.com/vultr/govultr/govultr.go generated vendored Normal file
View File

@ -0,0 +1,222 @@
package govultr
import (
"context"
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
const (
version = "0.1.3"
defaultBase = "https://api.vultr.com"
userAgent = "govultr/" + version
rateLimit = 600 * time.Millisecond
)
// APIKey contains a users API Key for interacting with the API
type APIKey struct {
// API Key
key string
}
// Client manages interaction with the Vultr V1 API
type Client struct {
// Http Client used to interact with the Vultr V1 API
client *http.Client
// BASE URL for APIs
BaseURL *url.URL
// User Agent for the client
UserAgent string
// API Key
APIKey APIKey
// API Rate Limit - Vultr rate limits based on time
RateLimit time.Duration
// Services used to interact with the API
Account AccountService
API APIService
Application ApplicationService
Backup BackupService
BareMetalServer BareMetalServerService
BlockStorage BlockStorageService
DNSDomain DNSDomainService
DNSRecord DNSRecordService
FirewallGroup FirewallGroupService
FirewallRule FireWallRuleService
ISO ISOService
Network NetworkService
OS OSService
Plan PlanService
Region RegionService
ReservedIP ReservedIPService
Server ServerService
Snapshot SnapshotService
SSHKey SSHKeyService
StartupScript StartupScriptService
User UserService
// Optional function called after every successful request made to the Vultr API
onRequestCompleted RequestCompletionCallback
}
// RequestCompletionCallback defines the type of the request callback function
type RequestCompletionCallback func(*http.Request, *http.Response)
// NewClient returns a Vultr API Client
func NewClient(httpClient *http.Client, key string) *Client {
if httpClient == nil {
httpClient = http.DefaultClient
}
baseURL, _ := url.Parse(defaultBase)
client := &Client{
client: httpClient,
BaseURL: baseURL,
UserAgent: userAgent,
RateLimit: rateLimit,
}
client.Account = &AccountServiceHandler{client}
client.API = &APIServiceHandler{client}
client.Application = &ApplicationServiceHandler{client}
client.Backup = &BackupServiceHandler{client}
client.BareMetalServer = &BareMetalServerServiceHandler{client}
client.BlockStorage = &BlockStorageServiceHandler{client}
client.DNSDomain = &DNSDomainServiceHandler{client}
client.DNSRecord = &DNSRecordsServiceHandler{client}
client.FirewallGroup = &FireWallGroupServiceHandler{client}
client.FirewallRule = &FireWallRuleServiceHandler{client}
client.ISO = &ISOServiceHandler{client}
client.Network = &NetworkServiceHandler{client}
client.OS = &OSServiceHandler{client}
client.Plan = &PlanServiceHandler{client}
client.Region = &RegionServiceHandler{client}
client.Server = &ServerServiceHandler{client}
client.ReservedIP = &ReservedIPServiceHandler{client}
client.Snapshot = &SnapshotServiceHandler{client}
client.SSHKey = &SSHKeyServiceHandler{client}
client.StartupScript = &StartupScriptServiceHandler{client}
client.User = &UserServiceHandler{client}
apiKey := APIKey{key: key}
client.APIKey = apiKey
return client
}
// NewRequest creates an API Request
func (c *Client) NewRequest(ctx context.Context, method, uri string, body url.Values) (*http.Request, error) {
path, err := url.Parse(uri)
resolvedURL := c.BaseURL.ResolveReference(path)
if err != nil {
return nil, err
}
var reqBody io.Reader
if body != nil {
reqBody = strings.NewReader(body.Encode())
} else {
reqBody = nil
}
req, err := http.NewRequest(method, resolvedURL.String(), reqBody)
if err != nil {
return nil, err
}
req.Header.Add("API-key", c.APIKey.key)
req.Header.Add("User-Agent", c.UserAgent)
req.Header.Add("Accept", "application/json")
if req.Method == "POST" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
return req, nil
}
// DoWithContext sends an API Request and returns back the response. The API response is checked to see if it was
// a successful call. A successful call is then checked to see if we need to unmarshal since some resources
// have their own implements of unmarshal.
func (c *Client) DoWithContext(ctx context.Context, r *http.Request, data interface{}) error {
// Sleep this call
time.Sleep(c.RateLimit)
req := r.WithContext(ctx)
res, err := c.client.Do(req)
if c.onRequestCompleted != nil {
c.onRequestCompleted(req, res)
}
if err != nil {
return err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if res.StatusCode == http.StatusOK {
if data != nil {
if string(body) == "[]" {
data = nil
} else {
if err := json.Unmarshal(body, data); err != nil {
return err
}
}
}
return nil
}
return errors.New(string(body))
}
// SetBaseURL Overrides the default BaseUrl
func (c *Client) SetBaseURL(baseURL string) error {
updatedURL, err := url.Parse(baseURL)
if err != nil {
return err
}
c.BaseURL = updatedURL
return nil
}
// SetRateLimit Overrides the default rateLimit
func (c *Client) SetRateLimit(time time.Duration) {
c.RateLimit = time
}
// SetUserAgent Overrides the default UserAgent
func (c *Client) SetUserAgent(ua string) {
c.UserAgent = ua
}
// OnRequestCompleted sets the API request completion callback
func (c *Client) OnRequestCompleted(rc RequestCompletionCallback) {
c.onRequestCompleted = rc
}

142
vendor/github.com/vultr/govultr/iso.go generated vendored Normal file
View File

@ -0,0 +1,142 @@
package govultr
import (
"context"
"net/http"
"net/url"
"strconv"
)
// ISOService is the interface to interact with the ISO endpoints on the Vultr API
// Link: https://www.vultr.com/api/#ISO
type ISOService interface {
CreateFromURL(ctx context.Context, ISOURL string) (*ISO, error)
Delete(ctx context.Context, ISOID int) error
List(ctx context.Context) ([]ISO, error)
GetPublicList(ctx context.Context) ([]PublicISO, error)
}
// ISOServiceHandler handles interaction with the ISO methods for the Vultr API
type ISOServiceHandler struct {
Client *Client
}
// ISO represents ISOs currently available on this account.
type ISO struct {
ISOID int `json:"ISOID"`
DateCreated string `json:"date_created"`
FileName string `json:"filename"`
Size int `json:"size"`
MD5Sum string `json:"md5sum"`
SHA512Sum string `json:"sha512sum"`
Status string `json:"status"`
}
// PublicISO represents public ISOs offered in the Vultr ISO library.
type PublicISO struct {
ISOID int `json:"ISOID"`
Name string `json:"name"`
Description string `json:"description"`
}
// CreateFromURL will create a new ISO image on your account
func (i *ISOServiceHandler) CreateFromURL(ctx context.Context, ISOURL string) (*ISO, error) {
uri := "/v1/iso/create_from_url"
values := url.Values{
"url": {ISOURL},
}
req, err := i.Client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
iso := new(ISO)
err = i.Client.DoWithContext(ctx, req, iso)
if err != nil {
return nil, err
}
return iso, nil
}
// Delete will delete an ISO image from your account
func (i *ISOServiceHandler) Delete(ctx context.Context, isoID int) error {
uri := "/v1/iso/destroy"
values := url.Values{
"ISOID": {strconv.Itoa(isoID)},
}
req, err := i.Client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = i.Client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will list all ISOs currently available on your account
func (i *ISOServiceHandler) List(ctx context.Context) ([]ISO, error) {
uri := "/v1/iso/list"
req, err := i.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var ISOMap map[string]ISO
err = i.Client.DoWithContext(ctx, req, &ISOMap)
if err != nil {
return nil, err
}
var iso []ISO
for _, i := range ISOMap {
iso = append(iso, i)
}
return iso, nil
}
// GetPublicList will list public ISOs offered in the Vultr ISO library.
func (i *ISOServiceHandler) GetPublicList(ctx context.Context) ([]PublicISO, error) {
uri := "/v1/iso/list_public"
req, err := i.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var ISOMap map[string]PublicISO
err = i.Client.DoWithContext(ctx, req, &ISOMap)
if err != nil {
return nil, err
}
var publicISO []PublicISO
for _, p := range ISOMap {
publicISO = append(publicISO, p)
}
return publicISO, nil
}

120
vendor/github.com/vultr/govultr/network.go generated vendored Normal file
View File

@ -0,0 +1,120 @@
package govultr
import (
"context"
"net"
"net/http"
"net/url"
"strconv"
)
// NetworkService is the interface to interact with the network endpoints on the Vultr API
// Link: https://www.vultr.com/api/#network
type NetworkService interface {
Create(ctx context.Context, regionID, description, cidrBlock string) (*Network, error)
Delete(ctx context.Context, networkID string) error
List(ctx context.Context) ([]Network, error)
}
// NetworkServiceHandler handles interaction with the network methods for the Vultr API
type NetworkServiceHandler struct {
client *Client
}
// Network represents a Vultr private network
type Network struct {
NetworkID string `json:"NETWORKID"`
RegionID string `json:"DCID"`
Description string `json:"description"`
V4Subnet string `json:"v4_subnet"`
V4SubnetMask int `json:"v4_subnet_mask"`
DateCreated string `json:"date_created"`
}
// Create a new private network. A private network can only be used at the location for which it was created.
func (n *NetworkServiceHandler) Create(ctx context.Context, regionID, description, cidrBlock string) (*Network, error) {
uri := "/v1/network/create"
values := url.Values{
"DCID": {regionID},
}
// Optional
if cidrBlock != "" {
_, ipNet, err := net.ParseCIDR(cidrBlock)
if err != nil {
return nil, err
}
if v4Subnet := ipNet.IP.To4(); v4Subnet != nil {
values.Add("v4_subnet", v4Subnet.String())
}
mask, _ := ipNet.Mask.Size()
values.Add("v4_subnet_mask", strconv.Itoa(mask))
}
if description != "" {
values.Add("description", description)
}
req, err := n.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
network := new(Network)
err = n.client.DoWithContext(ctx, req, network)
if err != nil {
return nil, err
}
return network, nil
}
// Delete a private network. Before deleting, a network must be disabled from all instances. See https://www.vultr.com/api/#server_private_network_disable
func (n *NetworkServiceHandler) Delete(ctx context.Context, networkID string) error {
uri := "/v1/network/destroy"
values := url.Values{
"NETWORKID": {networkID},
}
req, err := n.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = n.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List lists all private networks on the current account
func (n *NetworkServiceHandler) List(ctx context.Context) ([]Network, error) {
uri := "/v1/network/list"
req, err := n.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var networkMap map[string]Network
err = n.client.DoWithContext(ctx, req, &networkMap)
if err != nil {
return nil, err
}
var networks []Network
for _, network := range networkMap {
networks = append(networks, network)
}
return networks, nil
}

84
vendor/github.com/vultr/govultr/os.go generated vendored Normal file
View File

@ -0,0 +1,84 @@
package govultr
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strconv"
)
// OSService is the interface to interact with the operating system endpoint on the Vultr API
// Link: https://www.vultr.com/api/#os
type OSService interface {
List(ctx context.Context) ([]OS, error)
}
// OSServiceHandler handles interaction with the operating system methods for the Vultr API
type OSServiceHandler struct {
client *Client
}
// OS represents a Vultr operating system
type OS struct {
OsID int `json:"OSID"`
Name string `json:"name"`
Arch string `json:"arch"`
Family string `json:"family"`
Windows bool `json:"windows"`
}
// UnmarshalJSON implements json.Unmarshaller on OS to handle the inconsistent types returned from the Vultr API.
func (o *OS) UnmarshalJSON(data []byte) (err error) {
if o == nil {
*o = OS{}
}
var v map[string]interface{}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
i, err := strconv.Atoi(fmt.Sprintf("%v", v["OSID"]))
if err != nil {
return err
}
o.OsID = i
value := fmt.Sprintf("%v", v["windows"])
o.Windows = false
if value == "true" {
o.Windows = true
}
o.Name = fmt.Sprintf("%v", v["name"])
o.Arch = fmt.Sprintf("%v", v["arch"])
o.Family = fmt.Sprintf("%v", v["family"])
return nil
}
// List retrieves a list of available operating systems.
// If the Windows flag is true, a Windows license will be included with the instance, which will increase the cost.
func (o *OSServiceHandler) List(ctx context.Context) ([]OS, error) {
uri := "/v1/os/list"
req, err := o.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
osMap := make(map[string]OS)
err = o.client.DoWithContext(ctx, req, &osMap)
if err != nil {
return nil, err
}
var oses []OS
for _, os := range osMap {
oses = append(oses, os)
}
return oses, nil
}

199
vendor/github.com/vultr/govultr/plans.go generated vendored Normal file
View File

@ -0,0 +1,199 @@
package govultr
import (
"context"
"net/http"
)
// PlanService is the interface to interact with the Plans endpoints on the Vultr API
// Link: https://www.vultr.com/api/#plans
type PlanService interface {
List(ctx context.Context, planType string) ([]Plan, error)
GetBareMetalList(ctx context.Context) ([]BareMetalPlan, error)
GetVc2List(ctx context.Context) ([]VCPlan, error)
GetVdc2List(ctx context.Context) ([]VCPlan, error)
GetVc2zList(ctx context.Context) ([]VCPlan, error)
}
// PlanServiceHandler handles interaction with the Plans methods for the Vultr API
type PlanServiceHandler struct {
Client *Client
}
// Plan represents available Plans that Vultr offers
type Plan struct {
PlanID int `json:"VPSPLANID,string"`
Name string `json:"name"`
VCPUs int `json:"vcpu_count,string"`
RAM string `json:"ram"`
Disk string `json:"disk"`
Bandwidth string `json:"bandwidth"`
BandwidthGB string `json:"bandwidth_gb"`
Price string `json:"price_per_month"`
Windows bool `json:"windows"`
PlanType string `json:"plan_type"`
Regions []int `json:"available_locations"`
Deprecated bool `json:"deprecated"`
}
// BareMetalPlan represents bare metal plans
type BareMetalPlan struct {
PlanID string `json:"METALPLANID"`
Name string `json:"name"`
CPUs int `json:"cpu_count"`
CPUModel string `json:"cpu_model"`
RAM int `json:"ram"`
Disk string `json:"disk"`
BandwidthTB int `json:"bandwidth_tb"`
Price int `json:"price_per_month"`
PlanType string `json:"plan_type"`
Deprecated bool `json:"deprecated"`
Regions []int `json:"available_locations"`
}
// VCPlan represents either a vdc2 or a vc2 plan
type VCPlan struct {
PlanID string `json:"VPSPLANID"`
Name string `json:"name"`
VCPUs string `json:"vcpu_count"`
RAM string `json:"ram"`
Disk string `json:"disk"`
Bandwidth string `json:"bandwidth"`
BandwidthGB string `json:"bandwidth_gb"`
Price string `json:"price_per_month"`
PlanType string `json:"plan_type"`
}
// List retrieves a list of all active plans.
// planType is optional - pass an empty string to get all plans
func (p *PlanServiceHandler) List(ctx context.Context, planType string) ([]Plan, error) {
uri := "/v1/plans/list"
req, err := p.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
if planType != "" {
q := req.URL.Query()
q.Add("type", planType)
req.URL.RawQuery = q.Encode()
}
var planMap map[string]Plan
err = p.Client.DoWithContext(ctx, req, &planMap)
if err != nil {
return nil, err
}
var plans []Plan
for _, p := range planMap {
plans = append(plans, p)
}
return plans, nil
}
// GetBareMetalList retrieves a list of all active bare metal plans.
func (p *PlanServiceHandler) GetBareMetalList(ctx context.Context) ([]BareMetalPlan, error) {
uri := "/v1/plans/list_baremetal"
req, err := p.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var bareMetalMap map[string]BareMetalPlan
err = p.Client.DoWithContext(ctx, req, &bareMetalMap)
if err != nil {
return nil, err
}
var bareMetalPlan []BareMetalPlan
for _, b := range bareMetalMap {
bareMetalPlan = append(bareMetalPlan, b)
}
return bareMetalPlan, nil
}
// GetVc2List retrieve a list of all active vc2 plans.
func (p *PlanServiceHandler) GetVc2List(ctx context.Context) ([]VCPlan, error) {
uri := "/v1/plans/list_vc2"
req, err := p.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var vc2Plan map[string]VCPlan
err = p.Client.DoWithContext(ctx, req, &vc2Plan)
if err != nil {
return nil, err
}
var vc2 []VCPlan
for _, p := range vc2Plan {
vc2 = append(vc2, p)
}
return vc2, nil
}
// GetVdc2List Retrieve a list of all active vdc2 plans
func (p *PlanServiceHandler) GetVdc2List(ctx context.Context) ([]VCPlan, error) {
uri := "/v1/plans/list_vdc2"
req, err := p.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var vdc2Map map[string]VCPlan
err = p.Client.DoWithContext(ctx, req, &vdc2Map)
if err != nil {
return nil, err
}
var vdc2 []VCPlan
for _, p := range vdc2Map {
vdc2 = append(vdc2, p)
}
return vdc2, nil
}
// GetVc2zList Retrieve a list of all active vc2z plans (high frequency)
func (p *PlanServiceHandler) GetVc2zList(ctx context.Context) ([]VCPlan, error) {
uri := "/v1/plans/list_vc2z"
req, err := p.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var vc2zMap map[string]VCPlan
err = p.Client.DoWithContext(ctx, req, &vc2zMap)
if err != nil {
return nil, err
}
var vc2z []VCPlan
for _, p := range vc2zMap {
vc2z = append(vc2z, p)
}
return vc2z, nil
}

154
vendor/github.com/vultr/govultr/regions.go generated vendored Normal file
View File

@ -0,0 +1,154 @@
package govultr
import (
"context"
"net/http"
"strconv"
)
// RegionService is the interface to interact with Region endpoints on the Vultr API
// Link: https://www.vultr.com/api/#regions
type RegionService interface {
Availability(ctx context.Context, regionID int, planType string) ([]int, error)
BareMetalAvailability(ctx context.Context, regionID int) ([]int, error)
Vc2Availability(ctx context.Context, regionID int) ([]int, error)
Vdc2Availability(ctx context.Context, regionID int) ([]int, error)
List(ctx context.Context) ([]Region, error)
}
// RegionServiceHandler handles interaction with the region methods for the Vultr API
type RegionServiceHandler struct {
Client *Client
}
// Region represents a Vultr region
type Region struct {
RegionID string `json:"DCID"`
Name string `json:"name"`
Country string `json:"country"`
Continent string `json:"continent"`
State string `json:"state"`
Ddos bool `json:"ddos_protection"`
BlockStorage bool `json:"block_storage"`
RegionCode string `json:"regioncode"`
}
// Availability retrieves a list of the VPSPLANIDs currently available for a given location.
func (r *RegionServiceHandler) Availability(ctx context.Context, regionID int, planType string) ([]int, error) {
uri := "/v1/regions/availability"
req, err := r.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("DCID", strconv.Itoa(regionID))
// Optional planType filter
if planType != "" {
q.Add("type", planType)
}
req.URL.RawQuery = q.Encode()
var regions []int
err = r.Client.DoWithContext(ctx, req, &regions)
if err != nil {
return nil, err
}
return regions, nil
}
// BareMetalAvailability retrieve a list of the METALPLANIDs currently available for a given location.
func (r *RegionServiceHandler) BareMetalAvailability(ctx context.Context, regionID int) ([]int, error) {
uri := "/v1/regions/availability_baremetal"
regions, err := r.instanceAvailability(ctx, uri, regionID)
if err != nil {
return nil, err
}
return regions, nil
}
// Vc2Availability retrieve a list of the vc2 VPSPLANIDs currently available for a given location.
func (r *RegionServiceHandler) Vc2Availability(ctx context.Context, regionID int) ([]int, error) {
uri := "/v1/regions/availability_vc2"
regions, err := r.instanceAvailability(ctx, uri, regionID)
if err != nil {
return nil, err
}
return regions, nil
}
// Vdc2Availability retrieves a list of the vdc2 VPSPLANIDs currently available for a given location.
func (r *RegionServiceHandler) Vdc2Availability(ctx context.Context, regionID int) ([]int, error) {
uri := "/v1/regions/availability_vdc2"
regions, err := r.instanceAvailability(ctx, uri, regionID)
if err != nil {
return nil, err
}
return regions, nil
}
// List retrieves a list of all active regions
func (r *RegionServiceHandler) List(ctx context.Context) ([]Region, error) {
uri := "/v1/regions/list"
req, err := r.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var regionsMap map[string]Region
err = r.Client.DoWithContext(ctx, req, &regionsMap)
if err != nil {
return nil, err
}
var region []Region
for _, r := range regionsMap {
region = append(region, r)
}
return region, nil
}
// instanceAvailability keeps the similar calls dry
func (r *RegionServiceHandler) instanceAvailability(ctx context.Context, uri string, regionID int) ([]int, error) {
req, err := r.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
q.Add("DCID", strconv.Itoa(regionID))
req.URL.RawQuery = q.Encode()
var regions []int
err = r.Client.DoWithContext(ctx, req, &regions)
if err != nil {
return nil, err
}
return regions, nil
}

273
vendor/github.com/vultr/govultr/reserved_ip.go generated vendored Normal file
View File

@ -0,0 +1,273 @@
package govultr
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
)
// ReservedIPService is the interface to interact with the reserved IP endpoints on the Vultr API
// Link: https://www.vultr.com/api/#reservedip
type ReservedIPService interface {
Attach(ctx context.Context, ip, InstanceID string) error
Convert(ctx context.Context, ip, InstanceID, label string) (*ReservedIP, error)
Create(ctx context.Context, regionID int, ipType, label string) (*ReservedIP, error)
Delete(ctx context.Context, ip string) error
Detach(ctx context.Context, ip, InstanceID string) error
List(ctx context.Context) ([]ReservedIP, error)
}
// ReservedIPServiceHandler handles interaction with the reserved IP methods for the Vultr API
type ReservedIPServiceHandler struct {
client *Client
}
// ReservedIP represents an reserved IP on Vultr
type ReservedIP struct {
ReservedIPID string `json:"SUBID"`
RegionID int `json:"DCID"`
IPType string `json:"ip_type"`
Subnet string `json:"subnet"`
SubnetSize int `json:"subnet_size"`
Label string `json:"label"`
AttachedID string `json:"attached_SUBID"`
}
// UnmarshalJSON implements json.Unmarshaller on ReservedIP to handle the inconsistent types returned from the Vultr API.
func (r *ReservedIP) UnmarshalJSON(data []byte) (err error) {
if r == nil {
*r = ReservedIP{}
}
var v map[string]interface{}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
r.ReservedIPID, err = r.unmarshalStr(fmt.Sprintf("%v", v["SUBID"]))
if err != nil {
return err
}
r.AttachedID, err = r.unmarshalStr(fmt.Sprintf("%v", v["attached_SUBID"]))
if err != nil {
return err
}
r.RegionID, err = r.unmarshalInt(fmt.Sprintf("%v", v["DCID"]))
if err != nil {
return err
}
r.SubnetSize, err = r.unmarshalInt(fmt.Sprintf("%v", v["subnet_size"]))
if err != nil {
return err
}
if r.Subnet = fmt.Sprintf("%v", v["subnet"]); r.Subnet == "<nil>" {
r.Subnet = ""
}
if r.IPType = fmt.Sprintf("%v", v["ip_type"]); r.IPType == "<nil>" {
r.IPType = ""
}
if r.Label = fmt.Sprintf("%v", v["label"]); r.Label == "<nil>" {
r.Label = ""
}
return nil
}
func (r *ReservedIP) unmarshalInt(value string) (int, error) {
if len(value) == 0 || value == "<nil>" {
value = "0"
}
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0, err
}
return int(i), nil
}
func (r *ReservedIP) unmarshalStr(value string) (string, error) {
if len(value) == 0 || value == "<nil>" || value == "0" || value == "false" {
return "", nil
}
f, err := strconv.ParseFloat(value, 64)
if err != nil {
return "", err
}
return strconv.FormatFloat(f, 'f', -1, 64), nil
}
// Attach a reserved IP to an existing subscription
func (r *ReservedIPServiceHandler) Attach(ctx context.Context, ip, InstanceID string) error {
uri := "/v1/reservedip/attach"
values := url.Values{
"ip_address": {ip},
"attach_SUBID": {InstanceID},
}
req, err := r.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = r.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Convert an existing IP on a subscription to a reserved IP.
func (r *ReservedIPServiceHandler) Convert(ctx context.Context, ip, InstanceID, label string) (*ReservedIP, error) {
uri := "/v1/reservedip/convert"
values := url.Values{
"SUBID": {InstanceID},
"ip_address": {ip},
}
if label != "" {
values.Add("label", label)
}
req, err := r.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
rip := new(ReservedIP)
err = r.client.DoWithContext(ctx, req, rip)
if err != nil {
return nil, err
}
rip.Label = label
return rip, nil
}
// Create adds the specified reserved IP to your Vultr account
func (r *ReservedIPServiceHandler) Create(ctx context.Context, regionID int, ipType, label string) (*ReservedIP, error) {
uri := "/v1/reservedip/create"
values := url.Values{
"DCID": {strconv.Itoa(regionID)},
"ip_type": {ipType},
}
if label != "" {
values.Add("label", label)
}
req, err := r.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
rip := new(ReservedIP)
err = r.client.DoWithContext(ctx, req, rip)
if err != nil {
return nil, err
}
rip.RegionID = regionID
rip.IPType = ipType
rip.Label = label
return rip, nil
}
// Delete removes the specified reserved IP from your Vultr account
func (r *ReservedIPServiceHandler) Delete(ctx context.Context, ip string) error {
uri := "/v1/reservedip/destroy"
values := url.Values{
"ip_address": {ip},
}
req, err := r.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = r.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// Detach a reserved IP from an existing subscription.
func (r *ReservedIPServiceHandler) Detach(ctx context.Context, ip, InstanceID string) error {
uri := "/v1/reservedip/detach"
values := url.Values{
"ip_address": {ip},
"detach_SUBID": {InstanceID},
}
req, err := r.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = r.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List lists all the reserved IPs associated with your Vultr account
func (r *ReservedIPServiceHandler) List(ctx context.Context) ([]ReservedIP, error) {
uri := "/v1/reservedip/list"
req, err := r.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
ipMap := make(map[string]ReservedIP)
err = r.client.DoWithContext(ctx, req, &ipMap)
if err != nil {
return nil, err
}
var ips []ReservedIP
for _, ip := range ipMap {
ips = append(ips, ip)
}
return ips, nil
}

1469
vendor/github.com/vultr/govultr/server.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

168
vendor/github.com/vultr/govultr/snapshot.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
package govultr
import (
"context"
"net/http"
"net/url"
)
// SnapshotService is the interface to interact with Snapshot endpoints on the Vultr API
// Link: https://www.vultr.com/api/#snapshot
type SnapshotService interface {
Create(ctx context.Context, InstanceID, description string) (*Snapshot, error)
CreateFromURL(ctx context.Context, snapshotURL string) (*Snapshot, error)
Delete(ctx context.Context, snapshotID string) error
List(ctx context.Context) ([]Snapshot, error)
Get(ctx context.Context, snapshotID string) (*Snapshot, error)
}
// SnapshotServiceHandler handles interaction with the snapshot methods for the Vultr API
type SnapshotServiceHandler struct {
Client *Client
}
// Snapshot represents a Vultr snapshot
type Snapshot struct {
SnapshotID string `json:"SNAPSHOTID"`
DateCreated string `json:"date_created"`
Description string `json:"description"`
Size string `json:"size"`
Status string `json:"status"`
OsID string `json:"OSID"`
AppID string `json:"APPID"`
}
// Snapshots represent a collection of snapshots
type Snapshots []Snapshot
// Create makes a snapshot of a provided server
func (s *SnapshotServiceHandler) Create(ctx context.Context, InstanceID, description string) (*Snapshot, error) {
uri := "/v1/snapshot/create"
values := url.Values{
"SUBID": {InstanceID},
"description": {description},
}
req, err := s.Client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
snapshot := new(Snapshot)
err = s.Client.DoWithContext(ctx, req, snapshot)
if err != nil {
return nil, err
}
snapshot.Description = description
return snapshot, nil
}
// CreateFromURL will create a snapshot based on an image iso from a URL you provide
func (s *SnapshotServiceHandler) CreateFromURL(ctx context.Context, snapshotURL string) (*Snapshot, error) {
uri := "/v1/snapshot/create_from_url"
values := url.Values{
"url": {snapshotURL},
}
req, err := s.Client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
snapshot := new(Snapshot)
err = s.Client.DoWithContext(ctx, req, snapshot)
if err != nil {
return nil, err
}
return snapshot, nil
}
// Delete a snapshot based on snapshotID
func (s *SnapshotServiceHandler) Delete(ctx context.Context, snapshotID string) error {
uri := "/v1/snapshot/destroy"
values := url.Values{
"SNAPSHOTID": {snapshotID},
}
req, err := s.Client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = s.Client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List of snapshots details
func (s *SnapshotServiceHandler) List(ctx context.Context) ([]Snapshot, error) {
uri := "/v1/snapshot/list"
req, err := s.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
snapshotMap := make(map[string]Snapshot)
err = s.Client.DoWithContext(ctx, req, &snapshotMap)
if err != nil {
return nil, err
}
var snapshots []Snapshot
for _, s := range snapshotMap {
snapshots = append(snapshots, s)
}
return snapshots, nil
}
// Get individual details of a snapshot based on snapshotID
func (s *SnapshotServiceHandler) Get(ctx context.Context, snapshotID string) (*Snapshot, error) {
uri := "/v1/snapshot/list"
req, err := s.Client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
if snapshotID != "" {
q := req.URL.Query()
q.Add("SNAPSHOTID", snapshotID)
req.URL.RawQuery = q.Encode()
}
snapshotMap := make(map[string]Snapshot)
err = s.Client.DoWithContext(ctx, req, &snapshotMap)
if err != nil {
return nil, err
}
snapshot := new(Snapshot)
for _, s := range snapshotMap {
snapshot = &s
}
return snapshot, nil
}

140
vendor/github.com/vultr/govultr/ssh_key.go generated vendored Normal file
View File

@ -0,0 +1,140 @@
package govultr
import (
"context"
"net/http"
"net/url"
)
// SSHKeyService is the interface to interact with the SSH Key endpoints on the Vultr API
// Link: https://www.vultr.com/api/#sshkey
type SSHKeyService interface {
Create(ctx context.Context, name, sshKey string) (*SSHKey, error)
Delete(ctx context.Context, sshKeyID string) error
List(ctx context.Context) ([]SSHKey, error)
Update(ctx context.Context, sshKey *SSHKey) error
}
// SSHKeyServiceHandler handles interaction with the SSH Key methods for the Vultr API
type SSHKeyServiceHandler struct {
client *Client
}
// SSHKey represents an SSH Key on Vultr
type SSHKey struct {
SSHKeyID string `json:"SSHKEYID"`
Name string `json:"name"`
Key string `json:"ssh_key"`
DateCreated string `json:"date_created"`
}
// Create will add the specified SSH Key to your Vultr account
func (s *SSHKeyServiceHandler) Create(ctx context.Context, name, sshKey string) (*SSHKey, error) {
uri := "/v1/sshkey/create"
values := url.Values{
"name": {name},
"ssh_key": {sshKey},
}
req, err := s.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
key := new(SSHKey)
err = s.client.DoWithContext(ctx, req, key)
if err != nil {
return nil, err
}
key.Name = name
key.Key = sshKey
return key, nil
}
// Delete will delete the specified SHH Key from your Vultr account
func (s *SSHKeyServiceHandler) Delete(ctx context.Context, sshKeyID string) error {
uri := "/v1/sshkey/destroy"
values := url.Values{
"SSHKEYID": {sshKeyID},
}
req, err := s.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = s.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will list all the SSH Keys associated with your Vultr account
func (s *SSHKeyServiceHandler) List(ctx context.Context) ([]SSHKey, error) {
uri := "/v1/sshkey/list"
req, err := s.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
sshKeysMap := make(map[string]SSHKey)
err = s.client.DoWithContext(ctx, req, &sshKeysMap)
if err != nil {
return nil, err
}
var sshKeys []SSHKey
for _, key := range sshKeysMap {
sshKeys = append(sshKeys, key)
}
return sshKeys, nil
}
// Update will update the given SSH Key. Empty strings will be ignored.
func (s *SSHKeyServiceHandler) Update(ctx context.Context, sshKey *SSHKey) error {
uri := "/v1/sshkey/update"
values := url.Values{
"SSHKEYID": {sshKey.SSHKeyID},
}
// Optional
if sshKey.Name != "" {
values.Add("name", sshKey.Name)
}
if sshKey.Key != "" {
values.Add("ssh_key", sshKey.Key)
}
req, err := s.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = s.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

172
vendor/github.com/vultr/govultr/startup_script.go generated vendored Normal file
View File

@ -0,0 +1,172 @@
package govultr
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
)
// StartupScriptService is the interface to interact with the startup script endpoints on the Vultr API
// Link: https://www.vultr.com/api/#startupscript
type StartupScriptService interface {
Create(ctx context.Context, name, script, scriptType string) (*StartupScript, error)
Delete(ctx context.Context, scriptID string) error
List(ctx context.Context) ([]StartupScript, error)
Update(ctx context.Context, script *StartupScript) error
}
// StartupScriptServiceHandler handles interaction with the startup script methods for the Vultr API
type StartupScriptServiceHandler struct {
client *Client
}
// StartupScript represents an startup script on Vultr
type StartupScript struct {
ScriptID string `json:"SCRIPTID"`
DateCreated string `json:"date_created"`
DateModified string `json:"date_modified"`
Name string `json:"name"`
Type string `json:"type"`
Script string `json:"script"`
}
// UnmarshalJSON implements json.Unmarshaller on StartupScript to handle the inconsistent types returned from the Vultr API.
func (s *StartupScript) UnmarshalJSON(data []byte) (err error) {
if s == nil {
*s = StartupScript{}
}
var v map[string]interface{}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
s.ScriptID = fmt.Sprintf("%v", v["SCRIPTID"])
s.DateCreated = fmt.Sprintf("%v", v["date_created"])
s.DateModified = fmt.Sprintf("%v", v["date_modified"])
s.Name = fmt.Sprintf("%v", v["name"])
s.Type = fmt.Sprintf("%v", v["type"])
s.Script = fmt.Sprintf("%v", v["script"])
return nil
}
// Create will add the specified startup script to your Vultr account
func (s *StartupScriptServiceHandler) Create(ctx context.Context, name, script, scriptType string) (*StartupScript, error) {
uri := "/v1/startupscript/create"
values := url.Values{
"name": {name},
"script": {script},
}
if scriptType != "" {
values.Add("type", scriptType)
}
req, err := s.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
ss := new(StartupScript)
err = s.client.DoWithContext(ctx, req, ss)
if err != nil {
return nil, err
}
ss.DateCreated = ""
ss.DateModified = ""
ss.Name = name
ss.Type = scriptType
ss.Script = script
return ss, nil
}
// Delete will delete the specified startup script from your Vultr account
func (s *StartupScriptServiceHandler) Delete(ctx context.Context, scriptID string) error {
uri := "/v1/startupscript/destroy"
values := url.Values{
"SCRIPTID": {scriptID},
}
req, err := s.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = s.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will list all the startup scripts associated with your Vultr account
func (s *StartupScriptServiceHandler) List(ctx context.Context) ([]StartupScript, error) {
uri := "/v1/startupscript/list"
req, err := s.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
scriptsMap := make(map[string]StartupScript)
err = s.client.DoWithContext(ctx, req, &scriptsMap)
if err != nil {
return nil, err
}
var scripts []StartupScript
for _, key := range scriptsMap {
scripts = append(scripts, key)
}
return scripts, nil
}
// Update will update the given startup script. Empty strings will be ignored.
func (s *StartupScriptServiceHandler) Update(ctx context.Context, script *StartupScript) error {
uri := "/v1/startupscript/update"
values := url.Values{
"SCRIPTID": {script.ScriptID},
}
// Optional
if script.Name != "" {
values.Add("name", script.Name)
}
if script.Script != "" {
values.Add("script", script.Script)
}
req, err := s.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = s.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}

157
vendor/github.com/vultr/govultr/user.go generated vendored Normal file
View File

@ -0,0 +1,157 @@
package govultr
import (
"context"
"net/http"
"net/url"
)
// UserService is the interface to interact with the user management endpoints on the Vultr API
// Link: https://www.vultr.com/api/#user
type UserService interface {
Create(ctx context.Context, email, name, password, apiEnabled string, acls []string) (*User, error)
Delete(ctx context.Context, userID string) error
List(ctx context.Context) ([]User, error)
Update(ctx context.Context, user *User) error
}
// UserServiceHandler handles interaction with the user methods for the Vultr API
type UserServiceHandler struct {
client *Client
}
// User represents an user on Vultr
type User struct {
UserID string `json:"USERID"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
APIEnabled string `json:"api_enabled"`
ACL []string `json:"acls"`
APIKey string `json:"api_key"`
}
// Create will add the specified user to your Vultr account
func (u *UserServiceHandler) Create(ctx context.Context, email, name, password, apiEnabled string, acls []string) (*User, error) {
uri := "/v1/user/create"
values := url.Values{
"email": {email},
"name": {name},
"password": {password},
"acls[]": acls,
}
if apiEnabled != "" {
values.Add("api_enabled", apiEnabled)
}
req, err := u.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return nil, err
}
user := new(User)
err = u.client.DoWithContext(ctx, req, user)
if err != nil {
return nil, err
}
user.Name = name
user.Email = email
user.APIEnabled = apiEnabled
user.ACL = acls
return user, nil
}
// Delete will remove the specified user from your Vultr account
func (u *UserServiceHandler) Delete(ctx context.Context, userID string) error {
uri := "/v1/user/delete"
values := url.Values{
"USERID": {userID},
}
req, err := u.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = u.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}
// List will list all the users associated with your Vultr account
func (u *UserServiceHandler) List(ctx context.Context) ([]User, error) {
uri := "/v1/user/list"
req, err := u.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
var users []User
err = u.client.DoWithContext(ctx, req, &users)
if err != nil {
return nil, err
}
return users, nil
}
// Update will update the given user. Empty strings will be ignored.
func (u *UserServiceHandler) Update(ctx context.Context, user *User) error {
uri := "/v1/user/update"
values := url.Values{
"USERID": {user.UserID},
}
// Optional
if user.Email != "" {
values.Add("email", user.Email)
}
if user.Name != "" {
values.Add("name", user.Name)
}
if user.Password != "" {
values.Add("password", user.Password)
}
if user.APIEnabled != "" {
values.Add("api_enabled", user.APIEnabled)
}
if len(user.ACL) > 0 {
for _, acl := range user.ACL {
values.Add("acls[]", acl)
}
}
req, err := u.client.NewRequest(ctx, http.MethodPost, uri, values)
if err != nil {
return err
}
err = u.client.DoWithContext(ctx, req, nil)
if err != nil {
return err
}
return nil
}