Update Lego (Gandi API v5, cloudxns, ...)

This commit is contained in:
Ludovic Fernandez 2018-02-12 18:10:05 +01:00 committed by Traefiker Bot
parent dd873fbeee
commit 7d3dd5a0e4
43 changed files with 4112 additions and 1238 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
vendor/github.com/xenolf/lego/providers/dns/cloudxns/cloudxns.go eol=crlf

7
Gopkg.lock generated
View file

@ -525,7 +525,8 @@
[[projects]]
name = "github.com/exoscale/egoscale"
packages = ["."]
revision = "325740036187ddae3a5b74be00fbbc70011c4d96"
revision = "e4fedc381fbddb7fef4d7060388a726c6de37c88"
version = "v0.9.7"
[[projects]]
name = "github.com/fatih/color"
@ -1182,6 +1183,7 @@
"providers/dns/auroradns",
"providers/dns/azure",
"providers/dns/cloudflare",
"providers/dns/cloudxns",
"providers/dns/digitalocean",
"providers/dns/dnsimple",
"providers/dns/dnsmadeeasy",
@ -1189,6 +1191,7 @@
"providers/dns/dyn",
"providers/dns/exoscale",
"providers/dns/gandi",
"providers/dns/gandiv5",
"providers/dns/godaddy",
"providers/dns/googlecloud",
"providers/dns/linode",
@ -1202,7 +1205,7 @@
"providers/dns/route53",
"providers/dns/vultr"
]
revision = "b929aa5aab5ad2e197bb3d74ef99fac61bfa47bc"
revision = "06a8e7c475c03ef8d4773284ac63357d2810601b"
[[projects]]
branch = "master"

View file

@ -113,7 +113,7 @@ entryPoint = "https"
# Required
#
entryPoint = "http"
# Use a DNS-01 acme challenge rather than TLS-SNI-01 challenge
#
# Optional
@ -272,7 +272,7 @@ Use `DNS-01` challenge to generate/renew ACME certificates.
# ...
```
#### `provider`
#### `provider`
Select the provider that matches the DNS domain that will host the challenge TXT record, and provide environment variables to enable setting it:
@ -281,6 +281,7 @@ Select the provider that matches the DNS domain that will host the challenge TXT
| [Auroradns](https://www.pcextreme.com/aurora/dns) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` |
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP` |
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CLOUDFLARE_EMAIL`, `CLOUDFLARE_API_KEY` - The Cloudflare `Global API Key` needs to be used and not the `Origin CA Key` |
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` |
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` |
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` |
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` |
@ -288,6 +289,7 @@ Select the provider that matches the DNS domain that will host the challenge TXT
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` |
| [Exoscale](https://www.exoscale.ch) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` |
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` |
| [Gandi V5](http://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` |
| [GoDaddy](https://godaddy.com/domains) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` |
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, `GCE_SERVICE_ACCOUNT_FILE` |
| [Linode](https://www.linode.com) | `linode` | `LINODE_API_KEY` |
@ -330,7 +332,7 @@ This will request a certificate from Let's Encrypt during the first TLS handshak
!!! warning
TLS handshakes will be slow when requesting a hostname certificate for the first time, this can lead to DoS attacks.
!!! warning
Take note that Let's Encrypt have [rate limiting](https://letsencrypt.org/docs/rate-limits).

98
vendor/github.com/exoscale/egoscale/accounts.go generated vendored Normal file
View file

@ -0,0 +1,98 @@
package egoscale
const (
// UserAccount represents a User
UserAccount = iota
// AdminAccount represents an Admin
AdminAccount
// DomainAdminAccount represents a Domain Admin
DomainAdminAccount
)
// AccountType represents the type of an Account
//
// http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.8/accounts.html#accounts-users-and-domains
type AccountType int64
// Account provides the detailed account information
type Account struct {
ID string `json:"id"`
AccountType AccountType `json:"accounttype,omitempty"`
AccountDetails string `json:"accountdetails,omitempty"`
CPUAvailable string `json:"cpuavailable,omitempty"`
CPULimit string `json:"cpulimit,omitempty"`
CPUTotal int64 `json:"cputotal,omitempty"`
DefaultZoneID string `json:"defaultzoneid,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
EIPLimit string `json:"eiplimit,omitempty"`
Groups []string `json:"groups,omitempty"`
IPAvailable string `json:"ipavailable,omitempty"`
IPLimit string `json:"iplimit,omitempty"`
IPTotal int64 `json:"iptotal,omitempty"`
IsDefault bool `json:"isdefault,omitempty"`
MemoryAvailable string `json:"memoryavailable,omitempty"`
MemoryLimit string `json:"memorylimit,omitempty"`
MemoryTotal int64 `json:"memorytotal,omitempty"`
Name string `json:"name,omitempty"`
NetworkAvailable string `json:"networkavailable,omitempty"`
NetworkDomain string `json:"networkdomain,omitempty"`
NetworkLimit string `json:"networklimit,omitempty"`
NetworkTotal int16 `json:"networktotal,omitempty"`
PrimaryStorageAvailable string `json:"primarystorageavailable,omitempty"`
PrimaryStorageLimit string `json:"primarystoragelimit,omitempty"`
PrimaryStorageTotal int64 `json:"primarystoragetotal,omitempty"`
ProjectAvailable string `json:"projectavailable,omitempty"`
ProjectLimit string `json:"projectlimit,omitempty"`
ProjectTotal int64 `json:"projecttotal,omitempty"`
SecondaryStorageAvailable string `json:"secondarystorageavailable,omitempty"`
SecondaryStorageLimit string `json:"secondarystoragelimit,omitempty"`
SecondaryStorageTotal int64 `json:"secondarystoragetotal,omitempty"`
SnapshotAvailable string `json:"snapshotavailable,omitempty"`
SnapshotLimit string `json:"snapshotlimit,omitempty"`
SnapshotTotal int64 `json:"snapshottotal,omitempty"`
State string `json:"state,omitempty"`
TemplateAvailable string `json:"templateavailable,omitempty"`
TemplateLimit string `json:"templatelimit,omitempty"`
TemplateTotal int64 `json:"templatetotal,omitempty"`
VMAvailable string `json:"vmavailable,omitempty"`
VMLimit string `json:"vmlimit,omitempty"`
VMTotal int64 `json:"vmtotal,omitempty"`
VolumeAvailable string `json:"volumeavailable,omitempty"`
VolumeLimit string `json:"volumelimit,omitempty"`
VolumeTotal int64 `json:"volumetotal,omitempty"`
VPCAvailable string `json:"vpcavailable,omitempty"`
VPCLimit string `json:"vpclimit,omitempty"`
VPCTotal int64 `json:"vpctotal,omitempty"`
User []User `json:"user,omitempty"`
}
// ListAccounts represents a query to display the accounts
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listAccounts.html
type ListAccounts struct {
AccountType int64 `json:"accounttype,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IsCleanUpRequired bool `json:"iscleanuprequired,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
State string `json:"state,omitempty"`
}
func (*ListAccounts) name() string {
return "listAccounts"
}
func (*ListAccounts) response() interface{} {
return new(ListAccountsResponse)
}
// ListAccountsResponse represents a list of accounts
type ListAccountsResponse struct {
Count int `json:"count"`
Account []Account `json:"account"`
}

148
vendor/github.com/exoscale/egoscale/addresses.go generated vendored Normal file
View file

@ -0,0 +1,148 @@
package egoscale
import "net"
// IPAddress represents an IP Address
type IPAddress struct {
ID string `json:"id"`
Account string `json:"account,omitempty"`
AllocatedAt string `json:"allocated,omitempty"`
AssociatedNetworkID string `json:"associatednetworkid,omitempty"`
AssociatedNetworkName string `json:"associatednetworkname,omitempty"`
DomainID string `json:"domainid,omitempty"`
DomainName string `json:"domainname,omitempty"`
ForDisplay bool `json:"fordisplay,omitempty"`
ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty"`
IPAddress net.IP `json:"ipaddress"`
IsElastic bool `json:"iselastic,omitempty"`
IsPortable bool `json:"isportable,omitempty"`
IsSourceNat bool `json:"issourcenat,omitempty"`
IsSystem bool `json:"issystem,omitempty"`
NetworkID string `json:"networkid,omitempty"`
PhysicalNetworkID string `json:"physicalnetworkid,omitempty"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Purpose string `json:"purpose,omitempty"`
State string `json:"state,omitempty"`
VirtualMachineDisplayName string `json:"virtualmachinedisplayname,omitempty"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
VirtualMachineName string `json:"virtualmachineName,omitempty"`
VlanID string `json:"vlanid,omitempty"`
VlanName string `json:"vlanname,omitempty"`
VMIPAddress net.IP `json:"vmipaddress,omitempty"`
VpcID string `json:"vpcid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
ZoneName string `json:"zonename,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
JobID string `json:"jobid,omitempty"`
JobStatus JobStatusType `json:"jobstatus,omitempty"`
}
// ResourceType returns the type of the resource
func (*IPAddress) ResourceType() string {
return "PublicIpAddress"
}
// AssociateIPAddress (Async) represents the IP creation
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/associateIpAddress.html
type AssociateIPAddress struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ForDisplay bool `json:"fordisplay,omitempty"`
IsPortable bool `json:"isportable,omitempty"`
NetworkdID string `json:"networkid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
RegionID string `json:"regionid,omitempty"`
VpcID string `json:"vpcid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*AssociateIPAddress) name() string {
return "associateIpAddress"
}
func (*AssociateIPAddress) asyncResponse() interface{} {
return new(AssociateIPAddressResponse)
}
// AssociateIPAddressResponse represents the response to the creation of an IPAddress
type AssociateIPAddressResponse struct {
IPAddress IPAddress `json:"ipaddress"`
}
// DisassociateIPAddress (Async) represents the IP deletion
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/disassociateIpAddress.html
type DisassociateIPAddress struct {
ID string `json:"id"`
}
func (*DisassociateIPAddress) name() string {
return "disassociateIpAddress"
}
func (*DisassociateIPAddress) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// UpdateIPAddress (Async) represents the IP modification
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/updateIpAddress.html
type UpdateIPAddress struct {
ID string `json:"id"`
CustomID string `json:"customid,omitempty"` // root only
ForDisplay bool `json:"fordisplay,omitempty"`
}
func (*UpdateIPAddress) name() string {
return "updateIpAddress"
}
func (*UpdateIPAddress) asyncResponse() interface{} {
return new(UpdateIPAddressResponse)
}
// UpdateIPAddressResponse represents the modified IP Address
type UpdateIPAddressResponse AssociateIPAddressResponse
// ListPublicIPAddresses represents a search for public IP addresses
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listPublicIpAddresses.html
type ListPublicIPAddresses struct {
Account string `json:"account,omitempty"`
AllocatedOnly bool `json:"allocatedonly,omitempty"`
AllocatedNetworkID string `json:"allocatednetworkid,omitempty"`
DomainID string `json:"domainid,omitempty"`
ForDisplay bool `json:"fordisplay,omitempty"`
ForLoadBalancing bool `json:"forloadbalancing,omitempty"`
ForVirtualNetwork string `json:"forvirtualnetwork,omitempty"`
ID string `json:"id,omitempty"`
IPAddress net.IP `json:"ipaddress,omitempty"`
IsElastic bool `json:"iselastic,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
IsSourceNat bool `json:"issourcenat,omitempty"`
IsStaticNat bool `json:"isstaticnat,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omiempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
PhysicalNetworkID string `json:"physicalnetworkid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
VlanID string `json:"vlanid,omitempty"`
VpcID string `json:"vpcid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListPublicIPAddresses) name() string {
return "listPublicIpAddresses"
}
func (*ListPublicIPAddresses) response() interface{} {
return new(ListPublicIPAddressesResponse)
}
// ListPublicIPAddressesResponse represents a list of public IP addresses
type ListPublicIPAddressesResponse struct {
Count int `json:"count"`
PublicIPAddress []IPAddress `json:"publicipaddress"`
}

176
vendor/github.com/exoscale/egoscale/affinity_groups.go generated vendored Normal file
View file

@ -0,0 +1,176 @@
package egoscale
import (
"net/url"
)
// AffinityGroup represents an (anti-)affinity group
type AffinityGroup struct {
ID string `json:"id,omitempty"`
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
VirtualMachineIDs []string `json:"virtualmachineIDs,omitempty"` // *I*ds is not a typo
}
// AffinityGroupType represent an affinity group type
type AffinityGroupType struct {
Type string `json:"type"`
}
// CreateAffinityGroup (Async) represents a new (anti-)affinity group
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/createAffinityGroup.html
type CreateAffinityGroup struct {
Name string `json:"name"`
Type string `json:"type"`
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
DomainID string `json:"domainid,omitempty"`
}
func (*CreateAffinityGroup) name() string {
return "createAffinityGroup"
}
func (*CreateAffinityGroup) asyncResponse() interface{} {
return new(CreateAffinityGroupResponse)
}
// CreateAffinityGroupResponse represents the response of the creation of an (anti-)affinity group
type CreateAffinityGroupResponse struct {
AffinityGroup AffinityGroup `json:"affinitygroup"`
}
// UpdateVMAffinityGroup (Async) represents a modification of a (anti-)affinity group
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/updateVMAffinityGroup.html
type UpdateVMAffinityGroup struct {
ID string `json:"id"`
AffinityGroupIDs []string `json:"affinitygroupids,omitempty"` // mutually exclusive with names
AffinityGroupNames []string `json:"affinitygroupnames,omitempty"` // mutually exclusive with ids
}
func (*UpdateVMAffinityGroup) name() string {
return "updateVMAffinityGroup"
}
func (*UpdateVMAffinityGroup) asyncResponse() interface{} {
return new(UpdateVMAffinityGroupResponse)
}
func (req *UpdateVMAffinityGroup) onBeforeSend(params *url.Values) error {
// Either AffinityGroupIDs or AffinityGroupNames must be set
if len(req.AffinityGroupIDs) == 0 && len(req.AffinityGroupNames) == 0 {
params.Set("affinitygroupids", "")
}
return nil
}
// UpdateVMAffinityGroupResponse represents the new VM
type UpdateVMAffinityGroupResponse VirtualMachineResponse
// DeleteAffinityGroup (Async) represents an (anti-)affinity group to be deleted
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/deleteAffinityGroup.html
type DeleteAffinityGroup struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
DomainID string `json:"domainid,omitempty"`
}
func (*DeleteAffinityGroup) name() string {
return "deleteAffinityGroup"
}
func (*DeleteAffinityGroup) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ListAffinityGroups represents an (anti-)affinity groups search
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listAffinityGroups.html
type ListAffinityGroups struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
Type string `json:"type,omitempty"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
}
func (*ListAffinityGroups) name() string {
return "listAffinityGroups"
}
func (*ListAffinityGroups) response() interface{} {
return new(ListAffinityGroupsResponse)
}
// ListAffinityGroupTypes represents an (anti-)affinity groups search
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listAffinityGroupTypes.html
type ListAffinityGroupTypes struct {
Keyword string `json:"keyword,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
}
func (*ListAffinityGroupTypes) name() string {
return "listAffinityGroupTypes"
}
func (*ListAffinityGroupTypes) response() interface{} {
return new(ListAffinityGroupTypesResponse)
}
// ListAffinityGroupsResponse represents a list of (anti-)affinity groups
type ListAffinityGroupsResponse struct {
Count int `json:"count"`
AffinityGroup []AffinityGroup `json:"affinitygroup"`
}
// ListAffinityGroupTypesResponse represents a list of (anti-)affinity group types
type ListAffinityGroupTypesResponse struct {
Count int `json:"count"`
AffinityGroupType []AffinityGroupType `json:"affinitygrouptype"`
}
// Legacy methods
// CreateAffinityGroup creates a group
//
// Deprecated: Use the API directly
func (exo *Client) CreateAffinityGroup(name string, async AsyncInfo) (*AffinityGroup, error) {
req := &CreateAffinityGroup{
Name: name,
}
resp, err := exo.AsyncRequest(req, async)
if err != nil {
return nil, err
}
ag := resp.(*CreateAffinityGroupResponse).AffinityGroup
return &ag, nil
}
// DeleteAffinityGroup deletes a group
//
// Deprecated: Use the API directly
func (exo *Client) DeleteAffinityGroup(name string, async AsyncInfo) error {
req := &DeleteAffinityGroup{
Name: name,
}
return exo.BooleanAsyncRequest(req, async)
}

View file

@ -1,42 +0,0 @@
package egoscale
import (
"encoding/json"
"net/url"
)
func (exo *Client) CreateAffinityGroup(name string) (string, error) {
params := url.Values{}
params.Set("name", name)
params.Set("type", "host anti-affinity")
resp, err := exo.Request("createAffinityGroup", params)
if err != nil {
return "", err
}
var r CreateAffinityGroupResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobId, nil
}
func (exo *Client) DeleteAffinityGroup(name string) (string, error) {
params := url.Values{}
params.Set("name", name)
resp, err := exo.Request("deleteAffinityGroup", params)
if err != nil {
return "", err
}
var r DeleteAffinityGroupResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobId, nil
}

52
vendor/github.com/exoscale/egoscale/apis.go generated vendored Normal file
View file

@ -0,0 +1,52 @@
package egoscale
// API represents an API service
type API struct {
Description string `json:"description"`
IsAsync bool `json:"isasync"`
Name string `json:"name"`
Related string `json:"related"` // comma separated
Since string `json:"since"`
Type string `json:"type"`
Params []APIParam `json:"params"`
Response []APIResponse `json:"responses"`
}
// APIParam represents an API parameter field
type APIParam struct {
Description string `json:"description"`
Length int64 `json:"length"`
Name string `json:"name"`
Related string `json:"related"` // comma separated
Since string `json:"since"`
Type string `json:"type"`
}
// APIResponse represents an API response field
type APIResponse struct {
Description string `json:"description"`
Name string `json:"name"`
Response []APIResponse `json:"response"`
Type string `json:"type"`
}
// ListAPIs represents a query to list the api
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listApis.html
type ListAPIs struct {
Name string `json:"name,omitempty"`
}
func (*ListAPIs) name() string {
return "listApis"
}
func (*ListAPIs) response() interface{} {
return new(ListAPIsResponse)
}
// ListAPIsResponse represents a list of API
type ListAPIsResponse struct {
Count int `json:"count"`
API []API `json:"api"`
}

View file

@ -1,36 +0,0 @@
package egoscale
import (
"encoding/json"
"net/url"
)
func (exo *Client) PollAsyncJob(jobid string) (*QueryAsyncJobResultResponse, error) {
params := url.Values{}
params.Set("jobid", jobid)
resp, err := exo.Request("queryAsyncJobResult", params)
if err != nil {
return nil, err
}
var r QueryAsyncJobResultResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &r, nil
}
func (exo *Client) AsyncToVirtualMachine(resp QueryAsyncJobResultResponse) (*DeployVirtualMachineResponse, error) {
var r DeployVirtualMachineWrappedResponse
if err := json.Unmarshal(resp.Jobresult, &r); err != nil {
return nil, err
}
return &r.Wrapped, nil
}

66
vendor/github.com/exoscale/egoscale/async_jobs.go generated vendored Normal file
View file

@ -0,0 +1,66 @@
package egoscale
import (
"encoding/json"
)
// AsyncJobResult represents an asynchronous job result
type AsyncJobResult struct {
AccountID string `json:"accountid"`
Cmd string `json:"cmd"`
Created string `json:"created"`
JobInstanceID string `json:"jobinstanceid"`
JobInstanceType string `json:"jobinstancetype"`
JobProcStatus int `json:"jobprocstatus"`
JobResult *json.RawMessage `json:"jobresult"`
JobResultCode int `json:"jobresultcode"`
JobResultType string `json:"jobresulttype"`
JobStatus JobStatusType `json:"jobstatus"`
UserID string `json:"userid"`
JobID string `json:"jobid"`
}
// QueryAsyncJobResult represents a query to fetch the status of async job
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/queryAsyncJobResult.html
type QueryAsyncJobResult struct {
JobID string `json:"jobid"`
}
func (*QueryAsyncJobResult) name() string {
return "queryAsyncJobResult"
}
func (*QueryAsyncJobResult) response() interface{} {
return new(QueryAsyncJobResultResponse)
}
// QueryAsyncJobResultResponse represents the current status of an asynchronous job
type QueryAsyncJobResultResponse AsyncJobResult
// ListAsyncJobs list the asynchronous jobs
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listAsyncJobs.html
type ListAsyncJobs struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
StartDate string `json:"startdate,omitempty"`
}
func (*ListAsyncJobs) name() string {
return "listAsyncJobs"
}
func (*ListAsyncJobs) response() interface{} {
return new(ListAsyncJobsResponse)
}
// ListAsyncJobsResponse represents a list of job results
type ListAsyncJobsResponse struct {
Count int `json:"count"`
AsyncJobs []AsyncJobResult `json:"asyncjobs"`
}

