202 lines
9.1 KiB
Go
202 lines
9.1 KiB
Go
|
package linodego
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"strconv"
|
||
|
|
||
|
"github.com/go-resty/resty"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// APIHost Linode API hostname
|
||
|
APIHost = "api.linode.com"
|
||
|
// APIVersion Linode API version
|
||
|
APIVersion = "v4"
|
||
|
// APIProto connect to API with http(s)
|
||
|
APIProto = "https"
|
||
|
// Version of linodego
|
||
|
Version = "0.5.1"
|
||
|
// APIEnvVar environment var to check for API token
|
||
|
APIEnvVar = "LINODE_TOKEN"
|
||
|
// APISecondsPerPoll how frequently to poll for new Events
|
||
|
APISecondsPerPoll = 10
|
||
|
)
|
||
|
|
||
|
// DefaultUserAgent is the default User-Agent sent in HTTP request headers
|
||
|
const DefaultUserAgent = "linodego " + Version + " https://github.com/linode/linodego"
|
||
|
|
||
|
var envDebug = false
|
||
|
|
||
|
// Client is a wrapper around the Resty client
|
||
|
type Client struct {
|
||
|
resty *resty.Client
|
||
|
userAgent string
|
||
|
resources map[string]*Resource
|
||
|
debug bool
|
||
|
|
||
|
Images *Resource
|
||
|
InstanceDisks *Resource
|
||
|
InstanceConfigs *Resource
|
||
|
InstanceSnapshots *Resource
|
||
|
InstanceIPs *Resource
|
||
|
InstanceVolumes *Resource
|
||
|
Instances *Resource
|
||
|
IPAddresses *Resource
|
||
|
IPv6Pools *Resource
|
||
|
IPv6Ranges *Resource
|
||
|
Regions *Resource
|
||
|
StackScripts *Resource
|
||
|
Volumes *Resource
|
||
|
Kernels *Resource
|
||
|
Types *Resource
|
||
|
Domains *Resource
|
||
|
DomainRecords *Resource
|
||
|
Longview *Resource
|
||
|
LongviewClients *Resource
|
||
|
LongviewSubscriptions *Resource
|
||
|
NodeBalancers *Resource
|
||
|
NodeBalancerConfigs *Resource
|
||
|
NodeBalancerNodes *Resource
|
||
|
SSHKeys *Resource
|
||
|
Tickets *Resource
|
||
|
Account *Resource
|
||
|
Invoices *Resource
|
||
|
InvoiceItems *Resource
|
||
|
Events *Resource
|
||
|
Notifications *Resource
|
||
|
Profile *Resource
|
||
|
Managed *Resource
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
// Wether or not we will enable Resty debugging output
|
||
|
if apiDebug, ok := os.LookupEnv("LINODE_DEBUG"); ok {
|
||
|
if parsed, err := strconv.ParseBool(apiDebug); err == nil {
|
||
|
envDebug = parsed
|
||
|
log.Println("[INFO] LINODE_DEBUG being set to", envDebug)
|
||
|
} else {
|
||
|
log.Println("[WARN] LINODE_DEBUG should be an integer, 0 or 1")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// SetUserAgent sets a custom user-agent for HTTP requests
|
||
|
func (c *Client) SetUserAgent(ua string) *Client {
|
||
|
c.userAgent = ua
|
||
|
c.resty.SetHeader("User-Agent", c.userAgent)
|
||
|
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
// R wraps resty's R method
|
||
|
func (c *Client) R(ctx context.Context) *resty.Request {
|
||
|
return c.resty.R().
|
||
|
ExpectContentType("application/json").
|
||
|
SetHeader("Content-Type", "application/json").
|
||
|
SetContext(ctx).
|
||
|
SetError(APIError{})
|
||
|
}
|
||
|
|
||
|
// SetDebug sets the debug on resty's client
|
||
|
func (c *Client) SetDebug(debug bool) *Client {
|
||
|
c.debug = debug
|
||
|
c.resty.SetDebug(debug)
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
// SetBaseURL sets the base URL of the Linode v4 API (https://api.linode.com/v4)
|
||
|
func (c *Client) SetBaseURL(url string) *Client {
|
||
|
c.resty.SetHostURL(url)
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
// Resource looks up a resource by name
|
||
|
func (c Client) Resource(resourceName string) *Resource {
|
||
|
selectedResource, ok := c.resources[resourceName]
|
||
|
if !ok {
|
||
|
log.Fatalf("Could not find resource named '%s', exiting.", resourceName)
|
||
|
}
|
||
|
return selectedResource
|
||
|
}
|
||
|
|
||
|
// NewClient factory to create new Client struct
|
||
|
func NewClient(hc *http.Client) (client Client) {
|
||
|
restyClient := resty.NewWithClient(hc)
|
||
|
client.resty = restyClient
|
||
|
client.SetUserAgent(DefaultUserAgent)
|
||
|
client.SetBaseURL(fmt.Sprintf("%s://%s/%s", APIProto, APIHost, APIVersion))
|
||
|
|
||
|
resources := map[string]*Resource{
|
||
|
stackscriptsName: NewResource(&client, stackscriptsName, stackscriptsEndpoint, false, Stackscript{}, StackscriptsPagedResponse{}),
|
||
|
imagesName: NewResource(&client, imagesName, imagesEndpoint, false, Image{}, ImagesPagedResponse{}),
|
||
|
instancesName: NewResource(&client, instancesName, instancesEndpoint, false, Instance{}, InstancesPagedResponse{}),
|
||
|
instanceDisksName: NewResource(&client, instanceDisksName, instanceDisksEndpoint, true, InstanceDisk{}, InstanceDisksPagedResponse{}),
|
||
|
instanceConfigsName: NewResource(&client, instanceConfigsName, instanceConfigsEndpoint, true, InstanceConfig{}, InstanceConfigsPagedResponse{}),
|
||
|
instanceSnapshotsName: NewResource(&client, instanceSnapshotsName, instanceSnapshotsEndpoint, true, InstanceSnapshot{}, nil),
|
||
|
instanceIPsName: NewResource(&client, instanceIPsName, instanceIPsEndpoint, true, InstanceIP{}, nil), // really?
|
||
|
instanceVolumesName: NewResource(&client, instanceVolumesName, instanceVolumesEndpoint, true, nil, InstanceVolumesPagedResponse{}), // really?
|
||
|
ipaddressesName: NewResource(&client, ipaddressesName, ipaddressesEndpoint, false, nil, IPAddressesPagedResponse{}), // really?
|
||
|
ipv6poolsName: NewResource(&client, ipv6poolsName, ipv6poolsEndpoint, false, nil, IPv6PoolsPagedResponse{}), // really?
|
||
|
ipv6rangesName: NewResource(&client, ipv6rangesName, ipv6rangesEndpoint, false, IPv6Range{}, IPv6RangesPagedResponse{}),
|
||
|
regionsName: NewResource(&client, regionsName, regionsEndpoint, false, Region{}, RegionsPagedResponse{}),
|
||
|
volumesName: NewResource(&client, volumesName, volumesEndpoint, false, Volume{}, VolumesPagedResponse{}),
|
||
|
kernelsName: NewResource(&client, kernelsName, kernelsEndpoint, false, LinodeKernel{}, LinodeKernelsPagedResponse{}),
|
||
|
typesName: NewResource(&client, typesName, typesEndpoint, false, LinodeType{}, LinodeTypesPagedResponse{}),
|
||
|
domainsName: NewResource(&client, domainsName, domainsEndpoint, false, Domain{}, DomainsPagedResponse{}),
|
||
|
domainRecordsName: NewResource(&client, domainRecordsName, domainRecordsEndpoint, true, DomainRecord{}, DomainRecordsPagedResponse{}),
|
||
|
longviewName: NewResource(&client, longviewName, longviewEndpoint, false, nil, nil), // really?
|
||
|
longviewclientsName: NewResource(&client, longviewclientsName, longviewclientsEndpoint, false, LongviewClient{}, LongviewClientsPagedResponse{}),
|
||
|
longviewsubscriptionsName: NewResource(&client, longviewsubscriptionsName, longviewsubscriptionsEndpoint, false, LongviewSubscription{}, LongviewSubscriptionsPagedResponse{}),
|
||
|
nodebalancersName: NewResource(&client, nodebalancersName, nodebalancersEndpoint, false, NodeBalancer{}, NodeBalancerConfigsPagedResponse{}),
|
||
|
nodebalancerconfigsName: NewResource(&client, nodebalancerconfigsName, nodebalancerconfigsEndpoint, true, NodeBalancerConfig{}, NodeBalancerConfigsPagedResponse{}),
|
||
|
nodebalancernodesName: NewResource(&client, nodebalancernodesName, nodebalancernodesEndpoint, true, NodeBalancerNode{}, NodeBalancerNodesPagedResponse{}),
|
||
|
sshkeysName: NewResource(&client, sshkeysName, sshkeysEndpoint, false, SSHKey{}, SSHKeysPagedResponse{}),
|
||
|
ticketsName: NewResource(&client, ticketsName, ticketsEndpoint, false, Ticket{}, TicketsPagedResponse{}),
|
||
|
accountName: NewResource(&client, accountName, accountEndpoint, false, Account{}, nil), // really?
|
||
|
eventsName: NewResource(&client, eventsName, eventsEndpoint, false, Event{}, EventsPagedResponse{}),
|
||
|
invoicesName: NewResource(&client, invoicesName, invoicesEndpoint, false, Invoice{}, InvoicesPagedResponse{}),
|
||
|
invoiceItemsName: NewResource(&client, invoiceItemsName, invoiceItemsEndpoint, true, InvoiceItem{}, InvoiceItemsPagedResponse{}),
|
||
|
profileName: NewResource(&client, profileName, profileEndpoint, false, nil, nil), // really?
|
||
|
managedName: NewResource(&client, managedName, managedEndpoint, false, nil, nil), // really?
|
||
|
}
|
||
|
|
||
|
client.resources = resources
|
||
|
|
||
|
client.SetDebug(envDebug)
|
||
|
client.Images = resources[imagesName]
|
||
|
client.StackScripts = resources[stackscriptsName]
|
||
|
client.Instances = resources[instancesName]
|
||
|
client.Regions = resources[regionsName]
|
||
|
client.InstanceDisks = resources[instanceDisksName]
|
||
|
client.InstanceConfigs = resources[instanceConfigsName]
|
||
|
client.InstanceSnapshots = resources[instanceSnapshotsName]
|
||
|
client.InstanceIPs = resources[instanceIPsName]
|
||
|
client.InstanceVolumes = resources[instanceVolumesName]
|
||
|
client.IPAddresses = resources[ipaddressesName]
|
||
|
client.IPv6Pools = resources[ipv6poolsName]
|
||
|
client.IPv6Ranges = resources[ipv6rangesName]
|
||
|
client.Volumes = resources[volumesName]
|
||
|
client.Kernels = resources[kernelsName]
|
||
|
client.Types = resources[typesName]
|
||
|
client.Domains = resources[domainsName]
|
||
|
client.DomainRecords = resources[domainRecordsName]
|
||
|
client.Longview = resources[longviewName]
|
||
|
client.LongviewSubscriptions = resources[longviewsubscriptionsName]
|
||
|
client.NodeBalancers = resources[nodebalancersName]
|
||
|
client.NodeBalancerConfigs = resources[nodebalancerconfigsName]
|
||
|
client.NodeBalancerNodes = resources[nodebalancernodesName]
|
||
|
client.SSHKeys = resources[sshkeysName]
|
||
|
client.Tickets = resources[ticketsName]
|
||
|
client.Account = resources[accountName]
|
||
|
client.Events = resources[eventsName]
|
||
|
client.Invoices = resources[invoicesName]
|
||
|
client.Profile = resources[profileName]
|
||
|
client.Managed = resources[managedName]
|
||
|
return
|
||
|
}
|