mirror of
https://github.com/go-acme/lego.git
synced 2024-12-25 11:02:56 +02:00
Switch Vultr to official client (#929)
This commit is contained in:
parent
0dbc28193b
commit
87be19588b
26
Gopkg.lock
generated
26
Gopkg.lock
generated
@ -55,14 +55,6 @@
|
||||
revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005"
|
||||
version = "v0.3.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:ed3fc9992df610d07c85c24e0b792268cc1ce226dd9bf8cb2e6ad9a377b35415"
|
||||
name = "github.com/JamesClonk/vultr"
|
||||
packages = ["lib"]
|
||||
pruneopts = "NUT"
|
||||
revision = "fa1c0367800db75e4d10d0ec90c49a8731670224"
|
||||
version = "1.15.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:a4068a93355ba3cff0a719425713123d23c90010cb4d023b40c679a22465736d"
|
||||
@ -367,14 +359,6 @@
|
||||
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
|
||||
version = "v1.1.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8b3234b10eacd5edea45bf0c13a585b608749da23f94aaf29b46d9ef8a8babf4"
|
||||
name = "github.com/juju/ratelimit"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||
version = "1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:ec142582cd3bb5cc29a2bc7181a6e67367b90b19f6a957ce506dcd7d1500bf95"
|
||||
@ -599,6 +583,14 @@
|
||||
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
||||
version = "v1.20.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b1d2c51a689eef501cb5726f8d9997c0ca4415cbfa7105fe6e64b1844eddf1fb"
|
||||
name = "github.com/vultr/govultr"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "ca447e056e08d93aa6e5b09e6ae3565dd1825281"
|
||||
version = "v0.1.4"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:58f2854b50ff8862eb6a347f20dedaac83e1166f4040472e17bc37736841a12f"
|
||||
name = "go.opencensus.io"
|
||||
@ -885,7 +877,6 @@
|
||||
"github.com/Azure/go-autorest/autorest/azure/auth",
|
||||
"github.com/Azure/go-autorest/autorest/to",
|
||||
"github.com/BurntSushi/toml",
|
||||
"github.com/JamesClonk/vultr/lib",
|
||||
"github.com/OpenDNS/vegadns2client",
|
||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1",
|
||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid",
|
||||
@ -934,6 +925,7 @@
|
||||
"github.com/transip/gotransip",
|
||||
"github.com/transip/gotransip/domain",
|
||||
"github.com/urfave/cli",
|
||||
"github.com/vultr/govultr",
|
||||
"golang.org/x/crypto/ocsp",
|
||||
"golang.org/x/net/context",
|
||||
"golang.org/x/net/idna",
|
||||
|
@ -132,3 +132,7 @@
|
||||
[[constraint]]
|
||||
name = "github.com/nrdcg/namesilo"
|
||||
version = "0.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/vultr/govultr"
|
||||
version = "0.1.4"
|
||||
|
@ -53,7 +53,7 @@ More information [here](/lego/dns/#configuration-and-credentials).
|
||||
## More information
|
||||
|
||||
- [API documentation](https://www.vultr.com/api/#dns)
|
||||
- [Go client](https://github.com/JamesClonk/vultr)
|
||||
- [Go client](https://github.com/vultr/govultr)
|
||||
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
<!-- providers/dns/vultr/vultr.toml -->
|
||||
|
@ -1,18 +1,20 @@
|
||||
// Package vultr implements a DNS provider for solving the DNS-01 challenge using the vultr DNS.
|
||||
// Package vultr implements a DNS provider for solving the DNS-01 challenge using the Vultr DNS.
|
||||
// See https://www.vultr.com/api/#dns
|
||||
package vultr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
vultr "github.com/JamesClonk/vultr/lib"
|
||||
"github.com/go-acme/lego/challenge/dns01"
|
||||
"github.com/go-acme/lego/platform/config/env"
|
||||
"github.com/vultr/govultr"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider
|
||||
@ -43,7 +45,7 @@ func NewDefaultConfig() *Config {
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
client *vultr.Client
|
||||
client *govultr.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance with a configured Vultr client.
|
||||
@ -70,10 +72,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
return nil, fmt.Errorf("vultr: credentials missing")
|
||||
}
|
||||
|
||||
options := &vultr.Options{
|
||||
HTTPClient: config.HTTPClient,
|
||||
}
|
||||
client := vultr.NewClient(config.APIKey, options)
|
||||
client := govultr.NewClient(config.HTTPClient, config.APIKey)
|
||||
|
||||
return &DNSProvider{client: client, config: config}, nil
|
||||
}
|
||||
@ -89,7 +88,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
|
||||
name := d.extractRecordName(fqdn, zoneDomain)
|
||||
|
||||
err = d.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, d.config.TTL)
|
||||
err = d.client.DNSRecord.Create(context.Background(), zoneDomain, name, "TXT", value, d.config.TTL, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("vultr: API call failed: %v", err)
|
||||
}
|
||||
@ -108,7 +107,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
|
||||
var allErr []string
|
||||
for _, rec := range records {
|
||||
err := d.client.DeleteDNSRecord(zoneDomain, rec.RecordID)
|
||||
err := d.client.DNSRecord.Delete(context.Background(), zoneDomain, strconv.Itoa(rec.RecordID))
|
||||
if err != nil {
|
||||
allErr = append(allErr, err.Error())
|
||||
}
|
||||
@ -128,12 +127,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||
domains, err := d.client.GetDNSDomains()
|
||||
domains, err := d.client.DNSDomain.List(context.Background())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("API call failed: %v", err)
|
||||
}
|
||||
|
||||
var hostedDomain vultr.DNSDomain
|
||||
var hostedDomain govultr.DNSDomain
|
||||
for _, dom := range domains {
|
||||
if strings.HasSuffix(domain, dom.Domain) {
|
||||
if len(dom.Domain) > len(hostedDomain.Domain) {
|
||||
@ -148,14 +147,14 @@ func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||
return hostedDomain.Domain, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) {
|
||||
func (d *DNSProvider) findTxtRecords(domain, fqdn string) (string, []govultr.DNSRecord, error) {
|
||||
zoneDomain, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
var records []vultr.DNSRecord
|
||||
result, err := d.client.GetDNSRecords(zoneDomain)
|
||||
var records []govultr.DNSRecord
|
||||
result, err := d.client.DNSRecord.List(context.Background(), zoneDomain)
|
||||
if err != nil {
|
||||
return "", records, fmt.Errorf("API call has failed: %v", err)
|
||||
}
|
||||
|
@ -17,4 +17,4 @@ Example = ''''''
|
||||
|
||||
[Links]
|
||||
API = "https://www.vultr.com/api/#dns"
|
||||
GoClient = "https://github.com/JamesClonk/vultr"
|
||||
GoClient = "https://github.com/vultr/govultr"
|
||||
|
71
vendor/github.com/JamesClonk/vultr/lib/account_info.go
generated
vendored
71
vendor/github.com/JamesClonk/vultr/lib/account_info.go
generated
vendored
@ -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
|
||||
}
|
38
vendor/github.com/JamesClonk/vultr/lib/applications.go
generated
vendored
38
vendor/github.com/JamesClonk/vultr/lib/applications.go
generated
vendored
@ -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
|
||||
}
|
210
vendor/github.com/JamesClonk/vultr/lib/block_storage.go
generated
vendored
210
vendor/github.com/JamesClonk/vultr/lib/block_storage.go
generated
vendored
@ -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
|
||||
}
|
258
vendor/github.com/JamesClonk/vultr/lib/client.go
generated
vendored
258
vendor/github.com/JamesClonk/vultr/lib/client.go
generated
vendored
@ -1,258 +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.15.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
|
||||
|
||||
// Optional function called after every successful request made to the API
|
||||
onRequestCompleted RequestCompletionCallback
|
||||
}
|
||||
|
||||
// RequestCompletionCallback defines the type of the request callback function
|
||||
type RequestCompletionCallback func(*http.Request, *http.Response)
|
||||
|
||||
// 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 (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)
|
||||
}
|
||||
|
||||
// OnRequestCompleted sets the API request completion callback
|
||||
func (c *Client) OnRequestCompleted(rc RequestCompletionCallback) {
|
||||
c.onRequestCompleted = rc
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(method string, path string, body io.Reader) (*http.Request, error) {
|
||||
relPath, err := url.Parse(path)
|
||||
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("API-Key", c.APIKey)
|
||||
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
|
||||
}
|
||||
|
||||
if c.onRequestCompleted != nil {
|
||||
c.onRequestCompleted(req, resp)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
150
vendor/github.com/JamesClonk/vultr/lib/dns.go
generated
vendored
150
vendor/github.com/JamesClonk/vultr/lib/dns.go
generated
vendored
@ -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
|
||||
}
|
252
vendor/github.com/JamesClonk/vultr/lib/firewall.go
generated
vendored
252
vendor/github.com/JamesClonk/vultr/lib/firewall.go
generated
vendored
@ -1,252 +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 subnet == "<nil>" {
|
||||
subnet = ""
|
||||
}
|
||||
|
||||
if 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 {
|
||||
// This case is used to create a valid default CIDR when the Vultr API does not return a subnet/subnet size at all, e.g. the response after creating a new rule.
|
||||
_, 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
|
||||
}
|
192
vendor/github.com/JamesClonk/vultr/lib/ip.go
generated
vendored
192
vendor/github.com/JamesClonk/vultr/lib/ip.go
generated
vendored
@ -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
|
||||
}
|
44
vendor/github.com/JamesClonk/vultr/lib/iso.go
generated
vendored
44
vendor/github.com/JamesClonk/vultr/lib/iso.go
generated
vendored
@ -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
|
||||
}
|
37
vendor/github.com/JamesClonk/vultr/lib/os.go
generated
vendored
37
vendor/github.com/JamesClonk/vultr/lib/os.go
generated
vendored
@ -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
|
||||
}
|
78
vendor/github.com/JamesClonk/vultr/lib/plans.go
generated
vendored
78
vendor/github.com/JamesClonk/vultr/lib/plans.go
generated
vendored
@ -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
|
||||
}
|
44
vendor/github.com/JamesClonk/vultr/lib/regions.go
generated
vendored
44
vendor/github.com/JamesClonk/vultr/lib/regions.go
generated
vendored
@ -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`, ®ionMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var regionList []Region
|
||||
for _, os := range regionMap {
|
||||
regionList = append(regionList, os)
|
||||
}
|
||||
sort.Sort(regions(regionList))
|
||||
return regionList, nil
|
||||
}
|
192
vendor/github.com/JamesClonk/vultr/lib/reservedip.go
generated
vendored
192
vendor/github.com/JamesClonk/vultr/lib/reservedip.go
generated
vendored
@ -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
|
||||
}
|
126
vendor/github.com/JamesClonk/vultr/lib/scripts.go
generated
vendored
126
vendor/github.com/JamesClonk/vultr/lib/scripts.go
generated
vendored
@ -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
|
||||
}
|
561
vendor/github.com/JamesClonk/vultr/lib/servers.go
generated
vendored
561
vendor/github.com/JamesClonk/vultr/lib/servers.go
generated
vendored
@ -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
|
||||
}
|
72
vendor/github.com/JamesClonk/vultr/lib/snapshots.go
generated
vendored
72
vendor/github.com/JamesClonk/vultr/lib/snapshots.go
generated
vendored
@ -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
|
||||
}
|
82
vendor/github.com/JamesClonk/vultr/lib/sshkeys.go
generated
vendored
82
vendor/github.com/JamesClonk/vultr/lib/sshkeys.go
generated
vendored
@ -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
|
||||
}
|
191
vendor/github.com/juju/ratelimit/LICENSE
generated
vendored
191
vendor/github.com/juju/ratelimit/LICENSE
generated
vendored
@ -1,191 +0,0 @@
|
||||
All files in this repository are licensed as follows. If you contribute
|
||||
to this repository, it is assumed that you license your contribution
|
||||
under the same license unless you state otherwise.
|
||||
|
||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||
|
||||
This software is licensed under the LGPLv3, included below.
|
||||
|
||||
As a special exception to the GNU Lesser General Public License version 3
|
||||
("LGPL3"), the copyright holders of this Library give you permission to
|
||||
convey to a third party a Combined Work that links statically or dynamically
|
||||
to this Library without providing any Minimal Corresponding Source or
|
||||
Minimal Application Code as set out in 4d or providing the installation
|
||||
information set out in section 4e, provided that you comply with the other
|
||||
provisions of LGPL3 and provided that you meet, for the Application the
|
||||
terms and conditions of the license(s) which apply to the Application.
|
||||
|
||||
Except as stated in this special exception, the provisions of LGPL3 will
|
||||
continue to comply in full to this Library. If you modify this Library, you
|
||||
may apply this exception to your version of this Library, but you are not
|
||||
obliged to do so. If you do not wish to do so, delete this exception
|
||||
statement from your version. This exception does not (and cannot) modify any
|
||||
license terms which apply to the Application, with which you must still
|
||||
comply.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
344
vendor/github.com/juju/ratelimit/ratelimit.go
generated
vendored
344
vendor/github.com/juju/ratelimit/ratelimit.go
generated
vendored
@ -1,344 +0,0 @@
|
||||
// Copyright 2014 Canonical Ltd.
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
// Package ratelimit provides an efficient token bucket implementation
|
||||
// that can be used to limit the rate of arbitrary things.
|
||||
// See http://en.wikipedia.org/wiki/Token_bucket.
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// The algorithm that this implementation uses does computational work
|
||||
// only when tokens are removed from the bucket, and that work completes
|
||||
// in short, bounded-constant time (Bucket.Wait benchmarks at 175ns on
|
||||
// my laptop).
|
||||
//
|
||||
// Time is measured in equal measured ticks, a given interval
|
||||
// (fillInterval) apart. On each tick a number of tokens (quantum) are
|
||||
// added to the bucket.
|
||||
//
|
||||
// When any of the methods are called the bucket updates the number of
|
||||
// tokens that are in the bucket, and it records the current tick
|
||||
// number too. Note that it doesn't record the current time - by
|
||||
// keeping things in units of whole ticks, it's easy to dish out tokens
|
||||
// at exactly the right intervals as measured from the start time.
|
||||
//
|
||||
// This allows us to calculate the number of tokens that will be
|
||||
// available at some time in the future with a few simple arithmetic
|
||||
// operations.
|
||||
//
|
||||
// The main reason for being able to transfer multiple tokens on each tick
|
||||
// is so that we can represent rates greater than 1e9 (the resolution of the Go
|
||||
// time package) tokens per second, but it's also useful because
|
||||
// it means we can easily represent situations like "a person gets
|
||||
// five tokens an hour, replenished on the hour".
|
||||
|
||||
// Bucket represents a token bucket that fills at a predetermined rate.
|
||||
// Methods on Bucket may be called concurrently.
|
||||
type Bucket struct {
|
||||
clock Clock
|
||||
|
||||
// startTime holds the moment when the bucket was
|
||||
// first created and ticks began.
|
||||
startTime time.Time
|
||||
|
||||
// capacity holds the overall capacity of the bucket.
|
||||
capacity int64
|
||||
|
||||
// quantum holds how many tokens are added on
|
||||
// each tick.
|
||||
quantum int64
|
||||
|
||||
// fillInterval holds the interval between each tick.
|
||||
fillInterval time.Duration
|
||||
|
||||
// mu guards the fields below it.
|
||||
mu sync.Mutex
|
||||
|
||||
// availableTokens holds the number of available
|
||||
// tokens as of the associated latestTick.
|
||||
// It will be negative when there are consumers
|
||||
// waiting for tokens.
|
||||
availableTokens int64
|
||||
|
||||
// latestTick holds the latest tick for which
|
||||
// we know the number of tokens in the bucket.
|
||||
latestTick int64
|
||||
}
|
||||
|
||||
// NewBucket returns a new token bucket that fills at the
|
||||
// rate of one token every fillInterval, up to the given
|
||||
// maximum capacity. Both arguments must be
|
||||
// positive. The bucket is initially full.
|
||||
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket {
|
||||
return NewBucketWithClock(fillInterval, capacity, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithClock is identical to NewBucket but injects a testable clock
|
||||
// interface.
|
||||
func NewBucketWithClock(fillInterval time.Duration, capacity int64, clock Clock) *Bucket {
|
||||
return NewBucketWithQuantumAndClock(fillInterval, capacity, 1, clock)
|
||||
}
|
||||
|
||||
// rateMargin specifes the allowed variance of actual
|
||||
// rate from specified rate. 1% seems reasonable.
|
||||
const rateMargin = 0.01
|
||||
|
||||
// NewBucketWithRate returns a token bucket that fills the bucket
|
||||
// at the rate of rate tokens per second up to the given
|
||||
// maximum capacity. Because of limited clock resolution,
|
||||
// at high rates, the actual rate may be up to 1% different from the
|
||||
// specified rate.
|
||||
func NewBucketWithRate(rate float64, capacity int64) *Bucket {
|
||||
return NewBucketWithRateAndClock(rate, capacity, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithRateAndClock is identical to NewBucketWithRate but injects a
|
||||
// testable clock interface.
|
||||
func NewBucketWithRateAndClock(rate float64, capacity int64, clock Clock) *Bucket {
|
||||
// Use the same bucket each time through the loop
|
||||
// to save allocations.
|
||||
tb := NewBucketWithQuantumAndClock(1, capacity, 1, clock)
|
||||
for quantum := int64(1); quantum < 1<<50; quantum = nextQuantum(quantum) {
|
||||
fillInterval := time.Duration(1e9 * float64(quantum) / rate)
|
||||
if fillInterval <= 0 {
|
||||
continue
|
||||
}
|
||||
tb.fillInterval = fillInterval
|
||||
tb.quantum = quantum
|
||||
if diff := math.Abs(tb.Rate() - rate); diff/rate <= rateMargin {
|
||||
return tb
|
||||
}
|
||||
}
|
||||
panic("cannot find suitable quantum for " + strconv.FormatFloat(rate, 'g', -1, 64))
|
||||
}
|
||||
|
||||
// nextQuantum returns the next quantum to try after q.
|
||||
// We grow the quantum exponentially, but slowly, so we
|
||||
// get a good fit in the lower numbers.
|
||||
func nextQuantum(q int64) int64 {
|
||||
q1 := q * 11 / 10
|
||||
if q1 == q {
|
||||
q1++
|
||||
}
|
||||
return q1
|
||||
}
|
||||
|
||||
// NewBucketWithQuantum is similar to NewBucket, but allows
|
||||
// the specification of the quantum size - quantum tokens
|
||||
// are added every fillInterval.
|
||||
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket {
|
||||
return NewBucketWithQuantumAndClock(fillInterval, capacity, quantum, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithQuantumAndClock is like NewBucketWithQuantum, but
|
||||
// also has a clock argument that allows clients to fake the passing
|
||||
// of time. If clock is nil, the system clock will be used.
|
||||
func NewBucketWithQuantumAndClock(fillInterval time.Duration, capacity, quantum int64, clock Clock) *Bucket {
|
||||
if clock == nil {
|
||||
clock = realClock{}
|
||||
}
|
||||
if fillInterval <= 0 {
|
||||
panic("token bucket fill interval is not > 0")
|
||||
}
|
||||
if capacity <= 0 {
|
||||
panic("token bucket capacity is not > 0")
|
||||
}
|
||||
if quantum <= 0 {
|
||||
panic("token bucket quantum is not > 0")
|
||||
}
|
||||
return &Bucket{
|
||||
clock: clock,
|
||||
startTime: clock.Now(),
|
||||
latestTick: 0,
|
||||
fillInterval: fillInterval,
|
||||
capacity: capacity,
|
||||
quantum: quantum,
|
||||
availableTokens: capacity,
|
||||
}
|
||||
}
|
||||
|
||||
// Wait takes count tokens from the bucket, waiting until they are
|
||||
// available.
|
||||
func (tb *Bucket) Wait(count int64) {
|
||||
if d := tb.Take(count); d > 0 {
|
||||
tb.clock.Sleep(d)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitMaxDuration is like Wait except that it will
|
||||
// only take tokens from the bucket if it needs to wait
|
||||
// for no greater than maxWait. It reports whether
|
||||
// any tokens have been removed from the bucket
|
||||
// If no tokens have been removed, it returns immediately.
|
||||
func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool {
|
||||
d, ok := tb.TakeMaxDuration(count, maxWait)
|
||||
if d > 0 {
|
||||
tb.clock.Sleep(d)
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
const infinityDuration time.Duration = 0x7fffffffffffffff
|
||||
|
||||
// Take takes count tokens from the bucket without blocking. It returns
|
||||
// the time that the caller should wait until the tokens are actually
|
||||
// available.
|
||||
//
|
||||
// Note that if the request is irrevocable - there is no way to return
|
||||
// tokens to the bucket once this method commits us to taking them.
|
||||
func (tb *Bucket) Take(count int64) time.Duration {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
d, _ := tb.take(tb.clock.Now(), count, infinityDuration)
|
||||
return d
|
||||
}
|
||||
|
||||
// TakeMaxDuration is like Take, except that
|
||||
// it will only take tokens from the bucket if the wait
|
||||
// time for the tokens is no greater than maxWait.
|
||||
//
|
||||
// If it would take longer than maxWait for the tokens
|
||||
// to become available, it does nothing and reports false,
|
||||
// otherwise it returns the time that the caller should
|
||||
// wait until the tokens are actually available, and reports
|
||||
// true.
|
||||
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
return tb.take(tb.clock.Now(), count, maxWait)
|
||||
}
|
||||
|
||||
// TakeAvailable takes up to count immediately available tokens from the
|
||||
// bucket. It returns the number of tokens removed, or zero if there are
|
||||
// no available tokens. It does not block.
|
||||
func (tb *Bucket) TakeAvailable(count int64) int64 {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
return tb.takeAvailable(tb.clock.Now(), count)
|
||||
}
|
||||
|
||||
// takeAvailable is the internal version of TakeAvailable - it takes the
|
||||
// current time as an argument to enable easy testing.
|
||||
func (tb *Bucket) takeAvailable(now time.Time, count int64) int64 {
|
||||
if count <= 0 {
|
||||
return 0
|
||||
}
|
||||
tb.adjustavailableTokens(tb.currentTick(now))
|
||||
if tb.availableTokens <= 0 {
|
||||
return 0
|
||||
}
|
||||
if count > tb.availableTokens {
|
||||
count = tb.availableTokens
|
||||
}
|
||||
tb.availableTokens -= count
|
||||
return count
|
||||
}
|
||||
|
||||
// Available returns the number of available tokens. It will be negative
|
||||
// when there are consumers waiting for tokens. Note that if this
|
||||
// returns greater than zero, it does not guarantee that calls that take
|
||||
// tokens from the buffer will succeed, as the number of available
|
||||
// tokens could have changed in the meantime. This method is intended
|
||||
// primarily for metrics reporting and debugging.
|
||||
func (tb *Bucket) Available() int64 {
|
||||
return tb.available(tb.clock.Now())
|
||||
}
|
||||
|
||||
// available is the internal version of available - it takes the current time as
|
||||
// an argument to enable easy testing.
|
||||
func (tb *Bucket) available(now time.Time) int64 {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
tb.adjustavailableTokens(tb.currentTick(now))
|
||||
return tb.availableTokens
|
||||
}
|
||||
|
||||
// Capacity returns the capacity that the bucket was created with.
|
||||
func (tb *Bucket) Capacity() int64 {
|
||||
return tb.capacity
|
||||
}
|
||||
|
||||
// Rate returns the fill rate of the bucket, in tokens per second.
|
||||
func (tb *Bucket) Rate() float64 {
|
||||
return 1e9 * float64(tb.quantum) / float64(tb.fillInterval)
|
||||
}
|
||||
|
||||
// take is the internal version of Take - it takes the current time as
|
||||
// an argument to enable easy testing.
|
||||
func (tb *Bucket) take(now time.Time, count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
if count <= 0 {
|
||||
return 0, true
|
||||
}
|
||||
|
||||
tick := tb.currentTick(now)
|
||||
tb.adjustavailableTokens(tick)
|
||||
avail := tb.availableTokens - count
|
||||
if avail >= 0 {
|
||||
tb.availableTokens = avail
|
||||
return 0, true
|
||||
}
|
||||
// Round up the missing tokens to the nearest multiple
|
||||
// of quantum - the tokens won't be available until
|
||||
// that tick.
|
||||
|
||||
// endTick holds the tick when all the requested tokens will
|
||||
// become available.
|
||||
endTick := tick + (-avail+tb.quantum-1)/tb.quantum
|
||||
endTime := tb.startTime.Add(time.Duration(endTick) * tb.fillInterval)
|
||||
waitTime := endTime.Sub(now)
|
||||
if waitTime > maxWait {
|
||||
return 0, false
|
||||
}
|
||||
tb.availableTokens = avail
|
||||
return waitTime, true
|
||||
}
|
||||
|
||||
// currentTick returns the current time tick, measured
|
||||
// from tb.startTime.
|
||||
func (tb *Bucket) currentTick(now time.Time) int64 {
|
||||
return int64(now.Sub(tb.startTime) / tb.fillInterval)
|
||||
}
|
||||
|
||||
// adjustavailableTokens adjusts the current number of tokens
|
||||
// available in the bucket at the given time, which must
|
||||
// be in the future (positive) with respect to tb.latestTick.
|
||||
func (tb *Bucket) adjustavailableTokens(tick int64) {
|
||||
if tb.availableTokens >= tb.capacity {
|
||||
return
|
||||
}
|
||||
tb.availableTokens += (tick - tb.latestTick) * tb.quantum
|
||||
if tb.availableTokens > tb.capacity {
|
||||
tb.availableTokens = tb.capacity
|
||||
}
|
||||
tb.latestTick = tick
|
||||
return
|
||||
}
|
||||
|
||||
// Clock represents the passage of time in a way that
|
||||
// can be faked out for tests.
|
||||
type Clock interface {
|
||||
// Now returns the current time.
|
||||
Now() time.Time
|
||||
// Sleep sleeps for at least the given duration.
|
||||
Sleep(d time.Duration)
|
||||
}
|
||||
|
||||
// realClock implements Clock in terms of standard time functions.
|
||||
type realClock struct{}
|
||||
|
||||
// Now implements Clock.Now by calling time.Now.
|
||||
func (realClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// Now implements Clock.Sleep by calling time.Sleep.
|
||||
func (realClock) Sleep(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
}
|
51
vendor/github.com/juju/ratelimit/reader.go
generated
vendored
51
vendor/github.com/juju/ratelimit/reader.go
generated
vendored
@ -1,51 +0,0 @@
|
||||
// Copyright 2014 Canonical Ltd.
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
package ratelimit
|
||||
|
||||
import "io"
|
||||
|
||||
type reader struct {
|
||||
r io.Reader
|
||||
bucket *Bucket
|
||||
}
|
||||
|
||||
// Reader returns a reader that is rate limited by
|
||||
// the given token bucket. Each token in the bucket
|
||||
// represents one byte.
|
||||
func Reader(r io.Reader, bucket *Bucket) io.Reader {
|
||||
return &reader{
|
||||
r: r,
|
||||
bucket: bucket,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *reader) Read(buf []byte) (int, error) {
|
||||
n, err := r.r.Read(buf)
|
||||
if n <= 0 {
|
||||
return n, err
|
||||
}
|
||||
r.bucket.Wait(int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
type writer struct {
|
||||
w io.Writer
|
||||
bucket *Bucket
|
||||
}
|
||||
|
||||
// Writer returns a reader that is rate limited by
|
||||
// the given token bucket. Each token in the bucket
|
||||
// represents one byte.
|
||||
func Writer(w io.Writer, bucket *Bucket) io.Writer {
|
||||
return &writer{
|
||||
w: w,
|
||||
bucket: bucket,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writer) Write(buf []byte) (int, error) {
|
||||
w.bucket.Wait(int64(len(buf)))
|
||||
return w.w.Write(buf)
|
||||
}
|
5
vendor/github.com/JamesClonk/vultr/LICENSE → vendor/github.com/vultr/govultr/LICENSE
generated
vendored
5
vendor/github.com/JamesClonk/vultr/LICENSE → vendor/github.com/vultr/govultr/LICENSE
generated
vendored
@ -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.
|
||||
|
45
vendor/github.com/vultr/govultr/account.go
generated
vendored
Normal file
45
vendor/github.com/vultr/govultr/account.go
generated
vendored
Normal 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
44
vendor/github.com/vultr/govultr/api.go
generated
vendored
Normal 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
51
vendor/github.com/vultr/govultr/application.go
generated
vendored
Normal 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
105
vendor/github.com/vultr/govultr/backup.go
generated
vendored
Normal 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
790
vendor/github.com/vultr/govultr/bare_metal_server.go
generated
vendored
Normal 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
319
vendor/github.com/vultr/govultr/block_storage.go
generated
vendored
Normal 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
209
vendor/github.com/vultr/govultr/dns_domains.go
generated
vendored
Normal 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
150
vendor/github.com/vultr/govultr/dns_records.go
generated
vendored
Normal 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
163
vendor/github.com/vultr/govultr/firewall_group.go
generated
vendored
Normal 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
265
vendor/github.com/vultr/govultr/firewall_rule.go
generated
vendored
Normal 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
|
||||
}
|
222
vendor/github.com/vultr/govultr/govultr.go
generated
vendored
Normal file
222
vendor/github.com/vultr/govultr/govultr.go
generated
vendored
Normal 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.4"
|
||||
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
142
vendor/github.com/vultr/govultr/iso.go
generated
vendored
Normal 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
120
vendor/github.com/vultr/govultr/network.go
generated
vendored
Normal 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
84
vendor/github.com/vultr/govultr/os.go
generated
vendored
Normal 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
199
vendor/github.com/vultr/govultr/plans.go
generated
vendored
Normal 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
154
vendor/github.com/vultr/govultr/regions.go
generated
vendored
Normal 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, ®ions)
|
||||
|
||||
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, ®ionsMap)
|
||||
|
||||
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, ®ions)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return regions, nil
|
||||
}
|
273
vendor/github.com/vultr/govultr/reserved_ip.go
generated
vendored
Normal file
273
vendor/github.com/vultr/govultr/reserved_ip.go
generated
vendored
Normal 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
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
168
vendor/github.com/vultr/govultr/snapshot.go
generated
vendored
Normal 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
140
vendor/github.com/vultr/govultr/ssh_key.go
generated
vendored
Normal 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
172
vendor/github.com/vultr/govultr/startup_script.go
generated
vendored
Normal 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
157
vendor/github.com/vultr/govultr/user.go
generated
vendored
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user