View file

@ -2,59 +2,118 @@ package egoscale
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
)
// DNSDomain represents a domain
type DNSDomain struct {
ID int64 `json:"id"`
AccountID int64 `json:"account_id,omitempty"`
UserID int64 `json:"user_id,omitempty"`
RegistrantID int64 `json:"registrant_id,omitempty"`
Name string `json:"name"`
UnicodeName string `json:"unicode_name"`
Token string `json:"token"`
State string `json:"state"`
Language string `json:"language,omitempty"`
Lockable bool `json:"lockable"`
AutoRenew bool `json:"auto_renew"`
WhoisProtected bool `json:"whois_protected"`
RecordCount int64 `json:"record_count"`
ServiceCount int64 `json:"service_count"`
ExpiresOn string `json:"expires_on,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// DNSDomainResponse represents a domain creation response
type DNSDomainResponse struct {
Domain *DNSDomain `json:"domain"`
}
// DNSRecord represents a DNS record
type DNSRecord struct {
ID int64 `json:"id,omitempty"`
DomainID int64 `json:"domain_id,omitempty"`
Name string `json:"name"`
TTL int `json:"ttl,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
Content string `json:"content"`
RecordType string `json:"record_type"`
Prio int `json:"prio,omitempty"`
}
// DNSRecordResponse represents the creation of a DNS record
type DNSRecordResponse struct {
Record DNSRecord `json:"record"`
}
// DNSErrorResponse represents an error in the API
type DNSErrorResponse struct {
Message string `json:"message,omitempty"`
Errors *DNSError `json:"errors"`
}
// DNSError represents an error
type DNSError struct {
Name []string `json:"name"`
}
// Error formats the DNSerror into a string
func (req *DNSErrorResponse) Error() error {
if req.Errors != nil {
return fmt.Errorf("DNS error: %s", strings.Join(req.Errors.Name, ", "))
}
return fmt.Errorf("DNS error: %s", req.Message)
}
// CreateDomain creates a DNS domain
func (exo *Client) CreateDomain(name string) (*DNSDomain, error) {
var hdr = make(http.Header)
var domain DNSDomainCreateRequest
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
domain.Domain.Name = name
m, err := json.Marshal(domain)
m, err := json.Marshal(DNSDomainResponse{
Domain: &DNSDomain{
Name: name,
},
})
if err != nil {
return nil, err
}
resp, err := exo.DetailedRequest("/v1/domains", string(m), "POST", hdr)
resp, err := exo.dnsRequest("/v1/domains", string(m), "POST")
if err != nil {
return nil, err
}
var d *DNSDomain
var d *DNSDomainResponse
if err := json.Unmarshal(resp, &d); err != nil {
return nil, err
}
return d, nil
return d.Domain, nil
}
// GetDomain gets a DNS domain
func (exo *Client) GetDomain(name string) (*DNSDomain, error) {
var hdr = make(http.Header)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
resp, err := exo.DetailedRequest("/v1/domains/"+name, "", "GET", hdr)
resp, err := exo.dnsRequest("/v1/domains/"+name, "", "GET")
if err != nil {
return nil, err
}
var d *DNSDomain
var d *DNSDomainResponse
if err := json.Unmarshal(resp, &d); err != nil {
return nil, err
}
return d, nil
return d.Domain, nil
}
// DeleteDomain delets a DNS domain
func (exo *Client) DeleteDomain(name string) error {
var hdr = make(http.Header)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
_, err := exo.DetailedRequest("/v1/domains/"+name, "", "DELETE", hdr)
_, err := exo.dnsRequest("/v1/domains/"+name, "", "DELETE")
if err != nil {
return err
}
@ -62,92 +121,128 @@ func (exo *Client) DeleteDomain(name string) error {
return nil
}
func (exo *Client) GetRecords(name string) ([]*DNSRecordResponse, error) {
var hdr = make(http.Header)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
resp, err := exo.DetailedRequest("/v1/domains/"+name+"/records", "", "GET", hdr)
// GetRecord returns a DNS record
func (exo *Client) GetRecord(domain string, recordID int64) (*DNSRecord, error) {
id := strconv.FormatInt(recordID, 10)
resp, err := exo.dnsRequest("/v1/domains/"+domain+"/records/"+id, "", "GET")
if err != nil {
return nil, err
}
var r []*DNSRecordResponse
var r DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return r, nil
return &(r.Record), nil
}
func (exo *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecordResponse, error) {
var hdr = make(http.Header)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
hdr.Add("Content-Type", "application/json")
var rr DNSRecordResponse
rr.Record = rec
body, err := json.Marshal(rr)
// GetRecords returns the DNS records
func (exo *Client) GetRecords(name string) ([]DNSRecord, error) {
resp, err := exo.dnsRequest("/v1/domains/"+name+"/records", "", "GET")
if err != nil {
return nil, err
}
resp, err := exo.DetailedRequest("/v1/domains/"+name+"/records", string(body), "POST", hdr)
if err != nil {
return nil, err
}
var r *DNSRecordResponse
var r []DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return r, nil
records := make([]DNSRecord, 0, len(r))
for _, rec := range r {
records = append(records, rec.Record)
}
return records, nil
}
func (exo *Client) UpdateRecord(name string, rec DNSRecord) (*DNSRecordResponse, error) {
var hdr = make(http.Header)
id := strconv.FormatInt(rec.Id, 10)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
hdr.Add("Content-Type", "application/json")
var rr DNSRecordResponse
rr.Record = rec
body, err := json.Marshal(rr)
// CreateRecord creates a DNS record
func (exo *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, error) {
body, err := json.Marshal(DNSRecordResponse{
Record: rec,
})
if err != nil {
return nil, err
}
resp, err := exo.DetailedRequest("/v1/domains/"+name+"/records/"+id,
string(body), "PUT", hdr)
resp, err := exo.dnsRequest("/v1/domains/"+name+"/records", string(body), "POST")
if err != nil {
return nil, err
}
var r *DNSRecordResponse
var r DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return r, nil
return &(r.Record), nil
}
func (exo *Client) DeleteRecord(name string, rec DNSRecord) error {
var hdr = make(http.Header)
id := strconv.FormatInt(rec.Id, 10)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
hdr.Add("Content-Type", "application/json")
_, err := exo.DetailedRequest("/v1/domains/"+name+"/records/"+id,
"", "DELETE", hdr)
// UpdateRecord updates a DNS record
func (exo *Client) UpdateRecord(name string, rec DNSRecord) (*DNSRecord, error) {
body, err := json.Marshal(DNSRecordResponse{
Record: rec,
})
if err != nil {
return err
return nil, err
}
return nil
id := strconv.FormatInt(rec.ID, 10)
resp, err := exo.dnsRequest("/v1/domains/"+name+"/records/"+id, string(body), "PUT")
if err != nil {
return nil, err
}
var r DNSRecordResponse
if err = json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &(r.Record), nil
}
// DeleteRecord deletes a record
func (exo *Client) DeleteRecord(name string, recordID int64) error {
id := strconv.FormatInt(recordID, 10)
_, err := exo.dnsRequest("/v1/domains/"+name+"/records/"+id, "", "DELETE")
return err
}
func (exo *Client) dnsRequest(uri string, params string, method string) (json.RawMessage, error) {
url := exo.endpoint + uri
req, err := http.NewRequest(method, url, strings.NewReader(params))
if err != nil {
return nil, err
}
var hdr = make(http.Header)
hdr.Add("X-DNS-TOKEN", exo.apiKey+":"+exo.apiSecret)
hdr.Add("Accept", "application/json")
if params != "" {
hdr.Add("Content-Type", "application/json")
}
req.Header = hdr
response, err := exo.client.Do(req)
if err != nil {
return nil, err
}
defer response.Body.Close()
b, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
if response.StatusCode >= 400 {
var e DNSErrorResponse
if err := json.Unmarshal(b, &e); err != nil {
return nil, err
}
return nil, e.Error()
}
return b, nil
}

93
vendor/github.com/exoscale/egoscale/doc.go generated vendored Normal file
View file

@ -0,0 +1,93 @@
/*
Package egoscale is a mapping for with the CloudStack API (http://cloudstack.apache.org/api.html) from Go. It has been designed against the Exoscale (https://www.exoscale.ch/) infrastructure but should fit other CloudStack services.
Requests and Responses
The paradigm used in this library is that CloudStack defines two types of requests synchronous (client.Request) and asynchronous (client.AsyncRequest). And when the expected responses is a success message, you may use the boolean requests variants (client.BooleanRequest, client.BooleanAsyncRequest). To build a request, construct the adequate struct. This library expects a pointer for efficiency reasons only. The response is a struct corresponding to the request itself. E.g. DeployVirtualMachine gives DeployVirtualMachineResponse, as a pointer as well to avoid big copies.
Then everything within the struct is not a pointer.
Affinity and Anti-Affinity groups
Affinity and Anti-Affinity groups provide a way to influence where VMs should run. See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html#affinity-groups
APIs
All the available APIs on the server and provided by the API Discovery plugin
cs := egoscale.NewClient("https://api.exoscale.ch/compute", "EXO...", "...")
resp, err := cs.Request(&egoscale.ListAPIs{})
if err != nil {
panic(err)
}
for _, api := range resp.(*egoscale.ListAPIsResponse).API {
fmt.Println("%s %s", api.Name, api.Description)
}
// Output:
// listNetworks Lists all available networks
// ...
Elastic IPs
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/networking_and_traffic.html#about-elastic-ips
Networks
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.8/networking_and_traffic.html
NICs
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/networking_and_traffic.html#configuring-multiple-ip-addresses-on-a-single-nic
Security Groups
Security Groups provide a way to isolate traffic to VMs.
resp, err := cs.Request(&egoscale.CreateSecurityGroup{
Name: "Load balancer",
Description: "Opens HTTP/HTTPS ports from the outside world",
})
securityGroup := resp.(*egoscale.CreateSecurityGroupResponse).SecurityGroup
// ...
err = client.BooleanRequest(&egoscale.DeleteSecurityGroup{
ID: securityGroup.ID,
})
// ...
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/networking_and_traffic.html#security-groups
Service Offerings
A service offering correspond to some hardware features (CPU, RAM).
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/service_offerings.html
SSH Key Pairs
In addition to username and password (disabled on Exoscale), SSH keys are used to log into the infrastructure.
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html#creating-the-ssh-keypair
Virtual Machines
... todo ...
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html
Templates
... todo ...
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/templates.html
Zones
A Zone corresponds to a Data Center.
*/
package egoscale

View file

@ -1,9 +0,0 @@
package egoscale
import (
"fmt"
)
func (e *Error) Error() error {
return fmt.Errorf("exoscale API error %d (internal code: %d): %s", e.ErrorCode, e.CSErrorCode, e.ErrorText)
}

77
vendor/github.com/exoscale/egoscale/events.go generated vendored Normal file
View file

@ -0,0 +1,77 @@
package egoscale
// Event represents an event in the system
type Event struct {
ID string `json:"id"`
Account string `json:"account"`
Created string `json:"created"`
Description string `json:"description,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Level string `json:"level"` // INFO, WARN, ERROR
ParentID string `json:"parentid,omitempty"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
State string `json:"state,omitempty"`
Type string `json:"type"`
UserName string `json:"username,omitempty"`
}
// EventType represent a type of event
type EventType struct {
Name string `json:"name"`
}
// ListEvents list the events
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listEvents.html
type ListEvents struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
Duration int `json:"duration,omitempty"`
EndDate string `json:"enddate,omitempty"`
EntryTime int `json:"entrytime,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
Level string `json:"level,omitempty"` // INFO, WARN, ERROR
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
StartDate string `json:"startdate,omitempty"`
Type string `json:"type,omitempty"`
}
func (*ListEvents) name() string {
return "listEvents"
}
func (*ListEvents) response() interface{} {
return new(ListEventsResponse)
}
// ListEventsResponse represents a response of a list query
type ListEventsResponse struct {
Count int `json:"count"`
Event []Event `json:"event"`
}
// ListEventTypes list the event types
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listEventTypes.html
type ListEventTypes struct{}
func (*ListEventTypes) name() string {
return "listEventTypes"
}
func (*ListEventTypes) response() interface{} {
return new(ListEventTypesResponse)
}
// ListEventTypesResponse represents a response of a list query
type ListEventTypesResponse struct {
Count int `json:"count"`
EventType []EventType `json:"eventtype"`
}

View file

@ -1,144 +0,0 @@
package egoscale
import (
"encoding/json"
"fmt"
"net/url"
)
func (exo *Client) CreateEgressRule(rule SecurityGroupRule) (*AuthorizeSecurityGroupEgressResponse, error) {
params := url.Values{}
params.Set("securitygroupid", rule.SecurityGroupId)
if rule.Cidr != "" {
params.Set("cidrlist", rule.Cidr)
} else if len(rule.UserSecurityGroupList) > 0 {
usg, err := json.Marshal(rule.UserSecurityGroupList)
if err != nil {
return nil, err
}
params.Set("usersecuritygrouplist", string(usg))
} else {
return nil, fmt.Errorf("No Egress rule CIDR or Security Group List provided")
}
params.Set("protocol", rule.Protocol)
if rule.Protocol == "ICMP" {
params.Set("icmpcode", fmt.Sprintf("%d", rule.IcmpCode))
params.Set("icmptype", fmt.Sprintf("%d", rule.IcmpType))
} else if rule.Protocol == "TCP" || rule.Protocol == "UDP" {
params.Set("startport", fmt.Sprintf("%d", rule.Port))
params.Set("endport", fmt.Sprintf("%d", rule.Port))
} else {
return nil, fmt.Errorf("Invalid Egress rule Protocol: %s", rule.Protocol)
}
resp, err := exo.Request("authorizeSecurityGroupEgress", params)
if err != nil {
return nil, err
}
var r AuthorizeSecurityGroupEgressResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &r, nil
}
func (exo *Client) CreateIngressRule(rule SecurityGroupRule) (*AuthorizeSecurityGroupIngressResponse, error) {
params := url.Values{}
params.Set("securitygroupid", rule.SecurityGroupId)
if rule.Cidr != "" {
params.Set("cidrlist", rule.Cidr)
} else if len(rule.UserSecurityGroupList) > 0 {
for i := 0; i < len(rule.UserSecurityGroupList); i++ {
params.Set(fmt.Sprintf("usersecuritygrouplist[%d].account", i), rule.UserSecurityGroupList[i].Account)
params.Set(fmt.Sprintf("usersecuritygrouplist[%d].group", i), rule.UserSecurityGroupList[i].Group)
}
} else {
return nil, fmt.Errorf("No Ingress rule CIDR or Security Group List provided")
}
params.Set("protocol", rule.Protocol)
if rule.Protocol == "ICMP" {
params.Set("icmpcode", fmt.Sprintf("%d", rule.IcmpCode))
params.Set("icmptype", fmt.Sprintf("%d", rule.IcmpType))
} else if rule.Protocol == "TCP" || rule.Protocol == "UDP" {
params.Set("startport", fmt.Sprintf("%d", rule.Port))
params.Set("endport", fmt.Sprintf("%d", rule.Port))
} else {
return nil, fmt.Errorf("Invalid Egress rule Protocol: %s", rule.Protocol)
}
fmt.Printf("## params: %+v\n", params)
resp, err := exo.Request("authorizeSecurityGroupIngress", params)
if err != nil {
return nil, err
}
var r AuthorizeSecurityGroupIngressResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &r, nil
}
func (exo *Client) CreateSecurityGroupWithRules(name string, ingress []SecurityGroupRule, egress []SecurityGroupRule) (*CreateSecurityGroupResponse, error) {
params := url.Values{}
params.Set("name", name)
resp, err := exo.Request("createSecurityGroup", params)
var r CreateSecurityGroupResponseWrapper
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
if err != nil {
return nil, err
}
sgid := r.Wrapped.Id
for _, erule := range egress {
erule.SecurityGroupId = sgid
_, err = exo.CreateEgressRule(erule)
if err != nil {
return nil, err
}
}
for _, inrule := range ingress {
inrule.SecurityGroupId = sgid
_, err = exo.CreateIngressRule(inrule)
if err != nil {
return nil, err
}
}
return &r.Wrapped, nil
}
func (exo *Client) DeleteSecurityGroup(name string) error {
params := url.Values{}
params.Set("name", name)
resp, err := exo.Request("deleteSecurityGroup", params)
if err != nil {
return err
}
fmt.Printf("## response: %+v\n", resp)
return nil
}

View file

@ -5,6 +5,7 @@ import (
"net/http"
)
// NewClient creates a CloudStack API client
func NewClient(endpoint string, apiKey string, apiSecret string) *Client {
cs := &Client{
client: &http.Client{

View file

@ -1,40 +0,0 @@
package egoscale
import (
"encoding/json"
"net/url"
)
func (exo *Client) AddIpToNic(nic_id string, ip_address string) (string, error) {
params := url.Values{}
params.Set("nicid", nic_id)
params.Set("ipaddress", ip_address)
resp, err := exo.Request("addIpToNic", params)
if err != nil {
return "", err
}
var r AddIpToNicResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.Id, nil
}
func (exo *Client) RemoveIpFromNic(nic_id string) (string, error) {
params := url.Values{}
params.Set("id", nic_id)
resp, err := exo.Request("removeIpFromNic", params)
if err != nil {
return "", err
}
var r RemoveIpFromNicResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobID, nil
}

View file

@ -1,59 +0,0 @@
package egoscale
import (
"encoding/json"
"net/url"
)
func (exo *Client) CreateKeypair(name string) (*CreateSSHKeyPairResponse, error) {
params := url.Values{}
params.Set("name", name)
resp, err := exo.Request("createSSHKeyPair", params)
if err != nil {
return nil, err
}
var r CreateSSHKeyPairWrappedResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &r.Wrapped, nil
}
func (exo *Client) DeleteKeypair(name string) (*StandardResponse, error) {
params := url.Values{}
params.Set("name", name)
resp, err := exo.Request("deleteSSHKeyPair", params)
if err != nil {
return nil, err
}
var r StandardResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &r, nil
}
func (exo *Client) RegisterKeypair(name string, key string) (*CreateSSHKeyPairResponse, error) {
params := url.Values{}
params.Set("name", name)
params.Set("publicKey", key)
resp, err := exo.Request("registerSSHKeyPair", params)
if err != nil {
return nil, err
}
var r CreateSSHKeyPairWrappedResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return &r.Wrapped, nil
}

171
vendor/github.com/exoscale/egoscale/keypairs.go generated vendored Normal file
View file

@ -0,0 +1,171 @@
package egoscale
// SSHKeyPair represents an SSH key pair
type SSHKeyPair struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
Name string `json:"name,omitempty"`
PrivateKey string `json:"privatekey,omitempty"`
}
// CreateSSHKeyPair represents a new keypair to be created
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/createSSHKeyPair.html
type CreateSSHKeyPair struct {
Name string `json:"name"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*CreateSSHKeyPair) name() string {
return "createSSHKeyPair"
}
func (*CreateSSHKeyPair) response() interface{} {
return new(CreateSSHKeyPairResponse)
}
// CreateSSHKeyPairResponse represents the creation of an SSH Key Pair
type CreateSSHKeyPairResponse struct {
KeyPair SSHKeyPair `json:"keypair"`
}
// DeleteSSHKeyPair represents a new keypair to be created
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/deleteSSHKeyPair.html
type DeleteSSHKeyPair struct {
Name string `json:"name"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*DeleteSSHKeyPair) name() string {
return "deleteSSHKeyPair"
}
func (*DeleteSSHKeyPair) response() interface{} {
return new(booleanSyncResponse)
}
// RegisterSSHKeyPair represents a new registration of a public key in a keypair
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/registerSSHKeyPair.html
type RegisterSSHKeyPair struct {
Name string `json:"name"`
PublicKey string `json:"publickey"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*RegisterSSHKeyPair) name() string {
return "registerSSHKeyPair"
}
func (*RegisterSSHKeyPair) response() interface{} {
return new(RegisterSSHKeyPairResponse)
}
// RegisterSSHKeyPairResponse represents the creation of an SSH Key Pair
type RegisterSSHKeyPairResponse struct {
KeyPair SSHKeyPair `json:"keypair"`
}
// ListSSHKeyPairs represents a query for a list of SSH KeyPairs
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listSSHKeyPairs.html
type ListSSHKeyPairs struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*ListSSHKeyPairs) name() string {
return "listSSHKeyPairs"
}
func (*ListSSHKeyPairs) response() interface{} {
return new(ListSSHKeyPairsResponse)
}
// ListSSHKeyPairsResponse represents a list of SSH key pairs
type ListSSHKeyPairsResponse struct {
Count int `json:"count"`
SSHKeyPair []SSHKeyPair `json:"sshkeypair"`
}
// ResetSSHKeyForVirtualMachine (Async) represents a change for the key pairs
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/resetSSHKeyForVirtualMachine.html
type ResetSSHKeyForVirtualMachine struct {
ID string `json:"id"`
KeyPair string `json:"keypair"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*ResetSSHKeyForVirtualMachine) name() string {
return "resetSSHKeyForVirtualMachine"
}
func (*ResetSSHKeyForVirtualMachine) asyncResponse() interface{} {
return new(ResetSSHKeyForVirtualMachineResponse)
}
// ResetSSHKeyForVirtualMachineResponse represents the modified VirtualMachine
type ResetSSHKeyForVirtualMachineResponse VirtualMachineResponse
// CreateKeypair create a new SSH Key Pair
//
// Deprecated: will go away, use the API directly
func (exo *Client) CreateKeypair(name string) (*SSHKeyPair, error) {
req := &CreateSSHKeyPair{
Name: name,
}
resp, err := exo.Request(req)
if err != nil {
return nil, err
}
keypair := resp.(*CreateSSHKeyPairResponse).KeyPair
return &keypair, nil
}
// DeleteKeypair deletes an SSH key pair
//
// Deprecated: will go away, use the API directly
func (exo *Client) DeleteKeypair(name string) error {
req := &DeleteSSHKeyPair{
Name: name,
}
return exo.BooleanRequest(req)
}
// RegisterKeypair registers a public key in a keypair
//
// Deprecated: will go away, use the API directly
func (exo *Client) RegisterKeypair(name string, publicKey string) (*SSHKeyPair, error) {
req := &RegisterSSHKeyPair{
Name: name,
PublicKey: publicKey,
}
resp, err := exo.Request(req)
if err != nil {
return nil, err
}
keypair := resp.(*RegisterSSHKeyPairResponse).KeyPair
return &keypair, nil
}

106
vendor/github.com/exoscale/egoscale/limits.go generated vendored Normal file
View file

@ -0,0 +1,106 @@
package egoscale
// https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/configuration/Resource.java
// ResourceTypeName represents the name of a resource type (for limits)
type ResourceTypeName string
const (
// VirtualMachineTypeName is the resource type name of a VM
VirtualMachineTypeName ResourceTypeName = "user_vm"
// IPAddressTypeName is the resource type name of an IP address
IPAddressTypeName = "public_ip"
// VolumeTypeName is the resource type name of a volume
VolumeTypeName = "volume"
// SnapshotTypeName is the resource type name of a snapshot
SnapshotTypeName = "snapshot"
// TemplateTypeName is the resource type name of a template
TemplateTypeName = "template"
// ProjectTypeName is the resource type name of a project
ProjectTypeName = "project"
// NetworkTypeName is the resource type name of a network
NetworkTypeName = "network"
// VPCTypeName is the resource type name of a VPC
VPCTypeName = "vpc"
// CPUTypeName is the resource type name of a CPU
CPUTypeName = "cpu"
// MemoryTypeName is the resource type name of Memory
MemoryTypeName = "memory"
// PrimaryStorageTypeName is the resource type name of primary storage
PrimaryStorageTypeName = "primary_storage"
// SecondaryStorageTypeName is the resource type name of secondary storage
SecondaryStorageTypeName = "secondary_storage"
)
// ResourceType represents the ID of a resource type (for limits)
type ResourceType int64
const (
// VirtualMachineType is the resource type ID of a VM
VirtualMachineType ResourceType = iota
// IPAddressType is the resource type ID of an IP address
IPAddressType
// VolumeType is the resource type ID of a volume
VolumeType
// SnapshotType is the resource type ID of a snapshot
SnapshotType
// TemplateType is the resource type ID of a template
TemplateType
// ProjectType is the resource type ID of a project
ProjectType
// NetworkType is the resource type ID of a network
NetworkType
// VPCType is the resource type ID of a VPC
VPCType
// CPUType is the resource type ID of a CPU
CPUType
// MemoryType is the resource type ID of Memory
MemoryType
// PrimaryStorageType is the resource type ID of primary storage
PrimaryStorageType
// SecondaryStorageType is the resource type ID of secondary storage
SecondaryStorageType
)
// ListResourceLimits lists the resource limits
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listResourceLimits.html
type ListResourceLimits struct {
Account string `json:"account,omittempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
ResourceType ResourceType `json:"resourcetype,omitempty"`
ResourceTypeName ResourceTypeName `json:"resourcetypename,omitempty"`
}
func (*ListResourceLimits) name() string {
return "listResourceLimits"
}
func (*ListResourceLimits) response() interface{} {
return new(ListResourceLimitsResponse)
}
// ListResourceLimitsResponse represents a list of resource limits
type ListResourceLimitsResponse struct {
Count int `json:"count"`
ResourceLimit []ResourceLimit `json:"resourcelimit"`
}
// ResourceLimit represents the limit on a particular resource
type ResourceLimit struct {
Account string `json:"account,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Max int64 `json:"max,omitempty"` // -1 means the sky is the limit
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
ResourceType ResourceType `json:"resourcetype,omitempty"`
ResourceTypeName ResourceTypeName `json:"resourcetypename,omitempty"`
}

View file

@ -0,0 +1,68 @@
package egoscale
// NetworkOffering corresponds to the Compute Offerings
type NetworkOffering struct {
ID string `json:"id"`
Availability string `json:"availability,omitempty"`
ConserveMode bool `json:"conservemode,omitempty"`
Created string `json:"created"`
Details map[string]string `json:"details,omitempty"`
DisplayText string `json:"displaytext,omitempty"`
EgressDefaultPolicy bool `json:"egressdefaultpolicy,omitempty"`
ForVPC bool `json:"forvpc,omitempty"`
GuestIPType string `json:"guestiptype,omitempty"`
IsDefault bool `json:"isdefault,omitempty"`
IsPersistent bool `json:"ispersistent,omitempty"`
MaxConnections int `json:"maxconnections,omitempty"`
Name string `json:"name,omitempty"`
NetworkRate int `json:"networkrate,omitempty"`
ServiceOfferingID string `json:"serviceofferingid,omitempty"`
SpecifyIPRanges bool `json:"specifyipranges,omitempty"`
SpecifyVlan bool `json:"specifyvlan,omitempty"`
State string `json:"state"` // Disabled/Enabled/Inactive
SupportsPublicAccess bool `json:"supportspublicaccess,omitempty"`
SupportsStrechedL2Subnet bool `json:"supportsstrechedl2subnet,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
TrafficType string `json:"traffictype,omitempty"` // Public, Management, Control, ...
Service []Service `json:"service,omitempty"`
}
// ListNetworkOfferings represents a query for network offerings
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listNetworkOfferings.html
type ListNetworkOfferings struct {
Availability string `json:"availability,omitempty"`
DisplayText string `json:"displaytext,omitempty"`
ForVPC bool `json:"forvpc,omitempty"`
GuestIPType string `json:"guestiptype,omitempty"` // shared of isolated
ID string `json:"id,omitempty"`
IsDefault bool `json:"isdefault,omitempty"`
IsTagged bool `json:"istagged,omitempty"`
Keyword string `json:"keyword,omitempty"`
Name string `json:"name,omitempty"`
NetworkID string `json:"networkid,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
SourceNATSupported bool `json:"sourcenatsupported,omitempty"`
SpecifyIPRanges bool `json:"specifyipranges,omitempty"`
SpecifyVlan string `json:"specifyvlan,omitempty"`
State string `json:"state,omitempty"`
SupportedServices string `json:"supportedservices,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
TrafficType string `json:"traffictype,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListNetworkOfferings) name() string {
return "listNetworkOfferings"
}
func (*ListNetworkOfferings) response() interface{} {
return new(ListNetworkOfferingsResponse)
}
// ListNetworkOfferingsResponse represents a list of service offerings
type ListNetworkOfferingsResponse struct {
Count int `json:"count"`
NetworkOffering []NetworkOffering `json:"networkoffering"`
}

249
vendor/github.com/exoscale/egoscale/networks.go generated vendored Normal file
View file

@ -0,0 +1,249 @@
package egoscale
import (
"net"
"net/url"
)
// Network represents a network
type Network struct {
ID string `json:"id"`
Account string `json:"account"`
ACLID string `json:"aclid,omitempty"`
ACLType string `json:"acltype,omitempty"`
BroadcastDomainType string `json:"broadcastdomaintype,omitempty"`
BroadcastURI string `json:"broadcasturi,omitempty"`
CanUseForDeploy bool `json:"canusefordeploy,omitempty"`
Cidr string `json:"cidr,omitempty"`
DisplayNetwork bool `json:"diplaynetwork,omitempty"`
DisplayText string `json:"displaytext"`
DNS1 net.IP `json:"dns1,omitempty"`
DNS2 net.IP `json:"dns2,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Gateway net.IP `json:"gateway,omitempty"`
IP6Cidr string `json:"ip6cidr,omitempty"`
IP6Gateway net.IP `json:"ip6gateway,omitempty"`
IsDefault bool `json:"isdefault,omitempty"`
IsPersistent bool `json:"ispersistent,omitempty"`
Name string `json:"name"`
Netmask net.IP `json:"netmask,omitempty"`
NetworkCidr string `json:"networkcidr,omitempty"`
NetworkDomain string `json:"networkdomain,omitempty"`
NetworkOfferingAvailability string `json:"networkofferingavailability,omitempty"`
NetworkOfferingConserveMode bool `json:"networkofferingconservemode,omitempty"`
NetworkOfferingDisplayText string `json:"networkofferingdisplaytext,omitempty"`
NetworkOfferingID string `json:"networkofferingid,omitempty"`
NetworkOfferingName string `json:"networkofferingname,omitempty"`
PhysicalNetworkID string `json:"physicalnetworkid,omitempty"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Related string `json:"related,omitempty"`
ReserveIPRange string `json:"reserveiprange,omitempty"`
RestartRequired bool `json:"restartrequired,omitempty"`
SpecifyIPRanges bool `json:"specifyipranges,omitempty"`
State string `json:"state"`
StrechedL2Subnet bool `json:"strechedl2subnet,omitempty"`
SubdomainAccess bool `json:"subdomainaccess,omitempty"`
TrafficType string `json:"traffictype"`
Type string `json:"type"`
Vlan string `json:"vlan,omitemtpy"` // root only
VpcID string `json:"vpcid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
ZoneName string `json:"zonename,omitempty"`
ZonesNetworkSpans string `json:"zonesnetworkspans,omitempty"`
Service []Service `json:"service"`
Tags []ResourceTag `json:"tags"`
}
// ResourceType returns the type of the resource
func (*Network) ResourceType() string {
return "Network"
}
// Service is a feature of a network
type Service struct {
Name string `json:"name"`
Capability []ServiceCapability `json:"capability,omitempty"`
Provider []ServiceProvider `json:"provider,omitempty"`
}
// ServiceCapability represents optional capability of a service
type ServiceCapability struct {
CanChooseServiceCapability bool `json:"canchooseservicecapability"`
Name string `json:"name"`
Value string `json:"value"`
}
// ServiceProvider represents the provider of the service
type ServiceProvider struct {
ID string `json:"id"`
CanEnableIndividualService bool `json:"canenableindividualservice"`
DestinationPhysicalNetworkID string `json:"destinationphysicalnetworkid"`
Name string `json:"name"`
PhysicalNetworkID string `json:"physicalnetworkid"`
ServiceList []string `json:"servicelist,omitempty"`
}
// NetworkResponse represents a network
type NetworkResponse struct {
Network Network `json:"network"`
}
// CreateNetwork creates a network
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/createNetwork.html
type CreateNetwork struct {
DisplayText string `json:"displaytext,omitempty"`
Name string `json:"name,omitempty"`
NetworkOfferingID string `json:"networkofferingid"`
ZoneID string `json:"zoneid"`
Account string `json:"account,omitempty"`
ACLID string `json:"aclid,omitempty"`
ACLType string `json:"acltype,omitempty"` // Account or Domain
DisplayNetwork bool `json:"displaynetwork,omitempty"` // root only
DomainID string `json:"domainid,omitempty"`
EndIP net.IP `json:"endip,omitempty"`
EndIpv6 net.IP `json:"endipv6,omitempty"`
Gateway net.IP `json:"gateway,omitempty"`
IP6Cidr string `json:"ip6cidr,omitempty"`
IP6Gateway net.IP `json:"ip6gateway,omitempty"`
IsolatedPVlan string `json:"isolatedpvlan,omitempty"`
Netmask net.IP `json:"netmask,omitempty"`
NetworkDomain string `json:"networkdomain,omitempty"`
PhysicalNetworkID string `json:"physicalnetworkid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
StartIP net.IP `json:"startip,omitempty"`
StartIpv6 net.IP `json:"startipv6,omitempty"`
SubdomainAccess string `json:"subdomainaccess,omitempty"`
Vlan string `json:"vlan,omitempty"`
VpcID string `json:"vpcid,omitempty"`
}
func (*CreateNetwork) name() string {
return "createNetwork"
}
func (*CreateNetwork) response() interface{} {
return new(CreateNetworkResponse)
}
func (req *CreateNetwork) onBeforeSend(params *url.Values) error {
// Those fields are required but might be empty
if req.Name == "" {
params.Set("name", "")
}
if req.DisplayText == "" {
params.Set("displaytext", "")
}
return nil
}
// CreateNetworkResponse represents a freshly created network
type CreateNetworkResponse NetworkResponse
// UpdateNetwork updates a network
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/updateNetwork.html
type UpdateNetwork struct {
ID string `json:"id"`
ChangeCidr bool `json:"changecidr,omitempty"`
CustomID string `json:"customid,omitempty"` // root only
DisplayNetwork string `json:"displaynetwork,omitempty"`
DisplayText string `json:"displaytext,omitempty"`
Forced bool `json:"forced,omitempty"`
GuestVMCidr string `json:"guestvmcidr,omitempty"`
Name string `json:"name,omitempty"`
NetworkDomain string `json:"networkdomain,omitempty"`
NetworkOfferingID string `json:"networkofferingid,omitempty"`
UpdateInSequence bool `json:"updateinsequence,omitempty"`
}
func (*UpdateNetwork) name() string {
return "updateNetwork"
}
func (*UpdateNetwork) asyncResponse() interface{} {
return new(UpdateNetworkResponse)
}
// UpdateNetworkResponse represents a freshly created network
type UpdateNetworkResponse NetworkResponse
// RestartNetwork updates a network
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/restartNetwork.html
type RestartNetwork struct {
ID string `json:"id"`
Cleanup bool `json:"cleanup,omitempty"`
}
func (*RestartNetwork) name() string {
return "restartNetwork"
}
func (*RestartNetwork) asyncResponse() interface{} {
return new(RestartNetworkResponse)
}
// RestartNetworkResponse represents a freshly created network
type RestartNetworkResponse NetworkResponse
// DeleteNetwork deletes a network
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/deleteNetwork.html
type DeleteNetwork struct {
ID string `json:"id"`
Forced bool `json:"forced,omitempty"`
}
func (*DeleteNetwork) name() string {
return "deleteNetwork"
}
func (*DeleteNetwork) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ListNetworks represents a query to a network
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listNetworks.html
type ListNetworks struct {
Account string `json:"account,omitempty"`
ACLType string `json:"acltype,omitempty"` // Account or Domain
CanUseForDeploy bool `json:"canusefordeploy,omitempty"`
DisplayNetwork bool `json:"displaynetwork,omitempty"` // root only
DomainID string `json:"domainid,omitempty"`
ForVpc string `json:"forvpc,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
IsSystem bool `json:"issystem,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
PhysicalNetworkID string `json:"physicalnetworkid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
RestartRequired bool `json:"restartrequired,omitempty"`
SpecifyRanges bool `json:"specifyranges,omitempty"`
SupportedServices []Service `json:"supportedservices,omitempty"`
Tags []ResourceTag `json:"resourcetag,omitempty"`
TrafficType string `json:"traffictype,omitempty"`
Type string `json:"type,omitempty"`
VpcID string `json:"vpcid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListNetworks) name() string {
return "listNetworks"
}
func (*ListNetworks) response() interface{} {
return new(ListNetworksResponse)
}
// ListNetworksResponse represents the list of networks
type ListNetworksResponse struct {
Count int `json:"count"`
Network []Network `json:"network"`
}

135
vendor/github.com/exoscale/egoscale/nics.go generated vendored Normal file
View file

@ -0,0 +1,135 @@
package egoscale
import (
"fmt"
"net"
)
// Nic represents a Network Interface Controller (NIC)
type Nic struct {
ID string `json:"id,omitempty"`
BroadcastURI string `json:"broadcasturi,omitempty"`
Gateway net.IP `json:"gateway,omitempty"`
IP6Address net.IP `json:"ip6address,omitempty"`
IP6Cidr string `json:"ip6cidr,omitempty"`
IP6Gateway net.IP `json:"ip6gateway,omitempty"`
IPAddress net.IP `json:"ipaddress,omitempty"`
IsDefault bool `json:"isdefault,omitempty"`
IsolationURI string `json:"isolationuri,omitempty"`
MacAddress string `json:"macaddress,omitempty"`
Netmask net.IP `json:"netmask,omitempty"`
NetworkID string `json:"networkid,omitempty"`
NetworkName string `json:"networkname,omitempty"`
SecondaryIP []NicSecondaryIP `json:"secondaryip,omitempty"`
Traffictype string `json:"traffictype,omitempty"`
Type string `json:"type,omitempty"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
}
// NicSecondaryIP represents a link between NicID and IPAddress
type NicSecondaryIP struct {
ID string `json:"id"`
IPAddress net.IP `json:"ipaddress"`
NetworkID string `json:"networkid"`
NicID string `json:"nicid"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
}
// ListNics represents the NIC search
type ListNics struct {
VirtualMachineID string `json:"virtualmachineid"`
ForDisplay bool `json:"fordisplay,omitempty"`
Keyword string `json:"keyword,omitempty"`
NetworkID string `json:"networkid,omitempty"`
NicID string `json:"nicid,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
}
func (*ListNics) name() string {
return "listNics"
}
func (*ListNics) response() interface{} {
return new(ListNicsResponse)
}
// ListNicsResponse represents a list of templates
type ListNicsResponse struct {
Count int `json:"count"`
Nic []Nic `json:"nic"`
}
// AddIPToNic represents the assignation of a secondary IP
type AddIPToNic struct {
NicID string `json:"nicid"`
IPAddress net.IP `json:"ipaddress"`
}
func (*AddIPToNic) name() string {
return "addIpToNic"
}
func (*AddIPToNic) asyncResponse() interface{} {
return new(AddIPToNicResponse)
}
// AddIPToNicResponse represents the addition of an IP to a NIC
type AddIPToNicResponse struct {
NicSecondaryIP NicSecondaryIP `json:"nicsecondaryip"`
}
// RemoveIPFromNic represents a deletion request
type RemoveIPFromNic struct {
ID string `json:"id"`
}
func (*RemoveIPFromNic) name() string {
return "removeIpFromNic"
}
func (*RemoveIPFromNic) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ListNics lists the NIC of a VM
//
// Deprecated: use the API directly
func (exo *Client) ListNics(req *ListNics) ([]Nic, error) {
resp, err := exo.Request(req)
if err != nil {
return nil, err
}
return resp.(*ListNicsResponse).Nic, nil
}
// AddIPToNic adds an IP to a NIC
//
// Deprecated: use the API directly
func (exo *Client) AddIPToNic(nicID string, ipAddress string, async AsyncInfo) (*NicSecondaryIP, error) {
ip := net.ParseIP(ipAddress)
if ip == nil {
return nil, fmt.Errorf("%s is not a valid IP address", ipAddress)
}
req := &AddIPToNic{
NicID: nicID,
IPAddress: ip,
}
resp, err := exo.AsyncRequest(req, async)
if err != nil {
return nil, err
}
nic := resp.(AddIPToNicResponse).NicSecondaryIP
return &nic, nil
}
// RemoveIPFromNic removes an IP from a NIC
//
// Deprecated: use the API directly
func (exo *Client) RemoveIPFromNic(secondaryNicID string, async AsyncInfo) error {
req := &RemoveIPFromNic{
ID: secondaryNicID,
}
return exo.BooleanAsyncRequest(req, async)
}

View file

@ -1,20 +1,164 @@
package egoscale
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
"reflect"
"sort"
"strconv"
"strings"
"time"
)
// Command represent a CloudStack request
type Command interface {
// CloudStack API command name
name() string
// Response interface to Unmarshal the JSON into
response() interface{}
}
// AsyncCommand represents a async CloudStack request
type AsyncCommand interface {
// CloudStack API command name
name() string
// Response interface to Unmarshal the JSON into
asyncResponse() interface{}
}
// Command represents an action to be done on the params before sending them
//
// This little took helps with issue of relying on JSON serialization logic only.
// `omitempty` may make sense in some cases but not all the time.
type onBeforeHook interface {
onBeforeSend(params *url.Values) error
}
const (
// Pending represents a job in progress
Pending JobStatusType = iota
// Success represents a successfully completed job
Success
// Failure represents a job that has failed to complete
Failure
)
// JobStatusType represents the status of a Job
type JobStatusType int
const (
// Unauthorized represents ... (TODO)
Unauthorized ErrorCode = 401
// MethodNotAllowed represents ... (TODO)
MethodNotAllowed = 405
// UnsupportedActionError represents ... (TODO)
UnsupportedActionError = 422
// APILimitExceeded represents ... (TODO)
APILimitExceeded = 429
// MalformedParameterError represents ... (TODO)
MalformedParameterError = 430
// ParamError represents ... (TODO)
ParamError = 431
// InternalError represents a server error
InternalError = 530
// AccountError represents ... (TODO)
AccountError = 531
// AccountResourceLimitError represents ... (TODO)
AccountResourceLimitError = 532
// InsufficientCapacityError represents ... (TODO)
InsufficientCapacityError = 533
// ResourceUnavailableError represents ... (TODO)
ResourceUnavailableError = 534
// ResourceAllocationError represents ... (TODO)
ResourceAllocationError = 535
// ResourceInUseError represents ... (TODO)
ResourceInUseError = 536
// NetworkRuleConflictError represents ... (TODO)
NetworkRuleConflictError = 537
)
// ErrorCode represents the CloudStack ApiErrorCode enum
//
// See: https://github.com/apache/cloudstack/blob/master/api/src/org/apache/cloudstack/api/ApiErrorCode.java
type ErrorCode int
// JobResultResponse represents a generic response to a job task
type JobResultResponse struct {
AccountID string `json:"accountid,omitempty"`
Cmd string `json:"cmd"`
Created string `json:"created"`
JobID string `json:"jobid"`
JobProcStatus int `json:"jobprocstatus"`
JobResult *json.RawMessage `json:"jobresult"`
JobStatus JobStatusType `json:"jobstatus"`
JobResultType string `json:"jobresulttype"`
UserID string `json:"userid,omitempty"`
}
// ErrorResponse represents the standard error response from CloudStack
type ErrorResponse struct {
ErrorCode ErrorCode `json:"errorcode"`
CsErrorCode int `json:"cserrorcode"`
ErrorText string `json:"errortext"`
UUIDList []string `json:"uuidList,omitempty"` // uuid*L*ist is not a typo
}
// Error formats a CloudStack error into a standard error
func (e *ErrorResponse) Error() string {
return fmt.Sprintf("API error %d (internal code: %d): %s", e.ErrorCode, e.CsErrorCode, e.ErrorText)
}
// booleanAsyncResponse represents a boolean response (usually after a deletion)
type booleanAsyncResponse struct {
Success bool `json:"success"`
DisplayText string `json:"diplaytext,omitempty"`
}
// Error formats a CloudStack job response into a standard error
func (e *booleanAsyncResponse) Error() error {
if e.Success {
return nil
}
return fmt.Errorf("API error: %s", e.DisplayText)
}
// booleanAsyncResponse represents a boolean response for sync calls
type booleanSyncResponse struct {
Success string `json:"success"`
DisplayText string `json:"displaytext,omitempty"`
}
func (e *booleanSyncResponse) Error() error {
if e.Success == "true" {
return nil
}
return fmt.Errorf("API error: %s", e.DisplayText)
}
// AsyncInfo represents the details for any async call
//
// It retries at most Retries time and waits for Delay between each retry
type AsyncInfo struct {
Retries int
Delay int
}
func csQuotePlus(s string) string {
return strings.Replace(s, "+", "%20", -1)
s = strings.Replace(s, "+", "%20", -1)
s = strings.Replace(s, "%5B", "[", -1)
s = strings.Replace(s, "%5D", "]", -1)
return s
}
func csEncode(s string) string {
@ -43,7 +187,7 @@ func rawValues(b json.RawMessage) (json.RawMessage, error) {
return i[0], nil
}
func (exo *Client) ParseResponse(resp *http.Response) (json.RawMessage, error) {
func (exo *Client) parseResponse(resp *http.Response) (json.RawMessage, error) {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
@ -59,75 +203,362 @@ func (exo *Client) ParseResponse(resp *http.Response) (json.RawMessage, error) {
}
if resp.StatusCode >= 400 {
var e Error
var e ErrorResponse
if err := json.Unmarshal(b, &e); err != nil {
return nil, err
}
/* Need to account for differet error types */
if e.ErrorCode != 0 {
return nil, e.Error()
} else {
var de DNSError
if err := json.Unmarshal(b, &de); err != nil {
return nil, err
}
return nil, fmt.Errorf("Exoscale error (%d): %s", resp.StatusCode, strings.Join(de.Name, "\n"))
}
return b, &e
}
return b, nil
}
func (exo *Client) Request(command string, params url.Values) (json.RawMessage, error) {
// AsyncRequest performs an asynchronous request and polls it for retries * day [s]
func (exo *Client) AsyncRequest(req AsyncCommand, async AsyncInfo) (interface{}, error) {
body, err := exo.request(req.name(), req)
if err != nil {
return nil, err
}
mac := hmac.New(sha1.New, []byte(exo.apiSecret))
keys := make([]string, 0)
unencoded := make([]string, 0)
// Is it a Job?
job := new(JobResultResponse)
if err := json.Unmarshal(body, &job); err != nil {
return nil, err
}
// Error response
errorResponse := new(ErrorResponse)
// Successful response
resp := req.asyncResponse()
if job.JobID == "" || job.JobStatus != Pending {
if err := json.Unmarshal(*job.JobResult, resp); err != nil {
return job, err
}
return resp, nil
}
// we've got a pending job
result := &QueryAsyncJobResultResponse{
JobStatus: job.JobStatus,
}
for async.Retries > 0 && result.JobStatus == Pending {
time.Sleep(time.Duration(async.Delay) * time.Second)
async.Retries--
req := &QueryAsyncJobResult{JobID: job.JobID}
resp, err := exo.Request(req)
if err != nil {
return nil, err
}
result = resp.(*QueryAsyncJobResultResponse)
}
if result.JobStatus == Failure {
if err := json.Unmarshal(*result.JobResult, &errorResponse); err != nil {
return nil, err
}
return errorResponse, errorResponse
}
if result.JobStatus == Pending {
return result, fmt.Errorf("Maximum number of retries reached")
}
if err := json.Unmarshal(*result.JobResult, resp); err != nil {
if err := json.Unmarshal(*result.JobResult, errorResponse); err != nil {
return nil, err
}
return errorResponse, errorResponse
}
return resp, nil
}
// BooleanRequest performs a sync request on a boolean call
func (exo *Client) BooleanRequest(req Command) error {
resp, err := exo.Request(req)
if err != nil {
return err
}
return resp.(*booleanSyncResponse).Error()
}
// BooleanAsyncRequest performs a sync request on a boolean call
func (exo *Client) BooleanAsyncRequest(req AsyncCommand, async AsyncInfo) error {
resp, err := exo.AsyncRequest(req, async)
if err != nil {
return err
}
return resp.(*booleanAsyncResponse).Error()
}
// Request performs a sync request on a generic command
func (exo *Client) Request(req Command) (interface{}, error) {
body, err := exo.request(req.name(), req)
if err != nil {
return nil, err
}
resp := req.response()
if err := json.Unmarshal(body, resp); err != nil {
r := new(ErrorResponse)
if e := json.Unmarshal(body, r); e != nil {
return nil, r
}
return nil, err
}
return resp, nil
}
// request makes a Request while being close to the metal
func (exo *Client) request(command string, req interface{}) (json.RawMessage, error) {
params := url.Values{}
err := prepareValues("", &params, req)
if err != nil {
return nil, err
}
if hookReq, ok := req.(onBeforeHook); ok {
hookReq.onBeforeSend(&params)
}
params.Set("apikey", exo.apiKey)
params.Set("command", command)
params.Set("response", "json")
for k, _ := range params {
// This code is borrowed from net/url/url.go
// The way it's encoded by net/url doesn't match
// how CloudStack works.
var buf bytes.Buffer
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
arg := k + "=" + csEncode(params[k][0])
unencoded = append(unencoded, arg)
prefix := csEncode(k) + "="
for _, v := range params[k] {
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(prefix)
buf.WriteString(csEncode(v))
}
}
sign_string := strings.ToLower(strings.Join(unencoded, "&"))
mac.Write([]byte(sign_string))
query := buf.String()
mac := hmac.New(sha1.New, []byte(exo.apiSecret))
mac.Write([]byte(strings.ToLower(query)))
signature := csEncode(base64.StdEncoding.EncodeToString(mac.Sum(nil)))
query := params.Encode()
url := exo.endpoint + "?" + csQuotePlus(query) + "&signature=" + signature
resp, err := exo.client.Get(url)
reader := strings.NewReader(fmt.Sprintf("%s&signature=%s", csQuotePlus(query), signature))
resp, err := exo.client.Post(exo.endpoint, "application/x-www-form-urlencoded", reader)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return exo.ParseResponse(resp)
}
func (exo *Client) DetailedRequest(uri string, params string, method string, header http.Header) (json.RawMessage, error) {
url := exo.endpoint + uri
req, err := http.NewRequest(method, url, strings.NewReader(params))
body, err := exo.parseResponse(resp)
if err != nil {
return nil, err
}
req.Header = header
return body, nil
}
response, err := exo.client.Do(req)
if err != nil {
return nil, err
// prepareValues uses a command to build a POST request
//
// command is not a Command so it's easier to Test
func prepareValues(prefix string, params *url.Values, command interface{}) error {
value := reflect.ValueOf(command)
typeof := reflect.TypeOf(command)
// Going up the pointer chain to find the underlying struct
for typeof.Kind() == reflect.Ptr {
typeof = typeof.Elem()
value = value.Elem()
}
defer response.Body.Close()
return exo.ParseResponse(response)
for i := 0; i < typeof.NumField(); i++ {
field := typeof.Field(i)
val := value.Field(i)
tag := field.Tag
if json, ok := tag.Lookup("json"); ok {
n, required := extractJSONTag(field.Name, json)
name := prefix + n
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v := val.Int()
if v == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), field.Name, val.Kind())
}
} else {
(*params).Set(name, strconv.FormatInt(v, 10))
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v := val.Uint()
if v == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), field.Name, val.Kind())
}
} else {
(*params).Set(name, strconv.FormatUint(v, 10))
}
case reflect.Float32, reflect.Float64:
v := val.Float()
if v == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), field.Name, val.Kind())
}
} else {
(*params).Set(name, strconv.FormatFloat(v, 'f', -1, 64))
}
case reflect.String:
v := val.String()
if v == "" {
if required {
return fmt.Errorf("%s.%s (%v) is required, got \"\"", typeof.Name(), field.Name, val.Kind())
}
} else {
(*params).Set(name, v)
}
case reflect.Bool:
v := val.Bool()
if v == false {
if required {
params.Set(name, "false")
}
} else {
(*params).Set(name, "true")
}
case reflect.Slice:
switch field.Type.Elem().Kind() {
case reflect.Uint8:
switch field.Type {
case reflect.TypeOf(net.IPv4zero):
ip := (net.IP)(val.Bytes())
if ip == nil || ip.Equal(net.IPv4zero) {
if required {
return fmt.Errorf("%s.%s (%v) is required, got zero IPv4 address", typeof.Name(), field.Name, val.Kind())
}
} else {
(*params).Set(name, ip.String())
}
default:
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), field.Name, val.Kind())
}
} else {
v := val.Bytes()
(*params).Set(name, base64.StdEncoding.EncodeToString(v))
}
}
case reflect.String:
{
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), field.Name, val.Kind())
}
} else {
elems := make([]string, 0, val.Len())
for i := 0; i < val.Len(); i++ {
// XXX what if the value contains a comma? Double encode?
s := val.Index(i).String()
elems = append(elems, s)
}
(*params).Set(name, strings.Join(elems, ","))
}
}
default:
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), field.Name, val.Kind())
}
} else {
err := prepareList(name, params, val.Interface())
if err != nil {
return err
}
}
}
case reflect.Map:
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty map", typeof.Name(), field.Name, val.Kind())
}
} else {
err := prepareMap(name, params, val.Interface())
if err != nil {
return err
}
}
default:
if required {
return fmt.Errorf("Unsupported type %s.%s (%v)", typeof.Name(), field.Name, val.Kind())
}
}
} else {
log.Printf("[SKIP] %s.%s no json label found", typeof.Name(), field.Name)
}
}
return nil
}
func prepareList(prefix string, params *url.Values, slice interface{}) error {
value := reflect.ValueOf(slice)
for i := 0; i < value.Len(); i++ {
prepareValues(fmt.Sprintf("%s[%d].", prefix, i), params, value.Index(i).Interface())
}
return nil
}
func prepareMap(prefix string, params *url.Values, m interface{}) error {
value := reflect.ValueOf(m)
for i, key := range value.MapKeys() {
var keyName string
var keyValue string
switch key.Kind() {
case reflect.String:
keyName = key.String()
default:
return fmt.Errorf("Only map[string]string are supported (XXX)")
}
val := value.MapIndex(key)
switch val.Kind() {
case reflect.String:
keyValue = val.String()
default:
return fmt.Errorf("Only map[string]string are supported (XXX)")
}
params.Set(fmt.Sprintf("%s[%d].%s", prefix, i, keyName), keyValue)
}
return nil
}
// extractJSONTag returns the variable name or defaultName as well as if the field is required (!omitempty)
func extractJSONTag(defaultName, jsonTag string) (string, bool) {
tags := strings.Split(jsonTag, ",")
name := tags[0]
required := true
for _, tag := range tags {
if tag == "omitempty" {
required = false
}
}
if name == "" || name == "omitempty" {
name = defaultName
}
return name, required
}

