forked from TrueCloudLab/lego
Switch Vultr to official client (#929)
This commit is contained in:
parent
0dbc28193b
commit
87be19588b
47 changed files with 5471 additions and 3029 deletions
26
Gopkg.lock
generated
26
Gopkg.lock
generated
|
@ -55,14 +55,6 @@
|
||||||
revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005"
|
revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005"
|
||||||
version = "v0.3.1"
|
version = "v0.3.1"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:ed3fc9992df610d07c85c24e0b792268cc1ce226dd9bf8cb2e6ad9a377b35415"
|
|
||||||
name = "github.com/JamesClonk/vultr"
|
|
||||||
packages = ["lib"]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "fa1c0367800db75e4d10d0ec90c49a8731670224"
|
|
||||||
version = "1.15.0"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:a4068a93355ba3cff0a719425713123d23c90010cb4d023b40c679a22465736d"
|
digest = "1:a4068a93355ba3cff0a719425713123d23c90010cb4d023b40c679a22465736d"
|
||||||
|
@ -367,14 +359,6 @@
|
||||||
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
|
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
|
||||||
version = "v1.1.5"
|
version = "v1.1.5"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:8b3234b10eacd5edea45bf0c13a585b608749da23f94aaf29b46d9ef8a8babf4"
|
|
||||||
name = "github.com/juju/ratelimit"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
|
||||||
version = "1.0.1"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:ec142582cd3bb5cc29a2bc7181a6e67367b90b19f6a957ce506dcd7d1500bf95"
|
digest = "1:ec142582cd3bb5cc29a2bc7181a6e67367b90b19f6a957ce506dcd7d1500bf95"
|
||||||
|
@ -599,6 +583,14 @@
|
||||||
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
||||||
version = "v1.20.0"
|
version = "v1.20.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:b1d2c51a689eef501cb5726f8d9997c0ca4415cbfa7105fe6e64b1844eddf1fb"
|
||||||
|
name = "github.com/vultr/govultr"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "NUT"
|
||||||
|
revision = "ca447e056e08d93aa6e5b09e6ae3565dd1825281"
|
||||||
|
version = "v0.1.4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:58f2854b50ff8862eb6a347f20dedaac83e1166f4040472e17bc37736841a12f"
|
digest = "1:58f2854b50ff8862eb6a347f20dedaac83e1166f4040472e17bc37736841a12f"
|
||||||
name = "go.opencensus.io"
|
name = "go.opencensus.io"
|
||||||
|
@ -885,7 +877,6 @@
|
||||||
"github.com/Azure/go-autorest/autorest/azure/auth",
|
"github.com/Azure/go-autorest/autorest/azure/auth",
|
||||||
"github.com/Azure/go-autorest/autorest/to",
|
"github.com/Azure/go-autorest/autorest/to",
|
||||||
"github.com/BurntSushi/toml",
|
"github.com/BurntSushi/toml",
|
||||||
"github.com/JamesClonk/vultr/lib",
|
|
||||||
"github.com/OpenDNS/vegadns2client",
|
"github.com/OpenDNS/vegadns2client",
|
||||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1",
|
"github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1",
|
||||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid",
|
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid",
|
||||||
|
@ -934,6 +925,7 @@
|
||||||
"github.com/transip/gotransip",
|
"github.com/transip/gotransip",
|
||||||
"github.com/transip/gotransip/domain",
|
"github.com/transip/gotransip/domain",
|
||||||
"github.com/urfave/cli",
|
"github.com/urfave/cli",
|
||||||
|
"github.com/vultr/govultr",
|
||||||
"golang.org/x/crypto/ocsp",
|
"golang.org/x/crypto/ocsp",
|
||||||
"golang.org/x/net/context",
|
"golang.org/x/net/context",
|
||||||
"golang.org/x/net/idna",
|
"golang.org/x/net/idna",
|
||||||
|
|
|
@ -132,3 +132,7 @@
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/nrdcg/namesilo"
|
name = "github.com/nrdcg/namesilo"
|
||||||
version = "0.2.0"
|
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
|
## More information
|
||||||
|
|
||||||
- [API documentation](https://www.vultr.com/api/#dns)
|
- [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. -->
|
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||||
<!-- providers/dns/vultr/vultr.toml -->
|
<!-- 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
|
// See https://www.vultr.com/api/#dns
|
||||||
package vultr
|
package vultr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
vultr "github.com/JamesClonk/vultr/lib"
|
|
||||||
"github.com/go-acme/lego/challenge/dns01"
|
"github.com/go-acme/lego/challenge/dns01"
|
||||||
"github.com/go-acme/lego/platform/config/env"
|
"github.com/go-acme/lego/platform/config/env"
|
||||||
|
"github.com/vultr/govultr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config is used to configure the creation of the DNSProvider
|
// 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.
|
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||||
type DNSProvider struct {
|
type DNSProvider struct {
|
||||||
config *Config
|
config *Config
|
||||||
client *vultr.Client
|
client *govultr.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProvider returns a DNSProvider instance with a configured Vultr 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")
|
return nil, fmt.Errorf("vultr: credentials missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &vultr.Options{
|
client := govultr.NewClient(config.HTTPClient, config.APIKey)
|
||||||
HTTPClient: config.HTTPClient,
|
|
||||||
}
|
|
||||||
client := vultr.NewClient(config.APIKey, options)
|
|
||||||
|
|
||||||
return &DNSProvider{client: client, config: config}, nil
|
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)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("vultr: API call failed: %v", err)
|
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
|
var allErr []string
|
||||||
for _, rec := range records {
|
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 {
|
if err != nil {
|
||||||
allErr = append(allErr, err.Error())
|
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) {
|
func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||||
domains, err := d.client.GetDNSDomains()
|
domains, err := d.client.DNSDomain.List(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("API call failed: %v", err)
|
return "", fmt.Errorf("API call failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var hostedDomain vultr.DNSDomain
|
var hostedDomain govultr.DNSDomain
|
||||||
for _, dom := range domains {
|
for _, dom := range domains {
|
||||||
if strings.HasSuffix(domain, dom.Domain) {
|
if strings.HasSuffix(domain, dom.Domain) {
|
||||||
if len(dom.Domain) > len(hostedDomain.Domain) {
|
if len(dom.Domain) > len(hostedDomain.Domain) {
|
||||||
|
@ -148,14 +147,14 @@ func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||||
return hostedDomain.Domain, nil
|
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)
|
zoneDomain, err := d.getHostedZone(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var records []vultr.DNSRecord
|
var records []govultr.DNSRecord
|
||||||
result, err := d.client.GetDNSRecords(zoneDomain)
|
result, err := d.client.DNSRecord.List(context.Background(), zoneDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", records, fmt.Errorf("API call has failed: %v", err)
|
return "", records, fmt.Errorf("API call has failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,4 @@ Example = ''''''
|
||||||
|
|
||||||
[Links]
|
[Links]
|
||||||
API = "https://www.vultr.com/api/#dns"
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
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 a new issue