302
vendor/github.com/exoscale/egoscale/security_groups.go generated vendored Normal file
View file

@ -0,0 +1,302 @@
package egoscale
import (
"net/url"
"strconv"
)
// SecurityGroup represent a firewalling set of rules
type SecurityGroup struct {
ID string `json:"id"`
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Name string `json:"name"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
VirtualMachineCount int `json:"virtualmachinecount,omitempty"` // CloudStack 4.6+
VirtualMachineIDs []string `json:"virtualmachineids,omitempty"` // CloudStack 4.6+
IngressRule []IngressRule `json:"ingressrule"`
EgressRule []EgressRule `json:"egressrule"`
Tags []ResourceTag `json:"tags,omitempty"`
JobID string `json:"jobid,omitempty"`
JobStatus JobStatusType `json:"jobstatus,omitempty"`
}
// ResourceType returns the type of the resource
func (*SecurityGroup) ResourceType() string {
return "SecurityGroup"
}
// IngressRule represents the ingress rule
type IngressRule struct {
RuleID string `json:"ruleid"`
Account string `json:"account,omitempty"`
Cidr string `json:"cidr,omitempty"`
Description string `json:"description,omitempty"`
IcmpType int `json:"icmptype,omitempty"`
IcmpCode int `json:"icmpcode,omitempty"`
StartPort int `json:"startport,omitempty"`
EndPort int `json:"endport,omitempty"`
Protocol string `json:"protocol,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
SecurityGroupID string `json:"securitygroupid,omitempty"`
SecurityGroupName string `json:"securitygroupname,omitempty"`
UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty"`
JobID string `json:"jobid,omitempty"`
JobStatus JobStatusType `json:"jobstatus,omitempty"`
}
// EgressRule represents the ingress rule
type EgressRule IngressRule
// UserSecurityGroup represents the traffic of another security group
type UserSecurityGroup struct {
Group string `json:"group,omitempty"`
Account string `json:"account,omitempty"`
}
// SecurityGroupResponse represents a generic security group response
type SecurityGroupResponse struct {
SecurityGroup SecurityGroup `json:"securitygroup"`
}
// CreateSecurityGroup represents a security group creation
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/createSecurityGroup.html
type CreateSecurityGroup struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
}
func (*CreateSecurityGroup) name() string {
return "createSecurityGroup"
}
func (*CreateSecurityGroup) response() interface{} {
return new(CreateSecurityGroupResponse)
}
// CreateSecurityGroupResponse represents a new security group
type CreateSecurityGroupResponse SecurityGroupResponse
// DeleteSecurityGroup represents a security group deletion
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/deleteSecurityGroup.html
type DeleteSecurityGroup struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"` // Mutually exclusive with name
Name string `json:"name,omitempty"` // Mutually exclusive with id
ProjectID string `json:"project,omitempty"`
}
func (*DeleteSecurityGroup) name() string {
return "deleteSecurityGroup"
}
func (*DeleteSecurityGroup) response() interface{} {
return new(booleanSyncResponse)
}
// AuthorizeSecurityGroupIngress (Async) represents the ingress rule creation
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/authorizeSecurityGroupIngress.html
type AuthorizeSecurityGroupIngress struct {
Account string `json:"account,omitempty"`
CidrList []string `json:"cidrlist,omitempty"`
Description string `json:"description,omitempty"`
DomainID string `json:"domainid,omitempty"`
IcmpType int `json:"icmptype,omitempty"`
IcmpCode int `json:"icmpcode,omitempty"`
StartPort int `json:"startport,omitempty"`
EndPort int `json:"endport,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Protocol string `json:"protocol,omitempty"`
SecurityGroupID string `json:"securitygroupid,omitempty"`
SecurityGroupName string `json:"securitygroupname,omitempty"`
UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty"`
}
func (*AuthorizeSecurityGroupIngress) name() string {
return "authorizeSecurityGroupIngress"
}
func (*AuthorizeSecurityGroupIngress) asyncResponse() interface{} {
return new(AuthorizeSecurityGroupIngressResponse)
}
func (req *AuthorizeSecurityGroupIngress) onBeforeSend(params *url.Values) error {
// ICMP code and type may be zero but can also be omitted...
if req.Protocol == "ICMP" {
params.Set("icmpcode", strconv.FormatInt(int64(req.IcmpCode), 10))
params.Set("icmptype", strconv.FormatInt(int64(req.IcmpType), 10))
}
return nil
}
// AuthorizeSecurityGroupIngressResponse represents the new egress rule
// /!\ the Cloud Stack API document is not fully accurate. /!\
type AuthorizeSecurityGroupIngressResponse SecurityGroupResponse
// AuthorizeSecurityGroupEgress (Async) represents the egress rule creation
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/authorizeSecurityGroupEgress.html
type AuthorizeSecurityGroupEgress AuthorizeSecurityGroupIngress
func (*AuthorizeSecurityGroupEgress) name() string {
return "authorizeSecurityGroupEgress"
}
func (*AuthorizeSecurityGroupEgress) asyncResponse() interface{} {
return new(AuthorizeSecurityGroupEgressResponse)
}
func (req *AuthorizeSecurityGroupEgress) onBeforeSend(params *url.Values) error {
return (*AuthorizeSecurityGroupIngress)(req).onBeforeSend(params)
}
// AuthorizeSecurityGroupEgressResponse represents the new egress rule
// /!\ the Cloud Stack API document is not fully accurate. /!\
type AuthorizeSecurityGroupEgressResponse CreateSecurityGroupResponse
// RevokeSecurityGroupIngress (Async) represents the ingress/egress rule deletion
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/revokeSecurityGroupIngress.html
type RevokeSecurityGroupIngress struct {
ID string `json:"id"`
}
func (*RevokeSecurityGroupIngress) name() string {
return "revokeSecurityGroupIngress"
}
func (*RevokeSecurityGroupIngress) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// RevokeSecurityGroupEgress (Async) represents the ingress/egress rule deletion
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/revokeSecurityGroupEgress.html
type RevokeSecurityGroupEgress struct {
ID string `json:"id"`
}
func (*RevokeSecurityGroupEgress) name() string {
return "revokeSecurityGroupEgress"
}
func (*RevokeSecurityGroupEgress) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ListSecurityGroups represents a search for security groups
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listSecurityGroups.html
type ListSecurityGroups struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Type string `json:"type,omitempty"`
SecurityGroupName string `json:"securitygroupname,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
}
func (*ListSecurityGroups) name() string {
return "listSecurityGroups"
}
func (*ListSecurityGroups) response() interface{} {
return new(ListSecurityGroupsResponse)
}
// ListSecurityGroupsResponse represents a list of security groups
type ListSecurityGroupsResponse struct {
Count int `json:"count"`
SecurityGroup []SecurityGroup `json:"securitygroup"`
}
// CreateIngressRule creates a set of ingress rules
//
// Deprecated: use the API directly
func (exo *Client) CreateIngressRule(req *AuthorizeSecurityGroupIngress, async AsyncInfo) ([]IngressRule, error) {
resp, err := exo.AsyncRequest(req, async)
if err != nil {
return nil, err
}
return resp.(*AuthorizeSecurityGroupIngressResponse).SecurityGroup.IngressRule, nil
}
// CreateEgressRule creates a set of egress rules
//
// Deprecated: use the API directly
func (exo *Client) CreateEgressRule(req *AuthorizeSecurityGroupEgress, async AsyncInfo) ([]EgressRule, error) {
resp, err := exo.AsyncRequest(req, async)
if err != nil {
return nil, err
}
return resp.(*AuthorizeSecurityGroupEgressResponse).SecurityGroup.EgressRule, nil
}
// CreateSecurityGroupWithRules create a security group with its rules
// Warning: it doesn't rollback in case of a failure!
//
// Deprecated: use the API directly
func (exo *Client) CreateSecurityGroupWithRules(name string, ingress []AuthorizeSecurityGroupIngress, egress []AuthorizeSecurityGroupEgress, async AsyncInfo) (*SecurityGroup, error) {
req := &CreateSecurityGroup{
Name: name,
}
resp, err := exo.Request(req)
if err != nil {
return nil, err
}
sg := resp.(*SecurityGroupResponse).SecurityGroup
reqs := make([]AsyncCommand, 0, len(ingress)+len(egress))
// Egress rules
for _, ereq := range egress {
ereq.SecurityGroupID = sg.ID
reqs = append(reqs, &ereq)
}
// Ingress rules
for _, ireq := range ingress {
ireq.SecurityGroupID = sg.ID
reqs = append(reqs, &ireq)
}
for _, r := range reqs {
_, err := exo.AsyncRequest(r, async)
if err != nil {
return nil, err
}
}
r, err := exo.Request(&ListSecurityGroups{
ID: sg.ID,
})
if err != nil {
return nil, err
}
sg = r.(*ListSecurityGroupsResponse).SecurityGroup[0]
return &sg, nil
}
// DeleteSecurityGroup deletes a security group
//
// Deprecated: use the API directly
func (exo *Client) DeleteSecurityGroup(name string) error {
req := &DeleteSecurityGroup{
Name: name,
}
return exo.BooleanRequest(req)
}

View file

@ -0,0 +1,65 @@
package egoscale
// ServiceOffering corresponds to the Compute Offerings
type ServiceOffering struct {
ID string `json:"id"`
CPUNumber int `json:"cpunumber"`
CPUSpeed int `json:"cpuspeed"`
Created string `json:"created"`
DefaultUse bool `json:"defaultuse,omitempty"`
DeploymentPlanner string `json:"deploymentplanner,omitempty"`
DiskBytesReadRate int64 `json:"diskBytesReadRate,omitempty"`
DiskBytesWriteRate int64 `json:"diskBytesWriteRate,omitempty"`
DiskIopsReadRate int64 `json:"diskIopsReadRate,omitempty"`
DiskIopsWriteRate int64 `json:"diskIopsWriteRate,omitempty"`
DisplayText string `json:"displaytext,omitempty"`
Domain string `json:"domain"`
DomainID string `json:"domainid"`
HostTags string `json:"hosttags,omitempty"`
HypervisorSnapshotReserve int `json:"hypervisorsnapshotreserve,omitempty"`
IsCustomized bool `json:"iscustomized,omitempty"`
IsCustomizedIops bool `json:"iscustomizediops,omitempty"`
IsSystem bool `json:"issystem,omitempty"`
IsVolatile bool `json:"isvolatile,omitempty"`
LimitCPUUse bool `json:"limitcpuuse,omitempty"`
MaxIops int64 `json:"maxiops,omitempty"`
Memory int `json:"memory,omitempty"`
MinIops int64 `json:"miniops,omitempty"`
Name string `json:"name,omitempty"`
NetworkRate int `json:"networkrate,omitempty"`
OfferHA bool `json:"offerha,omitempty"`
ServiceOfferingDetails map[string]string `json:"serviceofferingdetails,omitempty"`
StorageType string `json:"storagetype,omitempty"`
SystemVMType string `json:"systemvmtype,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
}
// ListServiceOfferings represents a query for service offerings
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listServiceOfferings.html
type ListServiceOfferings struct {
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
IsSystem bool `json:"issystem,omitempty"`
Keyword string `json:"keyword,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
SystemVMType string `json:"systemvmtype,omitempty"` // consoleproxy, secondarystoragevm, or domainrouter
VirtualMachineID string `json:"virtualmachineid,omitempty"`
}
func (*ListServiceOfferings) name() string {
return "listServiceOfferings"
}
func (*ListServiceOfferings) response() interface{} {
return new(ListServiceOfferingsResponse)
}
// ListServiceOfferingsResponse represents a list of service offerings
type ListServiceOfferingsResponse struct {
Count int `json:"count"`
ServiceOffering []ServiceOffering `json:"serviceoffering"`
}

120
vendor/github.com/exoscale/egoscale/snapshots.go generated vendored Normal file
View file

@ -0,0 +1,120 @@
package egoscale
// Snapshot represents a volume snapshot
type Snapshot struct {
ID string `json:"id"`
Account string `json:"account"`
Created string `json:"created,omitempty"`
Domain string `json:"domain"`
DomainID string `json:"domainid"`
IntervalType string `json:"intervaltype,omitempty"` // hourly, daily, weekly, monthly, ..., none
Name string `json:"name,omitempty"`
PhysicalSize int64 `json:"physicalsize"`
Project string `json:"project"`
ProjectID string `json:"projectid"`
Revertable bool `json:"revertable,omitempty"`
Size int64 `json:"size,omitempty"`
SnapshotType string `json:"snapshottype,omitempty"`
State string `json:"state"` // BackedUp, Creating, BackingUp, ...
VolumeID string `json:"volumeid"`
VolumeName string `json:"volumename,omitempty"`
VolumeType string `json:"volumetype,omitempty"`
ZoneID string `json:"zoneid"`
Tags []ResourceTag `json:"tags"`
JobID string `json:"jobid,omitempty"`
JobStatus JobStatusType `json:"jobstatus,omitempty"`
}
// ResourceType returns the type of the resource
func (*Snapshot) ResourceType() string {
return "Snapshot"
}
// CreateSnapshot represents a request to create a volume snapshot
//
// CloudStackAPI: http://cloudstack.apache.org/api/apidocs-4.10/apis/createSnapshot.html
type CreateSnapshot struct {
VolumeID string `json:"volumeid"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
PolicyID string `json:"policyid,omitempty"`
QuiesceVM bool `json:"quiescevm,omitempty"`
}
func (*CreateSnapshot) name() string {
return "createSnapshot"
}
func (*CreateSnapshot) asyncResponse() interface{} {
return new(CreateSnapshotResponse)
}
// CreateSnapshotResponse represents a freshly created snapshot
type CreateSnapshotResponse struct {
Snapshot Snapshot `json:"snapshot"`
}
// ListSnapshots lists the volume snapshots
//
// CloudStackAPI: http://cloudstack.apache.org/api/apidocs-4.10/apis/listSnapshots.html
type ListSnapshots struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IntervalType string `json:"intervaltype,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
SnapshotType string `json:"snapshottype,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
VolumeID string `json:"volumeid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListSnapshots) name() string {
return "listSnapshots"
}
func (*ListSnapshots) response() interface{} {
return new(ListSnapshotsResponse)
}
// ListSnapshotsResponse represents a list of volume snapshots
type ListSnapshotsResponse struct {
Count int `json:"count"`
Snapshot []Snapshot `json:"snapshot"`
}
// DeleteSnapshot represents the deletion of a volume snapshot
//
// CloudStackAPI: http://cloudstack.apache.org/api/apidocs-4.10/apis/deleteSnapshot.html
type DeleteSnapshot struct {
ID string `json:"id"`
}
func (*DeleteSnapshot) name() string {
return "deleteSnapshot"
}
func (*DeleteSnapshot) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// RevertSnapshot revert a volume snapshot
//
// CloudStackAPI: http://cloudstack.apache.org/api/apidocs-4.10/apis/revertSnapshot.html
type RevertSnapshot struct {
ID string `json:"id"`
}
func (*RevertSnapshot) name() string {
return "revertSnapshot"
}
func (*RevertSnapshot) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}

93
vendor/github.com/exoscale/egoscale/tags.go generated vendored Normal file
View file

@ -0,0 +1,93 @@
package egoscale
// Taggable represents a resource which can have tags attached
//
// This is a helper to fill the resourcetype of a CreateTags call
type Taggable interface {
// CloudStack resource type of the Taggable type
ResourceType() string
}
// ResourceTag is a tag associated with a resource
//
// http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.9/management.html
type ResourceTag struct {
Account string `json:"account,omitempty"`
Customer string `json:"customer,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Key string `json:"key"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
ResourceID string `json:"resourceid,omitempty"`
ResourceType string `json:"resourcetype,omitempty"`
Value string `json:"value"`
}
// CreateTags (Async) creates resource tag(s)
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/createTags.html
type CreateTags struct {
ResourceIDs []string `json:"resourceids"`
ResourceType string `json:"resourcetype"`
Tags []ResourceTag `json:"tags"`
Customer string `json:"customer,omitempty"`
}
func (*CreateTags) name() string {
return "createTags"
}
func (*CreateTags) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// DeleteTags (Async) deletes the resource tag(s)
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/deleteTags.html
type DeleteTags struct {
ResourceIDs []string `json:"resourceids"`
ResourceType string `json:"resourcetype"`
Tags []ResourceTag `json:"tags,omitempty"`
}
func (*DeleteTags) name() string {
return "deleteTags"
}
func (*DeleteTags) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ListTags list resource tag(s)
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listTags.html
type ListTags struct {
Account string `json:"account,omitempty"`
Customer string `json:"customer,omitempty"`
DomainID string `json:"domainid,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Key string `json:"key,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
ResourceID string `json:"resourceid,omitempty"`
ResourceType string `json:"resourcetype,omitempty"`
Value string `json:"value,omitempty"`
}
func (*ListTags) name() string {
return "listTags"
}
func (*ListTags) response() interface{} {
return new(ListTagsResponse)
}
// ListTagsResponse represents a list of resource tags
type ListTagsResponse struct {
Count int `json:"count"`
Tag []ResourceTag `json:"tag"`
}

76
vendor/github.com/exoscale/egoscale/templates.go generated vendored Normal file
View file

@ -0,0 +1,76 @@
package egoscale
// Template represents a machine to be deployed
type Template struct {
Account string `json:"account,omitempty"`
AccountID string `json:"accountid,omitempty"`
Bootable bool `json:"bootable,omitempty"`
Checksum string `json:"checksum,omitempty"`
Created string `json:"created,omitempty"`
CrossZones bool `json:"crossZones,omitempty"`
Details map[string]string `json:"details,omitempty"`
DisplayText string `json:"displaytext,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Format string `json:"format,omitempty"`
HostID string `json:"hostid,omitempty"`
HostName string `json:"hostname,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
ID string `json:"id,omitempty"`
IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty"`
IsExtractable bool `json:"isextractable,omitempty"`
IsFeatured bool `json:"isfeatured,omitempty"`
IsPublic bool `json:"ispublic,omitempty"`
IsReady bool `json:"isready,omitempty"`
Name string `json:"name,omitempty"`
OsTypeID string `json:"ostypeid,omitempty"`
OsTypeName string `json:"ostypename,omitempty"`
PasswordEnabled bool `json:"passwordenabled,omitempty"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
Removed string `json:"removed,omitempty"`
Size int64 `json:"size,omitempty"`
SourceTemplateID string `json:"sourcetemplateid,omitempty"`
SSHKeyEnabled bool `json:"sshkeyenabled,omitempty"`
Status string `json:"status,omitempty"`
Zoneid string `json:"zoneid,omitempty"`
Zonename string `json:"zonename,omitempty"`
}
// ResourceType returns the type of the resource
func (*Template) ResourceType() string {
return "Template"
}
// ListTemplates represents a template query filter
type ListTemplates struct {
TemplateFilter string `json:"templatefilter"` // featured, etc.
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ProjectID string `json:"projectid,omitempty"`
ShowRemoved bool `json:"showremoved,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListTemplates) name() string {
return "listTemplates"
}
func (*ListTemplates) response() interface{} {
return new(ListTemplatesResponse)
}
// ListTemplatesResponse represents a list of templates
type ListTemplatesResponse struct {
Count int `json:"count"`
Template []Template `json:"template"`
}

View file

@ -1,186 +1,163 @@
package egoscale
import (
"encoding/json"
"fmt"
"net/url"
"regexp"
"strings"
)
// GetSecurityGroups returns all security groups
//
// Deprecated: do it yourself
func (exo *Client) GetSecurityGroups() (map[string]SecurityGroup, error) {
var sgs map[string]SecurityGroup
params := url.Values{}
resp, err := exo.Request("listSecurityGroups", params)
resp, err := exo.Request(&ListSecurityGroups{})
if err != nil {
return nil, err
}
var r ListSecurityGroupsResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
sgs = make(map[string]SecurityGroup)
for _, sg := range r.SecurityGroups {
sgs[sg.Name] = *sg
for _, sg := range resp.(*ListSecurityGroupsResponse).SecurityGroup {
sgs[sg.Name] = sg
}
return sgs, nil
}
func (exo *Client) GetSecurityGroupId(name string) (string, error) {
params := url.Values{}
resp, err := exo.Request("listSecurityGroups", params)
// GetSecurityGroupID returns security group by name
//
// Deprecated: do it yourself
func (exo *Client) GetSecurityGroupID(name string) (string, error) {
resp, err := exo.Request(&ListSecurityGroups{SecurityGroupName: name})
if err != nil {
return "", err
}
var r ListSecurityGroupsResponse
err = json.Unmarshal(resp, &r)
if err != nil {
return "", err
}
for _, sg := range r.SecurityGroups {
for _, sg := range resp.(*ListSecurityGroupsResponse).SecurityGroup {
if sg.Name == name {
return sg.Id, nil
return sg.ID, nil
}
}
return "", nil
}
func (exo *Client) GetZones() (map[string]string, error) {
// GetAllZones returns all the zone id by name
//
// Deprecated: do it yourself
func (exo *Client) GetAllZones() (map[string]string, error) {
var zones map[string]string
params := url.Values{}
resp, err := exo.Request("listZones", params)
resp, err := exo.Request(&ListZones{})
if err != nil {
return nil, err
}
var r ListZonesResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
return zones, err
}
zones = make(map[string]string)
for _, zone := range r.Zones {
zones[zone.Name] = zone.Id
for _, zone := range resp.(*ListZonesResponse).Zone {
zones[strings.ToLower(zone.Name)] = zone.ID
}
return zones, nil
}
// GetProfiles returns a mapping of the service offerings by name
//
// Deprecated: do it yourself
func (exo *Client) GetProfiles() (map[string]string, error) {
var profiles map[string]string
params := url.Values{}
resp, err := exo.Request("listServiceOfferings", params)
profiles := make(map[string]string)
resp, err := exo.Request(&ListServiceOfferings{})
if err != nil {
return nil, err
return profiles, nil
}
var r ListServiceOfferingsResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
profiles = make(map[string]string)
for _, offering := range r.ServiceOfferings {
profiles[strings.ToLower(offering.Name)] = offering.Id
for _, offering := range resp.(*ListServiceOfferingsResponse).ServiceOffering {
profiles[strings.ToLower(offering.Name)] = offering.ID
}
return profiles, nil
}
// GetKeypairs returns the list of SSH keyPairs
//
// Deprecated: do it yourself
func (exo *Client) GetKeypairs() ([]SSHKeyPair, error) {
params := url.Values{}
resp, err := exo.Request("listSSHKeyPairs", params)
var keypairs []SSHKeyPair
resp, err := exo.Request(&ListSSHKeyPairs{})
if err != nil {
return nil, err
return keypairs, err
}
var r ListSSHKeyPairsResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
var keypairs = make([]SSHKeyPair, r.Count, r.Count)
for i, keypair := range r.SSHKeyPairs {
keypairs[i] = *keypair
r := resp.(*ListSSHKeyPairsResponse)
keypairs = make([]SSHKeyPair, r.Count)
for i, keypair := range r.SSHKeyPair {
keypairs[i] = keypair
}
return keypairs, nil
}
// GetAffinityGroups returns a mapping of the (anti-)affinity groups
//
// Deprecated: do it yourself
func (exo *Client) GetAffinityGroups() (map[string]string, error) {
var affinitygroups map[string]string
params := url.Values{}
resp, err := exo.Request("listAffinityGroups", params)
resp, err := exo.Request(&ListAffinityGroups{})
if err != nil {
return nil, err
}
var r ListAffinityGroupsResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
return affinitygroups, err
}
affinitygroups = make(map[string]string)
for _, affinitygroup := range r.AffinityGroups {
affinitygroups[affinitygroup.Name] = affinitygroup.Id
for _, affinitygroup := range resp.(*ListAffinityGroupsResponse).AffinityGroup {
affinitygroups[affinitygroup.Name] = affinitygroup.ID
}
return affinitygroups, nil
}
func (exo *Client) GetImages() (map[string]map[int]string, error) {
var images map[string]map[int]string
images = make(map[string]map[int]string)
params := url.Values{}
params.Set("templatefilter", "featured")
resp, err := exo.Request("listTemplates", params)
// GetImages list the available featured images and group them by name, then size.
//
// Deprecated: do it yourself
func (exo *Client) GetImages() (map[string]map[int64]string, error) {
var images map[string]map[int64]string
images = make(map[string]map[int64]string)
re := regexp.MustCompile(`^Linux (?P<name>.+?) (?P<version>[0-9.]+)\b`)
resp, err := exo.Request(&ListTemplates{
TemplateFilter: "featured",
ZoneID: "1", // XXX: Hack to list only CH-GVA
})
if err != nil {
return nil, err
return images, err
}
var r ListTemplatesResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
for _, template := range resp.(*ListTemplatesResponse).Template {
size := int64(template.Size >> 30) // B to GiB
fullname := strings.ToLower(template.Name)
if _, present := images[fullname]; !present {
images[fullname] = make(map[int64]string)
}
images[fullname][size] = template.ID
re := regexp.MustCompile(`^Linux (?P<name>.+?) (?P<version>[0-9.]+).*$`)
for _, template := range r.Templates {
size := int(template.Size / (1024 * 1024 * 1024))
submatch := re.FindStringSubmatch(template.Name)
if len(submatch) > 0 {
name := strings.Replace(strings.ToLower(submatch[1]), " ", "-", -1)
version := submatch[2]
image := fmt.Sprintf("%s-%s", name, version)
_, present := images[image]
if !present {
images[image] = make(map[int]string)
if _, present := images[image]; !present {
images[image] = make(map[int64]string)
}
images[image][size] = template.Id
images[fmt.Sprintf("%s-%s", name, version)][size] = template.Id
images[image][size] = template.ID
}
}
return images, nil
}
// GetTopology returns an big, yet incomplete view of the world
//
// Deprecated: will go away in the future
func (exo *Client) GetTopology() (*Topology, error) {
zones, err := exo.GetZones()
zones, err := exo.GetAllZones()
if err != nil {
return nil, err
}
@ -194,7 +171,7 @@ func (exo *Client) GetTopology() (*Topology, error) {
}
groups := make(map[string]string)
for k, v := range securityGroups {
groups[k] = v.Id
groups[k] = v.ID
}
keypairs, err := exo.GetKeypairs()
@ -212,6 +189,7 @@ func (exo *Client) GetTopology() (*Topology, error) {
if err != nil {
return nil, err
}
profiles, err := exo.GetProfiles()
if err != nil {
return nil, err
@ -219,9 +197,9 @@ func (exo *Client) GetTopology() (*Topology, error) {
topo := &Topology{
Zones: zones,
Profiles: profiles,
Images: images,
Keypairs: keynames,
Profiles: profiles,
AffinityGroups: affinitygroups,
SecurityGroups: groups,
}

View file

@ -1,10 +1,10 @@
package egoscale
import (
"encoding/json"
"net/http"
)
// Client represents the CloudStack API client
type Client struct {
client *http.Client
endpoint string
@ -12,519 +12,12 @@ type Client struct {
apiSecret string
}
type Error struct {
ErrorCode int `json:"errorcode"`
CSErrorCode int `json:"cserrorcode"`
ErrorText string `json:"errortext"`
}
type StandardResponse struct {
Success string `json:"success"`
DisplayText string `json:"displaytext"`
}
// Topology represents a view of the servers
type Topology struct {
Zones map[string]string
Images map[string]map[int]string
Images map[string]map[int64]string
Profiles map[string]string
Keypairs []string
SecurityGroups map[string]string
AffinityGroups map[string]string
}
type SecurityGroupRule struct {
Cidr string
IcmpType int
IcmpCode int
Port int
Protocol string
SecurityGroupId string
UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty"`
}
type UserSecurityGroup struct {
Group string `json:"group,omitempty"`
Account string `json:"account,omitempty"`
}
type MachineProfile struct {
Name string
SecurityGroups []string
Keypair string
Userdata string
ServiceOffering string
Template string
Zone string
AffinityGroups []string
}
type ListZonesResponse struct {
Count int `json:"count"`
Zones []*Zone `json:"zone"`
}
type Zone struct {
Allocationstate string `json:"allocationstate,omitempty"`
Description string `json:"description,omitempty"`
Displaytext string `json:"displaytext,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Domainname string `json:"domainname,omitempty"`
Id string `json:"id,omitempty"`
Internaldns1 string `json:"internaldns1,omitempty"`
Internaldns2 string `json:"internaldns2,omitempty"`
Ip6dns1 string `json:"ip6dns1,omitempty"`
Ip6dns2 string `json:"ip6dns2,omitempty"`
Localstorageenabled bool `json:"localstorageenabled,omitempty"`
Name string `json:"name,omitempty"`
Networktype string `json:"networktype,omitempty"`
Resourcedetails map[string]string `json:"resourcedetails,omitempty"`
Securitygroupsenabled bool `json:"securitygroupsenabled,omitempty"`
Vlan string `json:"vlan,omitempty"`
Zonetoken string `json:"zonetoken,omitempty"`
}
type ListServiceOfferingsResponse struct {
Count int `json:"count"`
ServiceOfferings []*ServiceOffering `json:"serviceoffering"`
}
type ServiceOffering struct {
Cpunumber int `json:"cpunumber,omitempty"`
Cpuspeed int `json:"cpuspeed,omitempty"`
Displaytext string `json:"displaytext,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Hosttags string `json:"hosttags,omitempty"`
Id string `json:"id,omitempty"`
Iscustomized bool `json:"iscustomized,omitempty"`
Issystem bool `json:"issystem,omitempty"`
Isvolatile bool `json:"isvolatile,omitempty"`
Memory int `json:"memory,omitempty"`
Name string `json:"name,omitempty"`
Networkrate int `json:"networkrate,omitempty"`
Serviceofferingdetails map[string]string `json:"serviceofferingdetails,omitempty"`
}
type ListTemplatesResponse struct {
Count int `json:"count"`
Templates []*Template `json:"template"`
}
type Template struct {
Account string `json:"account,omitempty"`
Accountid string `json:"accountid,omitempty"`
Bootable bool `json:"bootable,omitempty"`
Checksum string `json:"checksum,omitempty"`
Created string `json:"created,omitempty"`
CrossZones bool `json:"crossZones,omitempty"`
Details map[string]string `json:"details,omitempty"`
Displaytext string `json:"displaytext,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Format string `json:"format,omitempty"`
Hostid string `json:"hostid,omitempty"`
Hostname string `json:"hostname,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
Id string `json:"id,omitempty"`
Isdynamicallyscalable bool `json:"isdynamicallyscalable,omitempty"`
Isextractable bool `json:"isextractable,omitempty"`
Isfeatured bool `json:"isfeatured,omitempty"`
Ispublic bool `json:"ispublic,omitempty"`
Isready bool `json:"isready,omitempty"`
Name string `json:"name,omitempty"`
Ostypeid string `json:"ostypeid,omitempty"`
Ostypename string `json:"ostypename,omitempty"`
Passwordenabled bool `json:"passwordenabled,omitempty"`
Project string `json:"project,omitempty"`
Projectid string `json:"projectid,omitempty"`
Removed string `json:"removed,omitempty"`
Size int64 `json:"size,omitempty"`
Sourcetemplateid string `json:"sourcetemplateid,omitempty"`
Sshkeyenabled bool `json:"sshkeyenabled,omitempty"`
Status string `json:"status,omitempty"`
Zoneid string `json:"zoneid,omitempty"`
Zonename string `json:"zonename,omitempty"`
}
type ListSSHKeyPairsResponse struct {
Count int `json:"count"`
SSHKeyPairs []*SSHKeyPair `json:"sshkeypair"`
}
type SSHKeyPair struct {
Fingerprint string `json:"fingerprint,omitempty"`
Name string `json:"name,omitempty"`
}
type ListAffinityGroupsResponse struct {
Count int `json:"count"`
AffinityGroups []*AffinityGroup `json:"affinitygroup"`
}
type AffinityGroup struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Description string `json:"description,omitempty"`
Id string `json:"id,omitempty"`
Domainid string `json:"domainid,omitempty"`
Domain string `json:"domain,omitempty"`
Account string `json:"account,omitempty"`
}
type CreateAffinityGroupResponseWrapper struct {
Wrapped AffinityGroup `json:"affinitygroup"`
}
type ListSecurityGroupsResponse struct {
Count int `json:"count"`
SecurityGroups []*SecurityGroup `json:"securitygroup"`
}
type SecurityGroup struct {
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Project string `json:"project,omitempty"`
Projectid string `json:"projectid,omitempty"`
IngressRules []struct {
RuleId string `json:"ruleid,omitempty"`
Protocol string `json:"protocol,omitempty"`
StartPort int `json:"startport,omitempty"`
EndPort int `json:"endport,omitempty"`
Cidr string `json:"cidr,omitempty"`
IcmpCode int `json:"icmpcode,omitempty"`
IcmpType int `json:"icmptype,omitempty"`
Tags []string `json:"tags,omitempty"`
} `json:"ingressrule,omitempty"`
EgressRules []struct {
RuleId string `json:"ruleid,omitempty"`
Protocol string `json:"protocol,omitempty"`
StartPort int `json:"startport,omitempty"`
EndPort int `json:"endport,omitempty"`
Cidr string `json:"cidr,omitempty"`
IcmpCode int `json:"icmpcode,omitempty"`
IcmpType int `json:"icmptype,omitempty"`
Tags []string `json:"tags,omitempty"`
} `json:"egressrule,omitempty"`
Tags []string `json:"tags,omitempty"`
}
type CreateSecurityGroupResponseWrapper struct {
Wrapped CreateSecurityGroupResponse `json:"securitygroup"`
}
type CreateSecurityGroupResponse struct {
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Project string `json:"project,omitempty"`
Projectid string `json:"projectid,omitempty"`
}
type AuthorizeSecurityGroupIngressResponse struct {
JobID string `json:"jobid,omitempty"`
Account string `json:"account,omitempty"`
Cidr string `json:"cidr,omitempty"`
Endport int `json:"endport,omitempty"`
Icmpcode int `json:"icmpcode,omitempty"`
Icmptype int `json:"icmptype,omitempty"`
Protocol string `json:"protocol,omitempty"`
Ruleid string `json:"ruleid,omitempty"`
Securitygroupname string `json:"securitygroupname,omitempty"`
Startport int `json:"startport,omitempty"`
}
type AuthorizeSecurityGroupEgressResponse struct {
JobID string `json:"jobid,omitempty"`
Account string `json:"account,omitempty"`
Cidr string `json:"cidr,omitempty"`
Endport int `json:"endport,omitempty"`
Icmpcode int `json:"icmpcode,omitempty"`
Icmptype int `json:"icmptype,omitempty"`
Protocol string `json:"protocol,omitempty"`
Ruleid string `json:"ruleid,omitempty"`
Securitygroupname string `json:"securitygroupname,omitempty"`
Startport int `json:"startport,omitempty"`
}
type DeployVirtualMachineWrappedResponse struct {
Wrapped DeployVirtualMachineResponse `json:"virtualmachine"`
}
type DeployVirtualMachineResponse struct {
JobID string `json:"jobid,omitempty"`
Account string `json:"account,omitempty"`
Affinitygroup []struct {
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
VirtualmachineIds []string `json:"virtualmachineIds,omitempty"`
} `json:"affinitygroup,omitempty"`
Cpunumber int `json:"cpunumber,omitempty"`
Cpuspeed int `json:"cpuspeed,omitempty"`
Cpuused string `json:"cpuused,omitempty"`
Created string `json:"created,omitempty"`
Details map[string]string `json:"details,omitempty"`
Diskioread int64 `json:"diskioread,omitempty"`
Diskiowrite int64 `json:"diskiowrite,omitempty"`
Diskkbsread int64 `json:"diskkbsread,omitempty"`
Diskkbswrite int64 `json:"diskkbswrite,omitempty"`
Displayname string `json:"displayname,omitempty"`
Displayvm bool `json:"displayvm,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Forvirtualnetwork bool `json:"forvirtualnetwork,omitempty"`
Group string `json:"group,omitempty"`
Groupid string `json:"groupid,omitempty"`
Guestosid string `json:"guestosid,omitempty"`
Haenable bool `json:"haenable,omitempty"`
Hostid string `json:"hostid,omitempty"`
Hostname string `json:"hostname,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
Id string `json:"id,omitempty"`
Instancename string `json:"instancename,omitempty"`
Isdynamicallyscalable bool `json:"isdynamicallyscalable,omitempty"`
Isodisplaytext string `json:"isodisplaytext,omitempty"`
Isoid string `json:"isoid,omitempty"`
Isoname string `json:"isoname,omitempty"`
Keypair string `json:"keypair,omitempty"`
Memory int `json:"memory,omitempty"`
Name string `json:"name,omitempty"`
Networkkbsread int64 `json:"networkkbsread,omitempty"`
Networkkbswrite int64 `json:"networkkbswrite,omitempty"`
Nic []struct {
Broadcasturi string `json:"broadcasturi,omitempty"`
Gateway string `json:"gateway,omitempty"`
Id string `json:"id,omitempty"`
Ipaddress string `json:"ipaddress,omitempty"`
Isdefault bool `json:"isdefault,omitempty"`
Isolationuri string `json:"isolationuri,omitempty"`
Macaddress string `json:"macaddress,omitempty"`
Netmask string `json:"netmask,omitempty"`
Networkid string `json:"networkid,omitempty"`
Networkname string `json:"networkname,omitempty"`
Secondaryip []string `json:"secondaryip,omitempty"`
Traffictype string `json:"traffictype,omitempty"`
Type string `json:"type,omitempty"`
} `json:"nic,omitempty"`
Password string `json:"password,omitempty"`
Passwordenabled bool `json:"passwordenabled,omitempty"`
Project string `json:"project,omitempty"`
Projectid string `json:"projectid,omitempty"`
Publicip string `json:"publicip,omitempty"`
Publicipid string `json:"publicipid,omitempty"`
Rootdeviceid int64 `json:"rootdeviceid,omitempty"`
Rootdevicetype string `json:"rootdevicetype,omitempty"`
Serviceofferingid string `json:"serviceofferingid,omitempty"`
Serviceofferingname string `json:"serviceofferingname,omitempty"`
Servicestate string `json:"servicestate,omitempty"`
State string `json:"state,omitempty"`
Templatedisplaytext string `json:"templatedisplaytext,omitempty"`
Templateid string `json:"templateid,omitempty"`
Templatename string `json:"templatename,omitempty"`
Zoneid string `json:"zoneid,omitempty"`
Zonename string `json:"zonename,omitempty"`
}
type QueryAsyncJobResultResponse struct {
Accountid string `json:"accountid,omitempty"`
Cmd string `json:"cmd,omitempty"`
Created string `json:"created,omitempty"`
Jobinstanceid string `json:"jobinstanceid,omitempty"`
Jobinstancetype string `json:"jobinstancetype,omitempty"`
Jobprocstatus int `json:"jobprocstatus,omitempty"`
Jobresult json.RawMessage `json:"jobresult,omitempty"`
Jobresultcode int `json:"jobresultcode,omitempty"`
Jobresulttype string `json:"jobresulttype,omitempty"`
Jobstatus int `json:"jobstatus,omitempty"`
Userid string `json:"userid,omitempty"`
}
type ListVirtualMachinesResponse struct {
Count int `json:"count"`
VirtualMachines []*VirtualMachine `json:"virtualmachine"`
}
type VirtualMachine struct {
Account string `json:"account,omitempty"`
Cpunumber int `json:"cpunumber,omitempty"`
Cpuspeed int `json:"cpuspeed,omitempty"`
Cpuused string `json:"cpuused,omitempty"`
Created string `json:"created,omitempty"`
Details map[string]string `json:"details,omitempty"`
Diskioread int64 `json:"diskioread,omitempty"`
Diskiowrite int64 `json:"diskiowrite,omitempty"`
Diskkbsread int64 `json:"diskkbsread,omitempty"`
Diskkbswrite int64 `json:"diskkbswrite,omitempty"`
Displayname string `json:"displayname,omitempty"`
Displayvm bool `json:"displayvm,omitempty"`
Domain string `json:"domain,omitempty"`
Domainid string `json:"domainid,omitempty"`
Forvirtualnetwork bool `json:"forvirtualnetwork,omitempty"`
Group string `json:"group,omitempty"`
Groupid string `json:"groupid,omitempty"`
Guestosid string `json:"guestosid,omitempty"`
Haenable bool `json:"haenable,omitempty"`
Hostid string `json:"hostid,omitempty"`
Hostname string `json:"hostname,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
Id string `json:"id,omitempty"`
Instancename string `json:"instancename,omitempty"`
Isdynamicallyscalable bool `json:"isdynamicallyscalable,omitempty"`
Isodisplaytext string `json:"isodisplaytext,omitempty"`
Isoid string `json:"isoid,omitempty"`
Isoname string `json:"isoname,omitempty"`
Keypair string `json:"keypair,omitempty"`
Memory int `json:"memory,omitempty"`
Name string `json:"name,omitempty"`
Networkkbsread int64 `json:"networkkbsread,omitempty"`
Networkkbswrite int64 `json:"networkkbswrite,omitempty"`
Nic []struct {
Broadcasturi string `json:"broadcasturi,omitempty"`
Gateway string `json:"gateway,omitempty"`
Id string `json:"id,omitempty"`
Ip6address string `json:"ip6address,omitempty"`
Ip6cidr string `json:"ip6cidr,omitempty"`
Ip6gateway string `json:"ip6gateway,omitempty"`
Ipaddress string `json:"ipaddress,omitempty"`
Isdefault bool `json:"isdefault,omitempty"`
Isolationuri string `json:"isolationuri,omitempty"`
Macaddress string `json:"macaddress,omitempty"`
Netmask string `json:"netmask,omitempty"`
Networkid string `json:"networkid,omitempty"`
Networkname string `json:"networkname,omitempty"`
Secondaryip []struct {
Id string `json:"id,omitempty"`
IpAddress string `json:"ipaddress,omitempty"`
} `json:"secondaryip,omitempty"`
Traffictype string `json:"traffictype,omitempty"`
Type string `json:"type,omitempty"`
} `json:"nic,omitempty"`
Password string `json:"password,omitempty"`
Passwordenabled bool `json:"passwordenabled,omitempty"`
Project string `json:"project,omitempty"`
Projectid string `json:"projectid,omitempty"`
Publicip string `json:"publicip,omitempty"`
Publicipid string `json:"publicipid,omitempty"`
Rootdeviceid int64 `json:"rootdeviceid,omitempty"`
Rootdevicetype string `json:"rootdevicetype,omitempty"`
SecurityGroups []struct {
Account string `json:"account,omitempty"`
Description string `json:"description,omitempty"`
Id string `json:"id,omitempty"`
Name string `json:"name,omitemtpy"`
Tags []string `json:"tags,omitempty"`
} `json:"securitygroup,omitempty"`
Serviceofferingid string `json:"serviceofferingid,omitempty"`
Serviceofferingname string `json:"serviceofferingname,omitempty"`
Servicestate string `json:"servicestate,omitempty"`
State string `json:"state,omitempty"`
Templatedisplaytext string `json:"templatedisplaytext,omitempty"`
Templateid string `json:"templateid,omitempty"`
Templatename string `json:"templatename,omitempty"`
Zoneid string `json:"zoneid,omitempty"`
Zonename string `json:"zonename,omitempty"`
}
type StartVirtualMachineResponse struct {
JobID string `json:"jobid,omitempty"`
}
type StopVirtualMachineResponse struct {
JobID string `json:"jobid,omitempty"`
}
type DestroyVirtualMachineResponse struct {
JobID string `json:"jobid,omitempty"`
}
type RebootVirtualMachineResponse struct {
JobID string `json:"jobid,omitempty"`
}
type CreateSSHKeyPairWrappedResponse struct {
Wrapped CreateSSHKeyPairResponse `json:"keypair,omitempty"`
}
type CreateSSHKeyPairResponse struct {
Privatekey string `json:"privatekey,omitempty"`
}
type RemoveIpFromNicResponse struct {
JobID string `json:"jobid,omitempty"`
}
type AddIpToNicResponse struct {
Id string `json:"id"`
IpAddress string `json:"ipaddress"`
NetworkId string `json:"networkid"`
NicId string `json:"nicid"`
VmId string `json:"virtualmachineid"`
}
type CreateAffinityGroupResponse struct {
JobId string `json:"jobid,omitempty"`
}
type DeleteAffinityGroupResponse struct {
JobId string `json:"jobid,omitempty"`
}
type DeleteSSHKeyPairResponse struct {
Privatekey string `json:"privatekey,omitempty"`
}
type DNSDomain struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
RegistrantId int64 `json:"registrant_id,omitempty"`
Name string `json:"name"`
UnicodeName string `json:"unicode_name"`
Token string `json:"token"`
State string `json:"state"`
Language string `json:"language,omitempty"`
Lockable bool `json:"lockable"`
AutoRenew bool `json:"auto_renew"`
WhoisProtected bool `json:"whois_protected"`
RecordCount int64 `json:"record_count"`
ServiceCount int64 `json:"service_count"`
ExpiresOn string `json:"expires_on,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
type DNSDomainCreateRequest struct {
Domain struct {
Name string `json:"name"`
} `json:"domain"`
}
type DNSRecord struct {
Id int64 `json:"id,omitempty"`
DomainId int64 `json:"domain_id,omitempty"`
Name string `json:"name"`
Ttl int `json:"ttl,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
Content string `json:"content"`
RecordType string `json:"record_type"`
Prio int `json:"prio,omitempty"`
}
type DNSRecordResponse struct {
Record DNSRecord `json:"record"`
}
type DNSError struct {
Name []string `json:"name"`
}

43
vendor/github.com/exoscale/egoscale/users.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
package egoscale
// User represents a User
type User struct {
Account string `json:"account,omitempty"`
AccountID string `json:"accountid,omitempty"`
AccountType string `json:"accounttype,omitempty"`
APIKey string `json:"apikey,omitempty"`
Created string `json:"created,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Email string `json:"email,omitempty"`
FirstName string `json:"firstname,omitempty"`
ID string `json:"id,omitempty"`
IsCallerChildDomain bool `json:"iscallerchilddomain,omitempty"`
IsDefault bool `json:"isdefault,omitempty"`
LastName string `json:"lastname,omitempty"`
SecretKey string `json:"secretkey,omitempty"`
State string `json:"state,omitempty"`
UserName string `json:"username,omitempty"`
}
// RegisterUserKeys registers a new set of key of the given user
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/registerUserKeys.html
type RegisterUserKeys struct {
ID string `json:"id"`
}
func (*RegisterUserKeys) name() string {
return "registerUserKeys"
}
func (*RegisterUserKeys) response() interface{} {
return new(RegisterUserKeysResponse)
}
// RegisterUserKeysResponse represents a new set of UserKeys
//
// NB: only the APIKey and SecretKey will be filled
type RegisterUserKeysResponse struct {
UserKeys User `json:"userkeys"`
}

514
vendor/github.com/exoscale/egoscale/virtual_machines.go generated vendored Normal file
View file

@ -0,0 +1,514 @@
package egoscale
import "net"
// VirtualMachine reprents a virtual machine
type VirtualMachine struct {
ID string `json:"id,omitempty"`
Account string `json:"account,omitempty"`
ClusterID string `json:"clusterid,omitempty"`
ClusterName string `json:"clustername,omitempty"`
CPUNumber int64 `json:"cpunumber,omitempty"`
CPUSpeed int64 `json:"cpuspeed,omitempty"`
CPUUsed string `json:"cpuused,omitempty"`
Created string `json:"created,omitempty"`
Details map[string]string `json:"details,omitempty"`
DiskIoRead int64 `json:"diskioread,omitempty"`
DiskIoWrite int64 `json:"diskiowrite,omitempty"`
DiskKbsRead int64 `json:"diskkbsread,omitempty"`
DiskKbsWrite int64 `json:"diskkbswrite,omitempty"`
DiskOfferingID string `json:"diskofferingid,omitempty"`
DiskOfferingName string `json:"diskofferingname,omitempty"`
DisplayName string `json:"displayname,omitempty"`
DisplayVM bool `json:"displayvm,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty"`
Group string `json:"group,omitempty"`
GroupID string `json:"groupid,omitempty"`
GuestOsID string `json:"guestosid,omitempty"`
HaEnable bool `json:"haenable,omitempty"`
HostID string `json:"hostid,omitempty"`
HostName string `json:"hostname,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
InstanceName string `json:"instancename,omitempty"` // root only
IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty"`
IsoDisplayText string `json:"isodisplaytext,omitempty"`
IsoID string `json:"isoid,omitempty"`
IsoName string `json:"isoname,omitempty"`
KeyPair string `json:"keypair,omitempty"`
Memory int64 `json:"memory,omitempty"`
MemoryIntFreeKbs int64 `json:"memoryintfreekbs,omitempty"`
MemoryKbs int64 `json:"memorykbs,omitempty"`
MemoryTargetKbs int64 `json:"memorytargetkbs,omitempty"`
Name string `json:"name,omitempty"`
NetworkKbsRead int64 `json:"networkkbsread,omitempty"`
NetworkKbsWrite int64 `json:"networkkbswrite,omitempty"`
OsCategoryID string `json:"oscategoryid,omitempty"`
OsTypeID int64 `json:"ostypeid,omitempty"`
Password string `json:"password,omitempty"`
PasswordEnabled bool `json:"passwordenabled,omitempty"`
PCIDevices string `json:"pcidevices,omitempty"` // not in the doc
PodID string `json:"podid,omitempty"`
PodName string `json:"podname,omitempty"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
PublicIP string `json:"publicip,omitempty"`
PublicIPID string `json:"publicipid,omitempty"`
RootDeviceID int64 `json:"rootdeviceid,omitempty"`
RootDeviceType string `json:"rootdevicetype,omitempty"`
ServiceOfferingID string `json:"serviceofferingid,omitempty"`
ServiceOfferingName string `json:"serviceofferingname,omitempty"`
ServiceState string `json:"servicestate,omitempty"`
State string `json:"state,omitempty"`
TemplateDisplayText string `json:"templatedisplaytext,omitempty"`
TemplateID string `json:"templateid,omitempty"`
TemplateName string `json:"templatename,omitempty"`
UserID string `json:"userid,omitempty"` // not in the doc
UserName string `json:"username,omitempty"` // not in the doc
Vgpu string `json:"vgpu,omitempty"` // not in the doc
ZoneID string `json:"zoneid,omitempty"`
ZoneName string `json:"zonename,omitempty"`
AffinityGroup []AffinityGroup `json:"affinitygroup,omitempty"`
Nic []Nic `json:"nic,omitempty"`
SecurityGroup []SecurityGroup `json:"securitygroup,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
JobID string `json:"jobid,omitempty"`
JobStatus JobStatusType `json:"jobstatus,omitempty"`
}
// ResourceType returns the type of the resource
func (*VirtualMachine) ResourceType() string {
return "UserVM"
}
// NicsByType returns the corresponding interfaces base on the given type
func (vm *VirtualMachine) NicsByType(nicType string) []Nic {
nics := make([]Nic, 0)
for _, nic := range vm.Nic {
if nic.Type == nicType {
// XXX The CloudStack API forgets to specify it
nic.VirtualMachineID = vm.ID
nics = append(nics, nic)
}
}
return nics
}
// NicByNetworkID returns the corresponding interface based on the given NetworkID
func (vm *VirtualMachine) NicByNetworkID(networkID string) *Nic {
for _, nic := range vm.Nic {
if nic.NetworkID == networkID {
nic.VirtualMachineID = vm.ID
return &nic
}
}
return nil
}
// NicByID returns the corresponding interface base on its ID
func (vm *VirtualMachine) NicByID(nicID string) *Nic {
for _, nic := range vm.Nic {
if nic.ID == nicID {
nic.VirtualMachineID = vm.ID
return &nic
}
}
return nil
}
// IPToNetwork represents a mapping between ip and networks
type IPToNetwork struct {
IP string `json:"ip,omitempty"`
IPV6 string `json:"ipv6,omitempty"`
NetworkID string `json:"networkid,omitempty"`
}
// VirtualMachineResponse represents a generic Virtual Machine response
type VirtualMachineResponse struct {
VirtualMachine VirtualMachine `json:"virtualmachine"`
}
// DeployVirtualMachine (Async) represents the machine creation
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/deployVirtualMachine.html
type DeployVirtualMachine struct {
ServiceOfferingID string `json:"serviceofferingid"`
TemplateID string `json:"templateid"`
ZoneID string `json:"zoneid"`
Account string `json:"account,omitempty"`
AffinityGroupIDs []string `json:"affinitygroupids,omitempty"`
AffinityGroupNames []string `json:"affinitygroupnames,omitempty"`
CustomID string `json:"customid,omitempty"` // root only
DeploymentPlanner string `json:"deploymentplanner,omitempty"` // root only
Details map[string]string `json:"details,omitempty"`
DiskOfferingID string `json:"diskofferingid,omitempty"`
DisplayName string `json:"displayname,omitempty"`
DisplayVM bool `json:"displayvm,omitempty"`
DomainID string `json:"domainid,omitempty"`
Group string `json:"group,omitempty"`
HostID string `json:"hostid,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
IP6Address net.IP `json:"ip6address,omitempty"`
IPAddress net.IP `json:"ipaddress,omitempty"`
IPToNetworkList []IPToNetwork `json:"iptonetworklist,omitempty"`
Keyboard string `json:"keyboard,omitempty"`
KeyPair string `json:"keypair,omitempty"`
Name string `json:"name,omitempty"`
NetworkIDs []string `json:"networkids,omitempty"` // mutually exclusive with IPToNetworkList
ProjectID string `json:"projectid,omitempty"`
RootDiskSize int64 `json:"rootdisksize,omitempty"` // in GiB
SecurityGroupIDs []string `json:"securitygroupids,omitempty"`
SecurityGroupNames []string `json:"securitygroupnames,omitempty"` // does nothing, mutually exclusive
Size string `json:"size,omitempty"` // mutually exclusive with DiskOfferingID
StartVM bool `json:"startvm,omitempty"`
UserData string `json:"userdata,omitempty"` // the client is responsible to base64/gzip it
}
func (*DeployVirtualMachine) name() string {
return "deployVirtualMachine"
}
func (*DeployVirtualMachine) asyncResponse() interface{} {
return new(DeployVirtualMachineResponse)
}
// DeployVirtualMachineResponse represents a deployed VM instance
type DeployVirtualMachineResponse VirtualMachineResponse
// StartVirtualMachine (Async) represents the creation of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/startVirtualMachine.html
type StartVirtualMachine struct {
ID string `json:"id"`
DeploymentPlanner string `json:"deploymentplanner,omitempty"` // root only
HostID string `json:"hostid,omitempty"` // root only
}
func (*StartVirtualMachine) name() string {
return "startVirtualMachine"
}
func (*StartVirtualMachine) asyncResponse() interface{} {
return new(StartVirtualMachineResponse)
}
// StartVirtualMachineResponse represents a started VM instance
type StartVirtualMachineResponse VirtualMachineResponse
// StopVirtualMachine (Async) represents the stopping of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/stopVirtualMachine.html
type StopVirtualMachine struct {
ID string `json:"id"`
Forced bool `json:"forced,omitempty"`
}
func (*StopVirtualMachine) name() string {
return "stopVirtualMachine"
}
func (*StopVirtualMachine) asyncResponse() interface{} {
return new(StopVirtualMachineResponse)
}
// StopVirtualMachineResponse represents a stopped VM instance
type StopVirtualMachineResponse VirtualMachineResponse
// RebootVirtualMachine (Async) represents the rebooting of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/rebootVirtualMachine.html
type RebootVirtualMachine struct {
ID string `json:"id"`
}
func (*RebootVirtualMachine) name() string {
return "rebootVirtualMachine"
}
func (*RebootVirtualMachine) asyncResponse() interface{} {
return new(RebootVirtualMachineResponse)
}
// RebootVirtualMachineResponse represents a rebooted VM instance
type RebootVirtualMachineResponse VirtualMachineResponse
// RestoreVirtualMachine (Async) represents the restoration of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/restoreVirtualMachine.html
type RestoreVirtualMachine struct {
VirtualMachineID string `json:"virtualmachineid"`
TemplateID string `json:"templateid,omitempty"`
}
func (*RestoreVirtualMachine) name() string {
return "restoreVirtualMachine"
}
func (*RestoreVirtualMachine) asyncResponse() interface{} {
return new(RestoreVirtualMachineResponse)
}
// RestoreVirtualMachineResponse represents a restored VM instance
type RestoreVirtualMachineResponse VirtualMachineResponse
// RecoverVirtualMachine represents the restoration of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/recoverVirtualMachine.html
type RecoverVirtualMachine struct {
ID string `json:"virtualmachineid"`
}
func (*RecoverVirtualMachine) name() string {
return "recoverVirtualMachine"
}
func (*RecoverVirtualMachine) response() interface{} {
return new(RecoverVirtualMachineResponse)
}
// RecoverVirtualMachineResponse represents a recovered VM instance
type RecoverVirtualMachineResponse VirtualMachineResponse
// DestroyVirtualMachine (Async) represents the destruction of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/destroyVirtualMachine.html
type DestroyVirtualMachine struct {
ID string `json:"id"`
Expunge bool `json:"expunge,omitempty"`
}
func (*DestroyVirtualMachine) name() string {
return "destroyVirtualMachine"
}
func (*DestroyVirtualMachine) asyncResponse() interface{} {
return new(DestroyVirtualMachineResponse)
}
// DestroyVirtualMachineResponse represents a destroyed VM instance
type DestroyVirtualMachineResponse VirtualMachineResponse
// UpdateVirtualMachine represents the update of the virtual machine
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/updateVirtualMachine.html
type UpdateVirtualMachine struct {
ID string `json:"id"`
CustomID string `json:"customid,omitempty"` // root only
Details map[string]string `json:"details,omitempty"`
DisplayName string `json:"displayname,omitempty"`
DisplayVM bool `json:"displayvm,omitempty"`
Group string `json:"group,omitempty"`
HAEnable bool `json:"haenable,omitempty"`
IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty"`
Name string `json:"name,omitempty"` // must reboot
OsTypeID int64 `json:"ostypeid,omitempty"`
SecurityGroupIDs []string `json:"securitygroupids,omitempty"`
UserData string `json:"userdata,omitempty"`
}
func (*UpdateVirtualMachine) name() string {
return "updateVirtualMachine"
}
func (*UpdateVirtualMachine) response() interface{} {
return new(UpdateVirtualMachineResponse)
}
// UpdateVirtualMachineResponse represents an updated VM instance
type UpdateVirtualMachineResponse VirtualMachineResponse
// ExpungeVirtualMachine represents the annihilation of a VM
type ExpungeVirtualMachine struct {
ID string `json:"id"`
}
func (*ExpungeVirtualMachine) name() string {
return "expungeVirtualMachine"
}
func (*ExpungeVirtualMachine) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ScaleVirtualMachine (Async) represents the scaling of a VM
//
// ChangeServiceForVirtualMachine does the same thing but returns the
// new Virtual Machine which is more consistent with the rest of the API.
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/scaleVirtualMachine.html
type ScaleVirtualMachine struct {
ID string `json:"id"`
ServiceOfferingID string `json:"serviceofferingid"`
Details map[string]string `json:"details,omitempty"`
}
func (*ScaleVirtualMachine) name() string {
return "scaleVirtualMachine"
}
func (*ScaleVirtualMachine) asyncResponse() interface{} {
return new(booleanAsyncResponse)
}
// ChangeServiceForVirtualMachine represents the scaling of a VM
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/changeServiceForVirtualMachine.html
type ChangeServiceForVirtualMachine ScaleVirtualMachine
func (*ChangeServiceForVirtualMachine) name() string {
return "changeServiceForVirtualMachine"
}
func (*ChangeServiceForVirtualMachine) response() interface{} {
return new(ChangeServiceForVirtualMachineResponse)
}
// ChangeServiceForVirtualMachineResponse represents an changed VM instance
type ChangeServiceForVirtualMachineResponse VirtualMachineResponse
// ResetPasswordForVirtualMachine (Async) represents the scaling of a VM
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/resetPasswordForVirtualMachine.html
type ResetPasswordForVirtualMachine ScaleVirtualMachine
func (*ResetPasswordForVirtualMachine) name() string {
return "resetPasswordForVirtualMachine"
}
func (*ResetPasswordForVirtualMachine) asyncResponse() interface{} {
return new(ResetPasswordForVirtualMachineResponse)
}
// ResetPasswordForVirtualMachineResponse represents the updated vm
type ResetPasswordForVirtualMachineResponse VirtualMachineResponse
// GetVMPassword asks for an encrypted password
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/getVMPassword.html
type GetVMPassword struct {
ID string `json:"id"`
}
func (*GetVMPassword) name() string {
return "getVMPassword"
}
func (*GetVMPassword) response() interface{} {
return new(GetVMPasswordResponse)
}
// GetVMPasswordResponse represents the encrypted password
type GetVMPasswordResponse struct {
// Base64 encrypted password for the VM
EncryptedPassword string `json:"encryptedpassword"`
}
// ListVirtualMachines represents a search for a VM
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listVirtualMachine.html
type ListVirtualMachines struct {
Account string `json:"account,omitempty"`
AffinityGroupID string `json:"affinitygroupid,omitempty"`
Details map[string]string `json:"details,omitempty"`
DisplayVM bool `json:"displayvm,omitempty"` // root only
DomainID string `json:"domainid,omitempty"`
ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty"`
GroupID string `json:"groupid,omitempty"`
HostID string `json:"hostid,omitempty"`
Hypervisor string `json:"hypervisor,omitempty"`
ID string `json:"id,omitempty"`
IDs []string `json:"ids,omitempty"` // mutually exclusive with id
IsoID string `json:"isoid,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
KeyPair string `json:"keypair,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Name string `json:"name,omitempty"`
NetworkID string `json:"networkid,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
PodID string `json:"podid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
ServiceOfferindID string `json:"serviceofferingid,omitempty"`
State string `json:"state,omitempty"` // Running, Stopped, Present, ...
StorageID string `json:"storageid,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
TemplateID string `json:"templateid,omitempty"`
UserID string `json:"userid,omitempty"`
VpcID string `json:"vpcid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListVirtualMachines) name() string {
return "listVirtualMachines"
}
func (*ListVirtualMachines) response() interface{} {
return new(ListVirtualMachinesResponse)
}
// ListVirtualMachinesResponse represents a list of virtual machines
type ListVirtualMachinesResponse struct {
Count int `json:"count"`
VirtualMachine []VirtualMachine `json:"virtualmachine"`
}
// AddNicToVirtualMachine (Async) adds a NIC to a VM
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/addNicToVirtualMachine.html
type AddNicToVirtualMachine struct {
NetworkID string `json:"networkid"`
VirtualMachineID string `json:"virtualmachineid"`
IPAddress net.IP `json:"ipaddress,omitempty"`
}
func (*AddNicToVirtualMachine) name() string {
return "addNicToVirtualMachine"
}
func (*AddNicToVirtualMachine) asyncResponse() interface{} {
return new(AddNicToVirtualMachineResponse)
}
// AddNicToVirtualMachineResponse represents the modified VM
type AddNicToVirtualMachineResponse VirtualMachineResponse
// RemoveNicFromVirtualMachine (Async) removes a NIC from a VM
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/removeNicFromVirtualMachine.html
type RemoveNicFromVirtualMachine struct {
NicID string `json:"nicid"`
VirtualMachineID string `json:"virtualmachineid"`
}
func (*RemoveNicFromVirtualMachine) name() string {
return "removeNicFromVirtualMachine"
}
func (*RemoveNicFromVirtualMachine) asyncResponse() interface{} {
return new(RemoveNicFromVirtualMachineResponse)
}
// RemoveNicFromVirtualMachineResponse represents the modified VM
type RemoveNicFromVirtualMachineResponse VirtualMachineResponse
// UpdateDefaultNicForVirtualMachine (Async) adds a NIC to a VM
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/updateDefaultNicForVirtualMachine.html
type UpdateDefaultNicForVirtualMachine struct {
NetworkID string `json:"networkid"`
VirtualMachineID string `json:"virtualmachineid"`
IPAddress net.IP `json:"ipaddress,omitempty"`
}
func (*UpdateDefaultNicForVirtualMachine) name() string {
return "updateDefaultNicForVirtualMachine"
}
func (*UpdateDefaultNicForVirtualMachine) asyncResponse() interface{} {
return new(UpdateDefaultNicForVirtualMachineResponse)
}
// UpdateDefaultNicForVirtualMachineResponse represents the modified VM
type UpdateDefaultNicForVirtualMachineResponse VirtualMachineResponse

View file

@ -1,159 +0,0 @@
package egoscale
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"strings"
)
func (exo *Client) CreateVirtualMachine(p MachineProfile) (string, error) {
params := url.Values{}
params.Set("serviceofferingid", p.ServiceOffering)
params.Set("templateid", p.Template)
params.Set("zoneid", p.Zone)
params.Set("displayname", p.Name)
if len(p.Userdata) > 0 {
params.Set("userdata", base64.StdEncoding.EncodeToString([]byte(p.Userdata)))
}
if len(p.Keypair) > 0 {
params.Set("keypair", p.Keypair)
}
if len(p.AffinityGroups) > 0 {
params.Set("affinitygroupnames", strings.Join(p.AffinityGroups, ","))
}
params.Set("securitygroupids", strings.Join(p.SecurityGroups, ","))
resp, err := exo.Request("deployVirtualMachine", params)
if err != nil {
return "", err
}
var r DeployVirtualMachineResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobID, nil
}
func (exo *Client) StartVirtualMachine(id string) (string, error) {
params := url.Values{}
params.Set("id", id)
resp, err := exo.Request("startVirtualMachine", params)
if err != nil {
return "", err
}
var r StartVirtualMachineResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobID, nil
}
func (exo *Client) StopVirtualMachine(id string) (string, error) {
params := url.Values{}
params.Set("id", id)
resp, err := exo.Request("stopVirtualMachine", params)
if err != nil {
return "", err
}
var r StopVirtualMachineResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobID, nil
}
func (exo *Client) RebootVirtualMachine(id string) (string, error) {
params := url.Values{}
params.Set("id", id)
resp, err := exo.Request("rebootVirtualMachine", params)
if err != nil {
return "", err
}
var r RebootVirtualMachineResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobID, nil
}
func (exo *Client) DestroyVirtualMachine(id string) (string, error) {
params := url.Values{}
params.Set("id", id)
resp, err := exo.Request("destroyVirtualMachine", params)
if err != nil {
return "", err
}
var r DestroyVirtualMachineResponse
if err := json.Unmarshal(resp, &r); err != nil {
return "", err
}
return r.JobID, nil
}
func (exo *Client) GetVirtualMachine(id string) (*VirtualMachine, error) {
params := url.Values{}
params.Set("id", id)
resp, err := exo.Request("listVirtualMachines", params)
if err != nil {
return nil, err
}
var r ListVirtualMachinesResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
if len(r.VirtualMachines) == 1 {
machine := r.VirtualMachines[0]
return machine, nil
} else {
return nil, fmt.Errorf("cannot retrieve virtualmachine with id %s", id)
}
}
func (exo *Client) ListVirtualMachines() ([]*VirtualMachine, error) {
resp, err := exo.Request("listVirtualMachines", url.Values{})
if err != nil {
return nil, err
}
var r ListVirtualMachinesResponse
if err := json.Unmarshal(resp, &r); err != nil {
return nil, err
}
return r.VirtualMachines, nil
}

106
vendor/github.com/exoscale/egoscale/vm_groups.go generated vendored Normal file
View file

@ -0,0 +1,106 @@
package egoscale
// InstanceGroup represents a group of VM
type InstanceGroup struct {
ID string `json:"id"`
Account string `json:"account,omitempty"`
Created string `json:"created,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Name string `json:"name,omitempty"`
Project string `json:"project,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
// InstanceGroupResponse represents a VM group
type InstanceGroupResponse struct {
InstanceGroup InstanceGroup `json:"instancegroup"`
}
// CreateInstanceGroup creates a VM group
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/createInstanceGroup.html
type CreateInstanceGroup struct {
Name string `json:"name"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*CreateInstanceGroup) name() string {
return "createInstanceGroup"
}
func (*CreateInstanceGroup) response() interface{} {
return new(CreateInstanceGroupResponse)
}
// CreateInstanceGroupResponse represents a freshly created VM group
type CreateInstanceGroupResponse InstanceGroupResponse
// UpdateInstanceGroup creates a VM group
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/updateInstanceGroup.html
type UpdateInstanceGroup struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
}
func (*UpdateInstanceGroup) name() string {
return "updateInstanceGroup"
}
func (*UpdateInstanceGroup) response() interface{} {
return new(UpdateInstanceGroupResponse)
}
// UpdateInstanceGroupResponse represents an updated VM group
type UpdateInstanceGroupResponse InstanceGroupResponse
// DeleteInstanceGroup creates a VM group
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/deleteInstanceGroup.html
type DeleteInstanceGroup struct {
Name string `json:"name"`
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*DeleteInstanceGroup) name() string {
return "deleteInstanceGroup"
}
func (*DeleteInstanceGroup) response() interface{} {
return new(booleanSyncResponse)
}
// ListInstanceGroups lists VM groups
//
// CloudStack API: http://cloudstack.apache.org/api/apidocs-4.10/apis/listInstanceGroups.html
type ListInstanceGroups struct {
Account string `json:"account,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
State string `json:"state,omitempty"`
ProjectID string `json:"projectid,omitempty"`
}
func (*ListInstanceGroups) name() string {
return "listInstanceGroups"
}
func (*ListInstanceGroups) response() interface{} {
return new(ListInstanceGroupsResponse)
}
// ListInstanceGroupsResponse represents a list of instance groups
type ListInstanceGroupsResponse struct {
Count int `json:"count"`
InstanceGroup []InstanceGroup `json:"instancegroup"`
}

121
vendor/github.com/exoscale/egoscale/volumes.go generated vendored Normal file
View file

@ -0,0 +1,121 @@
package egoscale
import (
"fmt"
)
// Volume represents a volume linked to a VM
type Volume struct {
ID string `json:"id"`
Account string `json:"account,omitempty"`
Attached string `json:"attached,omitempty"`
ChainInfo string `json:"chaininfo,omitempty"`
Created string `json:"created,omitempty"`
Destroyed bool `json:"destroyed,omitempty"`
DisplayVolume bool `json:"displayvolume,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
Name string `json:"name,omitempty"`
QuiesceVM bool `json:"quiescevm,omitempty"`
ServiceOfferingDisplayText string `json:"serviceofferingdisplaytext,omitempty"`
ServiceOfferingID string `json:"serviceofferingid,omitempty"`
ServiceOfferingName string `json:"serviceofferingname,omitempty"`
Size uint64 `json:"size,omitempty"`
State string `json:"state,omitempty"`
Type string `json:"type,omitempty"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
VMName string `json:"vmname,omitempty"`
VMState string `json:"vmstate,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
ZoneName string `json:"zonename,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
JobID string `json:"jobid,omitempty"`
JobStatus JobStatusType `json:"jobstatus,omitempty"`
}
// ResourceType returns the type of the resource
func (*Volume) ResourceType() string {
return "Volume"
}
// ResizeVolume (Async) resizes a volume
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/resizeVolume.html
type ResizeVolume struct {
ID string `json:"id"`
DiskOfferingID string `json:"diskofferingid,omitempty"`
ShrinkOk bool `json:"shrinkok,omitempty"`
Size int64 `json:"size,omitempty"` // in GiB
}
func (*ResizeVolume) name() string {
return "resizeVolume"
}
func (*ResizeVolume) asyncResponse() interface{} {
return new(ResizeVolumeResponse)
}
// ResizeVolumeResponse represents the new Volume
type ResizeVolumeResponse struct {
Volume Volume `json:"volume"`
}
// ListVolumes represents a query listing volumes
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listVolumes.html
type ListVolumes struct {
Account string `json:"account,omitempty"`
DiskOfferingID string `json:"diskoffering,omitempty"`
DisplayVolume string `json:"displayvolume,omitempty"` // root only
DomainID string `json:"domainid,omitempty"`
HostID string `json:"hostid,omitempty"`
ID string `json:"id,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty"`
Keyword string `json:"keyword,omitempty"`
ListAll bool `json:"listall,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
PodID string `json:"podid,omitempty"`
ProjectID string `json:"projectid,omitempty"`
StorageID string `json:"storageid,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
Type string `json:"type,omitempty"`
VirtualMachineID string `json:"virtualmachineid,omitempty"`
ZoneID string `json:"zoneid,omitempty"`
}
func (*ListVolumes) name() string {
return "listVolumes"
}
func (*ListVolumes) response() interface{} {
return new(ListVolumesResponse)
}
// ListVolumesResponse represents a list of volumes
type ListVolumesResponse struct {
Count int `json:"count"`
Volume []Volume `json:"volume"`
}
// GetRootVolumeForVirtualMachine returns the root volume of a VM
//
// Deprecated: helper function shouldn't be used
func (exo *Client) GetRootVolumeForVirtualMachine(virtualMachineID string) (*Volume, error) {
resp, err := exo.Request(&ListVolumes{
VirtualMachineID: virtualMachineID,
Type: "ROOT",
})
if err != nil {
return nil, err
}
r := resp.(*ListVolumesResponse)
if r.Count != 1 {
return nil, fmt.Errorf("Expected exactly one volume for %v, got %d", virtualMachineID, r.Count)
}
return &(r.Volume[0]), nil
}

60
vendor/github.com/exoscale/egoscale/zones.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
package egoscale
import "net"
// Zone represents a data center
type Zone struct {
ID string `json:"id"`
AllocationState string `json:"allocationstate,omitempty"`
Capacity string `json:"capacity,omitempty"`
Description string `json:"description,omitempty"`
DhcpProvider string `json:"dhcpprovider,omitempty"`
DisplayText string `json:"displaytext,omitempty"`
DNS1 net.IP `json:"dns1,omitempty"`
DNS2 net.IP `json:"dns2,omitempty"`
Domain string `json:"domain,omitempty"`
DomainID string `json:"domainid,omitempty"`
DomainName string `json:"domainname,omitempty"`
GuestCidrAddress string `json:"guestcidraddress,omitempty"`
InternalDNS1 net.IP `json:"internaldns1,omitempty"`
InternalDNS2 net.IP `json:"internaldns2,omitempty"`
IP6DNS1 net.IP `json:"ip6dns1,omitempty"`
IP6DNS2 net.IP `json:"ip6dns2,omitempty"`
LocalStorageEnabled bool `json:"localstorageenabled,omitempty"`
Name string `json:"name,omitempty"`
NetworkType string `json:"networktype,omitempty"`
ResourceDetails map[string]string `json:"resourcedetails,omitempty"`
SecurityGroupsEnabled bool `json:"securitygroupsenabled,omitempty"`
Vlan string `json:"vlan,omitempty"`
ZoneToken string `json:"zonetoken,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
}
// ListZones represents a query for zones
//
// CloudStack API: https://cloudstack.apache.org/api/apidocs-4.10/apis/listZones.html
type ListZones struct {
Available bool `json:"available,omitempty"`
DomainID string `json:"domainid,omitempty"`
ID string `json:"id,omitempty"`
Keyword string `json:"keyword,omitempty"`
Name string `json:"name,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ShowCapacities bool `json:"showcapacities,omitempty"`
Tags []ResourceTag `json:"tags,omitempty"`
}
func (*ListZones) name() string {
return "listZones"
}
func (*ListZones) response() interface{} {
return new(ListZonesResponse)
}
// ListZonesResponse represents a list of zones
type ListZonesResponse struct {
Count int `json:"count"`
Zone []Zone `json:"zone"`
}

View file

@ -18,6 +18,7 @@ var UserAgent string
// HTTPClient is an HTTP client with a reasonable timeout value.
var HTTPClient = http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,

View file

@ -0,0 +1,214 @@
// Package cloudxns implements a DNS provider for solving the DNS-01 challenge
// using cloudxns DNS.
package cloudxns
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"time"
"github.com/xenolf/lego/acme"
)
const cloudXNSBaseURL = "https://www.cloudxns.net/api2/"
// DNSProvider is an implementation of the acme.ChallengeProvider interface
type DNSProvider struct {
apiKey string
secretKey string
}
// NewDNSProvider returns a DNSProvider instance configured for cloudxns.
// Credentials must be passed in the environment variables: CLOUDXNS_API_KEY
// and CLOUDXNS_SECRET_KEY.
func NewDNSProvider() (*DNSProvider, error) {
apiKey := os.Getenv("CLOUDXNS_API_KEY")
secretKey := os.Getenv("CLOUDXNS_SECRET_KEY")
return NewDNSProviderCredentials(apiKey, secretKey)
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for cloudxns.
func NewDNSProviderCredentials(apiKey, secretKey string) (*DNSProvider, error) {
if apiKey == "" || secretKey == "" {
return nil, fmt.Errorf("CloudXNS credentials missing")
}
return &DNSProvider{
apiKey: apiKey,
secretKey: secretKey,
}, nil
}
// Present creates a TXT record to fulfil the dns-01 challenge.
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
zoneID, err := c.getHostedZoneID(fqdn)
if err != nil {
return err
}
return c.addTxtRecord(zoneID, fqdn, value, ttl)
}
// CleanUp removes the TXT record matching the specified parameters.
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
zoneID, err := c.getHostedZoneID(fqdn)
if err != nil {
return err
}
recordID, err := c.findTxtRecord(zoneID, fqdn)
if err != nil {
return err
}
return c.delTxtRecord(recordID, zoneID)
}
func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
type Data struct {
ID string `json:"id"`
Domain string `json:"domain"`
}
authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
if err != nil {
return "", err
}
result, err := c.makeRequest("GET", "domain", nil)
if err != nil {
return "", err
}
var domains []Data
err = json.Unmarshal(result, &domains)
if err != nil {
return "", err
}
for _, data := range domains {
if data.Domain == authZone {
return data.ID, nil
}
}
return "", fmt.Errorf("Zone %s not found in cloudxns for domain %s", authZone, fqdn)
}
func (c *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
result, err := c.makeRequest("GET", fmt.Sprintf("record/%s?host_id=0&offset=0&row_num=2000", zoneID), nil)
if err != nil {
return "", err
}
var records []cloudXNSRecord
err = json.Unmarshal(result, &records)
if err != nil {
return "", err
}
for _, record := range records {
if record.Host == acme.UnFqdn(fqdn) && record.Type == "TXT" {
return record.RecordID, nil
}
}
return "", fmt.Errorf("No existing record found for %s", fqdn)
}
func (c *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
id, err := strconv.Atoi(zoneID)
if err != nil {
return err
}
payload := cloudXNSRecord{
ID: id,
Host: acme.UnFqdn(fqdn),
Value: value,
Type: "TXT",
LineID: 1,
TTL: ttl,
}
body, err := json.Marshal(payload)
if err != nil {
return err
}
_, err = c.makeRequest("POST", "record", body)
if err != nil {
return err
}
return nil
}
func (c *DNSProvider) delTxtRecord(recordID, zoneID string) error {
_, err := c.makeRequest("DELETE", fmt.Sprintf("record/%s/%s", recordID, zoneID), nil)
return err
}
func (c *DNSProvider) hmac(url, date, body string) string {
sum := md5.Sum([]byte(c.apiKey + url + body + date + c.secretKey))
return hex.EncodeToString(sum[:])
}
func (c *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMessage, error) {
type APIResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data json.RawMessage `json:"data,omitempty"`
}
url := cloudXNSBaseURL + uri
req, err := http.NewRequest(method, url, bytes.NewReader(body))
if err != nil {
return nil, err
}
requestDate := time.Now().Format(time.RFC1123Z)
req.Header.Set("API-KEY", c.apiKey)
req.Header.Set("API-REQUEST-DATE", requestDate)
req.Header.Set("API-HMAC", c.hmac(url, requestDate, string(body)))
req.Header.Set("API-FORMAT", "json")
resp, err := acme.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var r APIResponse
err = json.NewDecoder(resp.Body).Decode(&r)
if err != nil {
return nil, err
}
if r.Code != 1 {
return nil, fmt.Errorf("CloudXNS API Error: %s", r.Message)
}
return r.Data, nil
}
type cloudXNSRecord struct {
ID int `json:"domain_id,omitempty"`
RecordID string `json:"record_id,omitempty"`
Host string `json:"host"`
Value string `json:"value"`
Type string `json:"type"`
LineID int `json:"line_id,string"`
TTL int `json:"ttl,string"`
}

View file

@ -8,6 +8,7 @@ import (
"github.com/xenolf/lego/providers/dns/auroradns"
"github.com/xenolf/lego/providers/dns/azure"
"github.com/xenolf/lego/providers/dns/cloudflare"
"github.com/xenolf/lego/providers/dns/cloudxns"
"github.com/xenolf/lego/providers/dns/digitalocean"
"github.com/xenolf/lego/providers/dns/dnsimple"
"github.com/xenolf/lego/providers/dns/dnsmadeeasy"
@ -15,8 +16,9 @@ import (
"github.com/xenolf/lego/providers/dns/dyn"
"github.com/xenolf/lego/providers/dns/exoscale"
"github.com/xenolf/lego/providers/dns/gandi"
"github.com/xenolf/lego/providers/dns/godaddy"
"github.com/xenolf/lego/providers/dns/gandiv5"
"github.com/xenolf/lego/providers/dns/googlecloud"
"github.com/xenolf/lego/providers/dns/godaddy"
"github.com/xenolf/lego/providers/dns/linode"
"github.com/xenolf/lego/providers/dns/namecheap"
"github.com/xenolf/lego/providers/dns/ns1"
@ -39,6 +41,8 @@ func NewDNSChallengeProviderByName(name string) (acme.ChallengeProvider, error)
provider, err = auroradns.NewDNSProvider()
case "cloudflare":
provider, err = cloudflare.NewDNSProvider()
case "cloudxns":
provider, err = cloudxns.NewDNSProvider()
case "digitalocean":
provider, err = digitalocean.NewDNSProvider()
case "dnsimple":
@ -53,6 +57,8 @@ func NewDNSChallengeProviderByName(name string) (acme.ChallengeProvider, error)
provider, err = exoscale.NewDNSProvider()
case "gandi":
provider, err = gandi.NewDNSProvider()
case "gandiv5":
provider, err = gandiv5.NewDNSProvider()
case "gcloud":
provider, err = googlecloud.NewDNSProvider()
case "godaddy":

View file

@ -48,25 +48,25 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
return err
}
recordId, err := c.FindExistingRecordId(zone, recordName)
recordID, err := c.FindExistingRecordId(zone, recordName)
if err != nil {
return err
}
record := egoscale.DNSRecord{
Name: recordName,
Ttl: ttl,
TTL: ttl,
Content: value,
RecordType: "TXT",
}
if recordId == 0 {
if recordID == 0 {
_, err := c.client.CreateRecord(zone, record)
if err != nil {
return errors.New("Error while creating DNS record: " + err.Error())
}
} else {
record.Id = recordId
record.ID = recordID
_, err := c.client.UpdateRecord(zone, record)
if err != nil {
return errors.New("Error while updating DNS record: " + err.Error())
@ -84,17 +84,13 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
return err
}
recordId, err := c.FindExistingRecordId(zone, recordName)
recordID, err := c.FindExistingRecordId(zone, recordName)
if err != nil {
return err
}
if recordId != 0 {
record := egoscale.DNSRecord{
Id: recordId,
}
err = c.client.DeleteRecord(zone, record)
if recordID != 0 {
err = c.client.DeleteRecord(zone, recordID)
if err != nil {
return errors.New("Error while deleting DNS record: " + err.Error())
}
@ -106,13 +102,13 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
// Query Exoscale to find an existing record for this name.
// Returns nil if no record could be found
func (c *DNSProvider) FindExistingRecordId(zone, recordName string) (int64, error) {
responses, err := c.client.GetRecords(zone)
records, err := c.client.GetRecords(zone)
if err != nil {
return -1, errors.New("Error while retrievening DNS records: " + err.Error())
}
for _, response := range responses {
if response.Record.Name == recordName {
return response.Record.Id, nil
for _, record := range records {
if record.Name == recordName {
return record.ID, nil
}
}
return 0, nil

View file

@ -0,0 +1,203 @@
// Package gandiv5 implements a DNS provider for solving the DNS-01
// challenge using Gandi LiveDNS api.
package gandiv5
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/xenolf/lego/acme"
)
// Gandi API reference: http://doc.livedns.gandi.net/
var (
// endpoint is the Gandi API endpoint used by Present and
// CleanUp. It is overridden during tests.
endpoint = "https://dns.api.gandi.net/api/v5"
// findZoneByFqdn determines the DNS zone of an fqdn. It is overridden
// during tests.
findZoneByFqdn = acme.FindZoneByFqdn
)
// inProgressInfo contains information about an in-progress challenge
type inProgressInfo struct {
fieldName string
authZone string
}
// DNSProvider is an implementation of the
// acme.ChallengeProviderTimeout interface that uses Gandi's LiveDNS
// API to manage TXT records for a domain.
type DNSProvider struct {
apiKey string
inProgressFQDNs map[string]inProgressInfo
inProgressMu sync.Mutex
}
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
// Credentials must be passed in the environment variable: GANDIV5_API_KEY.
func NewDNSProvider() (*DNSProvider, error) {
apiKey := os.Getenv("GANDIV5_API_KEY")
return NewDNSProviderCredentials(apiKey)
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for Gandi.
func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
if apiKey == "" {
return nil, fmt.Errorf("Gandi DNS: No Gandi API Key given")
}
return &DNSProvider{
apiKey: apiKey,
inProgressFQDNs: make(map[string]inProgressInfo),
}, nil
}
// Present creates a TXT record using the specified parameters.
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
if ttl < 300 {
ttl = 300 // 300 is gandi minimum value for ttl
}
// find authZone
authZone, err := findZoneByFqdn(fqdn, acme.RecursiveNameservers)
if err != nil {
return fmt.Errorf("Gandi DNS: findZoneByFqdn failure: %v", err)
}
// determine name of TXT record
if !strings.HasSuffix(
strings.ToLower(fqdn), strings.ToLower("."+authZone)) {
return fmt.Errorf(
"Gandi DNS: unexpected authZone %s for fqdn %s", authZone, fqdn)
}
name := fqdn[:len(fqdn)-len("."+authZone)]
// acquire lock and check there is not a challenge already in
// progress for this value of authZone
d.inProgressMu.Lock()
defer d.inProgressMu.Unlock()
// add TXT record into authZone
err = d.addTXTRecord(acme.UnFqdn(authZone), name, value, ttl)
if err != nil {
return err
}
// save data necessary for CleanUp
d.inProgressFQDNs[fqdn] = inProgressInfo{
authZone: authZone,
fieldName: name,
}
return nil
}
// CleanUp removes the TXT record matching the specified parameters.
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
// acquire lock and retrieve authZone
d.inProgressMu.Lock()
defer d.inProgressMu.Unlock()
if _, ok := d.inProgressFQDNs[fqdn]; !ok {
// if there is no cleanup information then just return
return nil
}
fieldName := d.inProgressFQDNs[fqdn].fieldName
authZone := d.inProgressFQDNs[fqdn].authZone
delete(d.inProgressFQDNs, fqdn)
// delete TXT record from authZone
err := d.deleteTXTRecord(acme.UnFqdn(authZone), fieldName)
if err != nil {
return err
}
return nil
}
// Timeout returns the values (20*time.Minute, 20*time.Second) which
// are used by the acme package as timeout and check interval values
// when checking for DNS record propagation with Gandi.
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return 20 * time.Minute, 20 * time.Second
}
// types for JSON method calls and parameters
type addFieldRequest struct {
RRSetTTL int `json:"rrset_ttl"`
RRSetValues []string `json:"rrset_values"`
}
type deleteFieldRequest struct {
Delete bool `json:"delete"`
}
// types for JSON responses
type responseStruct struct {
Message string `json:"message"`
}
// POSTing/Marshalling/Unmarshalling
func (d *DNSProvider) sendRequest(method string, resource string, payload interface{}) (*responseStruct, error) {
url := fmt.Sprintf("%s/%s", endpoint, resource)
body, err := json.Marshal(payload)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, url, bytes.NewReader(body))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
if len(d.apiKey) > 0 {
req.Header.Set("X-Api-Key", d.apiKey)
}
client := &http.Client{Timeout: time.Duration(10 * time.Second)}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("Gandi DNS: request failed with HTTP status code %d", resp.StatusCode)
}
var response responseStruct
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil && method != "DELETE" {
return nil, err
}
return &response, nil
}
// functions to perform API actions
func (d *DNSProvider) addTXTRecord(domain string, name string, value string, ttl int) error {
target := fmt.Sprintf("domains/%s/records/%s/TXT", domain, name)
response, err := d.sendRequest("PUT", target, addFieldRequest{
RRSetTTL: ttl,
RRSetValues: []string{value},
})
if response != nil {
fmt.Printf("Gandi DNS: %s\n", response.Message)
}
return err
}
func (d *DNSProvider) deleteTXTRecord(domain string, name string) error {
target := fmt.Sprintf("domains/%s/records/%s/TXT", domain, name)
response, err := d.sendRequest("DELETE", target, deleteFieldRequest{
Delete: true,
})
if response != nil && response.Message == "" {
fmt.Printf("Gandi DNS: Zone record deleted\n")
}
return err
}

View file

@ -257,12 +257,11 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
if c.host.Path != "/" {
path = c.host.Path
}
if c.apiVersion > 0 {
if !strings.HasPrefix(uri, "api/v") {
uri = "/api/v" + strconv.Itoa(c.apiVersion) + uri
} else {
uri = "/" + uri
}
if !strings.HasPrefix(uri, "/") {
uri = "/" + uri
}
if c.apiVersion > 0 && !strings.HasPrefix(uri, "/api/v") {
uri = "/api/v" + strconv.Itoa(c.apiVersion) + uri
}
url := c.host.Scheme + "://" + c.host.Host + path + uri
req, err := http.NewRequest(method, url, body)