exoscale: update library (#800)

This commit is contained in:
Yoan Blanc 2019-02-18 10:49:41 +01:00 committed by Ludovic Fernandez
parent d891600a89
commit 7cdfe9b36b
70 changed files with 3173 additions and 1869 deletions

6
Gopkg.lock generated
View file

@ -192,12 +192,12 @@
version = "v0.21.0" version = "v0.21.0"
[[projects]] [[projects]]
digest = "1:e68d50b8dc605565eb62df1c2b2c67fa729e5b55aa1a6c81456eecbe0326ecdb" digest = "1:9013e4c7a6ff077dcb478aa75524aa73b5763136efb4efe8949b18d9b90dd212"
name = "github.com/exoscale/egoscale" name = "github.com/exoscale/egoscale"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "67368ae928a70cb5cb44ecf6f418ee33a1ade044" revision = "4acc53d7aa0960f007acf1daedef69a6d24d8d1f"
version = "v0.11.6" version = "v0.14.0"
[[projects]] [[projects]]
digest = "1:aa3ed0a71c4e66e4ae6486bf97a3f4cab28edc78df2e50c5ad01dc7d91604b88" digest = "1:aa3ed0a71c4e66e4ae6486bf97a3f4cab28edc78df2e50c5ad01dc7d91604b88"

View file

@ -90,7 +90,7 @@
name = "github.com/transip/gotransip" name = "github.com/transip/gotransip"
[[constraint]] [[constraint]]
version = "0.11.1" version = "0.14.0"
name = "github.com/exoscale/egoscale" name = "github.com/exoscale/egoscale"
[[constraint]] [[constraint]]

View file

@ -2,6 +2,7 @@
package exoscale package exoscale
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
@ -12,7 +13,7 @@ import (
"github.com/xenolf/lego/platform/config/env" "github.com/xenolf/lego/platform/config/env"
) )
const defaultBaseURL = "https://api.exoscale.ch/dns" const defaultBaseURL = "https://api.exoscale.com/dns"
// Config is used to configure the creation of the DNSProvider // Config is used to configure the creation of the DNSProvider
type Config struct { type Config struct {
@ -81,6 +82,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
// Present creates a TXT record to fulfill the dns-01 challenge. // Present creates a TXT record to fulfill the dns-01 challenge.
func (d *DNSProvider) Present(domain, token, keyAuth string) error { func (d *DNSProvider) Present(domain, token, keyAuth string) error {
ctx := context.Background()
fqdn, value := dns01.GetRecord(domain, keyAuth) fqdn, value := dns01.GetRecord(domain, keyAuth)
zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain) zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
if err != nil { if err != nil {
@ -100,7 +102,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
RecordType: "TXT", RecordType: "TXT",
} }
_, err := d.client.CreateRecord(zone, record) _, err := d.client.CreateRecord(ctx, zone, record)
if err != nil { if err != nil {
return errors.New("Error while creating DNS record: " + err.Error()) return errors.New("Error while creating DNS record: " + err.Error())
} }
@ -113,7 +115,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
RecordType: "TXT", RecordType: "TXT",
} }
_, err := d.client.UpdateRecord(zone, record) _, err := d.client.UpdateRecord(ctx, zone, record)
if err != nil { if err != nil {
return errors.New("Error while updating DNS record: " + err.Error()) return errors.New("Error while updating DNS record: " + err.Error())
} }
@ -124,6 +126,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
// CleanUp removes the record matching the specified parameters. // CleanUp removes the record matching the specified parameters.
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
ctx := context.Background()
fqdn, _ := dns01.GetRecord(domain, keyAuth) fqdn, _ := dns01.GetRecord(domain, keyAuth)
zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain) zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
if err != nil { if err != nil {
@ -136,7 +139,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
} }
if recordID != 0 { if recordID != 0 {
err = d.client.DeleteRecord(zone, recordID) err = d.client.DeleteRecord(ctx, zone, recordID)
if err != nil { if err != nil {
return errors.New("Error while deleting DNS record: " + err.Error()) return errors.New("Error while deleting DNS record: " + err.Error())
} }
@ -154,7 +157,8 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
// FindExistingRecordID Query Exoscale to find an existing record for this name. // FindExistingRecordID Query Exoscale to find an existing record for this name.
// Returns nil if no record could be found // Returns nil if no record could be found
func (d *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, error) { func (d *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, error) {
records, err := d.client.GetRecords(zone) ctx := context.Background()
records, err := d.client.GetRecords(ctx, zone)
if err != nil { if err != nil {
return -1, errors.New("Error while retrievening DNS records: " + err.Error()) return -1, errors.New("Error while retrievening DNS records: " + err.Error())
} }

View file

@ -1,32 +1,12 @@
package egoscale package egoscale
import "fmt"
// 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 int16
//go:generate stringer -type AccountType
const (
// UserAccount represents a User
UserAccount AccountType = 0
// AdminAccount represents an Admin
AdminAccount AccountType = 1
// DomainAdminAccount represents a Domain Admin
DomainAdminAccount AccountType = 2
)
// Account provides the detailed account information // Account provides the detailed account information
type Account struct { type Account struct {
AccountDetails map[string]string `json:"accountdetails,omitempty" doc:"details for the account"` AccountDetails map[string]string `json:"accountdetails,omitempty" doc:"details for the account"`
AccountType AccountType `json:"accounttype,omitempty" doc:"account type (admin, domain-admin, user)"`
CPUAvailable string `json:"cpuavailable,omitempty" doc:"the total number of cpu cores available to be created for this account"` CPUAvailable string `json:"cpuavailable,omitempty" doc:"the total number of cpu cores available to be created for this account"`
CPULimit string `json:"cpulimit,omitempty" doc:"the total number of cpu cores the account can own"` CPULimit string `json:"cpulimit,omitempty" doc:"the total number of cpu cores the account can own"`
CPUTotal int64 `json:"cputotal,omitempty" doc:"the total number of cpu cores owned by account"` CPUTotal int64 `json:"cputotal,omitempty" doc:"the total number of cpu cores owned by account"`
DefaultZoneID *UUID `json:"defaultzoneid,omitempty" doc:"the default zone of the account"` DefaultZoneID *UUID `json:"defaultzoneid,omitempty" doc:"the default zone of the account"`
Domain string `json:"domain,omitempty" doc:"name of the Domain the account belongs too"`
DomainID *UUID `json:"domainid,omitempty" doc:"id of the Domain the account belongs too"`
EipLimit string `json:"eiplimit,omitempty" doc:"the total number of public elastic ip addresses this account can acquire"` EipLimit string `json:"eiplimit,omitempty" doc:"the total number of public elastic ip addresses this account can acquire"`
Groups []string `json:"groups,omitempty" doc:"the list of acl groups that account belongs to"` Groups []string `json:"groups,omitempty" doc:"the list of acl groups that account belongs to"`
ID *UUID `json:"id,omitempty" doc:"the id of the account"` ID *UUID `json:"id,omitempty" doc:"the id of the account"`
@ -74,55 +54,23 @@ type Account struct {
// ListRequest builds the ListAccountsGroups request // ListRequest builds the ListAccountsGroups request
func (a Account) ListRequest() (ListCommand, error) { func (a Account) ListRequest() (ListCommand, error) {
return &ListAccounts{ return &ListAccounts{
ID: a.ID, ID: a.ID,
DomainID: a.DomainID, State: a.State,
AccountType: a.AccountType,
State: a.State,
}, nil }, nil
} }
//go:generate go run generate/main.go -interface=Listable ListAccounts
// ListAccounts represents a query to display the accounts // ListAccounts represents a query to display the accounts
type ListAccounts struct { type ListAccounts struct {
AccountType AccountType `json:"accounttype,omitempty" doc:"list accounts by account type. Valid account types are 1 (admin), 2 (domain-admin), and 0 (user)."` ID *UUID `json:"id,omitempty" doc:"List account by account ID"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` IsCleanUpRequired *bool `json:"iscleanuprequired,omitempty" doc:"list accounts by cleanuprequired attribute (values are true or false)"`
ID *UUID `json:"id,omitempty" doc:"list account by account ID"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
IsCleanUpRequired *bool `json:"iscleanuprequired,omitempty" doc:"list accounts by cleanuprequired attribute (values are true or false)"` Name string `json:"name,omitempty" doc:"List account by account name"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` Page int `json:"page,omitempty"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` PageSize int `json:"pagesize,omitempty"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` State string `json:"state,omitempty" doc:"List accounts by state. Valid states are enabled, disabled, and locked."`
Name string `json:"name,omitempty" doc:"list account by account name"` _ bool `name:"listAccounts" description:"Lists accounts and provides detailed account information for listed accounts"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
State string `json:"state,omitempty" doc:"list accounts by state. Valid states are enabled, disabled, and locked."`
_ bool `name:"listAccounts" description:"Lists accounts and provides detailed account information for listed accounts"`
}
func (ListAccounts) response() interface{} {
return new(ListAccountsResponse)
}
// SetPage sets the current page
func (ls *ListAccounts) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListAccounts) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListAccounts) each(resp interface{}, callback IterateItemFunc) {
vms, ok := resp.(*ListAccountsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListAccountsResponse expected, got %T", resp))
return
}
for i := range vms.Account {
if !callback(&vms.Account[i], nil) {
break
}
}
} }
// ListAccountsResponse represents a list of accounts // ListAccountsResponse represents a list of accounts
@ -130,32 +78,3 @@ type ListAccountsResponse struct {
Count int `json:"count"` Count int `json:"count"`
Account []Account `json:"account"` Account []Account `json:"account"`
} }
// EnableAccount represents the activation of an account
type EnableAccount struct {
Account string `json:"account,omitempty" doc:"Enables specified account."`
DomainID *UUID `json:"domainid,omitempty" doc:"Enables specified account in this domain."`
ID *UUID `json:"id,omitempty" doc:"Account id"`
_ bool `name:"enableAccount" description:"Enables an account"`
}
func (EnableAccount) response() interface{} {
return new(Account)
}
// DisableAccount (Async) represents the deactivation of an account
type DisableAccount struct {
Lock *bool `json:"lock" doc:"If true, only lock the account; else disable the account"`
Account string `json:"account,omitempty" doc:"Disables specified account."`
DomainID *UUID `json:"domainid,omitempty" doc:"Disables specified account in this domain."`
ID *UUID `json:"id,omitempty" doc:"Account id"`
_ bool `name:"disableAccount" description:"Disables an account"`
}
func (DisableAccount) response() interface{} {
return new(AsyncJobResult)
}
func (DisableAccount) asyncResponse() interface{} {
return new(Account)
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListAccounts) Response() interface{} {
return new(ListAccountsResponse)
}
// ListRequest returns itself
func (ls *ListAccounts) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListAccounts) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListAccounts) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListAccounts) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListAccountsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListAccountsResponse was expected, got %T", resp))
return
}
for i := range items.Account {
if !callback(&items.Account[i], nil) {
break
}
}
}

View file

@ -1,16 +0,0 @@
// Code generated by "stringer -type AccountType"; DO NOT EDIT.
package egoscale
import "strconv"
const _AccountType_name = "UserAccountAdminAccountDomainAdminAccount"
var _AccountType_index = [...]uint8{0, 11, 23, 41}
func (i AccountType) String() string {
if i < 0 || i >= AccountType(len(_AccountType_index)-1) {
return "AccountType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _AccountType_name[_AccountType_index[i]:_AccountType_index[i+1]]
}

View file

@ -8,14 +8,10 @@ import (
// IPAddress represents an IP Address // IPAddress represents an IP Address
type IPAddress struct { type IPAddress struct {
Account string `json:"account,omitempty" doc:"the account the public IP address is associated with"`
Allocated string `json:"allocated,omitempty" doc:"date the public IP address was acquired"` Allocated string `json:"allocated,omitempty" doc:"date the public IP address was acquired"`
Associated string `json:"associated,omitempty" doc:"date the public IP address was associated"` Associated string `json:"associated,omitempty" doc:"date the public IP address was associated"`
AssociatedNetworkID *UUID `json:"associatednetworkid,omitempty" doc:"the ID of the Network associated with the IP address"` AssociatedNetworkID *UUID `json:"associatednetworkid,omitempty" doc:"the ID of the Network associated with the IP address"`
AssociatedNetworkName string `json:"associatednetworkname,omitempty" doc:"the name of the Network associated with the IP address"` AssociatedNetworkName string `json:"associatednetworkname,omitempty" doc:"the name of the Network associated with the IP address"`
Domain string `json:"domain,omitempty" doc:"the domain the public IP address is associated with"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID the public IP address is associated with"`
ForDisplay bool `json:"fordisplay,omitempty" doc:"is public ip for display to the regular user"`
ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"` ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"`
ID *UUID `json:"id,omitempty" doc:"public IP address id"` ID *UUID `json:"id,omitempty" doc:"public IP address id"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"public IP address"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"public IP address"`
@ -48,9 +44,7 @@ func (IPAddress) ResourceType() string {
// ListRequest builds the ListAdresses request // ListRequest builds the ListAdresses request
func (ipaddress IPAddress) ListRequest() (ListCommand, error) { func (ipaddress IPAddress) ListRequest() (ListCommand, error) {
req := &ListPublicIPAddresses{ req := &ListPublicIPAddresses{
Account: ipaddress.Account,
AssociatedNetworkID: ipaddress.AssociatedNetworkID, AssociatedNetworkID: ipaddress.AssociatedNetworkID,
DomainID: ipaddress.DomainID,
ID: ipaddress.ID, ID: ipaddress.ID,
IPAddress: ipaddress.IPAddress, IPAddress: ipaddress.IPAddress,
PhysicalNetworkID: ipaddress.PhysicalNetworkID, PhysicalNetworkID: ipaddress.PhysicalNetworkID,
@ -63,9 +57,6 @@ func (ipaddress IPAddress) ListRequest() (ListCommand, error) {
if ipaddress.IsSourceNat { if ipaddress.IsSourceNat {
req.IsSourceNat = &ipaddress.IsSourceNat req.IsSourceNat = &ipaddress.IsSourceNat
} }
if ipaddress.ForDisplay {
req.ForDisplay = &ipaddress.ForDisplay
}
if ipaddress.ForVirtualNetwork { if ipaddress.ForVirtualNetwork {
req.ForVirtualNetwork = &ipaddress.ForVirtualNetwork req.ForVirtualNetwork = &ipaddress.ForVirtualNetwork
} }
@ -86,21 +77,19 @@ func (ipaddress IPAddress) Delete(ctx context.Context, client *Client) error {
// AssociateIPAddress (Async) represents the IP creation // AssociateIPAddress (Async) represents the IP creation
type AssociateIPAddress struct { type AssociateIPAddress struct {
Account string `json:"account,omitempty" doc:"the account to associate with this IP address"` IsPortable *bool `json:"isportable,omitempty" doc:"should be set to true if public IP is required to be transferable across zones, if not specified defaults to false"`
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain to associate with this IP address"` NetworkdID *UUID `json:"networkid,omitempty" doc:"The network this ip address should be associated to."`
ForDisplay *bool `json:"fordisplay,omitempty" doc:"an optional field, whether to the display the ip to the end user or not"` ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availability zone you want to acquire an public IP address from"`
IsPortable *bool `json:"isportable,omitempty" doc:"should be set to true if public IP is required to be transferable across zones, if not specified defaults to false"` _ bool `name:"associateIpAddress" description:"Acquires and associates a public IP to an account."`
NetworkdID *UUID `json:"networkid,omitempty" doc:"The network this ip address should be associated to."`
RegionID int `json:"regionid,omitempty" doc:"region ID from where portable ip is to be associated."`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availability zone you want to acquire an public IP address from"`
_ bool `name:"associateIpAddress" description:"Acquires and associates a public IP to an account."`
} }
func (AssociateIPAddress) response() interface{} { // Response returns the struct to unmarshal
func (AssociateIPAddress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (AssociateIPAddress) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (AssociateIPAddress) AsyncResponse() interface{} {
return new(IPAddress) return new(IPAddress)
} }
@ -110,47 +99,47 @@ type DisassociateIPAddress struct {
_ bool `name:"disassociateIpAddress" description:"Disassociates an ip address from the account."` _ bool `name:"disassociateIpAddress" description:"Disassociates an ip address from the account."`
} }
func (DisassociateIPAddress) response() interface{} { // Response returns the struct to unmarshal
func (DisassociateIPAddress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DisassociateIPAddress) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (DisassociateIPAddress) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// UpdateIPAddress (Async) represents the IP modification // UpdateIPAddress (Async) represents the IP modification
type UpdateIPAddress struct { type UpdateIPAddress struct {
ID *UUID `json:"id" doc:"the id of the public ip address to update"` ID *UUID `json:"id" doc:"the id of the public ip address to update"`
CustomID *UUID `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"` CustomID *UUID `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"`
ForDisplay *bool `json:"fordisplay,omitempty" doc:"an optional field, whether to the display the ip to the end user or not"` _ bool `name:"updateIpAddress" description:"Updates an ip address"`
_ bool `name:"updateIpAddress" description:"Updates an ip address"`
} }
func (UpdateIPAddress) response() interface{} { // Response returns the struct to unmarshal
func (UpdateIPAddress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (UpdateIPAddress) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (UpdateIPAddress) AsyncResponse() interface{} {
return new(IPAddress) return new(IPAddress)
} }
//go:generate go run generate/main.go -interface=Listable ListPublicIPAddresses
// ListPublicIPAddresses represents a search for public IP addresses // ListPublicIPAddresses represents a search for public IP addresses
type ListPublicIPAddresses struct { type ListPublicIPAddresses struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
AllocatedOnly *bool `json:"allocatedonly,omitempty" doc:"limits search results to allocated public IP addresses"` AllocatedOnly *bool `json:"allocatedonly,omitempty" doc:"limits search results to allocated public IP addresses"`
AssociatedNetworkID *UUID `json:"associatednetworkid,omitempty" doc:"lists all public IP addresses associated to the network specified"` AssociatedNetworkID *UUID `json:"associatednetworkid,omitempty" doc:"lists all public IP addresses associated to the network specified"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ForDisplay *bool `json:"fordisplay,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"`
ForLoadBalancing *bool `json:"forloadbalancing,omitempty" doc:"list only ips used for load balancing"` ForLoadBalancing *bool `json:"forloadbalancing,omitempty" doc:"list only ips used for load balancing"`
ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"` ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the IP address"`
ID *UUID `json:"id,omitempty" doc:"lists ip address by id"` ID *UUID `json:"id,omitempty" doc:"lists ip address by id"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"lists the specified IP address"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"lists the specified IP address"`
IsElastic *bool `json:"iselastic,omitempty" doc:"list only elastic ip addresses"` IsElastic *bool `json:"iselastic,omitempty" doc:"list only elastic ip addresses"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
IsSourceNat *bool `json:"issourcenat,omitempty" doc:"list only source nat ip addresses"` IsSourceNat *bool `json:"issourcenat,omitempty" doc:"list only source nat ip addresses"`
IsStaticNat *bool `json:"isstaticnat,omitempty" doc:"list only static nat ip addresses"` IsStaticNat *bool `json:"isstaticnat,omitempty" doc:"list only static nat ip addresses"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"lists all public IP addresses by physical network id"` PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"lists all public IP addresses by physical network id"`
@ -165,31 +154,3 @@ type ListPublicIPAddressesResponse struct {
Count int `json:"count"` Count int `json:"count"`
PublicIPAddress []IPAddress `json:"publicipaddress"` PublicIPAddress []IPAddress `json:"publicipaddress"`
} }
func (ListPublicIPAddresses) response() interface{} {
return new(ListPublicIPAddressesResponse)
}
// SetPage sets the current page
func (ls *ListPublicIPAddresses) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListPublicIPAddresses) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListPublicIPAddresses) each(resp interface{}, callback IterateItemFunc) {
ips, ok := resp.(*ListPublicIPAddressesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListPublicIPAddressesResponse expected, got %T", resp))
return
}
for i := range ips.PublicIPAddress {
if !callback(&ips.PublicIPAddress[i], nil) {
break
}
}
}

View file

@ -13,8 +13,6 @@ import (
type AffinityGroup struct { type AffinityGroup struct {
Account string `json:"account,omitempty" doc:"the account owning the affinity group"` Account string `json:"account,omitempty" doc:"the account owning the affinity group"`
Description string `json:"description,omitempty" doc:"the description of the affinity group"` Description string `json:"description,omitempty" doc:"the description of the affinity group"`
Domain string `json:"domain,omitempty" doc:"the domain name of the affinity group"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of the affinity group"`
ID *UUID `json:"id,omitempty" doc:"the ID of the affinity group"` ID *UUID `json:"id,omitempty" doc:"the ID of the affinity group"`
Name string `json:"name,omitempty" doc:"the name of the affinity group"` Name string `json:"name,omitempty" doc:"the name of the affinity group"`
Type string `json:"type,omitempty" doc:"the type of the affinity group"` Type string `json:"type,omitempty" doc:"the type of the affinity group"`
@ -35,10 +33,7 @@ func (ag AffinityGroup) Delete(ctx context.Context, client *Client) error {
return fmt.Errorf("an Affinity Group may only be deleted using ID or Name") return fmt.Errorf("an Affinity Group may only be deleted using ID or Name")
} }
req := &DeleteAffinityGroup{ req := &DeleteAffinityGroup{}
Account: ag.Account,
DomainID: ag.DomainID,
}
if ag.ID != nil { if ag.ID != nil {
req.ID = ag.ID req.ID = ag.ID
@ -56,19 +51,27 @@ type AffinityGroupType struct {
// CreateAffinityGroup (Async) represents a new (anti-)affinity group // CreateAffinityGroup (Async) represents a new (anti-)affinity group
type CreateAffinityGroup struct { type CreateAffinityGroup struct {
Account string `json:"account,omitempty" doc:"an account for the affinity group. Must be used with domainId."` Description string `json:"description,omitempty" doc:"Optional description of the affinity group"`
Description string `json:"description,omitempty" doc:"optional description of the affinity group"` Name string `json:"name,omitempty" doc:"Name of the affinity group"`
DomainID *UUID `json:"domainid,omitempty" doc:"domainId of the account owning the affinity group"`
Name string `json:"name" doc:"name of the affinity group"`
Type string `json:"type" doc:"Type of the affinity group from the available affinity/anti-affinity group types"` Type string `json:"type" doc:"Type of the affinity group from the available affinity/anti-affinity group types"`
_ bool `name:"createAffinityGroup" description:"Creates an affinity/anti-affinity group"` _ bool `name:"createAffinityGroup" description:"Creates an affinity/anti-affinity group"`
} }
func (CreateAffinityGroup) response() interface{} { func (req CreateAffinityGroup) onBeforeSend(params url.Values) error {
// Name must be set, but can be empty
if req.Name == "" {
params.Set("name", "")
}
return nil
}
// Response returns the struct to unmarshal
func (CreateAffinityGroup) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (CreateAffinityGroup) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (CreateAffinityGroup) AsyncResponse() interface{} {
return new(AffinityGroup) return new(AffinityGroup)
} }
@ -88,75 +91,47 @@ func (req UpdateVMAffinityGroup) onBeforeSend(params url.Values) error {
return nil return nil
} }
func (UpdateVMAffinityGroup) response() interface{} { // Response returns the struct to unmarshal
func (UpdateVMAffinityGroup) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (UpdateVMAffinityGroup) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (UpdateVMAffinityGroup) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
// DeleteAffinityGroup (Async) represents an (anti-)affinity group to be deleted // DeleteAffinityGroup (Async) represents an (anti-)affinity group to be deleted
type DeleteAffinityGroup struct { type DeleteAffinityGroup struct {
Account string `json:"account,omitempty" doc:"the account of the affinity group. Must be specified with domain ID"` ID *UUID `json:"id,omitempty" doc:"The ID of the affinity group. Mutually exclusive with name parameter"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of account owning the affinity group"` Name string `json:"name,omitempty" doc:"The name of the affinity group. Mutually exclusive with ID parameter"`
ID *UUID `json:"id,omitempty" doc:"The ID of the affinity group. Mutually exclusive with name parameter"` _ bool `name:"deleteAffinityGroup" description:"Deletes affinity group"`
Name string `json:"name,omitempty" doc:"The name of the affinity group. Mutually exclusive with ID parameter"`
_ bool `name:"deleteAffinityGroup" description:"Deletes affinity group"`
} }
func (DeleteAffinityGroup) response() interface{} { // Response returns the struct to unmarshal
func (DeleteAffinityGroup) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DeleteAffinityGroup) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (DeleteAffinityGroup) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
//go:generate go run generate/main.go -interface=Listable ListAffinityGroups
// ListAffinityGroups represents an (anti-)affinity groups search // ListAffinityGroups represents an (anti-)affinity groups search
type ListAffinityGroups struct { type ListAffinityGroups struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` ID *UUID `json:"id,omitempty" doc:"List the affinity group by the ID provided"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ID *UUID `json:"id,omitempty" doc:"list the affinity group by the ID provided"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Name string `json:"name,omitempty" doc:"Lists affinity groups by name"`
Name string `json:"name,omitempty" doc:"lists affinity groups by name"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
Type string `json:"type,omitempty" doc:"lists affinity groups by type"` Type string `json:"type,omitempty" doc:"Lists affinity groups by type"`
VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"lists affinity groups by virtual machine ID"` VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"Lists affinity groups by virtual machine ID"`
_ bool `name:"listAffinityGroups" description:"Lists affinity groups"` _ bool `name:"listAffinityGroups" description:"Lists affinity groups"`
} }
func (ListAffinityGroups) response() interface{} {
return new(ListAffinityGroupsResponse)
}
// SetPage sets the current page
func (ls *ListAffinityGroups) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListAffinityGroups) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListAffinityGroups) each(resp interface{}, callback IterateItemFunc) {
vms, ok := resp.(*ListAffinityGroupsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListAffinityGroupsResponse expected, got %T", resp))
return
}
for i := range vms.AffinityGroup {
if !callback(&vms.AffinityGroup[i], nil) {
break
}
}
}
// ListAffinityGroupsResponse represents a list of (anti-)affinity groups // ListAffinityGroupsResponse represents a list of (anti-)affinity groups
type ListAffinityGroupsResponse struct { type ListAffinityGroupsResponse struct {
Count int `json:"count"` Count int `json:"count"`
@ -171,7 +146,8 @@ type ListAffinityGroupTypes struct {
_ bool `name:"listAffinityGroupTypes" description:"Lists affinity group types available"` _ bool `name:"listAffinityGroupTypes" description:"Lists affinity group types available"`
} }
func (ListAffinityGroupTypes) response() interface{} { // Response returns the struct to unmarshal
func (ListAffinityGroupTypes) Response() interface{} {
return new(ListAffinityGroupTypesResponse) return new(ListAffinityGroupTypesResponse)
} }

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListAffinityGroups) Response() interface{} {
return new(ListAffinityGroupsResponse)
}
// ListRequest returns itself
func (ls *ListAffinityGroups) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListAffinityGroups) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListAffinityGroups) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListAffinityGroups) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListAffinityGroupsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListAffinityGroupsResponse was expected, got %T", resp))
return
}
for i := range items.AffinityGroup {
if !callback(&items.AffinityGroup[i], nil) {
break
}
}
}

View file

@ -3,7 +3,7 @@ package egoscale
// API represents an API service // API represents an API service
type API struct { type API struct {
Description string `json:"description,omitempty" doc:"description of the api"` Description string `json:"description,omitempty" doc:"description of the api"`
IsAsync bool `json:"isasync,omitempty" doc:"true if api is asynchronous"` IsAsync bool `json:"isasync" doc:"true if api is asynchronous"`
Name string `json:"name,omitempty" doc:"the name of the api command"` Name string `json:"name,omitempty" doc:"the name of the api command"`
Related string `json:"related,omitempty" doc:"comma separated related apis"` Related string `json:"related,omitempty" doc:"comma separated related apis"`
Since string `json:"since,omitempty" doc:"version of CloudStack the api was introduced in"` Since string `json:"since,omitempty" doc:"version of CloudStack the api was introduced in"`
@ -42,6 +42,7 @@ type ListAPIsResponse struct {
API []API `json:"api"` API []API `json:"api"`
} }
func (*ListAPIs) response() interface{} { // Response returns the struct to unmarshal
func (*ListAPIs) Response() interface{} {
return new(ListAPIsResponse) return new(ListAPIsResponse)
} }

View file

@ -10,7 +10,7 @@ type AsyncJobResult struct {
AccountID *UUID `json:"accountid,omitempty" doc:"the account that executed the async command"` AccountID *UUID `json:"accountid,omitempty" doc:"the account that executed the async command"`
Cmd string `json:"cmd,omitempty" doc:"the async command executed"` Cmd string `json:"cmd,omitempty" doc:"the async command executed"`
Created string `json:"created,omitempty" doc:"the created date of the job"` Created string `json:"created,omitempty" doc:"the created date of the job"`
JobID *UUID `json:"jobid,omitempty" doc:"extra field for the initial async call"` JobID *UUID `json:"jobid" doc:"extra field for the initial async call"`
JobInstanceID *UUID `json:"jobinstanceid,omitempty" doc:"the unique ID of the instance/entity object related to the job"` JobInstanceID *UUID `json:"jobinstanceid,omitempty" doc:"the unique ID of the instance/entity object related to the job"`
JobInstanceType string `json:"jobinstancetype,omitempty" doc:"the instance/entity object related to the job"` JobInstanceType string `json:"jobinstancetype,omitempty" doc:"the instance/entity object related to the job"`
JobProcStatus int `json:"jobprocstatus,omitempty" doc:"the progress information of the PENDING job"` JobProcStatus int `json:"jobprocstatus,omitempty" doc:"the progress information of the PENDING job"`
@ -21,6 +21,16 @@ type AsyncJobResult struct {
UserID *UUID `json:"userid,omitempty" doc:"the user that executed the async command"` UserID *UUID `json:"userid,omitempty" doc:"the user that executed the async command"`
} }
// ListRequest buils the (empty) ListAsyncJobs request
func (a AsyncJobResult) ListRequest() (ListCommand, error) {
req := &ListAsyncJobs{
StartDate: a.Created,
}
return req, nil
}
// Error builds an error message from the result
func (a AsyncJobResult) Error() error { func (a AsyncJobResult) Error() error {
r := new(ErrorResponse) r := new(ErrorResponse)
if e := json.Unmarshal(*a.JobResult, r); e != nil { if e := json.Unmarshal(*a.JobResult, r); e != nil {
@ -35,31 +45,26 @@ type QueryAsyncJobResult struct {
_ bool `name:"queryAsyncJobResult" description:"Retrieves the current status of asynchronous job."` _ bool `name:"queryAsyncJobResult" description:"Retrieves the current status of asynchronous job."`
} }
func (QueryAsyncJobResult) response() interface{} { // Response returns the struct to unmarshal
func (QueryAsyncJobResult) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
//go:generate go run generate/main.go -interface=Listable ListAsyncJobs
// ListAsyncJobs list the asynchronous jobs // ListAsyncJobs list the asynchronous jobs
type ListAsyncJobs struct { type ListAsyncJobs struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` Page int `json:"page,omitempty"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` PageSize int `json:"pagesize,omitempty"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` StartDate string `json:"startdate,omitempty" doc:"the start date of the async job"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` _ bool `name:"listAsyncJobs" description:"Lists all pending asynchronous jobs for the account."`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
StartDate string `json:"startdate,omitempty" doc:"the start date of the async job"`
_ bool `name:"listAsyncJobs" description:"Lists all pending asynchronous jobs for the account."`
} }
// ListAsyncJobsResponse represents a list of job results // ListAsyncJobsResponse represents a list of job results
type ListAsyncJobsResponse struct { type ListAsyncJobsResponse struct {
Count int `json:"count"` Count int `json:"count"`
AsyncJobs []AsyncJobResult `json:"asyncjobs"` AsyncJob []AsyncJobResult `json:"asyncjobs"`
}
func (ListAsyncJobs) response() interface{} {
return new(ListAsyncJobsResponse)
} }
// Result unmarshals the result of an AsyncJobResult into the given interface // Result unmarshals the result of an AsyncJobResult into the given interface

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListAsyncJobs) Response() interface{} {
return new(ListAsyncJobsResponse)
}
// ListRequest returns itself
func (ls *ListAsyncJobs) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListAsyncJobs) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListAsyncJobs) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListAsyncJobs) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListAsyncJobsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListAsyncJobsResponse was expected, got %T", resp))
return
}
for i := range items.AsyncJob {
if !callback(&items.AsyncJob[i], nil) {
break
}
}
}

View file

@ -13,11 +13,11 @@ import (
"time" "time"
) )
// Taggable represents a resource which can have tags attached // Taggable represents a resource to which tags can be attached
// //
// This is a helper to fill the resourcetype of a CreateTags call // This is a helper to fill the resourcetype of a CreateTags call
type Taggable interface { type Taggable interface {
// CloudStack resource type of the Taggable type // ResourceType is the name of the Taggable type
ResourceType() string ResourceType() string
} }
@ -33,16 +33,11 @@ type Listable interface {
ListRequest() (ListCommand, error) ListRequest() (ListCommand, error)
} }
// Gettable represents an Interface that can be "Get" by the client // Client represents the API client
type Gettable interface {
Listable
}
// Client represents the CloudStack API client
type Client struct { type Client struct {
// HTTPClient holds the HTTP client // HTTPClient holds the HTTP client
HTTPClient *http.Client HTTPClient *http.Client
// Endpoints is CloudStack API // Endpoint is the HTTP URL
Endpoint string Endpoint string
// APIKey is the API identifier // APIKey is the API identifier
APIKey string APIKey string
@ -52,13 +47,15 @@ type Client struct {
PageSize int PageSize int
// Timeout represents the default timeout for the async requests // Timeout represents the default timeout for the async requests
Timeout time.Duration Timeout time.Duration
// Expiration representation how long a signed payload may be used
Expiration time.Duration
// RetryStrategy represents the waiting strategy for polling the async requests // RetryStrategy represents the waiting strategy for polling the async requests
RetryStrategy RetryStrategyFunc RetryStrategy RetryStrategyFunc
// Logger contains any log, plug your own // Logger contains any log, plug your own
Logger *log.Logger Logger *log.Logger
} }
// RetryStrategyFunc represents a how much time to wait between two calls to CloudStack // RetryStrategyFunc represents a how much time to wait between two calls to the API
type RetryStrategyFunc func(int64) time.Duration type RetryStrategyFunc func(int64) time.Duration
// IterateItemFunc represents the callback to iterate a list of results, if false stops // IterateItemFunc represents the callback to iterate a list of results, if false stops
@ -67,11 +64,12 @@ type IterateItemFunc func(interface{}, error) bool
// WaitAsyncJobResultFunc represents the callback to wait a results of an async request, if false stops // WaitAsyncJobResultFunc represents the callback to wait a results of an async request, if false stops
type WaitAsyncJobResultFunc func(*AsyncJobResult, error) bool type WaitAsyncJobResultFunc func(*AsyncJobResult, error) bool
// NewClient creates a CloudStack API client with default timeout (60) // NewClient creates an API client with default timeout (60)
// //
// Timeout is set to both the HTTP client and the client itself. // Timeout is set to both the HTTP client and the client itself.
func NewClient(endpoint, apiKey, apiSecret string) *Client { func NewClient(endpoint, apiKey, apiSecret string) *Client {
timeout := 60 * time.Second timeout := 60 * time.Second
expiration := 10 * time.Minute
httpClient := &http.Client{ httpClient := &http.Client{
Transport: http.DefaultTransport, Transport: http.DefaultTransport,
@ -84,6 +82,7 @@ func NewClient(endpoint, apiKey, apiSecret string) *Client {
apiSecret: apiSecret, apiSecret: apiSecret,
PageSize: 50, PageSize: 50,
Timeout: timeout, Timeout: timeout,
Expiration: expiration,
RetryStrategy: MonotonicRetryStrategyFunc(2), RetryStrategy: MonotonicRetryStrategyFunc(2),
Logger: log.New(ioutil.Discard, "", 0), Logger: log.New(ioutil.Discard, "", 0),
} }
@ -97,45 +96,52 @@ func NewClient(endpoint, apiKey, apiSecret string) *Client {
} }
// Get populates the given resource or fails // Get populates the given resource or fails
func (client *Client) Get(g Gettable) error { func (client *Client) Get(ls Listable) (interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout) ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel() defer cancel()
return client.GetWithContext(ctx, g) return client.GetWithContext(ctx, ls)
} }
// GetWithContext populates the given resource or fails // GetWithContext populates the given resource or fails
func (client *Client) GetWithContext(ctx context.Context, g Gettable) error { func (client *Client) GetWithContext(ctx context.Context, ls Listable) (interface{}, error) {
gs, err := client.ListWithContext(ctx, g) gs, err := client.ListWithContext(ctx, ls)
if err != nil { if err != nil {
return err return nil, err
} }
count := len(gs) count := len(gs)
if count != 1 { if count != 1 {
req, err := g.ListRequest() req, err := ls.ListRequest()
if err != nil { if err != nil {
return err return nil, err
} }
params, err := client.Payload(req) params, err := client.Payload(req)
if err != nil { if err != nil {
return err return nil, err
} }
// removing sensitive/useless informations
params.Del("expires")
params.Del("response")
params.Del("signature")
params.Del("signatureversion")
// formatting the query string nicely // formatting the query string nicely
payload := params.Encode() payload := params.Encode()
payload = strings.Replace(payload, "&", ", ", -1) payload = strings.Replace(payload, "&", ", ", -1)
if count == 0 { if count == 0 {
return &ErrorResponse{ return nil, &ErrorResponse{
ErrorCode: ParamError, CSErrorCode: ServerAPIException,
ErrorText: fmt.Sprintf("not found, query: %s", payload), ErrorCode: ParamError,
ErrorText: fmt.Sprintf("not found, query: %s", payload),
} }
} }
return fmt.Errorf("more than one element found: %s", payload) return nil, fmt.Errorf("more than one element found: %s", payload)
} }
return Copy(g, gs[0]) return gs[0], nil
} }
// Delete removes the given resource of fails // Delete removes the given resource of fails
@ -160,18 +166,25 @@ func (client *Client) List(g Listable) ([]interface{}, error) {
} }
// ListWithContext lists the given resources (and paginate till the end) // ListWithContext lists the given resources (and paginate till the end)
func (client *Client) ListWithContext(ctx context.Context, g Listable) ([]interface{}, error) { func (client *Client) ListWithContext(ctx context.Context, g Listable) (s []interface{}, err error) {
s := make([]interface{}, 0) s = make([]interface{}, 0)
if g == nil || reflect.ValueOf(g).IsNil() { defer func() {
return s, fmt.Errorf("g Listable shouldn't be nil, got %#v", g) if e := recover(); e != nil {
if g == nil || reflect.ValueOf(g).IsNil() {
err = fmt.Errorf("g Listable shouldn't be nil, got %#v", g)
return
}
panic(e)
}
}()
req, e := g.ListRequest()
if e != nil {
err = e
return
} }
req, err := g.ListRequest()
if err != nil {
return s, err
}
client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool { client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool {
if item != nil { if item != nil {
s = append(s, item) s = append(s, item)
@ -181,7 +194,7 @@ func (client *Client) ListWithContext(ctx context.Context, g Listable) ([]interf
return false return false
}) })
return s, err return
} }
// AsyncListWithContext lists the given resources (and paginate till the end) // AsyncListWithContext lists the given resources (and paginate till the end)
@ -227,7 +240,6 @@ func (client *Client) AsyncListWithContext(ctx context.Context, g Listable) (<-c
errChan <- err errChan <- err
return return
} }
client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool { client.PaginateWithContext(ctx, req, func(item interface{}, e error) bool {
if item != nil { if item != nil {
outChan <- item outChan <- item
@ -242,15 +254,21 @@ func (client *Client) AsyncListWithContext(ctx context.Context, g Listable) (<-c
} }
// Paginate runs the ListCommand and paginates // Paginate runs the ListCommand and paginates
func (client *Client) Paginate(req ListCommand, callback IterateItemFunc) { func (client *Client) Paginate(g Listable, callback IterateItemFunc) {
ctx, cancel := context.WithTimeout(context.Background(), client.Timeout) ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
defer cancel() defer cancel()
client.PaginateWithContext(ctx, req, callback) client.PaginateWithContext(ctx, g, callback)
} }
// PaginateWithContext runs the ListCommand as long as the ctx is valid // PaginateWithContext runs the ListCommand as long as the ctx is valid
func (client *Client) PaginateWithContext(ctx context.Context, req ListCommand, callback IterateItemFunc) { func (client *Client) PaginateWithContext(ctx context.Context, g Listable, callback IterateItemFunc) {
req, err := g.ListRequest()
if err != nil {
callback(nil, err)
return
}
pageSize := client.PageSize pageSize := client.PageSize
page := 1 page := 1
@ -260,13 +278,18 @@ func (client *Client) PaginateWithContext(ctx context.Context, req ListCommand,
req.SetPageSize(pageSize) req.SetPageSize(pageSize)
resp, err := client.RequestWithContext(ctx, req) resp, err := client.RequestWithContext(ctx, req)
if err != nil { if err != nil {
// in case of 431, the response is knowingly empty
if errResponse, ok := err.(*ErrorResponse); ok && page == 1 && errResponse.ErrorCode == ParamError {
break
}
callback(nil, err) callback(nil, err)
break break
} }
size := 0 size := 0
didErr := false didErr := false
req.each(resp, func(element interface{}, err error) bool { req.Each(resp, func(element interface{}, err error) bool {
// If the context was cancelled, kill it in flight // If the context was cancelled, kill it in flight
if e := ctx.Err(); e != nil { if e := ctx.Err(); e != nil {
element = nil element = nil
@ -290,10 +313,12 @@ func (client *Client) PaginateWithContext(ctx context.Context, req ListCommand,
} }
} }
// APIName returns the CloudStack name of the given command // APIName returns the name of the given command
func (client *Client) APIName(command Command) string { func (client *Client) APIName(command Command) string {
// This is due to a limitation of Go<=1.7 // This is due to a limitation of Go<=1.7
if _, ok := command.(*AuthorizeSecurityGroupEgress); ok { _, ok := command.(*AuthorizeSecurityGroupEgress)
_, okPtr := command.(AuthorizeSecurityGroupEgress)
if ok || okPtr {
return "authorizeSecurityGroupEgress" return "authorizeSecurityGroupEgress"
} }
@ -304,7 +329,7 @@ func (client *Client) APIName(command Command) string {
return info.Name return info.Name
} }
// APIDescription returns the description of the given CloudStack command // APIDescription returns the description of the given command
func (client *Client) APIDescription(command Command) string { func (client *Client) APIDescription(command Command) string {
info, err := info(command) info, err := info(command)
if err != nil { if err != nil {
@ -315,11 +340,11 @@ func (client *Client) APIDescription(command Command) string {
// Response returns the response structure of the given command // Response returns the response structure of the given command
func (client *Client) Response(command Command) interface{} { func (client *Client) Response(command Command) interface{} {
switch command.(type) { switch c := command.(type) {
case AsyncCommand: case AsyncCommand:
return (command.(AsyncCommand)).asyncResponse() return c.AsyncResponse()
default: default:
return command.response() return command.Response()
} }
} }

View file

@ -1,37 +0,0 @@
package egoscale
import (
"fmt"
"reflect"
)
// Copy copies the value from from into to. The type of "from" must be convertible into the type of "to".
func Copy(to, from interface{}) error {
tt := reflect.TypeOf(to)
tv := reflect.ValueOf(to)
ft := reflect.TypeOf(from)
fv := reflect.ValueOf(from)
if tt.Kind() != reflect.Ptr {
return fmt.Errorf("must copy to a pointer, got %q", tt.Name())
}
tt = tt.Elem()
tv = tv.Elem()
for {
if ft.ConvertibleTo(tt) {
break
}
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
fv = fv.Elem()
} else {
return fmt.Errorf("cannot convert %q into %q", tt.Name(), ft.Name())
}
}
tv.Set(fv.Convert(tt))
return nil
}

View file

@ -1,6 +1,7 @@
package egoscale package egoscale
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -128,7 +129,7 @@ func (req *DNSErrorResponse) Error() string {
} }
// CreateDomain creates a DNS domain // CreateDomain creates a DNS domain
func (client *Client) CreateDomain(name string) (*DNSDomain, error) { func (client *Client) CreateDomain(ctx context.Context, name string) (*DNSDomain, error) {
m, err := json.Marshal(DNSDomainResponse{ m, err := json.Marshal(DNSDomainResponse{
Domain: &DNSDomain{ Domain: &DNSDomain{
Name: name, Name: name,
@ -138,7 +139,7 @@ func (client *Client) CreateDomain(name string) (*DNSDomain, error) {
return nil, err return nil, err
} }
resp, err := client.dnsRequest("/v1/domains", nil, string(m), "POST") resp, err := client.dnsRequest(ctx, "/v1/domains", nil, string(m), "POST")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -152,8 +153,8 @@ func (client *Client) CreateDomain(name string) (*DNSDomain, error) {
} }
// GetDomain gets a DNS domain // GetDomain gets a DNS domain
func (client *Client) GetDomain(name string) (*DNSDomain, error) { func (client *Client) GetDomain(ctx context.Context, name string) (*DNSDomain, error) {
resp, err := client.dnsRequest("/v1/domains/"+name, nil, "", "GET") resp, err := client.dnsRequest(ctx, "/v1/domains/"+name, nil, "", "GET")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -167,8 +168,8 @@ func (client *Client) GetDomain(name string) (*DNSDomain, error) {
} }
// GetDomains gets DNS domains // GetDomains gets DNS domains
func (client *Client) GetDomains() ([]DNSDomain, error) { func (client *Client) GetDomains(ctx context.Context) ([]DNSDomain, error) {
resp, err := client.dnsRequest("/v1/domains", nil, "", "GET") resp, err := client.dnsRequest(ctx, "/v1/domains", nil, "", "GET")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -186,15 +187,15 @@ func (client *Client) GetDomains() ([]DNSDomain, error) {
} }
// DeleteDomain delets a DNS domain // DeleteDomain delets a DNS domain
func (client *Client) DeleteDomain(name string) error { func (client *Client) DeleteDomain(ctx context.Context, name string) error {
_, err := client.dnsRequest("/v1/domains/"+name, nil, "", "DELETE") _, err := client.dnsRequest(ctx, "/v1/domains/"+name, nil, "", "DELETE")
return err return err
} }
// GetRecord returns a DNS record // GetRecord returns a DNS record
func (client *Client) GetRecord(domain string, recordID int64) (*DNSRecord, error) { func (client *Client) GetRecord(ctx context.Context, domain string, recordID int64) (*DNSRecord, error) {
id := strconv.FormatInt(recordID, 10) id := strconv.FormatInt(recordID, 10)
resp, err := client.dnsRequest("/v1/domains/"+domain+"/records/"+id, nil, "", "GET") resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records/"+id, nil, "", "GET")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -208,8 +209,8 @@ func (client *Client) GetRecord(domain string, recordID int64) (*DNSRecord, erro
} }
// GetRecords returns the DNS records // GetRecords returns the DNS records
func (client *Client) GetRecords(domain string) ([]DNSRecord, error) { func (client *Client) GetRecords(ctx context.Context, domain string) ([]DNSRecord, error) {
resp, err := client.dnsRequest("/v1/domains/"+domain+"/records", nil, "", "GET") resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records", nil, "", "GET")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -228,7 +229,7 @@ func (client *Client) GetRecords(domain string) ([]DNSRecord, error) {
} }
// GetRecordsWithFilters returns the DNS records (filters can be empty) // GetRecordsWithFilters returns the DNS records (filters can be empty)
func (client *Client) GetRecordsWithFilters(domain, name, recordType string) ([]DNSRecord, error) { func (client *Client) GetRecordsWithFilters(ctx context.Context, domain, name, recordType string) ([]DNSRecord, error) {
filters := url.Values{} filters := url.Values{}
if name != "" { if name != "" {
@ -238,7 +239,7 @@ func (client *Client) GetRecordsWithFilters(domain, name, recordType string) ([]
filters.Add("record_type", recordType) filters.Add("record_type", recordType)
} }
resp, err := client.dnsRequest("/v1/domains/"+domain+"/records", filters, "", "GET") resp, err := client.dnsRequest(ctx, "/v1/domains/"+domain+"/records", filters, "", "GET")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -257,7 +258,7 @@ func (client *Client) GetRecordsWithFilters(domain, name, recordType string) ([]
} }
// CreateRecord creates a DNS record // CreateRecord creates a DNS record
func (client *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, error) { func (client *Client) CreateRecord(ctx context.Context, name string, rec DNSRecord) (*DNSRecord, error) {
body, err := json.Marshal(DNSRecordResponse{ body, err := json.Marshal(DNSRecordResponse{
Record: rec, Record: rec,
}) })
@ -265,7 +266,7 @@ func (client *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, erro
return nil, err return nil, err
} }
resp, err := client.dnsRequest("/v1/domains/"+name+"/records", nil, string(body), "POST") resp, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records", nil, string(body), "POST")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -279,7 +280,7 @@ func (client *Client) CreateRecord(name string, rec DNSRecord) (*DNSRecord, erro
} }
// UpdateRecord updates a DNS record // UpdateRecord updates a DNS record
func (client *Client) UpdateRecord(name string, rec UpdateDNSRecord) (*DNSRecord, error) { func (client *Client) UpdateRecord(ctx context.Context, name string, rec UpdateDNSRecord) (*DNSRecord, error) {
body, err := json.Marshal(UpdateDNSRecordResponse{ body, err := json.Marshal(UpdateDNSRecordResponse{
Record: rec, Record: rec,
}) })
@ -288,7 +289,7 @@ func (client *Client) UpdateRecord(name string, rec UpdateDNSRecord) (*DNSRecord
} }
id := strconv.FormatInt(rec.ID, 10) id := strconv.FormatInt(rec.ID, 10)
resp, err := client.dnsRequest("/v1/domains/"+name+"/records/"+id, nil, string(body), "PUT") resp, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records/"+id, nil, string(body), "PUT")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -302,14 +303,14 @@ func (client *Client) UpdateRecord(name string, rec UpdateDNSRecord) (*DNSRecord
} }
// DeleteRecord deletes a record // DeleteRecord deletes a record
func (client *Client) DeleteRecord(name string, recordID int64) error { func (client *Client) DeleteRecord(ctx context.Context, name string, recordID int64) error {
id := strconv.FormatInt(recordID, 10) id := strconv.FormatInt(recordID, 10)
_, err := client.dnsRequest("/v1/domains/"+name+"/records/"+id, nil, "", "DELETE") _, err := client.dnsRequest(ctx, "/v1/domains/"+name+"/records/"+id, nil, "", "DELETE")
return err return err
} }
func (client *Client) dnsRequest(uri string, urlValues url.Values, params, method string) (json.RawMessage, error) { func (client *Client) dnsRequest(ctx context.Context, uri string, urlValues url.Values, params, method string) (json.RawMessage, error) {
rawURL := client.Endpoint + uri rawURL := client.Endpoint + uri
url, err := url.Parse(rawURL) url, err := url.Parse(rawURL)
if err != nil { if err != nil {
@ -338,7 +339,7 @@ func (client *Client) dnsRequest(uri string, urlValues url.Values, params, metho
} }
req.Header = hdr req.Header = hdr
resp, err := client.HTTPClient.Do(req) resp, err := client.HTTPClient.Do(req.WithContext(ctx))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,18 +1,18 @@
/* /*
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.com/) infrastructure but should fit other CloudStack services. Package egoscale is a mapping for the Exoscale API (https://community.exoscale.com/api/compute/).
Requests and Responses Requests and Responses
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 data at stake. E.g. DeployVirtualMachine gives a VirtualMachine, as a pointer as well to avoid big copies. 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 data at stake. E.g. DeployVirtualMachine gives a VirtualMachine, as a pointer as well to avoid big copies.
Then everything within the struct is not a pointer. Find below some examples of how egoscale may be used to interact with a CloudStack endpoint, especially Exoscale itself. If anything feels odd or unclear, please let us know: https://github.com/exoscale/egoscale/issues Then everything within the struct is not a pointer. Find below some examples of how egoscale may be used. If anything feels odd or unclear, please let us know: https://github.com/exoscale/egoscale/issues
req := &egoscale.DeployVirtualMachine{ req := &egoscale.DeployVirtualMachine{
Size: 10, Size: 10,
ServiceOfferingID: "...", ServiceOfferingID: egoscale.MustParseUUID("..."),
TemplateID: "...", TemplateID: egoscale.MustParseUUID("..."),
ZoneID: "...", ZoneID: egoscale.MastParseUUID("..."),
} }
fmt.Println("Deployment started") fmt.Println("Deployment started")
@ -28,9 +28,9 @@ This example deploys a virtual machine while controlling the job status as it go
req := &egoscale.DeployVirtualMachine{ req := &egoscale.DeployVirtualMachine{
Size: 10, Size: 10,
ServiceOfferingID: "...", ServiceOfferingID: egoscale.MustParseUUID("..."),
TemplateID: "...", TemplateID: egoscale.MustParseUUID("..."),
ZoneID: "...", ZoneID: egoscale.MustParseUUID("..."),
} }
vm := &egoscale.VirtualMachine{} vm := &egoscale.VirtualMachine{}
@ -63,20 +63,20 @@ Debugging and traces
As this library is mostly an HTTP client, you can reuse all the existing tools around it. As this library is mostly an HTTP client, you can reuse all the existing tools around it.
cs := egoscale.NewClient("https://api.exoscale.ch/compute", "EXO...", "...") cs := egoscale.NewClient("https://api.exoscale.com/compute", "EXO...", "...")
// sets a logger on stderr // sets a logger on stderr
cs.Logger = log.Newos.Stderr, "prefix", log.LstdFlags) cs.Logger = log.New(os.Stderr, "prefix", log.LstdFlags)
// activates the HTTP traces // activates the HTTP traces
cs.TraceOn() cs.TraceOn()
Nota bene: when running the tests or the egoscale library via another tool, e.g. the exo cli (or the cs cli), the environment variable EXOSCALE_TRACE=prefix does the above configuration for you. As a developer using egoscale as a library, you'll find it more convenient to plug your favorite io.Writer as it's Logger. Nota bene: when running the tests or the egoscale library via another tool, e.g. the exo cli, the environment variable EXOSCALE_TRACE=prefix does the above configuration for you. As a developer using egoscale as a library, you'll find it more convenient to plug your favorite io.Writer as it's a Logger.
APIs APIs
All the available APIs on the server and provided by the API Discovery plugin All the available APIs on the server and provided by the API Discovery plugin.
cs := egoscale.NewClient("https://api.exoscale.ch/compute", "EXO...", "...") cs := egoscale.NewClient("https://api.exoscale.com/compute", "EXO...", "...")
resp, err := cs.Request(&egoscale.ListAPIs{}) resp, err := cs.Request(&egoscale.ListAPIs{})
if err != nil { if err != nil {
@ -96,14 +96,17 @@ Security Groups provide a way to isolate traffic to VMs. Rules are added via the
resp, err := cs.Request(&egoscale.CreateSecurityGroup{ resp, err := cs.Request(&egoscale.CreateSecurityGroup{
Name: "Load balancer", Name: "Load balancer",
Description: "Opens HTTP/HTTPS ports from the outside world", Description: "Open HTTP/HTTPS ports from the outside world",
}) })
securityGroup := resp.(*egoscale.SecurityGroup) securityGroup := resp.(*egoscale.SecurityGroup)
resp, err = cs.Request(&egoscale.AuthorizeSecurityGroupIngress{ resp, err = cs.Request(&egoscale.AuthorizeSecurityGroupIngress{
Description: "SSH traffic", Description: "SSH traffic",
SecurityGroupID: securityGroup.ID, SecurityGroupID: securityGroup.ID,
CidrList: []string{"0.0.0.0/0"}, CidrList: []CIDR{
*egoscale.MustParseCIDR("0.0.0.0/0"),
*egoscale.MustParseCIDR("::/0"),
},
Protocol: "tcp", Protocol: "tcp",
StartPort: 22, StartPort: 22,
EndPort: 22, EndPort: 22,
@ -117,32 +120,32 @@ Security Groups provide a way to isolate traffic to VMs. Rules are added via the
}) })
// ... // ...
Security Group also implement the generic List, Get and Delete interfaces (Listable, Gettable and Deletable). Security Group also implement the generic List, Get and Delete interfaces (Listable and Deletable).
// List all Security Groups // List all Security Groups
sgs, err := cs.List(new(egoscale.SecurityGroup)) sgs, _ := cs.List(&egoscale.SecurityGroup{})
for _, s := range sgs { for _, s := range sgs {
sg := s.(egoscale.SecurityGroup) sg := s.(egoscale.SecurityGroup)
// ... // ...
} }
// Get a Security Group // Get a Security Group
sg := &egoscale.SecurityGroup{Name: "Load balancer"} sgQuery := &egoscale.SecurityGroup{Name: "Load balancer"}
if err := cs.Get(sg); err != nil { resp, err := cs.Get(sgQuery); err != nil {
... ...
} }
// The SecurityGroup struct has been loaded with the SecurityGroup informations sg := resp.(*egoscale.SecurityGroup)
if err := cs.Delete(sg); err != nil { if err := cs.Delete(sg); err != nil {
... ...
} }
// The SecurityGroup has been deleted // The SecurityGroup has been deleted
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/networking_and_traffic.html#security-groups See: https://community.exoscale.com/documentation/compute/security-groups/
Zones Zones
A Zone corresponds to a Data Center. You may list them. Zone implements the Listable interface, which let you perform a list in two different ways. The first exposes the underlying CloudStack request while the second one hide them and you only manipulate the structs of your interest. A Zone corresponds to a Data Center. You may list them. Zone implements the Listable interface, which let you perform a list in two different ways. The first exposes the underlying request while the second one hide them and you only manipulate the structs of your interest.
// Using ListZones request // Using ListZones request
req := &egoscale.ListZones{} req := &egoscale.ListZones{}
@ -171,7 +174,7 @@ Elastic IPs
An Elastic IP is a way to attach an IP address to many Virtual Machines. The API side of the story configures the external environment, like the routing. Some work is required within the machine to properly configure the interfaces. An Elastic IP is a way to attach an IP address to many Virtual Machines. The API side of the story configures the external environment, like the routing. Some work is required within the machine to properly configure the interfaces.
See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/networking_and_traffic.html#about-elastic-ips See: https://community.exoscale.com/documentation/compute/eip/
*/ */
package egoscale package egoscale

View file

@ -5,9 +5,7 @@ type Event struct {
Account string `json:"account,omitempty" doc:"the account name for the account that owns the object being acted on in the event (e.g. the owner of the virtual machine, ip address, or security group)"` Account string `json:"account,omitempty" doc:"the account name for the account that owns the object being acted on in the event (e.g. the owner of the virtual machine, ip address, or security group)"`
Created string `json:"created,omitempty" doc:"the date the event was created"` Created string `json:"created,omitempty" doc:"the date the event was created"`
Description string `json:"description,omitempty" doc:"a brief description of the event"` Description string `json:"description,omitempty" doc:"a brief description of the event"`
Domain string `json:"domain,omitempty" doc:"the name of the account's domain"` ID *UUID `json:"id" doc:"the ID of the event"`
DomainID *UUID `json:"domainid,omitempty" doc:"the id of the account's domain"`
ID *UUID `json:"id,omitempty" doc:"the ID of the event"`
Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"` Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"`
ParentID *UUID `json:"parentid,omitempty" doc:"whether the event is parented"` ParentID *UUID `json:"parentid,omitempty" doc:"whether the event is parented"`
State string `json:"state,omitempty" doc:"the state of the event"` State string `json:"state,omitempty" doc:"the state of the event"`
@ -15,28 +13,44 @@ type Event struct {
UserName string `json:"username,omitempty" doc:"the name of the user who performed the action (can be different from the account if an admin is performing an action for a user, e.g. starting/stopping a user's virtual machine)"` UserName string `json:"username,omitempty" doc:"the name of the user who performed the action (can be different from the account if an admin is performing an action for a user, e.g. starting/stopping a user's virtual machine)"`
} }
// ListRequest builds the ListEvents request
func (event Event) ListRequest() (ListCommand, error) {
req := &ListEvents{
ID: event.ID,
Level: event.Level,
Type: event.Type,
}
return req, nil
}
// EventType represent a type of event // EventType represent a type of event
type EventType struct { type EventType struct {
Name string `json:"name,omitempty" doc:"Event Type"` Name string `json:"name,omitempty" doc:"Event Type"`
} }
// ListRequest builds the ListEventTypes request
func (EventType) ListRequest() (ListCommand, error) {
req := &ListEventTypes{}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListEvents
// ListEvents list the events // ListEvents list the events
type ListEvents struct { type ListEvents struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` Duration int `json:"duration,omitempty" doc:"the duration of the event"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` EndDate string `json:"enddate,omitempty" doc:"the end date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"`
Duration int `json:"duration,omitempty" doc:"the duration of the event"` EntryTime int `json:"entrytime,omitempty" doc:"the time the event was entered"`
EndDate string `json:"enddate,omitempty" doc:"the end date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"` ID *UUID `json:"id,omitempty" doc:"the ID of the event"`
EntryTime int `json:"entrytime,omitempty" doc:"the time the event was entered"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ID *UUID `json:"id,omitempty" doc:"the ID of the event"` Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves." doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` Page int `json:"page,omitempty"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` PageSize int `json:"pagesize,omitempty"`
Level string `json:"level,omitempty" doc:"the event level (INFO, WARN, ERROR)"` StartDate string `json:"startdate,omitempty" doc:"the start date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Type string `json:"type,omitempty" doc:"the event type (see event types)"`
Page int `json:"page,omitempty" ` _ bool `name:"listEvents" description:"A command to list events."`
PageSize int `json:"pagesize,omitempty"`
StartDate string `json:"startdate,omitempty" doc:"the start date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")"`
Type string `json:"type,omitempty" doc:"the event type (see event types)"`
_ bool `name:"listEvents" description:"A command to list events."`
} }
// ListEventsResponse represents a response of a list query // ListEventsResponse represents a response of a list query
@ -45,13 +59,13 @@ type ListEventsResponse struct {
Event []Event `json:"event"` Event []Event `json:"event"`
} }
func (ListEvents) response() interface{} { //go:generate go run generate/main.go -interface=Listable ListEventTypes
return new(ListEventsResponse)
}
// ListEventTypes list the event types // ListEventTypes list the event types
type ListEventTypes struct { type ListEventTypes struct {
_ bool `name:"listEventTypes" description:"List Event Types"` Page int `json:"page,omitempty"` // fake
PageSize int `json:"pagesize,omitempty"` // fake
_ bool `name:"listEventTypes" description:"List Event Types"`
} }
// ListEventTypesResponse represents a response of a list query // ListEventTypesResponse represents a response of a list query
@ -60,7 +74,3 @@ type ListEventTypesResponse struct {
EventType []EventType `json:"eventtype"` EventType []EventType `json:"eventtype"`
_ bool `name:"listEventTypes" description:"List Event Types"` _ bool `name:"listEventTypes" description:"List Event Types"`
} }
func (ListEventTypes) response() interface{} {
return new(ListEventTypesResponse)
}

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

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListEvents) Response() interface{} {
return new(ListEventsResponse)
}
// ListRequest returns itself
func (ls *ListEvents) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListEvents) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListEvents) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListEvents) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListEventsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListEventsResponse was expected, got %T", resp))
return
}
for i := range items.Event {
if !callback(&items.Event[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListEventTypes) Response() interface{} {
return new(ListEventTypesResponse)
}
// ListRequest returns itself
func (ls *ListEventTypes) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListEventTypes) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListEventTypes) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListEventTypes) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListEventTypesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListEventTypesResponse was expected, got %T", resp))
return
}
for i := range items.EventType {
if !callback(&items.EventType[i], nil) {
break
}
}
}

View file

@ -1,99 +0,0 @@
package egoscale
import (
"net"
)
// Host represents the Hypervisor
type Host struct {
Capabilities string `json:"capabilities,omitempty" doc:"capabilities of the host"`
ClusterID *UUID `json:"clusterid,omitempty" doc:"the cluster ID of the host"`
ClusterName string `json:"clustername,omitempty" doc:"the cluster name of the host"`
ClusterType string `json:"clustertype,omitempty" doc:"the cluster type of the cluster that host belongs to"`
CPUAllocated int64 `json:"cpuallocated,omitempty" doc:"the amount of the host's CPU currently allocated"`
CPUNumber int `json:"cpunumber,omitempty" doc:"the CPU number of the host"`
CPUSockets int `json:"cpusockets,omitempty" doc:"the number of CPU sockets on the host"`
CPUSpeed int64 `json:"cpuspeed,omitempty" doc:"the CPU speed of the host"`
CPUUsed int64 `json:"cpuused,omitempty" doc:"the amount of the host's CPU currently used"`
CPUWithOverProvisioning int64 `json:"cpuwithoverprovisioning,omitempty" doc:"the amount of the host's CPU after applying the cpu.overprovisioning.factor"`
Created string `json:"created,omitempty" doc:"the date and time the host was created"`
Disconnected string `json:"disconnected,omitempty" doc:"true if the host is disconnected. False otherwise."`
DiskSizeAllocated int64 `json:"disksizeallocated,omitempty" doc:"the host's or host storage pool's currently allocated disk size"`
DiskSizeTotal int64 `json:"disksizetotal,omitempty" doc:"the total disk size of the host or host storage pool"`
DiskSizeUsed int64 `json:"disksizeused,omitempty" doc:"the host's or host storage pool's currently used disk size"`
DiskWithOverProvisioning int64 `json:"diskwithoverprovisioning,omitempty" doc:"the total disk size of the host or host storage pool with over provisioning factor"`
Events string `json:"events,omitempty" doc:"events available for the host"`
HAHost *bool `json:"hahost,omitempty" doc:"true if the host is Ha host (dedicated to vms started by HA process; false otherwise"`
HostTags string `json:"hosttags,omitempty" doc:"comma-separated list of tags for the host"`
Hypervisor string `json:"hypervisor,omitempty" doc:"the host hypervisor"`
HypervisorVersion string `json:"hypervisorversion,omitempty" doc:"the hypervisor version"`
ID *UUID `json:"id,omitempty" doc:"the ID of the host"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"the IP address of the host"`
IsLocalstorageActive *bool `json:"islocalstorageactive,omitempty" doc:"true if local storage is active, false otherwise"`
LastPinged string `json:"lastpinged,omitempty" doc:"the date and time the host was last pinged"`
ManagementServerID *UUID `json:"managementserverid,omitempty" doc:"the management server ID of the host"`
MemoryAllocated int64 `json:"memoryallocated,omitempty" doc:"the amount of VM's memory allocated onto the host"`
MemoryPhysical int64 `json:"memoryphysical,omitempty" doc:"the total physical memory of the host"`
MemoryReserved int64 `json:"memoryreserved,omitempty" doc:"the amount of the host's memory reserved"`
MemoryTotal int64 `json:"memorytotal,omitempty" doc:"the total memory of the host available (must be physical - reserved)"`
MemoryUsed int64 `json:"memoryused,omitempty" doc:"the amount of the host's memory used by running vm"`
Name string `json:"name,omitempty" doc:"the name of the host"`
NetworkKbsRead int64 `json:"networkkbsread,omitempty" doc:"the incoming network traffic on the host"`
NetworkKbsWrite int64 `json:"networkkbswrite,omitempty" doc:"the outgoing network traffic on the host"`
OSCategoryID *UUID `json:"oscategoryid,omitempty" doc:"the OS category ID of the host"`
OSCategoryName string `json:"oscategoryname,omitempty" doc:"the OS category name of the host"`
PCIDevices []PCIDevice `json:"pcidevices,omitempty" doc:"PCI cards present in the host"`
PodID *UUID `json:"podid,omitempty" doc:"the Pod ID of the host"`
PodName string `json:"podname,omitempty" doc:"the Pod name of the host"`
Removed string `json:"removed,omitempty" doc:"the date and time the host was removed"`
ResourceState string `json:"resourcestate,omitempty" doc:"the resource state of the host"`
State string `json:"state,omitempty" doc:"the state of the host"`
StorageID *UUID `json:"storageid,omitempty" doc:"the host's storage pool id"`
Type string `json:"type,omitempty" doc:"the host type"`
Version string `json:"version,omitempty" doc:"the host version"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the Zone ID of the host"`
ZoneName string `json:"zonename,omitempty" doc:"the Zone name of the host"`
}
// ListHosts lists hosts
type ListHosts struct {
ClusterID *UUID `json:"clusterid,omitempty" doc:"lists hosts existing in particular cluster"`
Details []string `json:"details,omitempty" doc:"comma separated list of host details requested, value can be a list of [ min, all, capacity, events, stats]"`
HAHost *bool `json:"hahost,omitempty" doc:"if true, list only hosts dedicated to HA"`
Hypervisor string `json:"hypervisor,omitempty" doc:"hypervisor type of host: KVM,Simulator"`
ID *UUID `json:"id,omitempty" doc:"the id of the host"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"the name of the host"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
PodID *UUID `json:"podid,omitempty" doc:"the Pod ID for the host"`
ResourceState string `json:"resourcestate,omitempty" doc:"list hosts by resource state. Resource state represents current state determined by admin of host, value can be one of [Enabled, Disabled, Unmanaged, PrepareForMaintenance, ErrorInMaintenance, Maintenance, Error]"`
State string `json:"state,omitempty" doc:"the state of the host"`
Type string `json:"type,omitempty" doc:"the host type"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the Zone ID for the host"`
_ bool `name:"listHosts" description:"Lists hosts."`
}
func (ListHosts) response() interface{} {
return new(ListHostsResponse)
}
// ListHostsResponse represents a list of hosts
type ListHostsResponse struct {
Count int `json:"count"`
Host []Host `json:"host"`
}
// UpdateHost changes the resources state of a host
type UpdateHost struct {
Allocationstate string `json:"allocationstate,omitempty" doc:"Change resource state of host, valid values are [Enable, Disable]. Operation may failed if host in states not allowing Enable/Disable"`
HostTags []string `json:"hosttags,omitempty" doc:"list of tags to be added to the host"`
ID *UUID `json:"id" doc:"the ID of the host to update"`
OSCategoryID *UUID `json:"oscategoryid,omitempty" doc:"the id of Os category to update the host with"`
URL string `json:"url,omitempty" doc:"the new uri for the secondary storage: nfs://host/path"`
_ bool `name:"updateHost" description:"Updates a host."`
}
func (UpdateHost) response() interface{} {
return new(Host)
}

71
vendor/github.com/exoscale/egoscale/instance_groups.go generated vendored Normal file
View file

@ -0,0 +1,71 @@
package egoscale
// InstanceGroup represents a group of VM
type InstanceGroup struct {
Account string `json:"account,omitempty" doc:"the account owning the instance group"`
Created string `json:"created,omitempty" doc:"time and date the instance group was created"`
ID *UUID `json:"id,omitempty" doc:"the id of the instance group"`
Name string `json:"name,omitempty" doc:"the name of the instance group"`
}
// ListRequest builds the ListInstanceGroups request
func (ig InstanceGroup) ListRequest() (ListCommand, error) {
req := &ListInstanceGroups{
ID: ig.ID,
Name: ig.Name,
}
return req, nil
}
// CreateInstanceGroup creates a VM group
type CreateInstanceGroup struct {
Name string `json:"name" doc:"the name of the instance group"`
_ bool `name:"createInstanceGroup" description:"Creates a vm group"`
}
// Response returns the struct to unmarshal
func (CreateInstanceGroup) Response() interface{} {
return new(InstanceGroup)
}
// UpdateInstanceGroup updates a VM group
type UpdateInstanceGroup struct {
ID *UUID `json:"id" doc:"Instance group ID"`
Name string `json:"name,omitempty" doc:"new instance group name"`
_ bool `name:"updateInstanceGroup" description:"Updates a vm group"`
}
// Response returns the struct to unmarshal
func (UpdateInstanceGroup) Response() interface{} {
return new(InstanceGroup)
}
// DeleteInstanceGroup deletes a VM group
type DeleteInstanceGroup struct {
ID *UUID `json:"id" doc:"the ID of the instance group"`
_ bool `name:"deleteInstanceGroup" description:"Deletes a vm group"`
}
// Response returns the struct to unmarshal
func (DeleteInstanceGroup) Response() interface{} {
return new(BooleanResponse)
}
//go:generate go run generate/main.go -interface=Listable ListInstanceGroups
// ListInstanceGroups lists VM groups
type ListInstanceGroups struct {
ID *UUID `json:"id,omitempty" doc:"List instance groups by ID"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"List instance groups by name"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
_ bool `name:"listInstanceGroups" description:"Lists vm groups"`
}
// ListInstanceGroupsResponse represents a list of instance groups
type ListInstanceGroupsResponse struct {
Count int `json:"count"`
InstanceGroup []InstanceGroup `json:"instancegroup"`
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListInstanceGroups) Response() interface{} {
return new(ListInstanceGroupsResponse)
}
// ListRequest returns itself
func (ls *ListInstanceGroups) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListInstanceGroups) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListInstanceGroups) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListInstanceGroups) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListInstanceGroupsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListInstanceGroupsResponse was expected, got %T", resp))
return
}
for i := range items.InstanceGroup {
if !callback(&items.InstanceGroup[i], nil) {
break
}
}
}

94
vendor/github.com/exoscale/egoscale/isos.go generated vendored Normal file
View file

@ -0,0 +1,94 @@
package egoscale
// ISO represents an attachable ISO disc
type ISO Template
// ResourceType returns the type of the resource
func (ISO) ResourceType() string {
return "ISO"
}
// ListRequest produces the ListIsos command.
func (iso ISO) ListRequest() (ListCommand, error) {
req := &ListISOs{
ID: iso.ID,
Name: iso.Name,
ZoneID: iso.ZoneID,
}
if iso.Bootable {
*req.Bootable = true
}
if iso.IsFeatured {
req.IsoFilter = "featured"
}
if iso.IsPublic {
*req.IsPublic = true
}
if iso.IsReady {
*req.IsReady = true
}
for i := range iso.Tags {
req.Tags = append(req.Tags, iso.Tags[i])
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListISOs
// ListISOs represents the list all available ISO files request
type ListISOs struct {
_ bool `name:"listIsos" description:"Lists all available ISO files."`
Bootable *bool `json:"bootable,omitempty" doc:"True if the ISO is bootable, false otherwise"`
ID *UUID `json:"id,omitempty" doc:"List ISO by id"`
IsoFilter string `json:"isofilter,omitempty" doc:"Possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". * featured : templates that have been marked as featured and public. * self : templates that have been registered or created by the calling user. * selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. * sharedexecutable : templates ready to be deployed that have been granted to the calling user by another user. * executable : templates that are owned by the calling user, or public templates, that can be used to deploy a VM. * community : templates that have been marked as public but not featured. * all : all templates (only usable by admins)."`
IsPublic *bool `json:"ispublic,omitempty" doc:"True if the ISO is publicly available to all users, false otherwise."`
IsReady *bool `json:"isready,omitempty" doc:"True if this ISO is ready to be deployed"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"List all isos by name"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ShowRemoved *bool `json:"showremoved,omitempty" doc:"Show removed ISOs as well"`
Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"The ID of the zone"`
}
// ListISOsResponse represents a list of ISO files
type ListISOsResponse struct {
Count int `json:"count"`
ISO []ISO `json:"iso"`
}
// AttachISO represents the request to attach an ISO to a virtual machine.
type AttachISO struct {
_ bool `name:"attachIso" description:"Attaches an ISO to a virtual machine."`
ID *UUID `json:"id" doc:"the ID of the ISO file"`
VirtualMachineID *UUID `json:"virtualmachineid" doc:"the ID of the virtual machine"`
}
// Response returns the struct to unmarshal
func (AttachISO) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (AttachISO) AsyncResponse() interface{} {
return new(VirtualMachine)
}
// DetachISO represents the request to detach an ISO to a virtual machine.
type DetachISO struct {
_ bool `name:"detachIso" description:"Detaches any ISO file (if any) currently attached to a virtual machine."`
VirtualMachineID *UUID `json:"virtualmachineid" doc:"The ID of the virtual machine"`
}
// Response returns the struct to unmarshal
func (DetachISO) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (DetachISO) AsyncResponse() interface{} {
return new(VirtualMachine)
}

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

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListISOs) Response() interface{} {
return new(ListISOsResponse)
}
// ListRequest returns itself
func (ls *ListISOs) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListISOs) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListISOs) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListISOs) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListISOsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListISOsResponse was expected, got %T", resp))
return
}
for i := range items.ISO {
if !callback(&items.ISO[i], nil) {
break
}
}
}

View file

@ -1,139 +0,0 @@
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 ResourceTypeName = "public_ip"
// VolumeTypeName is the resource type name of a volume
VolumeTypeName ResourceTypeName = "volume"
// SnapshotTypeName is the resource type name of a snapshot
SnapshotTypeName ResourceTypeName = "snapshot"
// TemplateTypeName is the resource type name of a template
TemplateTypeName ResourceTypeName = "template"
// ProjectTypeName is the resource type name of a project
ProjectTypeName ResourceTypeName = "project"
// NetworkTypeName is the resource type name of a network
NetworkTypeName ResourceTypeName = "network"
// VPCTypeName is the resource type name of a VPC
VPCTypeName ResourceTypeName = "vpc"
// CPUTypeName is the resource type name of a CPU
CPUTypeName ResourceTypeName = "cpu"
// MemoryTypeName is the resource type name of Memory
MemoryTypeName ResourceTypeName = "memory"
// PrimaryStorageTypeName is the resource type name of primary storage
PrimaryStorageTypeName ResourceTypeName = "primary_storage"
// SecondaryStorageTypeName is the resource type name of secondary storage
SecondaryStorageTypeName ResourceTypeName = "secondary_storage"
)
// ResourceType represents the ID of a resource type (for limits)
type ResourceType string
const (
// VirtualMachineType is the resource type ID of a VM
VirtualMachineType ResourceType = "0"
// IPAddressType is the resource type ID of an IP address
IPAddressType ResourceType = "1"
// VolumeType is the resource type ID of a volume
VolumeType ResourceType = "2"
// SnapshotType is the resource type ID of a snapshot
SnapshotType ResourceType = "3"
// TemplateType is the resource type ID of a template
TemplateType ResourceType = "4"
// ProjectType is the resource type ID of a project
ProjectType ResourceType = "5"
// NetworkType is the resource type ID of a network
NetworkType ResourceType = "6"
// VPCType is the resource type ID of a VPC
VPCType ResourceType = "7"
// CPUType is the resource type ID of a CPU
CPUType ResourceType = "8"
// MemoryType is the resource type ID of Memory
MemoryType ResourceType = "9"
// PrimaryStorageType is the resource type ID of primary storage
PrimaryStorageType ResourceType = "10"
// SecondaryStorageType is the resource type ID of secondary storage
SecondaryStorageType ResourceType = "11"
)
// ResourceLimit represents the limit on a particular resource
type ResourceLimit struct {
Account string `json:"account,omitempty" doc:"the account of the resource limit"`
Domain string `json:"domain,omitempty" doc:"the domain name of the resource limit"`
DomainID string `json:"domainid,omitempty" doc:"the domain ID of the resource limit"`
Max int64 `json:"max,omitempty" doc:"the maximum number of the resource. A -1 means the resource currently has no limit."`
ResourceType ResourceType `json:"resourcetype,omitempty" doc:"resource type. Values include 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11. See the resourceType parameter for more information on these values."`
ResourceTypeName string `json:"resourcetypename,omitempty" doc:"resource type name. Values include user_vm, public_ip, volume, snapshot, template, project, network, vpc, cpu, memory, primary_storage, secondary_storage."`
}
// APILimit represents the limit count
type APILimit struct {
Account string `json:"account,omitempty" doc:"the account name of the api remaining count"`
Accountid string `json:"accountid,omitempty" doc:"the account uuid of the api remaining count"`
APIAllowed int `json:"apiAllowed,omitempty" doc:"currently allowed number of apis"`
APIIssued int `json:"apiIssued,omitempty" doc:"number of api already issued"`
ExpireAfter int64 `json:"expireAfter,omitempty" doc:"seconds left to reset counters"`
}
// ListResourceLimits lists the resource limits
type ListResourceLimits struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID string `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ID int64 `json:"id,omitempty" doc:"Lists resource limits by ID."`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ResourceType ResourceType `json:"resourcetype,omitempty" doc:"Type of resource. Values are 0, 1, 2, 3, 4, 6, 7, 8, 9, 10 and 11. 0 - Instance. Number of instances a user can create. 1 - IP. Number of public IP addresses an account can own. 2 - Volume. Number of disk volumes an account can own. 3 - Snapshot. Number of snapshots an account can own. 4 - Template. Number of templates an account can register/create. 5 - Project. Number of projects an account can own. 6 - Network. Number of networks an account can own. 7 - VPC. Number of VPC an account can own. 8 - CPU. Number of CPU an account can allocate for his resources. 9 - Memory. Amount of RAM an account can allocate for his resources. 10 - PrimaryStorage. Total primary storage space (in GiB) a user can use. 11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use. 12 - Elastic IP. Number of public elastic IP addresses an account can own. 13 - SMTP. If the account is allowed SMTP outbound traffic."`
ResourceTypeName string `json:"resourcetypename,omitempty" doc:"Type of resource (wins over resourceType if both are provided). Values are: user_vm - Instance. Number of instances a user can create. public_ip - IP. Number of public IP addresses an account can own. volume - Volume. Number of disk volumes an account can own. snapshot - Snapshot. Number of snapshots an account can own. template - Template. Number of templates an account can register/create. project - Project. Number of projects an account can own. network - Network. Number of networks an account can own. vpc - VPC. Number of VPC an account can own. cpu - CPU. Number of CPU an account can allocate for his resources. memory - Memory. Amount of RAM an account can allocate for his resources. primary_storage - PrimaryStorage. Total primary storage space (in GiB) a user can use. secondary_storage - SecondaryStorage. Total secondary storage space (in GiB) a user can use. public_elastic_ip - IP. Number of public elastic IP addresses an account can own. smtp - SG. If the account is allowed SMTP outbound traffic."`
_ bool `name:"listResourceLimits" description:"Lists resource limits."`
}
// ListResourceLimitsResponse represents a list of resource limits
type ListResourceLimitsResponse struct {
Count int `json:"count"`
ResourceLimit []ResourceLimit `json:"resourcelimit"`
}
func (ListResourceLimits) response() interface{} {
return new(ListResourceLimitsResponse)
}
// UpdateResourceLimit updates the resource limit
type UpdateResourceLimit struct {
Account string `json:"account,omitempty" doc:"Update resource for a specified account. Must be used with the domainId parameter."`
DomainID string `json:"domainid,omitempty" doc:"Update resource limits for all accounts in specified domain. If used with the account parameter, updates resource limits for a specified account in specified domain."`
Max int64 `json:"max,omitempty" doc:"Maximum resource limit."`
ResourceType ResourceType `json:"resourcetype" doc:"Type of resource to update. Values are 0, 1, 2, 3, 4, 6, 7, 8, 9, 10 and 11. 0 - Instance. Number of instances a user can create. 1 - IP. Number of public IP addresses a user can own. 2 - Volume. Number of disk volumes a user can create. 3 - Snapshot. Number of snapshots a user can create. 4 - Template. Number of templates that a user can register/create. 6 - Network. Number of guest network a user can create. 7 - VPC. Number of VPC a user can create. 8 - CPU. Total number of CPU cores a user can use. 9 - Memory. Total Memory (in MB) a user can use. 10 - PrimaryStorage. Total primary storage space (in GiB) a user can use. 11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use."`
_ bool `name:"updateResourceLimit" description:"Updates resource limits for an account or domain."`
}
// UpdateResourceLimitResponse represents an updated resource limit
type UpdateResourceLimitResponse struct {
ResourceLimit ResourceLimit `json:"resourcelimit"`
}
func (UpdateResourceLimit) response() interface{} {
return new(UpdateResourceLimitResponse)
}
// GetAPILimit gets API limit count for the caller
type GetAPILimit struct {
_ bool `name:"getApiLimit" description:"Get API limit count for the caller"`
}
// GetAPILimitResponse represents the limits towards the API call
type GetAPILimitResponse struct {
APILimit APILimit `json:"apilimit"`
}
func (GetAPILimit) response() interface{} {
return new(GetAPILimitResponse)
}

View file

@ -25,6 +25,23 @@ type NetworkOffering struct {
TrafficType string `json:"traffictype,omitempty" doc:"the traffic type for the network offering, supported types are Public, Management, Control, Guest, Vlan or Storage."` TrafficType string `json:"traffictype,omitempty" doc:"the traffic type for the network offering, supported types are Public, Management, Control, Guest, Vlan or Storage."`
} }
// ListRequest builds the ListNetworkOfferings request
//
// This doesn't take into account the IsDefault flag as the default value is true.
func (no NetworkOffering) ListRequest() (ListCommand, error) {
req := &ListNetworkOfferings{
Availability: no.Availability,
ID: no.ID,
Name: no.Name,
State: no.State,
TrafficType: no.TrafficType,
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListNetworkOfferings
// ListNetworkOfferings represents a query for network offerings // ListNetworkOfferings represents a query for network offerings
type ListNetworkOfferings struct { type ListNetworkOfferings struct {
Availability string `json:"availability,omitempty" doc:"the availability of network offering. Default value is Required"` Availability string `json:"availability,omitempty" doc:"the availability of network offering. Default value is Required"`
@ -55,10 +72,6 @@ type ListNetworkOfferingsResponse struct {
NetworkOffering []NetworkOffering `json:"networkoffering"` NetworkOffering []NetworkOffering `json:"networkoffering"`
} }
func (ListNetworkOfferings) response() interface{} {
return new(ListNetworkOfferingsResponse)
}
// UpdateNetworkOffering represents a modification of a network offering // UpdateNetworkOffering represents a modification of a network offering
type UpdateNetworkOffering struct { type UpdateNetworkOffering struct {
Availability string `json:"availability,omitempty" doc:"the availability of network offering. Default value is Required for Guest Virtual network offering; Optional for Guest Direct network offering"` Availability string `json:"availability,omitempty" doc:"the availability of network offering. Default value is Required for Guest Virtual network offering; Optional for Guest Direct network offering"`
@ -72,6 +85,7 @@ type UpdateNetworkOffering struct {
_ bool `name:"updateNetworkOffering" description:"Updates a network offering."` _ bool `name:"updateNetworkOffering" description:"Updates a network offering."`
} }
func (UpdateNetworkOffering) response() interface{} { // Response returns the struct to unmarshal
func (UpdateNetworkOffering) Response() interface{} {
return new(NetworkOffering) return new(NetworkOffering)
} }

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListNetworkOfferings) Response() interface{} {
return new(ListNetworkOfferingsResponse)
}
// ListRequest returns itself
func (ls *ListNetworkOfferings) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListNetworkOfferings) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListNetworkOfferings) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListNetworkOfferings) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListNetworkOfferingsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListNetworkOfferingsResponse was expected, got %T", resp))
return
}
for i := range items.NetworkOffering {
if !callback(&items.NetworkOffering[i], nil) {
break
}
}
}

View file

@ -1,7 +1,6 @@
package egoscale package egoscale
import ( import (
"fmt"
"net" "net"
"net/url" "net/url"
) )
@ -16,12 +15,9 @@ type Network struct {
BroadcastURI string `json:"broadcasturi,omitempty" doc:"broadcast uri of the network."` BroadcastURI string `json:"broadcasturi,omitempty" doc:"broadcast uri of the network."`
CanUseForDeploy bool `json:"canusefordeploy,omitempty" doc:"list networks available for vm deployment"` CanUseForDeploy bool `json:"canusefordeploy,omitempty" doc:"list networks available for vm deployment"`
CIDR *CIDR `json:"cidr,omitempty" doc:"Cloudstack managed address space, all CloudStack managed VMs get IP address from CIDR"` CIDR *CIDR `json:"cidr,omitempty" doc:"Cloudstack managed address space, all CloudStack managed VMs get IP address from CIDR"`
DisplayNetwork bool `json:"displaynetwork,omitempty" doc:"an optional field, whether to the display the network to the end user or not."`
DisplayText string `json:"displaytext,omitempty" doc:"the displaytext of the network"` DisplayText string `json:"displaytext,omitempty" doc:"the displaytext of the network"`
DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the network"` DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the network"`
DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the network"` DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the network"`
Domain string `json:"domain,omitempty" doc:"the domain name of the network owner"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain id of the network owner"`
EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."` EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."`
Gateway net.IP `json:"gateway,omitempty" doc:"the network's gateway"` Gateway net.IP `json:"gateway,omitempty" doc:"the network's gateway"`
ID *UUID `json:"id,omitempty" doc:"the id of the network"` ID *UUID `json:"id,omitempty" doc:"the id of the network"`
@ -62,8 +58,6 @@ type Network struct {
func (network Network) ListRequest() (ListCommand, error) { func (network Network) ListRequest() (ListCommand, error) {
//TODO add tags support //TODO add tags support
req := &ListNetworks{ req := &ListNetworks{
Account: network.Account,
DomainID: network.DomainID,
ID: network.ID, ID: network.ID,
Keyword: network.Name, // this is a hack as listNetworks doesn't support to search by name. Keyword: network.Name, // this is a hack as listNetworks doesn't support to search by name.
PhysicalNetworkID: network.PhysicalNetworkID, PhysicalNetworkID: network.PhysicalNetworkID,
@ -113,10 +107,7 @@ type ServiceProvider struct {
// CreateNetwork creates a network // CreateNetwork creates a network
type CreateNetwork struct { type CreateNetwork struct {
Account string `json:"account,omitempty" doc:"account who will own the network"`
DisplayNetwork *bool `json:"displaynetwork,omitempty" doc:"an optional field, whether to the display the network to the end user or not."`
DisplayText string `json:"displaytext,omitempty" doc:"the display text of the network"` // This field is required but might be empty DisplayText string `json:"displaytext,omitempty" doc:"the display text of the network"` // This field is required but might be empty
DomainID *UUID `json:"domainid,omitempty" doc:"domain ID of the account owning a network"`
EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."` EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."`
EndIpv6 net.IP `json:"endipv6,omitempty" doc:"the ending IPv6 address in the IPv6 network range"` EndIpv6 net.IP `json:"endipv6,omitempty" doc:"the ending IPv6 address in the IPv6 network range"`
Gateway net.IP `json:"gateway,omitempty" doc:"the gateway of the network. Required for Shared networks and Isolated networks when it belongs to VPC"` Gateway net.IP `json:"gateway,omitempty" doc:"the gateway of the network. Required for Shared networks and Isolated networks when it belongs to VPC"`
@ -130,13 +121,13 @@ type CreateNetwork struct {
PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"the Physical Network ID the network belongs to"` PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"the Physical Network ID the network belongs to"`
StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."` StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."`
StartIpv6 net.IP `json:"startipv6,omitempty" doc:"the beginning IPv6 address in the IPv6 network range"` StartIpv6 net.IP `json:"startipv6,omitempty" doc:"the beginning IPv6 address in the IPv6 network range"`
SubdomainAccess *bool `json:"subdomainaccess,omitempty" doc:"Defines whether to allow subdomains to use networks dedicated to their parent domain(s). Should be used with aclType=Domain, defaulted to allow.subdomain.network.access global config if not specified"`
Vlan string `json:"vlan,omitempty" doc:"the ID or VID of the network"` Vlan string `json:"vlan,omitempty" doc:"the ID or VID of the network"`
ZoneID *UUID `json:"zoneid" doc:"the Zone ID for the network"` ZoneID *UUID `json:"zoneid" doc:"the Zone ID for the network"`
_ bool `name:"createNetwork" description:"Creates a network"` _ bool `name:"createNetwork" description:"Creates a network"`
} }
func (CreateNetwork) response() interface{} { // Response returns the struct to unmarshal
func (CreateNetwork) Response() interface{} {
return new(Network) return new(Network)
} }
@ -153,23 +144,26 @@ func (req CreateNetwork) onBeforeSend(params url.Values) error {
// UpdateNetwork (Async) updates a network // UpdateNetwork (Async) updates a network
type UpdateNetwork struct { type UpdateNetwork struct {
ID *UUID `json:"id" doc:"the ID of the network"` _ bool `name:"updateNetwork" description:"Updates a network"`
ChangeCIDR *bool `json:"changecidr,omitempty" doc:"Force update even if cidr type is different"` ChangeCIDR *bool `json:"changecidr,omitempty" doc:"Force update even if cidr type is different"`
CustomID *UUID `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"`
DisplayNetwork *bool `json:"displaynetwork,omitempty" doc:"an optional field, whether to the display the network to the end user or not."`
DisplayText string `json:"displaytext,omitempty" doc:"the new display text for the network"` DisplayText string `json:"displaytext,omitempty" doc:"the new display text for the network"`
EndIP net.IP `json:"endip,omitempty" doc:"the ending IP address in the network IP range. Required for managed networks."`
GuestVMCIDR *CIDR `json:"guestvmcidr,omitempty" doc:"CIDR for Guest VMs,Cloudstack allocates IPs to Guest VMs only from this CIDR"` GuestVMCIDR *CIDR `json:"guestvmcidr,omitempty" doc:"CIDR for Guest VMs,Cloudstack allocates IPs to Guest VMs only from this CIDR"`
ID *UUID `json:"id" doc:"the ID of the network"`
Name string `json:"name,omitempty" doc:"the new name for the network"` Name string `json:"name,omitempty" doc:"the new name for the network"`
Netmask net.IP `json:"netmask,omitempty" doc:"the netmask of the network. Required for managed networks."`
NetworkDomain string `json:"networkdomain,omitempty" doc:"network domain"` NetworkDomain string `json:"networkdomain,omitempty" doc:"network domain"`
NetworkOfferingID *UUID `json:"networkofferingid,omitempty" doc:"network offering ID"` NetworkOfferingID *UUID `json:"networkofferingid,omitempty" doc:"network offering ID"`
_ bool `name:"updateNetwork" description:"Updates a network"` StartIP net.IP `json:"startip,omitempty" doc:"the beginning IP address in the network IP range. Required for managed networks."`
} }
func (UpdateNetwork) response() interface{} { // Response returns the struct to unmarshal
func (UpdateNetwork) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (UpdateNetwork) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (UpdateNetwork) AsyncResponse() interface{} {
return new(Network) return new(Network)
} }
@ -180,11 +174,13 @@ type RestartNetwork struct {
_ bool `name:"restartNetwork" description:"Restarts the network; includes 1) restarting network elements - virtual routers, dhcp servers 2) reapplying all public ips 3) reapplying loadBalancing/portForwarding rules"` _ bool `name:"restartNetwork" description:"Restarts the network; includes 1) restarting network elements - virtual routers, dhcp servers 2) reapplying all public ips 3) reapplying loadBalancing/portForwarding rules"`
} }
func (RestartNetwork) response() interface{} { // Response returns the struct to unmarshal
func (RestartNetwork) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RestartNetwork) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (RestartNetwork) AsyncResponse() interface{} {
return new(Network) return new(Network)
} }
@ -195,35 +191,34 @@ type DeleteNetwork struct {
_ bool `name:"deleteNetwork" description:"Deletes a network"` _ bool `name:"deleteNetwork" description:"Deletes a network"`
} }
func (DeleteNetwork) response() interface{} { // Response returns the struct to unmarshal
func (DeleteNetwork) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DeleteNetwork) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (DeleteNetwork) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
//go:generate go run generate/main.go -interface=Listable ListNetworks
// ListNetworks represents a query to a network // ListNetworks represents a query to a network
type ListNetworks struct { type ListNetworks struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` CanUseForDeploy *bool `json:"canusefordeploy,omitempty" doc:"List networks available for vm deployment"`
CanUseForDeploy *bool `json:"canusefordeploy,omitempty" doc:"list networks available for vm deployment"` ID *UUID `json:"id,omitempty" doc:"List networks by id"`
DisplayNetwork *bool `json:"displaynetwork,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"` IsSystem *bool `json:"issystem,omitempty" doc:"true If network is system, false otherwise"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ID *UUID `json:"id,omitempty" doc:"list networks by id"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
IsSystem *bool `json:"issystem,omitempty" doc:"true if network is system, false otherwise"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"list networks by physical network id"` PhysicalNetworkID *UUID `json:"physicalnetworkid,omitempty" doc:"List networks by physical network id"`
RestartRequired *bool `json:"restartrequired,omitempty" doc:"list networks by restartRequired"` RestartRequired *bool `json:"restartrequired,omitempty" doc:"List networks by restartRequired"`
SpecifyIPRanges *bool `json:"specifyipranges,omitempty" doc:"true if need to list only networks which support specifying ip ranges"` SpecifyIPRanges *bool `json:"specifyipranges,omitempty" doc:"True if need to list only networks which support specifying ip ranges"`
SupportedServices []Service `json:"supportedservices,omitempty" doc:"list networks supporting certain services"` SupportedServices []Service `json:"supportedservices,omitempty" doc:"List networks supporting certain services"`
Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"`
TrafficType string `json:"traffictype,omitempty" doc:"type of the traffic"` TrafficType string `json:"traffictype,omitempty" doc:"Type of the traffic"`
Type string `json:"type,omitempty" doc:"the type of the network. Supported values are: Isolated and Shared"` Type string `json:"type,omitempty" doc:"The type of the network. Supported values are: Isolated and Shared"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the Zone ID of the network"` ZoneID *UUID `json:"zoneid,omitempty" doc:"The Zone ID of the network"`
_ bool `name:"listNetworks" description:"Lists all available networks."` _ bool `name:"listNetworks" description:"Lists all available networks."`
} }
@ -232,31 +227,3 @@ type ListNetworksResponse struct {
Count int `json:"count"` Count int `json:"count"`
Network []Network `json:"network"` Network []Network `json:"network"`
} }
func (ListNetworks) response() interface{} {
return new(ListNetworksResponse)
}
// SetPage sets the current page
func (listNetwork *ListNetworks) SetPage(page int) {
listNetwork.Page = page
}
// SetPageSize sets the page size
func (listNetwork *ListNetworks) SetPageSize(pageSize int) {
listNetwork.PageSize = pageSize
}
func (ListNetworks) each(resp interface{}, callback IterateItemFunc) {
networks, ok := resp.(*ListNetworksResponse)
if !ok {
callback(nil, fmt.Errorf("type error: ListNetworksResponse expected, got %T", resp))
return
}
for i := range networks.Network {
if !callback(&networks.Network[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListNetworks) Response() interface{} {
return new(ListNetworksResponse)
}
// ListRequest returns itself
func (ls *ListNetworks) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListNetworks) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListNetworks) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListNetworks) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListNetworksResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListNetworksResponse was expected, got %T", resp))
return
}
for i := range items.Network {
if !callback(&items.Network[i], nil) {
break
}
}
}

View file

@ -1,7 +1,6 @@
package egoscale package egoscale
import ( import (
"errors"
"net" "net"
) )
@ -32,10 +31,6 @@ type Nic struct {
// ListRequest build a ListNics request from the given Nic // ListRequest build a ListNics request from the given Nic
func (nic Nic) ListRequest() (ListCommand, error) { func (nic Nic) ListRequest() (ListCommand, error) {
if nic.VirtualMachineID == nil {
return nil, errors.New("command ListNics requires the VirtualMachineID field to be set")
}
req := &ListNics{ req := &ListNics{
VirtualMachineID: nic.VirtualMachineID, VirtualMachineID: nic.VirtualMachineID,
NicID: nic.ID, NicID: nic.ID,
@ -54,15 +49,16 @@ type NicSecondaryIP struct {
VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the vm"` VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the vm"`
} }
//go:generate go run generate/main.go -interface=Listable ListNics
// ListNics represents the NIC search // ListNics represents the NIC search
type ListNics struct { type ListNics struct {
ForDisplay bool `json:"fordisplay,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
NetworkID *UUID `json:"networkid,omitempty" doc:"list nic of the specific vm's network"` NetworkID *UUID `json:"networkid,omitempty" doc:"list nic of the specific vm's network"`
NicID *UUID `json:"nicid,omitempty" doc:"the ID of the nic to to list IPs"` NicID *UUID `json:"nicid,omitempty" doc:"the ID of the nic to to list IPs"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
VirtualMachineID *UUID `json:"virtualmachineid" doc:"the ID of the vm"` VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the vm"`
_ bool `name:"listNics" description:"list the vm nics IP to NIC"` _ bool `name:"listNics" description:"list the vm nics IP to NIC"`
} }
@ -72,29 +68,6 @@ type ListNicsResponse struct {
Nic []Nic `json:"nic"` Nic []Nic `json:"nic"`
} }
func (ListNics) response() interface{} {
return new(ListNicsResponse)
}
// SetPage sets the current page
func (ls *ListNics) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListNics) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListNics) each(resp interface{}, callback IterateItemFunc) {
nics := resp.(*ListNicsResponse)
for i := range nics.Nic {
if !callback(&(nics.Nic[i]), nil) {
break
}
}
}
// AddIPToNic (Async) represents the assignation of a secondary IP // AddIPToNic (Async) represents the assignation of a secondary IP
type AddIPToNic struct { type AddIPToNic struct {
NicID *UUID `json:"nicid" doc:"the ID of the nic to which you want to assign private IP"` NicID *UUID `json:"nicid" doc:"the ID of the nic to which you want to assign private IP"`
@ -102,11 +75,13 @@ type AddIPToNic struct {
_ bool `name:"addIpToNic" description:"Assigns secondary IP to NIC"` _ bool `name:"addIpToNic" description:"Assigns secondary IP to NIC"`
} }
func (AddIPToNic) response() interface{} { // Response returns the struct to unmarshal
func (AddIPToNic) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (AddIPToNic) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (AddIPToNic) AsyncResponse() interface{} {
return new(NicSecondaryIP) return new(NicSecondaryIP)
} }
@ -116,12 +91,14 @@ type RemoveIPFromNic struct {
_ bool `name:"removeIpFromNic" description:"Removes secondary IP from the NIC."` _ bool `name:"removeIpFromNic" description:"Removes secondary IP from the NIC."`
} }
func (RemoveIPFromNic) response() interface{} { // Response returns the struct to unmarshal
func (RemoveIPFromNic) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RemoveIPFromNic) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (RemoveIPFromNic) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// ActivateIP6 (Async) activates the IP6 on the given NIC // ActivateIP6 (Async) activates the IP6 on the given NIC
@ -132,10 +109,12 @@ type ActivateIP6 struct {
_ bool `name:"activateIp6" description:"Activate the IPv6 on the VM's nic"` _ bool `name:"activateIp6" description:"Activate the IPv6 on the VM's nic"`
} }
func (ActivateIP6) response() interface{} { // Response returns the struct to unmarshal
func (ActivateIP6) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (ActivateIP6) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (ActivateIP6) AsyncResponse() interface{} {
return new(Nic) return new(Nic)
} }

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

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListNics) Response() interface{} {
return new(ListNicsResponse)
}
// ListRequest returns itself
func (ls *ListNics) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListNics) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListNics) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListNics) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListNicsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListNicsResponse was expected, got %T", resp))
return
}
for i := range items.Nic {
if !callback(&items.Nic[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListOSCategories) Response() interface{} {
return new(ListOSCategoriesResponse)
}
// ListRequest returns itself
func (ls *ListOSCategories) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListOSCategories) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListOSCategories) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListOSCategories) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListOSCategoriesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListOSCategoriesResponse was expected, got %T", resp))
return
}
for i := range items.OSCategory {
if !callback(&items.OSCategory[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListPublicIPAddresses) Response() interface{} {
return new(ListPublicIPAddressesResponse)
}
// ListRequest returns itself
func (ls *ListPublicIPAddresses) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListPublicIPAddresses) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListPublicIPAddresses) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListPublicIPAddresses) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListPublicIPAddressesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListPublicIPAddressesResponse was expected, got %T", resp))
return
}
for i := range items.PublicIPAddress {
if !callback(&items.PublicIPAddress[i], nil) {
break
}
}
}

View file

@ -24,7 +24,7 @@ func (e ErrorResponse) Error() string {
} }
// Error formats a CloudStack job response into a standard error // Error formats a CloudStack job response into a standard error
func (e booleanResponse) Error() error { func (e BooleanResponse) Error() error {
if !e.Success { if !e.Success {
return fmt.Errorf("API error: %s", e.DisplayText) return fmt.Errorf("API error: %s", e.DisplayText)
} }
@ -32,12 +32,17 @@ func (e booleanResponse) Error() error {
return nil return nil
} }
// XXX: addIpToNic, activateIp6, restorevmresponse are kind of special func responseKey(key string) (string, bool) {
var responseKeys = map[string]string{ // XXX: addIpToNic, activateIp6, restorevmresponse are kind of special
"addiptonicresponse": "addiptovmnicresponse", var responseKeys = map[string]string{
"activateip6response": "activateip6nicresponse", "addiptonicresponse": "addiptovmnicresponse",
"restorevirtualmachineresponse": "restorevmresponse", "activateip6response": "activateip6nicresponse",
"updatevmaffinitygroupresponse": "updatevirtualmachineresponse", "restorevirtualmachineresponse": "restorevmresponse",
"updatevmaffinitygroupresponse": "updatevirtualmachineresponse",
}
k, ok := responseKeys[key]
return k, ok
} }
func (client *Client) parseResponse(resp *http.Response, apiName string) (json.RawMessage, error) { func (client *Client) parseResponse(resp *http.Response, apiName string) (json.RawMessage, error) {
@ -60,7 +65,7 @@ func (client *Client) parseResponse(resp *http.Response, apiName string) (json.R
if !ok { if !ok {
// try again with the special keys // try again with the special keys
value, ok := responseKeys[key] value, ok := responseKey(key)
if ok { if ok {
key = value key = value
} }
@ -68,9 +73,7 @@ func (client *Client) parseResponse(resp *http.Response, apiName string) (json.R
response, ok = m[key] response, ok = m[key]
if !ok { if !ok {
for k := range m { return nil, fmt.Errorf("malformed JSON response %d, %q was expected.\n%s", resp.StatusCode, key, b)
return nil, fmt.Errorf("malformed JSON response, %q was expected, got %q", key, k)
}
} }
} }
} }
@ -111,7 +114,7 @@ func (client *Client) parseResponse(resp *http.Response, apiName string) (json.R
func (client *Client) asyncRequest(ctx context.Context, asyncCommand AsyncCommand) (interface{}, error) { func (client *Client) asyncRequest(ctx context.Context, asyncCommand AsyncCommand) (interface{}, error) {
var err error var err error
resp := asyncCommand.asyncResponse() resp := asyncCommand.AsyncResponse()
client.AsyncRequestWithContext( client.AsyncRequestWithContext(
ctx, ctx,
asyncCommand, asyncCommand,
@ -139,8 +142,8 @@ func (client *Client) SyncRequestWithContext(ctx context.Context, command Comman
return nil, err return nil, err
} }
response := command.response() response := command.Response()
b, ok := response.(*booleanResponse) b, ok := response.(*BooleanResponse)
if ok { if ok {
m := make(map[string]interface{}) m := make(map[string]interface{})
if errUnmarshal := json.Unmarshal(body, &m); errUnmarshal != nil { if errUnmarshal := json.Unmarshal(body, &m); errUnmarshal != nil {
@ -178,7 +181,7 @@ func (client *Client) BooleanRequest(command Command) error {
return err return err
} }
if b, ok := resp.(*booleanResponse); ok { if b, ok := resp.(*BooleanResponse); ok {
return b.Error() return b.Error()
} }
@ -192,7 +195,7 @@ func (client *Client) BooleanRequestWithContext(ctx context.Context, command Com
return err return err
} }
if b, ok := resp.(*booleanResponse); ok { if b, ok := resp.(*BooleanResponse); ok {
return b.Error() return b.Error()
} }
@ -209,9 +212,9 @@ func (client *Client) Request(command Command) (interface{}, error) {
// RequestWithContext preforms a command with a context // RequestWithContext preforms a command with a context
func (client *Client) RequestWithContext(ctx context.Context, command Command) (interface{}, error) { func (client *Client) RequestWithContext(ctx context.Context, command Command) (interface{}, error) {
switch command.(type) { switch c := command.(type) {
case AsyncCommand: case AsyncCommand:
return client.asyncRequest(ctx, command.(AsyncCommand)) return client.asyncRequest(ctx, c)
default: default:
return client.SyncRequestWithContext(ctx, command) return client.SyncRequestWithContext(ctx, command)
} }
@ -278,10 +281,9 @@ func (client *Client) AsyncRequestWithContext(ctx context.Context, asyncCommand
// Payload builds the HTTP request params from the given command // Payload builds the HTTP request params from the given command
func (client *Client) Payload(command Command) (url.Values, error) { func (client *Client) Payload(command Command) (url.Values, error) {
params := url.Values{} params, err := prepareValues("", command)
err := prepareValues("", params, command)
if err != nil { if err != nil {
return params, err return nil, err
} }
if hookReq, ok := command.(onBeforeHook); ok { if hookReq, ok := command.(onBeforeHook); ok {
if err := hookReq.onBeforeSend(params); err != nil { if err := hookReq.onBeforeSend(params); err != nil {
@ -292,6 +294,11 @@ func (client *Client) Payload(command Command) (url.Values, error) {
params.Set("command", client.APIName(command)) params.Set("command", client.APIName(command))
params.Set("response", "json") params.Set("response", "json")
if params.Get("expires") == "" && client.Expiration >= 0 {
params.Set("signatureversion", "3")
params.Set("expires", time.Now().Add(client.Expiration).Local().Format("2006-01-02T15:04:05-0700"))
}
return params, nil return params, nil
} }

View file

@ -4,27 +4,27 @@ import (
"net/url" "net/url"
) )
// Command represents a CloudStack request // Command represents a generic request
type Command interface { type Command interface {
response() interface{} Response() interface{}
} }
// AsyncCommand represents a async CloudStack request // AsyncCommand represents a async request
type AsyncCommand interface { type AsyncCommand interface {
Command Command
// Response interface to Unmarshal the JSON into AsyncResponse() interface{}
asyncResponse() interface{}
} }
// ListCommand represents a CloudStack list request // ListCommand represents a listing request
type ListCommand interface { type ListCommand interface {
Listable
Command Command
// SetPage defines the current pages // SetPage defines the current pages
SetPage(int) SetPage(int)
// SetPageSize defines the size of the page // SetPageSize defines the size of the page
SetPageSize(int) SetPageSize(int)
// each reads the data from the response and feeds channels, and returns true if we are on the last page // Each reads the data from the response and feeds channels, and returns true if we are on the last page
each(interface{}, IterateItemFunc) Each(interface{}, IterateItemFunc)
} }
// onBeforeHook represents an action to be done on the params before sending them // onBeforeHook represents an action to be done on the params before sending them
@ -57,7 +57,7 @@ const (
// ErrorCode represents the CloudStack ApiErrorCode enum // ErrorCode represents the CloudStack ApiErrorCode enum
// //
// See: https://github.com/apache/cloudstack/blob/master/api/src/org/apache/cloudstack/api/ApiErrorCode.java // See: https://github.com/apache/cloudstack/blob/master/api/src/main/java/org/apache/cloudstack/api/ApiErrorCode.java
type ErrorCode int type ErrorCode int
//go:generate stringer -type ErrorCode //go:generate stringer -type ErrorCode
@ -162,7 +162,7 @@ const (
ServerAPIException CSErrorCode = 9999 ServerAPIException CSErrorCode = 9999
) )
// ErrorResponse represents the standard error response from CloudStack // ErrorResponse represents the standard error response
type ErrorResponse struct { type ErrorResponse struct {
CSErrorCode CSErrorCode `json:"cserrorcode"` CSErrorCode CSErrorCode `json:"cserrorcode"`
ErrorCode ErrorCode `json:"errorcode"` ErrorCode ErrorCode `json:"errorcode"`
@ -177,8 +177,8 @@ type UUIDItem struct {
UUID string `json:"uuid"` UUID string `json:"uuid"`
} }
// booleanResponse represents a boolean response (usually after a deletion) // BooleanResponse represents a boolean response (usually after a deletion)
type booleanResponse struct { type BooleanResponse struct {
DisplayText string `json:"displaytext,omitempty"` DisplayText string `json:"displaytext,omitempty"`
Success bool `json:"success"` Success bool `json:"success"`
} }

100
vendor/github.com/exoscale/egoscale/resource_limits.go generated vendored Normal file
View file

@ -0,0 +1,100 @@
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 ResourceTypeName = "public_ip"
// VolumeTypeName is the resource type name of a volume
VolumeTypeName ResourceTypeName = "volume"
// SnapshotTypeName is the resource type name of a snapshot
SnapshotTypeName ResourceTypeName = "snapshot"
// TemplateTypeName is the resource type name of a template
TemplateTypeName ResourceTypeName = "template"
// ProjectTypeName is the resource type name of a project
ProjectTypeName ResourceTypeName = "project"
// NetworkTypeName is the resource type name of a network
NetworkTypeName ResourceTypeName = "network"
// VPCTypeName is the resource type name of a VPC
VPCTypeName ResourceTypeName = "vpc"
// CPUTypeName is the resource type name of a CPU
CPUTypeName ResourceTypeName = "cpu"
// MemoryTypeName is the resource type name of Memory
MemoryTypeName ResourceTypeName = "memory"
// PrimaryStorageTypeName is the resource type name of primary storage
PrimaryStorageTypeName ResourceTypeName = "primary_storage"
// SecondaryStorageTypeName is the resource type name of secondary storage
SecondaryStorageTypeName ResourceTypeName = "secondary_storage"
)
// ResourceType represents the ID of a resource type (for limits)
type ResourceType string
const (
// VirtualMachineType is the resource type ID of a VM
VirtualMachineType ResourceType = "0"
// IPAddressType is the resource type ID of an IP address
IPAddressType ResourceType = "1"
// VolumeType is the resource type ID of a volume
VolumeType ResourceType = "2"
// SnapshotType is the resource type ID of a snapshot
SnapshotType ResourceType = "3"
// TemplateType is the resource type ID of a template
TemplateType ResourceType = "4"
// ProjectType is the resource type ID of a project
ProjectType ResourceType = "5"
// NetworkType is the resource type ID of a network
NetworkType ResourceType = "6"
// VPCType is the resource type ID of a VPC
VPCType ResourceType = "7"
// CPUType is the resource type ID of a CPU
CPUType ResourceType = "8"
// MemoryType is the resource type ID of Memory
MemoryType ResourceType = "9"
// PrimaryStorageType is the resource type ID of primary storage
PrimaryStorageType ResourceType = "10"
// SecondaryStorageType is the resource type ID of secondary storage
SecondaryStorageType ResourceType = "11"
)
// ResourceLimit represents the limit on a particular resource
type ResourceLimit struct {
Max int64 `json:"max,omitempty" doc:"the maximum number of the resource. A -1 means the resource currently has no limit."`
ResourceType ResourceType `json:"resourcetype,omitempty" doc:"resource type. Values include 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11. See the resourceType parameter for more information on these values."`
ResourceTypeName string `json:"resourcetypename,omitempty" doc:"resource type name. Values include user_vm, public_ip, volume, snapshot, template, network, cpu, memory, primary_storage, secondary_storage."`
}
// ListRequest builds the ListResourceLimits request
func (limit ResourceLimit) ListRequest() (ListCommand, error) {
req := &ListResourceLimits{
ResourceType: limit.ResourceType,
ResourceTypeName: limit.ResourceTypeName,
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListResourceLimits
// ListResourceLimits lists the resource limits
type ListResourceLimits struct {
ID int64 `json:"id,omitempty" doc:"Lists resource limits by ID."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
ResourceType ResourceType `json:"resourcetype,omitempty" doc:"Type of resource. Values are 0, 1, 2, 3, 4, 6, 8, 9, 10, 11, 12, and 13. 0 - Instance. Number of instances a user can create. 1 - IP. Number of public IP addresses an account can own. 2 - Volume. Number of disk volumes an account can own. 3 - Snapshot. Number of snapshots an account can own. 4 - Template. Number of templates an account can register/create. 6 - Network. Number of networks an account can own. 8 - CPU. Number of CPU an account can allocate for his resources. 9 - Memory. Amount of RAM an account can allocate for his resources. 10 - PrimaryStorage. Total primary storage space (in GiB) a user can use. 11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use. 12 - Elastic IP. Number of public elastic IP addresses an account can own. 13 - SMTP. If the account is allowed SMTP outbound traffic."`
ResourceTypeName string `json:"resourcetypename,omitempty" doc:"Type of resource (wins over resourceType if both are provided). Values are: user_vm - Instance. Number of instances a user can create. public_ip - IP. Number of public IP addresses an account can own. volume - Volume. Number of disk volumes an account can own. snapshot - Snapshot. Number of snapshots an account can own. template - Template. Number of templates an account can register/create. network - Network. Number of networks an account can own. cpu - CPU. Number of CPU an account can allocate for his resources. memory - Memory. Amount of RAM an account can allocate for his resources. primary_storage - PrimaryStorage. Total primary storage space (in GiB) a user can use. secondary_storage - SecondaryStorage. Total secondary storage space (in GiB) a user can use. public_elastic_ip - IP. Number of public elastic IP addresses an account can own. smtp - SG. If the account is allowed SMTP outbound traffic."`
_ bool `name:"listResourceLimits" description:"Lists resource limits."`
}
// ListResourceLimitsResponse represents a list of resource limits
type ListResourceLimitsResponse struct {
Count int `json:"count"`
ResourceLimit []ResourceLimit `json:"resourcelimit"`
}

View file

@ -1,19 +1,36 @@
package egoscale package egoscale
import "fmt"
// ResourceDetail represents extra details
type ResourceDetail ResourceTag
// ListRequest builds the ListResourceDetails request
func (detail ResourceDetail) ListRequest() (ListCommand, error) {
if detail.ResourceType == "" {
return nil, fmt.Errorf("the resourcetype parameter is required")
}
req := &ListResourceDetails{
ResourceType: detail.ResourceType,
ResourceID: detail.ResourceID,
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListResourceDetails
// ListResourceDetails lists the resource tag(s) (but different from listTags...) // ListResourceDetails lists the resource tag(s) (but different from listTags...)
type ListResourceDetails struct { type ListResourceDetails struct {
ResourceType string `json:"resourcetype" doc:"list by resource type"` ResourceType string `json:"resourcetype" doc:"list by resource type"`
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ForDisplay bool `json:"fordisplay,omitempty" doc:"if set to true, only details marked with display=true, are returned. False by default"` ForDisplay bool `json:"fordisplay,omitempty" doc:"if set to true, only details marked with display=true, are returned. False by default"`
Key string `json:"key,omitempty" doc:"list by key"` Key string `json:"key,omitempty" doc:"list by key"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
ResourceID *UUID `json:"resourceid,omitempty" doc:"list by resource id"` ResourceID *UUID `json:"resourceid,omitempty" doc:"list by resource id"`
Value string `json:"value,omitempty" doc:"list by key, value. Needs to be passed only along with key"` Value string `json:"value,omitempty" doc:"list by key, value. Needs to be passed only along with key"`
IsRecursive bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
_ bool `name:"listResourceDetails" description:"List resource detail(s)"` _ bool `name:"listResourceDetails" description:"List resource detail(s)"`
} }
@ -22,15 +39,3 @@ type ListResourceDetailsResponse struct {
Count int `json:"count"` Count int `json:"count"`
ResourceDetail []ResourceTag `json:"resourcedetail"` ResourceDetail []ResourceTag `json:"resourcedetail"`
} }
func (*ListResourceDetails) name() string {
return "listResourceDetails"
}
func (*ListResourceDetails) description() string {
return "List resource detail(s)"
}
func (*ListResourceDetails) response() interface{} {
return new(ListResourceDetailsResponse)
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListResourceDetails) Response() interface{} {
return new(ListResourceDetailsResponse)
}
// ListRequest returns itself
func (ls *ListResourceDetails) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListResourceDetails) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListResourceDetails) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListResourceDetails) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListResourceDetailsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListResourceDetailsResponse was expected, got %T", resp))
return
}
for i := range items.ResourceDetail {
if !callback(&items.ResourceDetail[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListResourceLimits) Response() interface{} {
return new(ListResourceLimitsResponse)
}
// ListRequest returns itself
func (ls *ListResourceLimits) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListResourceLimits) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListResourceLimits) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListResourceLimits) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListResourceLimitsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListResourceLimitsResponse was expected, got %T", resp))
return
}
for i := range items.ResourceLimit {
if !callback(&items.ResourceLimit[i], nil) {
break
}
}
}

View file

@ -20,8 +20,9 @@ type DeleteReverseDNSFromPublicIPAddress struct {
_ bool `name:"deleteReverseDnsFromPublicIpAddress" description:"delete the PTR DNS record from the public IP address"` _ bool `name:"deleteReverseDnsFromPublicIpAddress" description:"delete the PTR DNS record from the public IP address"`
} }
func (*DeleteReverseDNSFromPublicIPAddress) response() interface{} { // Response returns the struct to unmarshal
return new(booleanResponse) func (*DeleteReverseDNSFromPublicIPAddress) Response() interface{} {
return new(BooleanResponse)
} }
// DeleteReverseDNSFromVirtualMachine is a command to create/delete the PTR record(s) of a virtual machine // DeleteReverseDNSFromVirtualMachine is a command to create/delete the PTR record(s) of a virtual machine
@ -30,8 +31,9 @@ type DeleteReverseDNSFromVirtualMachine struct {
_ bool `name:"deleteReverseDnsFromVirtualMachine" description:"Delete the PTR DNS record(s) from the virtual machine"` _ bool `name:"deleteReverseDnsFromVirtualMachine" description:"Delete the PTR DNS record(s) from the virtual machine"`
} }
func (*DeleteReverseDNSFromVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
return new(booleanResponse) func (*DeleteReverseDNSFromVirtualMachine) Response() interface{} {
return new(BooleanResponse)
} }
// QueryReverseDNSForPublicIPAddress is a command to create/query the PTR record of a public IP address // QueryReverseDNSForPublicIPAddress is a command to create/query the PTR record of a public IP address
@ -40,7 +42,8 @@ type QueryReverseDNSForPublicIPAddress struct {
_ bool `name:"queryReverseDnsForPublicIpAddress" description:"Query the PTR DNS record for the public IP address"` _ bool `name:"queryReverseDnsForPublicIpAddress" description:"Query the PTR DNS record for the public IP address"`
} }
func (*QueryReverseDNSForPublicIPAddress) response() interface{} { // Response returns the struct to unmarshal
func (*QueryReverseDNSForPublicIPAddress) Response() interface{} {
return new(IPAddress) return new(IPAddress)
} }
@ -50,7 +53,8 @@ type QueryReverseDNSForVirtualMachine struct {
_ bool `name:"queryReverseDnsForVirtualMachine" description:"Query the PTR DNS record(s) for the virtual machine"` _ bool `name:"queryReverseDnsForVirtualMachine" description:"Query the PTR DNS record(s) for the virtual machine"`
} }
func (*QueryReverseDNSForVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (*QueryReverseDNSForVirtualMachine) Response() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -61,7 +65,8 @@ type UpdateReverseDNSForPublicIPAddress struct {
_ bool `name:"updateReverseDnsForPublicIpAddress" description:"Update/create the PTR DNS record for the public IP address"` _ bool `name:"updateReverseDnsForPublicIpAddress" description:"Update/create the PTR DNS record for the public IP address"`
} }
func (*UpdateReverseDNSForPublicIPAddress) response() interface{} { // Response returns the struct to unmarshal
func (*UpdateReverseDNSForPublicIPAddress) Response() interface{} {
return new(IPAddress) return new(IPAddress)
} }
@ -72,6 +77,7 @@ type UpdateReverseDNSForVirtualMachine struct {
_ bool `name:"updateReverseDnsForVirtualMachine" description:"Update/create the PTR DNS record(s) for the virtual machine"` _ bool `name:"updateReverseDnsForVirtualMachine" description:"Update/create the PTR DNS record(s) for the virtual machine"`
} }
func (*UpdateReverseDNSForVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (*UpdateReverseDNSForVirtualMachine) Response() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }

264
vendor/github.com/exoscale/egoscale/runstatus.go generated vendored Normal file
View file

@ -0,0 +1,264 @@
package egoscale
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strings"
"time"
)
// RunstatusValidationErrorResponse represents an error in the API
type RunstatusValidationErrorResponse map[string][]string
// RunstatusErrorResponse represents the default errors
type RunstatusErrorResponse struct {
Detail string `json:"detail"`
}
// runstatusPagesURL is the only URL that cannot be guessed
const runstatusPagesURL = "/pages"
// RunstatusPage runstatus page
type RunstatusPage struct {
Created *time.Time `json:"created,omitempty"`
DarkTheme bool `json:"dark_theme,omitempty"`
Domain string `json:"domain,omitempty"`
GradientEnd string `json:"gradient_end,omitempty"`
GradientStart string `json:"gradient_start,omitempty"`
HeaderBackground string `json:"header_background,omitempty"`
ID int `json:"id,omitempty"`
Incidents []RunstatusIncident `json:"incidents,omitempty"`
IncidentsURL string `json:"incidents_url,omitempty"`
Logo string `json:"logo,omitempty"`
Maintenances []RunstatusMaintenance `json:"maintenances,omitempty"`
MaintenancesURL string `json:"maintenances_url,omitempty"`
Name string `json:"name"` //fake field (used to post a new runstatus page)
OkText string `json:"ok_text,omitempty"`
Plan string `json:"plan,omitempty"`
PublicURL string `json:"public_url,omitempty"`
Services []RunstatusService `json:"services,omitempty"`
ServicesURL string `json:"services_url,omitempty"`
State string `json:"state,omitempty"`
Subdomain string `json:"subdomain"`
SupportEmail string `json:"support_email,omitempty"`
TimeZone string `json:"time_zone,omitempty"`
Title string `json:"title,omitempty"`
TitleColor string `json:"title_color,omitempty"`
TwitterUsername string `json:"twitter_username,omitempty"`
URL string `json:"url,omitempty"`
}
// Match returns true if the other page has got similarities with itself
func (page RunstatusPage) Match(other RunstatusPage) bool {
if other.Subdomain != "" && page.Subdomain == other.Subdomain {
return true
}
if other.ID > 0 && page.ID == other.ID {
return true
}
return false
}
//RunstatusPageList runstatus page list
type RunstatusPageList struct {
Count int `json:"count"`
Next string `json:"next"`
Previous string `json:"previous"`
Results []RunstatusPage `json:"results"`
}
// CreateRunstatusPage create runstatus page
func (client *Client) CreateRunstatusPage(ctx context.Context, page RunstatusPage) (*RunstatusPage, error) {
resp, err := client.runstatusRequest(ctx, client.Endpoint+runstatusPagesURL, page, "POST")
if err != nil {
return nil, err
}
var p *RunstatusPage
if err := json.Unmarshal(resp, &p); err != nil {
return nil, err
}
return p, nil
}
// DeleteRunstatusPage delete runstatus page
func (client *Client) DeleteRunstatusPage(ctx context.Context, page RunstatusPage) error {
if page.URL == "" {
return fmt.Errorf("empty URL for %#v", page)
}
_, err := client.runstatusRequest(ctx, page.URL, nil, "DELETE")
return err
}
// GetRunstatusPage fetches the runstatus page
func (client *Client) GetRunstatusPage(ctx context.Context, page RunstatusPage) (*RunstatusPage, error) {
if page.URL != "" {
return client.getRunstatusPage(ctx, page.URL)
}
ps, err := client.ListRunstatusPages(ctx)
if err != nil {
return nil, err
}
for i := range ps {
if ps[i].Match(page) {
return &ps[i], nil
}
}
return nil, fmt.Errorf("%#v not found", page)
}
func (client *Client) getRunstatusPage(ctx context.Context, pageURL string) (*RunstatusPage, error) {
resp, err := client.runstatusRequest(ctx, pageURL, nil, "GET")
if err != nil {
return nil, err
}
p := new(RunstatusPage)
if err := json.Unmarshal(resp, p); err != nil {
return nil, err
}
// NOTE: fix the missing IDs
for i := range p.Maintenances {
if err := p.Maintenances[i].FakeID(); err != nil {
log.Printf("bad fake ID for %#v, %s", p.Maintenances[i], err)
}
}
return p, nil
}
// ListRunstatusPages list all the runstatus pages
func (client *Client) ListRunstatusPages(ctx context.Context) ([]RunstatusPage, error) {
resp, err := client.runstatusRequest(ctx, client.Endpoint+runstatusPagesURL, nil, "GET")
if err != nil {
return nil, err
}
var p *RunstatusPageList
if err := json.Unmarshal(resp, &p); err != nil {
return nil, err
}
// XXX: handle pagination
return p.Results, nil
}
// Error formats the DNSerror into a string
func (req RunstatusErrorResponse) Error() string {
return fmt.Sprintf("Runstatus error: %s", req.Detail)
}
// Error formats the DNSerror into a string
func (req RunstatusValidationErrorResponse) Error() string {
if len(req) > 0 {
errs := []string{}
for name, ss := range req {
if len(ss) > 0 {
errs = append(errs, fmt.Sprintf("%s: %s", name, strings.Join(ss, ", ")))
}
}
return fmt.Sprintf("Runstatus error: %s", strings.Join(errs, "; "))
}
return fmt.Sprintf("Runstatus error")
}
func (client *Client) runstatusRequest(ctx context.Context, uri string, structParam interface{}, method string) (json.RawMessage, error) {
reqURL, err := url.Parse(uri)
if err != nil {
return nil, err
}
if reqURL.Scheme == "" {
return nil, fmt.Errorf("only absolute URI are considered valid, got %q", uri)
}
var params string
if structParam != nil {
m, err := json.Marshal(structParam)
if err != nil {
return nil, err
}
params = string(m)
}
req, err := http.NewRequest(method, reqURL.String(), strings.NewReader(params))
if err != nil {
return nil, err
}
time := time.Now().Local().Format("2006-01-02T15:04:05-0700")
payload := fmt.Sprintf("%s%s%s", req.URL.String(), time, params)
mac := hmac.New(sha256.New, []byte(client.apiSecret))
_, err = mac.Write([]byte(payload))
if err != nil {
return nil, err
}
signature := hex.EncodeToString(mac.Sum(nil))
var hdr = make(http.Header)
hdr.Add("Authorization", fmt.Sprintf("Exoscale-HMAC-SHA256 %s:%s", client.APIKey, signature))
hdr.Add("Exoscale-Date", time)
hdr.Add("User-Agent", fmt.Sprintf("exoscale/egoscale (%v)", Version))
hdr.Add("Accept", "application/json")
if params != "" {
hdr.Add("Content-Type", "application/json")
}
req.Header = hdr
req = req.WithContext(ctx)
resp, err := client.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close() // nolint: errcheck
if resp.StatusCode == 204 {
if method != "DELETE" {
return nil, fmt.Errorf("only DELETE is expected to produce 204, was %q", method)
}
return nil, nil
}
contentType := resp.Header.Get("content-type")
if !strings.Contains(contentType, "application/json") {
return nil, fmt.Errorf(`response content-type expected to be "application/json", got %q`, contentType)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
rerr := new(RunstatusValidationErrorResponse)
if err := json.Unmarshal(b, rerr); err == nil {
return nil, rerr
}
rverr := new(RunstatusErrorResponse)
if err := json.Unmarshal(b, rverr); err != nil {
return nil, err
}
return nil, rverr
}
return b, nil
}

37
vendor/github.com/exoscale/egoscale/runstatus_event.go generated vendored Normal file
View file

@ -0,0 +1,37 @@
package egoscale
import (
"context"
"fmt"
"time"
)
//RunstatusEvent is a runstatus event
type RunstatusEvent struct {
Created *time.Time `json:"created,omitempty"`
State string `json:"state,omitempty"`
Status string `json:"status"`
Text string `json:"text"`
}
// UpdateRunstatusIncident create runstatus incident event
// Events can be updates or final message with status completed.
func (client *Client) UpdateRunstatusIncident(ctx context.Context, incident RunstatusIncident, event RunstatusEvent) error {
if incident.EventsURL == "" {
return fmt.Errorf("empty Events URL for %#v", incident)
}
_, err := client.runstatusRequest(ctx, incident.EventsURL, event, "POST")
return err
}
// UpdateRunstatusMaintenance adds a event to a maintenance.
// Events can be updates or final message with status completed.
func (client *Client) UpdateRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance, event RunstatusEvent) error {
if maintenance.EventsURL == "" {
return fmt.Errorf("empty Events URL for %#v", maintenance)
}
_, err := client.runstatusRequest(ctx, maintenance.EventsURL, event, "POST")
return err
}

View file

@ -0,0 +1,144 @@
package egoscale
import (
"context"
"encoding/json"
"fmt"
"time"
)
//RunstatusIncident is a runstatus incident
type RunstatusIncident struct {
EndDate *time.Time `json:"end_date,omitempty"`
Events []RunstatusEvent `json:"events,omitempty"`
EventsURL string `json:"events_url,omitempty"`
ID int `json:"id,omitempty"`
PageURL string `json:"page_url,omitempty"` // fake field
PostMortem string `json:"post_mortem,omitempty"`
RealTime bool `json:"real_time,omitempty"`
Services []string `json:"services"`
StartDate *time.Time `json:"start_date,omitempty"`
State string `json:"state"`
Status string `json:"status"`
StatusText string `json:"status_text"`
Title string `json:"title"`
URL string `json:"url,omitempty"`
}
// Match returns true if the other incident has got similarities with itself
func (incident RunstatusIncident) Match(other RunstatusIncident) bool {
if other.Title != "" && incident.Title == other.Title {
return true
}
if other.ID > 0 && incident.ID == other.ID {
return true
}
return false
}
//RunstatusIncidentList is a list of incident
type RunstatusIncidentList struct {
Incidents []RunstatusIncident `json:"incidents"`
}
// GetRunstatusIncident retrieves the details of a specific incident.
func (client *Client) GetRunstatusIncident(ctx context.Context, incident RunstatusIncident) (*RunstatusIncident, error) {
if incident.URL != "" {
return client.getRunstatusIncident(ctx, incident.URL)
}
if incident.PageURL == "" {
return nil, fmt.Errorf("empty Page URL for %#v", incident)
}
page, err := client.getRunstatusPage(ctx, incident.PageURL)
if err != nil {
return nil, err
}
is, err := client.ListRunstatusIncidents(ctx, *page)
if err != nil {
return nil, err
}
for i := range is {
if is[i].Match(incident) {
return &is[i], nil
}
}
return nil, fmt.Errorf("%#v not found", incident)
}
func (client *Client) getRunstatusIncident(ctx context.Context, incidentURL string) (*RunstatusIncident, error) {
resp, err := client.runstatusRequest(ctx, incidentURL, nil, "GET")
if err != nil {
return nil, err
}
i := new(RunstatusIncident)
if err := json.Unmarshal(resp, i); err != nil {
return nil, err
}
return i, nil
}
// ListRunstatusIncidents lists the incidents for a specific page.
func (client *Client) ListRunstatusIncidents(ctx context.Context, page RunstatusPage) ([]RunstatusIncident, error) {
if page.IncidentsURL == "" {
return nil, fmt.Errorf("empty Incidents URL for %#v", page)
}
resp, err := client.runstatusRequest(ctx, page.IncidentsURL, nil, "GET")
if err != nil {
return nil, err
}
var p *RunstatusIncidentList
if err := json.Unmarshal(resp, &p); err != nil {
return nil, err
}
// NOTE: no pagination
return p.Incidents, nil
}
// CreateRunstatusIncident create runstatus incident
func (client *Client) CreateRunstatusIncident(ctx context.Context, incident RunstatusIncident) (*RunstatusIncident, error) {
if incident.PageURL == "" {
return nil, fmt.Errorf("empty Page URL for %#v", incident)
}
page, err := client.getRunstatusPage(ctx, incident.PageURL)
if err != nil {
return nil, err
}
if page.IncidentsURL == "" {
return nil, fmt.Errorf("empty Incidents URL for %#v", page)
}
resp, err := client.runstatusRequest(ctx, page.IncidentsURL, incident, "POST")
if err != nil {
return nil, err
}
i := &RunstatusIncident{}
if err := json.Unmarshal(resp, &i); err != nil {
return nil, err
}
return i, nil
}
// DeleteRunstatusIncident delete runstatus incident
func (client *Client) DeleteRunstatusIncident(ctx context.Context, incident RunstatusIncident) error {
if incident.URL == "" {
return fmt.Errorf("empty URL for %#v", incident)
}
_, err := client.runstatusRequest(ctx, incident.URL, nil, "DELETE")
return err
}

View file

@ -0,0 +1,178 @@
package egoscale
import (
"context"
"encoding/json"
"fmt"
"log"
"net/url"
"path"
"strconv"
"time"
)
// RunstatusMaintenance is a runstatus maintenance
type RunstatusMaintenance struct {
Created *time.Time `json:"created,omitempty"`
Description string `json:"description,omitempty"`
EndDate *time.Time `json:"end_date"`
Events []RunstatusEvent `json:"events,omitempty"`
EventsURL string `json:"events_url,omitempty"`
ID int `json:"id,omitempty"` // missing field
PageURL string `json:"page_url,omitempty"` // fake field
RealTime bool `json:"real_time,omitempty"`
Services []string `json:"services"`
StartDate *time.Time `json:"start_date"`
Status string `json:"status"`
Title string `json:"title"`
URL string `json:"url,omitempty"`
}
// Match returns true if the other maintenance has got similarities with itself
func (maintenance RunstatusMaintenance) Match(other RunstatusMaintenance) bool {
if other.Title != "" && maintenance.Title == other.Title {
return true
}
if other.ID > 0 && maintenance.ID == other.ID {
return true
}
return false
}
// FakeID fills up the ID field as it's currently missing
func (maintenance *RunstatusMaintenance) FakeID() error {
if maintenance.ID > 0 {
return nil
}
if maintenance.URL == "" {
return fmt.Errorf("empty URL for %#v", maintenance)
}
u, err := url.Parse(maintenance.URL)
if err != nil {
return err
}
s := path.Base(u.Path)
id, err := strconv.Atoi(s)
if err != nil {
return err
}
maintenance.ID = id
return nil
}
//RunstatusMaintenanceList is a list of incident
type RunstatusMaintenanceList struct {
Maintenances []RunstatusMaintenance `json:"maintenances"`
}
// GetRunstatusMaintenance retrieves the details of a specific maintenance.
func (client *Client) GetRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance) (*RunstatusMaintenance, error) {
if maintenance.URL != "" {
return client.getRunstatusMaintenance(ctx, maintenance.URL)
}
if maintenance.PageURL == "" {
return nil, fmt.Errorf("empty Page URL for %#v", maintenance)
}
page, err := client.getRunstatusPage(ctx, maintenance.PageURL)
if err != nil {
return nil, err
}
ms, err := client.ListRunstatusMaintenances(ctx, *page)
if err != nil {
return nil, err
}
for i := range ms {
if ms[i].Match(maintenance) {
return &ms[i], nil
}
}
return nil, fmt.Errorf("%#v not found", maintenance)
}
func (client *Client) getRunstatusMaintenance(ctx context.Context, maintenanceURL string) (*RunstatusMaintenance, error) {
resp, err := client.runstatusRequest(ctx, maintenanceURL, nil, "GET")
if err != nil {
return nil, err
}
m := new(RunstatusMaintenance)
if err := json.Unmarshal(resp, m); err != nil {
return nil, err
}
return m, nil
}
// ListRunstatusMaintenances returns the list of maintenances for the page.
func (client *Client) ListRunstatusMaintenances(ctx context.Context, page RunstatusPage) ([]RunstatusMaintenance, error) {
if page.MaintenancesURL == "" {
return nil, fmt.Errorf("empty Maintenances URL for %#v", page)
}
resp, err := client.runstatusRequest(ctx, page.MaintenancesURL, nil, "GET")
if err != nil {
return nil, err
}
var p *RunstatusMaintenanceList
if err := json.Unmarshal(resp, &p); err != nil {
return nil, err
}
// NOTE: fix the missing IDs
for i := range p.Maintenances {
if err := p.Maintenances[i].FakeID(); err != nil {
log.Printf("bad fake ID for %#v, %s", p.Maintenances[i], err)
}
}
// NOTE: the list of maintenances doesn't have any pagination
return p.Maintenances, nil
}
// CreateRunstatusMaintenance create runstatus Maintenance
func (client *Client) CreateRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance) (*RunstatusMaintenance, error) {
if maintenance.PageURL == "" {
return nil, fmt.Errorf("empty Page URL for %#v", maintenance)
}
page, err := client.getRunstatusPage(ctx, maintenance.PageURL)
if err != nil {
return nil, err
}
resp, err := client.runstatusRequest(ctx, page.MaintenancesURL, maintenance, "POST")
if err != nil {
return nil, err
}
m := &RunstatusMaintenance{}
if err := json.Unmarshal(resp, &m); err != nil {
return nil, err
}
if err := m.FakeID(); err != nil {
log.Printf("bad fake ID for %#v, %s", m, err)
}
return m, nil
}
// DeleteRunstatusMaintenance delete runstatus Maintenance
func (client *Client) DeleteRunstatusMaintenance(ctx context.Context, maintenance RunstatusMaintenance) error {
if maintenance.URL == "" {
return fmt.Errorf("empty URL for %#v", maintenance)
}
_, err := client.runstatusRequest(ctx, maintenance.URL, nil, "DELETE")
return err
}

View file

@ -0,0 +1,170 @@
package egoscale
import (
"context"
"encoding/json"
"fmt"
"log"
"net/url"
"path"
"strconv"
)
// RunstatusService is a runstatus service
type RunstatusService struct {
ID int `json:"id"` // missing field
Name string `json:"name"`
PageURL string `json:"page_url,omitempty"` // fake field
State string `json:"state,omitempty"`
URL string `json:"url,omitempty"`
}
// FakeID fills up the ID field as it's currently missing
func (service *RunstatusService) FakeID() error {
if service.ID > 0 {
return nil
}
if service.URL == "" {
return fmt.Errorf("empty URL for %#v", service)
}
u, err := url.Parse(service.URL)
if err != nil {
return err
}
s := path.Base(u.Path)
id, err := strconv.Atoi(s)
if err != nil {
return err
}
service.ID = id
return nil
}
// Match returns true if the other service has got similarities with itself
func (service RunstatusService) Match(other RunstatusService) bool {
if other.Name != "" && service.Name == other.Name {
return true
}
if other.ID > 0 && service.ID == other.ID {
return true
}
return false
}
// RunstatusServiceList service list
type RunstatusServiceList struct {
Services []RunstatusService `json:"services"`
}
// DeleteRunstatusService delete runstatus service
func (client *Client) DeleteRunstatusService(ctx context.Context, service RunstatusService) error {
if service.URL == "" {
return fmt.Errorf("empty URL for %#v", service)
}
_, err := client.runstatusRequest(ctx, service.URL, nil, "DELETE")
return err
}
// CreateRunstatusService create runstatus service
func (client *Client) CreateRunstatusService(ctx context.Context, service RunstatusService) (*RunstatusService, error) {
if service.PageURL == "" {
return nil, fmt.Errorf("empty Page URL for %#v", service)
}
page, err := client.GetRunstatusPage(ctx, RunstatusPage{URL: service.PageURL})
if err != nil {
return nil, err
}
resp, err := client.runstatusRequest(ctx, page.ServicesURL, service, "POST")
if err != nil {
return nil, err
}
s := &RunstatusService{}
if err := json.Unmarshal(resp, s); err != nil {
return nil, err
}
return s, nil
}
// GetRunstatusService displays service detail.
func (client *Client) GetRunstatusService(ctx context.Context, service RunstatusService) (*RunstatusService, error) {
if service.URL != "" {
return client.getRunstatusService(ctx, service.URL)
}
if service.PageURL == "" {
return nil, fmt.Errorf("empty Page URL in %#v", service)
}
page, err := client.getRunstatusPage(ctx, service.PageURL)
if err != nil {
return nil, err
}
ss, err := client.ListRunstatusServices(ctx, *page)
if err != nil {
return nil, err
}
for i := range ss {
if ss[i].Match(service) {
return &ss[i], nil
}
}
return nil, fmt.Errorf("%#v not found", service)
}
func (client *Client) getRunstatusService(ctx context.Context, serviceURL string) (*RunstatusService, error) {
resp, err := client.runstatusRequest(ctx, serviceURL, nil, "GET")
if err != nil {
return nil, err
}
s := &RunstatusService{}
if err := json.Unmarshal(resp, &s); err != nil {
return nil, err
}
if err := s.FakeID(); err != nil {
log.Printf("bad fake ID for %#v, %s", s, err)
}
return s, nil
}
// ListRunstatusServices displays the list of services.
func (client *Client) ListRunstatusServices(ctx context.Context, page RunstatusPage) ([]RunstatusService, error) {
if page.ServicesURL == "" {
return nil, fmt.Errorf("empty Services URL for %#v", page)
}
resp, err := client.runstatusRequest(ctx, page.ServicesURL, nil, "GET")
if err != nil {
return nil, err
}
var p *RunstatusServiceList
if err := json.Unmarshal(resp, &p); err != nil {
return nil, err
}
// NOTE: fix the missing IDs
for i := range p.Services {
if err := p.Services[i].FakeID(); err != nil {
log.Printf("bad fake ID for %#v, %s", p.Services[i], err)
}
}
// NOTE: no pagination
return p.Services, nil
}

View file

@ -12,10 +12,8 @@ import (
type SecurityGroup struct { type SecurityGroup struct {
Account string `json:"account,omitempty" doc:"the account owning the security group"` Account string `json:"account,omitempty" doc:"the account owning the security group"`
Description string `json:"description,omitempty" doc:"the description of the security group"` Description string `json:"description,omitempty" doc:"the description of the security group"`
Domain string `json:"domain,omitempty" doc:"the domain name of the security group"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of the security group"`
EgressRule []EgressRule `json:"egressrule,omitempty" doc:"the list of egress rules associated with the security group"` EgressRule []EgressRule `json:"egressrule,omitempty" doc:"the list of egress rules associated with the security group"`
ID *UUID `json:"id,omitempty" doc:"the ID of the security group"` ID *UUID `json:"id" doc:"the ID of the security group"`
IngressRule []IngressRule `json:"ingressrule,omitempty" doc:"the list of ingress rules associated with the security group"` IngressRule []IngressRule `json:"ingressrule,omitempty" doc:"the list of ingress rules associated with the security group"`
Name string `json:"name,omitempty" doc:"the name of the security group"` Name string `json:"name,omitempty" doc:"the name of the security group"`
} }
@ -23,16 +21,13 @@ type SecurityGroup struct {
// UserSecurityGroup converts a SecurityGroup to a UserSecurityGroup // UserSecurityGroup converts a SecurityGroup to a UserSecurityGroup
func (sg SecurityGroup) UserSecurityGroup() UserSecurityGroup { func (sg SecurityGroup) UserSecurityGroup() UserSecurityGroup {
return UserSecurityGroup{ return UserSecurityGroup{
Account: sg.Account, Group: sg.Name,
Group: sg.Name,
} }
} }
// ListRequest builds the ListSecurityGroups request // ListRequest builds the ListSecurityGroups request
func (sg SecurityGroup) ListRequest() (ListCommand, error) { func (sg SecurityGroup) ListRequest() (ListCommand, error) {
req := &ListSecurityGroups{ req := &ListSecurityGroups{
Account: sg.Account,
DomainID: sg.DomainID,
ID: sg.ID, ID: sg.ID,
SecurityGroupName: sg.Name, SecurityGroupName: sg.Name,
} }
@ -46,10 +41,7 @@ func (sg SecurityGroup) Delete(ctx context.Context, client *Client) error {
return fmt.Errorf("a SecurityGroup may only be deleted using ID or Name") return fmt.Errorf("a SecurityGroup may only be deleted using ID or Name")
} }
req := &DeleteSecurityGroup{ req := &DeleteSecurityGroup{}
Account: sg.Account,
DomainID: sg.DomainID,
}
if sg.ID != nil { if sg.ID != nil {
req.ID = sg.ID req.ID = sg.ID
@ -79,18 +71,15 @@ func (sg SecurityGroup) RuleByID(ruleID UUID) (*IngressRule, *EgressRule) {
// IngressRule represents the ingress rule // IngressRule represents the ingress rule
type IngressRule struct { type IngressRule struct {
Account string `json:"account,omitempty" doc:"account owning the security group rule"` CIDR *CIDR `json:"cidr,omitempty" doc:"the CIDR notation for the base IP address of the security group rule"`
CIDR *CIDR `json:"cidr,omitempty" doc:"the CIDR notation for the base IP address of the security group rule"` Description string `json:"description,omitempty" doc:"description of the security group rule"`
Description string `json:"description,omitempty" doc:"description of the security group rule"` EndPort uint16 `json:"endport,omitempty" doc:"the ending port of the security group rule "`
EndPort uint16 `json:"endport,omitempty" doc:"the ending port of the security group rule "` IcmpCode uint8 `json:"icmpcode,omitempty" doc:"the code for the ICMP message response"`
IcmpCode uint8 `json:"icmpcode,omitempty" doc:"the code for the ICMP message response"` IcmpType uint8 `json:"icmptype,omitempty" doc:"the type of the ICMP message response"`
IcmpType uint8 `json:"icmptype,omitempty" doc:"the type of the ICMP message response"` Protocol string `json:"protocol,omitempty" doc:"the protocol of the security group rule"`
Protocol string `json:"protocol,omitempty" doc:"the protocol of the security group rule"` RuleID *UUID `json:"ruleid" doc:"the id of the security group rule"`
RuleID *UUID `json:"ruleid,omitempty" doc:"the id of the security group rule"` SecurityGroupName string `json:"securitygroupname,omitempty" doc:"security group name"`
SecurityGroupID *UUID `json:"securitygroupid,omitempty"` StartPort uint16 `json:"startport,omitempty" doc:"the starting port of the security group rule"`
SecurityGroupName string `json:"securitygroupname,omitempty" doc:"security group name"`
StartPort uint16 `json:"startport,omitempty" doc:"the starting port of the security group rule"`
UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty"`
} }
// EgressRule represents the ingress rule // EgressRule represents the ingress rule
@ -98,8 +87,7 @@ type EgressRule IngressRule
// UserSecurityGroup represents the traffic of another security group // UserSecurityGroup represents the traffic of another security group
type UserSecurityGroup struct { type UserSecurityGroup struct {
Group string `json:"group,omitempty"` Group string `json:"group,omitempty"`
Account string `json:"account,omitempty"`
} }
// String gives the UserSecurityGroup name // String gives the UserSecurityGroup name
@ -110,51 +98,49 @@ func (usg UserSecurityGroup) String() string {
// CreateSecurityGroup represents a security group creation // CreateSecurityGroup represents a security group creation
type CreateSecurityGroup struct { type CreateSecurityGroup struct {
Name string `json:"name" doc:"name of the security group"` Name string `json:"name" doc:"name of the security group"`
Account string `json:"account,omitempty" doc:"an optional account for the security group. Must be used with domainId."`
Description string `json:"description,omitempty" doc:"the description of the security group"` Description string `json:"description,omitempty" doc:"the description of the security group"`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainId for the security group. If the account parameter is used, domainId must also be used."`
_ bool `name:"createSecurityGroup" description:"Creates a security group"` _ bool `name:"createSecurityGroup" description:"Creates a security group"`
} }
func (CreateSecurityGroup) response() interface{} { // Response returns the struct to unmarshal
func (CreateSecurityGroup) Response() interface{} {
return new(SecurityGroup) return new(SecurityGroup)
} }
// DeleteSecurityGroup represents a security group deletion // DeleteSecurityGroup represents a security group deletion
type DeleteSecurityGroup struct { type DeleteSecurityGroup struct {
Account string `json:"account,omitempty" doc:"the account of the security group. Must be specified with domain ID"` ID *UUID `json:"id,omitempty" doc:"The ID of the security group. Mutually exclusive with name parameter"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of account owning the security group"` Name string `json:"name,omitempty" doc:"The ID of the security group. Mutually exclusive with id parameter"`
ID *UUID `json:"id,omitempty" doc:"The ID of the security group. Mutually exclusive with name parameter"` _ bool `name:"deleteSecurityGroup" description:"Deletes security group"`
Name string `json:"name,omitempty" doc:"The ID of the security group. Mutually exclusive with id parameter"`
_ bool `name:"deleteSecurityGroup" description:"Deletes security group"`
} }
func (DeleteSecurityGroup) response() interface{} { // Response returns the struct to unmarshal
return new(booleanResponse) func (DeleteSecurityGroup) Response() interface{} {
return new(BooleanResponse)
} }
// AuthorizeSecurityGroupIngress (Async) represents the ingress rule creation // AuthorizeSecurityGroupIngress (Async) represents the ingress rule creation
type AuthorizeSecurityGroupIngress struct { type AuthorizeSecurityGroupIngress struct {
Account string `json:"account,omitempty" doc:"an optional account for the security group. Must be used with domainId."`
CIDRList []CIDR `json:"cidrlist,omitempty" doc:"the cidr list associated"` CIDRList []CIDR `json:"cidrlist,omitempty" doc:"the cidr list associated"`
Description string `json:"description,omitempty" doc:"the description of the ingress/egress rule"` Description string `json:"description,omitempty" doc:"the description of the ingress/egress rule"`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainid for the security group. If the account parameter is used, domainid must also be used."` EndPort uint16 `json:"endport,omitempty" doc:"end port for this ingress/egress rule"`
EndPort uint16 `json:"endport,omitempty" doc:"end port for this ingress rule"`
IcmpCode uint8 `json:"icmpcode,omitempty" doc:"error code for this icmp message"` IcmpCode uint8 `json:"icmpcode,omitempty" doc:"error code for this icmp message"`
IcmpType uint8 `json:"icmptype,omitempty" doc:"type of the icmp message being sent"` IcmpType uint8 `json:"icmptype,omitempty" doc:"type of the icmp message being sent"`
Protocol string `json:"protocol,omitempty" doc:"TCP is default. UDP, ICMP, ICMPv6, AH, ESP, GRE are the other supported protocols"` Protocol string `json:"protocol,omitempty" doc:"TCP is default. UDP, ICMP, ICMPv6, AH, ESP, GRE, IPIP are the other supported protocols"`
SecurityGroupID *UUID `json:"securitygroupid,omitempty" doc:"The ID of the security group. Mutually exclusive with securitygroupname parameter"` SecurityGroupID *UUID `json:"securitygroupid,omitempty" doc:"The ID of the security group. Mutually exclusive with securitygroupname parameter"`
SecurityGroupName string `json:"securitygroupname,omitempty" doc:"The name of the security group. Mutually exclusive with securitygroupid parameter"` SecurityGroupName string `json:"securitygroupname,omitempty" doc:"The name of the security group. Mutually exclusive with securitygroupid parameter"`
StartPort uint16 `json:"startport,omitempty" doc:"start port for this ingress rule"` StartPort uint16 `json:"startport,omitempty" doc:"start port for this ingress/egress rule"`
UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty" doc:"user to security group mapping"` UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty" doc:"user to security group mapping"`
_ bool `name:"authorizeSecurityGroupIngress" description:"Authorizes a particular ingress/egress rule for this security group"` _ bool `name:"authorizeSecurityGroupIngress" description:"Authorize a particular ingress/egress rule for this security group"`
} }
func (AuthorizeSecurityGroupIngress) response() interface{} { // Response returns the struct to unmarshal
func (AuthorizeSecurityGroupIngress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (AuthorizeSecurityGroupIngress) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (AuthorizeSecurityGroupIngress) AsyncResponse() interface{} {
return new(SecurityGroup) return new(SecurityGroup)
} }
@ -174,11 +160,13 @@ func (req AuthorizeSecurityGroupIngress) onBeforeSend(params url.Values) error {
// AuthorizeSecurityGroupEgress (Async) represents the egress rule creation // AuthorizeSecurityGroupEgress (Async) represents the egress rule creation
type AuthorizeSecurityGroupEgress AuthorizeSecurityGroupIngress type AuthorizeSecurityGroupEgress AuthorizeSecurityGroupIngress
func (AuthorizeSecurityGroupEgress) response() interface{} { // Response returns the struct to unmarshal
func (AuthorizeSecurityGroupEgress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (AuthorizeSecurityGroupEgress) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (AuthorizeSecurityGroupEgress) AsyncResponse() interface{} {
return new(SecurityGroup) return new(SecurityGroup)
} }
@ -192,11 +180,14 @@ type RevokeSecurityGroupIngress struct {
_ bool `name:"revokeSecurityGroupIngress" description:"Deletes a particular ingress rule from this security group"` _ bool `name:"revokeSecurityGroupIngress" description:"Deletes a particular ingress rule from this security group"`
} }
func (RevokeSecurityGroupIngress) response() interface{} { // Response returns the struct to unmarshal
func (RevokeSecurityGroupIngress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RevokeSecurityGroupIngress) asyncResponse() interface{} {
return new(booleanResponse) // AsyncResponse returns the struct to unmarshal the async job
func (RevokeSecurityGroupIngress) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// RevokeSecurityGroupEgress (Async) represents the ingress/egress rule deletion // RevokeSecurityGroupEgress (Async) represents the ingress/egress rule deletion
@ -205,22 +196,22 @@ type RevokeSecurityGroupEgress struct {
_ bool `name:"revokeSecurityGroupEgress" description:"Deletes a particular egress rule from this security group"` _ bool `name:"revokeSecurityGroupEgress" description:"Deletes a particular egress rule from this security group"`
} }
func (RevokeSecurityGroupEgress) response() interface{} { // Response returns the struct to unmarshal
func (RevokeSecurityGroupEgress) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RevokeSecurityGroupEgress) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (RevokeSecurityGroupEgress) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
//go:generate go run generate/main.go -interface=Listable ListSecurityGroups
// ListSecurityGroups represents a search for security groups // ListSecurityGroups represents a search for security groups
type ListSecurityGroups struct { type ListSecurityGroups struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ID *UUID `json:"id,omitempty" doc:"list the security group by the id provided"` ID *UUID `json:"id,omitempty" doc:"list the security group by the id provided"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
SecurityGroupName string `json:"securitygroupname,omitempty" doc:"lists security groups by name"` SecurityGroupName string `json:"securitygroupname,omitempty" doc:"lists security groups by name"`
@ -233,31 +224,3 @@ type ListSecurityGroupsResponse struct {
Count int `json:"count"` Count int `json:"count"`
SecurityGroup []SecurityGroup `json:"securitygroup"` SecurityGroup []SecurityGroup `json:"securitygroup"`
} }
func (ListSecurityGroups) response() interface{} {
return new(ListSecurityGroupsResponse)
}
// SetPage sets the current page
func (lsg *ListSecurityGroups) SetPage(page int) {
lsg.Page = page
}
// SetPageSize sets the page size
func (lsg *ListSecurityGroups) SetPageSize(pageSize int) {
lsg.PageSize = pageSize
}
func (ListSecurityGroups) each(resp interface{}, callback IterateItemFunc) {
sgs, ok := resp.(*ListSecurityGroupsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListSecurityGroupsResponse expected, got %T", resp))
return
}
for i := range sgs.SecurityGroup {
if !callback(&sgs.SecurityGroup[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListSecurityGroups) Response() interface{} {
return new(ListSecurityGroupsResponse)
}
// ListRequest returns itself
func (ls *ListSecurityGroups) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListSecurityGroups) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListSecurityGroups) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListSecurityGroups) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListSecurityGroupsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListSecurityGroupsResponse was expected, got %T", resp))
return
}
for i := range items.SecurityGroup {
if !callback(&items.SecurityGroup[i], nil) {
break
}
}
}

View file

@ -54,7 +54,9 @@ func info(command interface{}) (*CommandInfo, error) {
// prepareValues uses a command to build a POST request // prepareValues uses a command to build a POST request
// //
// command is not a Command so it's easier to Test // command is not a Command so it's easier to Test
func prepareValues(prefix string, params url.Values, command interface{}) error { func prepareValues(prefix string, command interface{}) (url.Values, error) {
params := url.Values{}
value := reflect.ValueOf(command) value := reflect.ValueOf(command)
typeof := reflect.TypeOf(command) typeof := reflect.TypeOf(command)
@ -66,7 +68,7 @@ func prepareValues(prefix string, params url.Values, command interface{}) error
// Checking for nil commands // Checking for nil commands
if !value.IsValid() { if !value.IsValid() {
return fmt.Errorf("cannot serialize the invalid value %#v", command) return nil, fmt.Errorf("cannot serialize the invalid value %#v", command)
} }
for i := 0; i < typeof.NumField(); i++ { for i := 0; i < typeof.NumField(); i++ {
@ -77,217 +79,165 @@ func prepareValues(prefix string, params url.Values, command interface{}) error
val := value.Field(i) val := value.Field(i)
tag := field.Tag tag := field.Tag
var err error
var name string
var value interface{}
if json, ok := tag.Lookup("json"); ok { if json, ok := tag.Lookup("json"); ok {
n, required := ExtractJSONTag(field.Name, json) n, required := ExtractJSONTag(field.Name, json)
name := prefix + n name = prefix + n
switch val.Kind() { switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v := val.Int() value, err = prepareInt(val.Int(), required)
if v == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), n, val.Kind())
}
} else {
params.Set(name, strconv.FormatInt(v, 10))
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v := val.Uint() value, err = prepareUint(val.Uint(), required)
if v == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), n, val.Kind())
}
} else {
params.Set(name, strconv.FormatUint(v, 10))
}
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
v := val.Float() value, err = prepareFloat(val.Float(), required)
if v == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got 0", typeof.Name(), n, val.Kind())
}
} else {
params.Set(name, strconv.FormatFloat(v, 'f', -1, 64))
}
case reflect.String: case reflect.String:
v := val.String() value, err = prepareString(val.String(), required)
if v == "" {
if required {
return fmt.Errorf("%s.%s (%v) is required, got \"\"", typeof.Name(), n, val.Kind())
}
} else {
params.Set(name, v)
}
case reflect.Bool: case reflect.Bool:
v := val.Bool() value, err = prepareBool(val.Bool(), required)
if !v {
if required {
params.Set(name, "false")
}
} else {
params.Set(name, "true")
}
case reflect.Ptr:
if val.IsNil() {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty ptr", typeof.Name(), n, val.Kind())
}
} else {
switch field.Type.Elem().Kind() {
case reflect.Bool:
params.Set(name, strconv.FormatBool(val.Elem().Bool()))
case reflect.Struct:
i := val.Interface()
s, ok := i.(fmt.Stringer)
if !ok {
return fmt.Errorf("%s.%s (%v) is not a Stringer", typeof.Name(), field.Name, val.Kind())
}
if s != nil && s.String() == "" {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty value", typeof.Name(), field.Name, val.Kind())
}
} else {
params.Set(n, s.String())
}
default:
log.Printf("[SKIP] %s.%s (%v) not supported", typeof.Name(), n, field.Type.Elem().Kind())
}
}
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(), n, val.Kind())
}
} else {
params.Set(name, ip.String())
}
case reflect.TypeOf(MAC48(0, 0, 0, 0, 0, 0)):
mac := val.Interface().(MACAddress)
s := mac.String()
if s == "" {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty MAC address", typeof.Name(), field.Name, val.Kind())
}
} else {
params.Set(name, s)
}
default:
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, 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(), n, 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:
switch field.Type.Elem() {
case reflect.TypeOf(CIDR{}), reflect.TypeOf(UUID{}):
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, val.Kind())
}
} else {
value := reflect.ValueOf(val.Interface())
ss := make([]string, val.Len())
for i := 0; i < value.Len(); i++ {
v := value.Index(i).Interface()
s, ok := v.(fmt.Stringer)
if !ok {
return fmt.Errorf("not a String, %T", v)
}
ss[i] = s.String()
}
params.Set(name, strings.Join(ss, ","))
}
default:
if val.Len() == 0 {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty slice", typeof.Name(), n, val.Kind())
}
} else {
err := prepareList(name, params, val.Interface())
if err != nil {
return err
}
}
}
}
case reflect.Map: case reflect.Map:
if val.Len() == 0 { if val.Len() == 0 {
if required { if required {
return fmt.Errorf("%s.%s (%v) is required, got empty map", typeof.Name(), field.Name, val.Kind()) err = fmt.Errorf("field is required, got empty map")
} }
} else { } else {
err := prepareMap(name, params, val.Interface()) value, err = prepareMap(name, val.Interface())
if err != nil {
return err
}
} }
case reflect.Ptr:
value, err = preparePtr(field.Type.Elem().Kind(), val, required)
case reflect.Slice:
value, err = prepareSlice(name, field.Type, val, required)
case reflect.Struct: case reflect.Struct:
i := val.Interface() value, err = prepareStruct(val.Interface(), required)
s, ok := i.(fmt.Stringer)
if !ok {
return fmt.Errorf("%s.%s (%v) is not a Stringer", typeof.Name(), field.Name, val.Kind())
}
if s != nil && s.String() == "" {
if required {
return fmt.Errorf("%s.%s (%v) is required, got empty value", typeof.Name(), field.Name, val.Kind())
}
} else {
params.Set(n, s.String())
}
default: default:
if required { if required {
return fmt.Errorf("unsupported type %s.%s (%v)", typeof.Name(), n, val.Kind()) err = fmt.Errorf("unsupported type")
} }
fmt.Printf("%s\n", val.Kind())
} }
} else { } else {
log.Printf("[SKIP] %s.%s no json label found", typeof.Name(), field.Name) switch val.Kind() {
case reflect.Struct:
value, err = prepareEmbedStruct(val.Interface())
default:
log.Printf("[SKIP] %s.%s no json label found", typeof.Name(), field.Name)
}
}
if err != nil {
return nil, fmt.Errorf("%s.%s (%v) %s", typeof.Name(), field.Name, val.Kind(), err)
}
switch v := value.(type) {
case *string:
if name != "" && v != nil {
params.Set(name, *v)
}
case url.Values:
for k, xs := range v {
for _, x := range xs {
params.Add(k, x)
}
}
} }
} }
return nil return params, nil
} }
func prepareList(prefix string, params url.Values, slice interface{}) error { func prepareInt(v int64, required bool) (*string, error) {
if v == 0 {
if required {
return nil, fmt.Errorf("field is required, got %d", v)
}
return nil, nil
}
value := strconv.FormatInt(v, 10)
return &value, nil
}
func prepareUint(v uint64, required bool) (*string, error) {
if v == 0 {
if required {
return nil, fmt.Errorf("field is required, got %d", v)
}
return nil, nil
}
value := strconv.FormatUint(v, 10)
return &value, nil
}
func prepareFloat(v float64, required bool) (*string, error) {
if v == 0 {
if required {
return nil, fmt.Errorf("field is required, got %f", v)
}
return nil, nil
}
value := strconv.FormatFloat(v, 'f', -1, 64)
return &value, nil
}
func prepareString(v string, required bool) (*string, error) {
if v == "" {
if required {
return nil, fmt.Errorf("field is required, got %q", v)
}
return nil, nil
}
return &v, nil
}
func prepareBool(v bool, required bool) (*string, error) {
value := strconv.FormatBool(v)
if !v {
if required {
return &value, nil
}
return nil, nil
}
return &value, nil
}
func prepareList(prefix string, slice interface{}) (url.Values, error) {
params := url.Values{}
value := reflect.ValueOf(slice) value := reflect.ValueOf(slice)
for i := 0; i < value.Len(); i++ { for i := 0; i < value.Len(); i++ {
err := prepareValues(fmt.Sprintf("%s[%d].", prefix, i), params, value.Index(i).Interface()) ps, err := prepareValues(fmt.Sprintf("%s[%d].", prefix, i), value.Index(i).Interface())
if err != nil { if err != nil {
return err return nil, err
}
for k, xs := range ps {
for _, x := range xs {
params.Add(k, x)
}
} }
} }
return nil return params, nil
} }
func prepareMap(prefix string, params url.Values, m interface{}) error { func prepareMap(prefix string, m interface{}) (url.Values, error) {
value := reflect.ValueOf(m) value := url.Values{}
v := reflect.ValueOf(m)
for i, key := range value.MapKeys() { for i, key := range v.MapKeys() {
var keyName string var keyName string
var keyValue string var keyValue string
@ -295,19 +245,143 @@ func prepareMap(prefix string, params url.Values, m interface{}) error {
case reflect.String: case reflect.String:
keyName = key.String() keyName = key.String()
default: default:
return fmt.Errorf("only map[string]string are supported (XXX)") return value, fmt.Errorf("only map[string]string are supported (XXX)")
} }
val := value.MapIndex(key) val := v.MapIndex(key)
switch val.Kind() { switch val.Kind() {
case reflect.String: case reflect.String:
keyValue = val.String() keyValue = val.String()
default: default:
return fmt.Errorf("only map[string]string are supported (XXX)") return value, fmt.Errorf("only map[string]string are supported (XXX)")
} }
params.Set(fmt.Sprintf("%s[%d].%s", prefix, i, keyName), keyValue)
value.Set(fmt.Sprintf("%s[%d].%s", prefix, i, keyName), keyValue)
} }
return nil
return value, nil
}
func preparePtr(kind reflect.Kind, val reflect.Value, required bool) (*string, error) {
if val.IsNil() {
if required {
return nil, fmt.Errorf("field is required, got empty ptr")
}
return nil, nil
}
switch kind {
case reflect.Bool:
return prepareBool(val.Elem().Bool(), true)
case reflect.Struct:
return prepareStruct(val.Interface(), required)
default:
return nil, fmt.Errorf("kind %v is not supported as a ptr", kind)
}
}
func prepareSlice(name string, fieldType reflect.Type, val reflect.Value, required bool) (interface{}, error) {
switch fieldType.Elem().Kind() {
case reflect.Uint8:
switch fieldType {
case reflect.TypeOf(net.IPv4zero):
ip := (net.IP)(val.Bytes())
if ip == nil || ip.Equal(net.IP{}) {
if required {
return nil, fmt.Errorf("field is required, got zero IPv4 address")
}
} else {
value := ip.String()
return &value, nil
}
case reflect.TypeOf(MAC48(0, 0, 0, 0, 0, 0)):
mac := val.Interface().(MACAddress)
s := mac.String()
if s == "" {
if required {
return nil, fmt.Errorf("field is required, got empty MAC address")
}
} else {
return &s, nil
}
default:
if val.Len() == 0 {
if required {
return nil, fmt.Errorf("field is required, got empty slice")
}
} else {
value := base64.StdEncoding.EncodeToString(val.Bytes())
return &value, nil
}
}
case reflect.String:
if val.Len() == 0 {
if required {
return nil, fmt.Errorf("field is required, got empty slice")
}
} 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)
}
value := strings.Join(elems, ",")
return &value, nil
}
default:
switch fieldType.Elem() {
case reflect.TypeOf(CIDR{}), reflect.TypeOf(UUID{}):
if val.Len() == 0 {
if required {
return nil, fmt.Errorf("field is required, got empty slice")
}
} else {
v := reflect.ValueOf(val.Interface())
ss := make([]string, val.Len())
for i := 0; i < v.Len(); i++ {
e := v.Index(i).Interface()
s, ok := e.(fmt.Stringer)
if !ok {
return nil, fmt.Errorf("not a String, %T", e)
}
ss[i] = s.String()
}
value := strings.Join(ss, ",")
return &value, nil
}
default:
if val.Len() == 0 {
if required {
return nil, fmt.Errorf("field is required, got empty slice")
}
} else {
return prepareList(name, val.Interface())
}
}
}
return nil, nil
}
func prepareStruct(i interface{}, required bool) (*string, error) {
s, ok := i.(fmt.Stringer)
if !ok {
return nil, fmt.Errorf("struct field not a Stringer")
}
if s == nil {
if required {
return nil, fmt.Errorf("field is required, got %#v", s)
}
}
return prepareString(s.String(), required)
}
func prepareEmbedStruct(i interface{}) (url.Values, error) {
return prepareValues("", i)
} }
// ExtractJSONTag returns the variable name or defaultName as well as if the field is required (!omitempty) // ExtractJSONTag returns the variable name or defaultName as well as if the field is required (!omitempty)

View file

@ -1,9 +1,5 @@
package egoscale package egoscale
import (
"fmt"
)
// ServiceOffering corresponds to the Compute Offerings // ServiceOffering corresponds to the Compute Offerings
// //
// A service offering correspond to some hardware features (CPU, RAM). // A service offering correspond to some hardware features (CPU, RAM).
@ -21,11 +17,9 @@ type ServiceOffering struct {
DiskIopsReadRate int64 `json:"diskIopsReadRate,omitempty" doc:"io requests read rate of the service offering"` DiskIopsReadRate int64 `json:"diskIopsReadRate,omitempty" doc:"io requests read rate of the service offering"`
DiskIopsWriteRate int64 `json:"diskIopsWriteRate,omitempty" doc:"io requests write rate of the service offering"` DiskIopsWriteRate int64 `json:"diskIopsWriteRate,omitempty" doc:"io requests write rate of the service offering"`
Displaytext string `json:"displaytext,omitempty" doc:"an alternate display text of the service offering."` Displaytext string `json:"displaytext,omitempty" doc:"an alternate display text of the service offering."`
Domain string `json:"domain,omitempty" doc:"Domain name for the offering"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain id of the service offering"`
HostTags string `json:"hosttags,omitempty" doc:"the host tag for the service offering"` HostTags string `json:"hosttags,omitempty" doc:"the host tag for the service offering"`
HypervisorSnapshotReserve int `json:"hypervisorsnapshotreserve,omitempty" doc:"Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)"` HypervisorSnapshotReserve int `json:"hypervisorsnapshotreserve,omitempty" doc:"Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)"`
ID *UUID `json:"id,omitempty" doc:"the id of the service offering"` ID *UUID `json:"id" doc:"the id of the service offering"`
IsCustomized bool `json:"iscustomized,omitempty" doc:"is true if the offering is customized"` IsCustomized bool `json:"iscustomized,omitempty" doc:"is true if the offering is customized"`
IsCustomizedIops bool `json:"iscustomizediops,omitempty" doc:"true if disk offering uses custom iops, false otherwise"` IsCustomizedIops bool `json:"iscustomizediops,omitempty" doc:"true if disk offering uses custom iops, false otherwise"`
IsSystem bool `json:"issystem,omitempty" doc:"is this a system vm offering"` IsSystem bool `json:"issystem,omitempty" doc:"is this a system vm offering"`
@ -49,7 +43,6 @@ func (so ServiceOffering) ListRequest() (ListCommand, error) {
// Restricted cannot be applied here because it really has three states // Restricted cannot be applied here because it really has three states
req := &ListServiceOfferings{ req := &ListServiceOfferings{
ID: so.ID, ID: so.ID,
DomainID: so.DomainID,
Name: so.Name, Name: so.Name,
SystemVMType: so.SystemVMType, SystemVMType: so.SystemVMType,
} }
@ -61,9 +54,10 @@ func (so ServiceOffering) ListRequest() (ListCommand, error) {
return req, nil return req, nil
} }
//go:generate go run generate/main.go -interface=Listable ListServiceOfferings
// ListServiceOfferings represents a query for service offerings // ListServiceOfferings represents a query for service offerings
type ListServiceOfferings struct { type ListServiceOfferings struct {
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain associated with the service offering"`
ID *UUID `json:"id,omitempty" doc:"ID of the service offering"` ID *UUID `json:"id,omitempty" doc:"ID of the service offering"`
IsSystem *bool `json:"issystem,omitempty" doc:"is this a system vm offering"` IsSystem *bool `json:"issystem,omitempty" doc:"is this a system vm offering"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
@ -81,31 +75,3 @@ type ListServiceOfferingsResponse struct {
Count int `json:"count"` Count int `json:"count"`
ServiceOffering []ServiceOffering `json:"serviceoffering"` ServiceOffering []ServiceOffering `json:"serviceoffering"`
} }
func (ListServiceOfferings) response() interface{} {
return new(ListServiceOfferingsResponse)
}
// SetPage sets the current page
func (lso *ListServiceOfferings) SetPage(page int) {
lso.Page = page
}
// SetPageSize sets the page size
func (lso *ListServiceOfferings) SetPageSize(pageSize int) {
lso.PageSize = pageSize
}
func (ListServiceOfferings) each(resp interface{}, callback IterateItemFunc) {
sos, ok := resp.(*ListServiceOfferingsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListServiceOfferingsResponse expected, got %T", resp))
return
}
for i := range sos.ServiceOffering {
if !callback(&sos.ServiceOffering[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListServiceOfferings) Response() interface{} {
return new(ListServiceOfferingsResponse)
}
// ListRequest returns itself
func (ls *ListServiceOfferings) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListServiceOfferings) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListServiceOfferings) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListServiceOfferings) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListServiceOfferingsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListServiceOfferingsResponse was expected, got %T", resp))
return
}
for i := range items.ServiceOffering {
if !callback(&items.ServiceOffering[i], nil) {
break
}
}
}

View file

@ -3,28 +3,27 @@ package egoscale
// SnapshotState represents the Snapshot.State enum // SnapshotState represents the Snapshot.State enum
// //
// See: https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/storage/Snapshot.java // See: https://github.com/apache/cloudstack/blob/master/api/src/main/java/com/cloud/storage/Snapshot.java
type SnapshotState int type SnapshotState string
//go:generate stringer -type SnapshotState
const ( const (
// Allocated ... (TODO) // Allocated ... (TODO)
Allocated SnapshotState = iota Allocated SnapshotState = "Allocated"
// Creating ... (TODO) // Creating ... (TODO)
Creating Creating SnapshotState = "Creating"
// CreatedOnPrimary ... (TODO) // CreatedOnPrimary ... (TODO)
CreatedOnPrimary CreatedOnPrimary SnapshotState = "CreatedOnPrimary"
// BackingUp ... (TODO) // BackingUp ... (TODO)
BackingUp BackingUp SnapshotState = "BackingUp"
// BackedUp ... (TODO) // BackedUp ... (TODO)
BackedUp BackedUp SnapshotState = "BackedUp"
// Copying ... (TODO) // Copying ... (TODO)
Copying Copying SnapshotState = "Copying"
// Destroying ... (TODO) // Destroying ... (TODO)
Destroying Destroying SnapshotState = "Destroying"
// Destroyed ... (TODO) // Destroyed ... (TODO)
Destroyed Destroyed SnapshotState = "Destroyed"
// Error is a state where the user can't see the snapshot while the snapshot may still exist on the storage // Error is a state where the user can't see the snapshot while the snapshot may still exist on the storage
Error Error SnapshotState = "Error"
) )
// Snapshot represents a volume snapshot // Snapshot represents a volume snapshot
@ -32,8 +31,6 @@ type Snapshot struct {
Account string `json:"account,omitempty" doc:"the account associated with the snapshot"` Account string `json:"account,omitempty" doc:"the account associated with the snapshot"`
AccountID *UUID `json:"accountid,omitempty" doc:"the account ID associated with the snapshot"` AccountID *UUID `json:"accountid,omitempty" doc:"the account ID associated with the snapshot"`
Created string `json:"created,omitempty" doc:"the date the snapshot was created"` Created string `json:"created,omitempty" doc:"the date the snapshot was created"`
Domain string `json:"domain,omitempty" doc:"the domain name of the snapshot's account"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of the snapshot's account"`
ID *UUID `json:"id,omitempty" doc:"ID of the snapshot"` ID *UUID `json:"id,omitempty" doc:"ID of the snapshot"`
IntervalType string `json:"intervaltype,omitempty" doc:"valid types are hourly, daily, weekly, monthy, template, and none."` IntervalType string `json:"intervaltype,omitempty" doc:"valid types are hourly, daily, weekly, monthy, template, and none."`
Name string `json:"name,omitempty" doc:"name of the snapshot"` Name string `json:"name,omitempty" doc:"name of the snapshot"`
@ -41,7 +38,7 @@ type Snapshot struct {
Revertable *bool `json:"revertable,omitempty" doc:"indicates whether the underlying storage supports reverting the volume to this snapshot"` Revertable *bool `json:"revertable,omitempty" doc:"indicates whether the underlying storage supports reverting the volume to this snapshot"`
Size int64 `json:"size,omitempty" doc:"the size of original volume"` Size int64 `json:"size,omitempty" doc:"the size of original volume"`
SnapshotType string `json:"snapshottype,omitempty" doc:"the type of the snapshot"` SnapshotType string `json:"snapshottype,omitempty" doc:"the type of the snapshot"`
State SnapshotState `json:"state,omitempty" doc:"the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage"` State string `json:"state,omitempty" doc:"the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage"`
Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with snapshot"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with snapshot"`
VolumeID *UUID `json:"volumeid,omitempty" doc:"ID of the disk volume"` VolumeID *UUID `json:"volumeid,omitempty" doc:"ID of the disk volume"`
VolumeName string `json:"volumename,omitempty" doc:"name of the disk volume"` VolumeName string `json:"volumename,omitempty" doc:"name of the disk volume"`
@ -56,30 +53,43 @@ func (Snapshot) ResourceType() string {
// CreateSnapshot (Async) creates an instant snapshot of a volume // CreateSnapshot (Async) creates an instant snapshot of a volume
type CreateSnapshot struct { type CreateSnapshot struct {
VolumeID *UUID `json:"volumeid" doc:"The ID of the disk volume"` VolumeID *UUID `json:"volumeid" doc:"The ID of the disk volume"`
Account string `json:"account,omitempty" doc:"The account of the snapshot. The account parameter must be used with the domainId parameter."` QuiesceVM *bool `json:"quiescevm,omitempty" doc:"quiesce vm if true"`
DomainID *UUID `json:"domainid,omitempty" doc:"The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume."` _ bool `name:"createSnapshot" description:"Creates an instant snapshot of a volume."`
QuiesceVM *bool `json:"quiescevm,omitempty" doc:"quiesce vm if true"`
_ bool `name:"createSnapshot" description:"Creates an instant snapshot of a volume."`
} }
func (CreateSnapshot) response() interface{} { // Response returns the struct to unmarshal
func (CreateSnapshot) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (CreateSnapshot) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (CreateSnapshot) AsyncResponse() interface{} {
return new(Snapshot) return new(Snapshot)
} }
// ListRequest builds the ListSnapshot request
func (ss Snapshot) ListRequest() (ListCommand, error) {
// Restricted cannot be applied here because it really has three states
req := &ListSnapshots{
ID: ss.ID,
Name: ss.Name,
VolumeID: ss.VolumeID,
SnapshotType: ss.SnapshotType,
ZoneID: ss.ZoneID,
// TODO: tags
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListSnapshots
// ListSnapshots lists the volume snapshots // ListSnapshots lists the volume snapshots
type ListSnapshots struct { type ListSnapshots struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ID *UUID `json:"id,omitempty" doc:"lists snapshot by snapshot ID"` ID *UUID `json:"id,omitempty" doc:"lists snapshot by snapshot ID"`
IntervalType string `json:"intervaltype,omitempty" doc:"valid values are HOURLY, DAILY, WEEKLY, and MONTHLY."` IntervalType string `json:"intervaltype,omitempty" doc:"valid values are HOURLY, DAILY, WEEKLY, and MONTHLY."`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Name string `json:"name,omitempty" doc:"lists snapshot by snapshot name"` Name string `json:"name,omitempty" doc:"lists snapshot by snapshot name"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
@ -96,22 +106,20 @@ type ListSnapshotsResponse struct {
Snapshot []Snapshot `json:"snapshot"` Snapshot []Snapshot `json:"snapshot"`
} }
func (ListSnapshots) response() interface{} {
return new(ListSnapshotsResponse)
}
// DeleteSnapshot (Async) deletes a snapshot of a disk volume // DeleteSnapshot (Async) deletes a snapshot of a disk volume
type DeleteSnapshot struct { type DeleteSnapshot struct {
ID *UUID `json:"id" doc:"The ID of the snapshot"` ID *UUID `json:"id" doc:"The ID of the snapshot"`
_ bool `name:"deleteSnapshot" description:"Deletes a snapshot of a disk volume."` _ bool `name:"deleteSnapshot" description:"Deletes a snapshot of a disk volume."`
} }
func (DeleteSnapshot) response() interface{} { // Response returns the struct to unmarshal
func (DeleteSnapshot) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DeleteSnapshot) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (DeleteSnapshot) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// RevertSnapshot (Async) reverts a volume snapshot // RevertSnapshot (Async) reverts a volume snapshot
@ -120,10 +128,12 @@ type RevertSnapshot struct {
_ bool `name:"revertSnapshot" description:"revert a volume snapshot."` _ bool `name:"revertSnapshot" description:"revert a volume snapshot."`
} }
func (RevertSnapshot) response() interface{} { // Response returns the struct to unmarshal
func (RevertSnapshot) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RevertSnapshot) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (RevertSnapshot) AsyncResponse() interface{} {
return new(BooleanResponse)
} }

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListSnapshots) Response() interface{} {
return new(ListSnapshotsResponse)
}
// ListRequest returns itself
func (ls *ListSnapshots) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListSnapshots) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListSnapshots) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListSnapshots) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListSnapshotsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListSnapshotsResponse was expected, got %T", resp))
return
}
for i := range items.Snapshot {
if !callback(&items.Snapshot[i], nil) {
break
}
}
}

View file

@ -1,16 +0,0 @@
// Code generated by "stringer -type SnapshotState"; DO NOT EDIT.
package egoscale
import "strconv"
const _SnapshotState_name = "AllocatedCreatingCreatedOnPrimaryBackingUpBackedUpCopyingDestroyingDestroyedError"
var _SnapshotState_index = [...]uint8{0, 9, 17, 33, 42, 50, 57, 67, 76, 81}
func (i SnapshotState) String() string {
if i < 0 || i >= SnapshotState(len(_SnapshotState_index)-1) {
return "SnapshotState(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _SnapshotState_name[_SnapshotState_index[i]:_SnapshotState_index[i+1]]
}

View file

@ -37,49 +37,44 @@ func (ssh SSHKeyPair) ListRequest() (ListCommand, error) {
// CreateSSHKeyPair represents a new keypair to be created // CreateSSHKeyPair represents a new keypair to be created
type CreateSSHKeyPair struct { type CreateSSHKeyPair struct {
Name string `json:"name" doc:"Name of the keypair"` Name string `json:"name" doc:"Name of the keypair"`
Account string `json:"account,omitempty" doc:"an optional account for the ssh key. Must be used with domainId."` _ bool `name:"createSSHKeyPair" description:"Create a new keypair and returns the private key"`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainId for the ssh key. If the account parameter is used, domainId must also be used."`
_ bool `name:"createSSHKeyPair" description:"Create a new keypair and returns the private key"`
} }
func (CreateSSHKeyPair) response() interface{} { // Response returns the struct to unmarshal
func (CreateSSHKeyPair) Response() interface{} {
return new(SSHKeyPair) return new(SSHKeyPair)
} }
// DeleteSSHKeyPair represents a new keypair to be created // DeleteSSHKeyPair represents a new keypair to be created
type DeleteSSHKeyPair struct { type DeleteSSHKeyPair struct {
Name string `json:"name" doc:"Name of the keypair"` Name string `json:"name" doc:"Name of the keypair"`
Account string `json:"account,omitempty" doc:"the account associated with the keypair. Must be used with the domainId parameter."` _ bool `name:"deleteSSHKeyPair" description:"Deletes a keypair by name"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID associated with the keypair"`
_ bool `name:"deleteSSHKeyPair" description:"Deletes a keypair by name"`
} }
func (DeleteSSHKeyPair) response() interface{} { // Response returns the struct to unmarshal
return new(booleanResponse) func (DeleteSSHKeyPair) Response() interface{} {
return new(BooleanResponse)
} }
// RegisterSSHKeyPair represents a new registration of a public key in a keypair // RegisterSSHKeyPair represents a new registration of a public key in a keypair
type RegisterSSHKeyPair struct { type RegisterSSHKeyPair struct {
Name string `json:"name" doc:"Name of the keypair"` Name string `json:"name" doc:"Name of the keypair"`
PublicKey string `json:"publickey" doc:"Public key material of the keypair"` PublicKey string `json:"publickey" doc:"Public key material of the keypair"`
Account string `json:"account,omitempty" doc:"an optional account for the ssh key. Must be used with domainId."`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainId for the ssh key. If the account parameter is used, domainId must also be used."`
_ bool `name:"registerSSHKeyPair" description:"Register a public key in a keypair under a certain name"` _ bool `name:"registerSSHKeyPair" description:"Register a public key in a keypair under a certain name"`
} }
func (RegisterSSHKeyPair) response() interface{} { // Response returns the struct to unmarshal
func (RegisterSSHKeyPair) Response() interface{} {
return new(SSHKeyPair) return new(SSHKeyPair)
} }
//go:generate go run generate/main.go -interface=Listable ListSSHKeyPairs
// ListSSHKeyPairs represents a query for a list of SSH KeyPairs // ListSSHKeyPairs represents a query for a list of SSH KeyPairs
type ListSSHKeyPairs struct { type ListSSHKeyPairs struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
Fingerprint string `json:"fingerprint,omitempty" doc:"A public key fingerprint to look for"` Fingerprint string `json:"fingerprint,omitempty" doc:"A public key fingerprint to look for"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Name string `json:"name,omitempty" doc:"A key pair name to look for"` Name string `json:"name,omitempty" doc:"A key pair name to look for"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
@ -92,47 +87,19 @@ type ListSSHKeyPairsResponse struct {
SSHKeyPair []SSHKeyPair `json:"sshkeypair"` SSHKeyPair []SSHKeyPair `json:"sshkeypair"`
} }
func (ListSSHKeyPairs) response() interface{} {
return new(ListSSHKeyPairsResponse)
}
// SetPage sets the current page
func (ls *ListSSHKeyPairs) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListSSHKeyPairs) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListSSHKeyPairs) each(resp interface{}, callback IterateItemFunc) {
sshs, ok := resp.(*ListSSHKeyPairsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListSSHKeyPairsResponse expected, got %T", resp))
return
}
for i := range sshs.SSHKeyPair {
if !callback(&sshs.SSHKeyPair[i], nil) {
break
}
}
}
// ResetSSHKeyForVirtualMachine (Async) represents a change for the key pairs // ResetSSHKeyForVirtualMachine (Async) represents a change for the key pairs
type ResetSSHKeyForVirtualMachine struct { type ResetSSHKeyForVirtualMachine struct {
ID *UUID `json:"id" doc:"The ID of the virtual machine"` ID *UUID `json:"id" doc:"The ID of the virtual machine"`
KeyPair string `json:"keypair" doc:"name of the ssh key pair used to login to the virtual machine"` KeyPair string `json:"keypair" doc:"Name of the ssh key pair used to login to the virtual machine"`
Account string `json:"account,omitempty" doc:"an optional account for the ssh key. Must be used with domainId."` _ bool `name:"resetSSHKeyForVirtualMachine" description:"Resets the SSH Key for virtual machine. The virtual machine must be in a \"Stopped\" state."`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used."`
_ bool `name:"resetSSHKeyForVirtualMachine" description:"Resets the SSH Key for virtual machine. The virtual machine must be in a \"Stopped\" state."`
} }
func (ResetSSHKeyForVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (ResetSSHKeyForVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (ResetSSHKeyForVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (ResetSSHKeyForVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListSSHKeyPairs) Response() interface{} {
return new(ListSSHKeyPairsResponse)
}
// ListRequest returns itself
func (ls *ListSSHKeyPairs) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListSSHKeyPairs) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListSSHKeyPairs) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListSSHKeyPairs) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListSSHKeyPairsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListSSHKeyPairsResponse was expected, got %T", resp))
return
}
for i := range items.SSHKeyPair {
if !callback(&items.SSHKeyPair[i], nil) {
break
}
}
}

View file

@ -2,18 +2,29 @@ package egoscale
// ResourceTag is a tag associated with a resource // ResourceTag is a tag associated with a resource
// //
// http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/4.9/management.html // https://community.exoscale.com/documentation/compute/instance-tags/
type ResourceTag struct { type ResourceTag struct {
Account string `json:"account,omitempty" doc:"the account associated with the tag"` Account string `json:"account,omitempty" doc:"the account associated with the tag"`
Customer string `json:"customer,omitempty" doc:"customer associated with the tag"` Customer string `json:"customer,omitempty" doc:"customer associated with the tag"`
Domain string `json:"domain,omitempty" doc:"the domain associated with the tag"`
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain associated with the tag"`
Key string `json:"key,omitempty" doc:"tag key name"` Key string `json:"key,omitempty" doc:"tag key name"`
ResourceID *UUID `json:"resourceid,omitempty" doc:"id of the resource"` ResourceID *UUID `json:"resourceid,omitempty" doc:"id of the resource"`
ResourceType string `json:"resourcetype,omitempty" doc:"resource type"` ResourceType string `json:"resourcetype,omitempty" doc:"resource type"`
Value string `json:"value,omitempty" doc:"tag value"` Value string `json:"value,omitempty" doc:"tag value"`
} }
// ListRequest builds the ListZones request
func (tag ResourceTag) ListRequest() (ListCommand, error) {
req := &ListTags{
Customer: tag.Customer,
Key: tag.Key,
ResourceID: tag.ResourceID,
ResourceType: tag.ResourceType,
Value: tag.Value,
}
return req, nil
}
// CreateTags (Async) creates resource tag(s) // CreateTags (Async) creates resource tag(s)
type CreateTags struct { type CreateTags struct {
ResourceIDs []UUID `json:"resourceids" doc:"list of resources to create the tags for"` ResourceIDs []UUID `json:"resourceids" doc:"list of resources to create the tags for"`
@ -23,12 +34,14 @@ type CreateTags struct {
_ bool `name:"createTags" description:"Creates resource tag(s)"` _ bool `name:"createTags" description:"Creates resource tag(s)"`
} }
func (CreateTags) response() interface{} { // Response returns the struct to unmarshal
func (CreateTags) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (CreateTags) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (CreateTags) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// DeleteTags (Async) deletes the resource tag(s) // DeleteTags (Async) deletes the resource tag(s)
@ -39,23 +52,23 @@ type DeleteTags struct {
_ bool `name:"deleteTags" description:"Deleting resource tag(s)"` _ bool `name:"deleteTags" description:"Deleting resource tag(s)"`
} }
func (DeleteTags) response() interface{} { // Response returns the struct to unmarshal
func (DeleteTags) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DeleteTags) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (DeleteTags) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
//go:generate go run generate/main.go -interface=Listable ListTags
// ListTags list resource tag(s) // ListTags list resource tag(s)
type ListTags struct { type ListTags struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
Customer string `json:"customer,omitempty" doc:"list by customer name"` Customer string `json:"customer,omitempty" doc:"list by customer name"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Key string `json:"key,omitempty" doc:"list by key"` Key string `json:"key,omitempty" doc:"list by key"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
ResourceID *UUID `json:"resourceid,omitempty" doc:"list by resource id"` ResourceID *UUID `json:"resourceid,omitempty" doc:"list by resource id"`
@ -69,7 +82,3 @@ type ListTagsResponse struct {
Count int `json:"count"` Count int `json:"count"`
Tag []ResourceTag `json:"tag"` Tag []ResourceTag `json:"tag"`
} }
func (ListTags) response() interface{} {
return new(ListTagsResponse)
}

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

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListTags) Response() interface{} {
return new(ListTagsResponse)
}
// ListRequest returns itself
func (ls *ListTags) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListTags) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListTags) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListTags) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListTagsResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListTagsResponse was expected, got %T", resp))
return
}
for i := range items.Tag {
if !callback(&items.Tag[i], nil) {
break
}
}
}

View file

@ -1,12 +1,6 @@
package egoscale package egoscale
import ( // Template represents a machine to be deployed.
"fmt"
)
// Template represents a machine to be deployed
//
// See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/templates.html
type Template struct { type Template struct {
Account string `json:"account,omitempty" doc:"the account name to which the template belongs"` Account string `json:"account,omitempty" doc:"the account name to which the template belongs"`
AccountID *UUID `json:"accountid,omitempty" doc:"the account id to which the template belongs"` AccountID *UUID `json:"accountid,omitempty" doc:"the account id to which the template belongs"`
@ -16,12 +10,9 @@ type Template struct {
CrossZones bool `json:"crossZones,omitempty" doc:"true if the template is managed across all Zones, false otherwise"` CrossZones bool `json:"crossZones,omitempty" doc:"true if the template is managed across all Zones, false otherwise"`
Details map[string]string `json:"details,omitempty" doc:"additional key/value details tied with template"` Details map[string]string `json:"details,omitempty" doc:"additional key/value details tied with template"`
DisplayText string `json:"displaytext,omitempty" doc:"the template display text"` DisplayText string `json:"displaytext,omitempty" doc:"the template display text"`
Domain string `json:"domain,omitempty" doc:"the name of the domain to which the template belongs"`
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain to which the template belongs"`
Format string `json:"format,omitempty" doc:"the format of the template."` Format string `json:"format,omitempty" doc:"the format of the template."`
HostID *UUID `json:"hostid,omitempty" doc:"the ID of the secondary storage host for the template"` HostID *UUID `json:"hostid,omitempty" doc:"the ID of the secondary storage host for the template"`
HostName string `json:"hostname,omitempty" doc:"the name of the secondary storage host for the template"` HostName string `json:"hostname,omitempty" doc:"the name of the secondary storage host for the template"`
Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor on which the template runs"`
ID *UUID `json:"id,omitempty" doc:"the template ID"` ID *UUID `json:"id,omitempty" doc:"the template ID"`
IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"`
IsExtractable bool `json:"isextractable,omitempty" doc:"true if the template is extractable, false otherwise"` IsExtractable bool `json:"isextractable,omitempty" doc:"true if the template is extractable, false otherwise"`
@ -52,42 +43,39 @@ func (Template) ResourceType() string {
} }
// ListRequest builds the ListTemplates request // ListRequest builds the ListTemplates request
func (temp Template) ListRequest() (ListCommand, error) { func (template Template) ListRequest() (ListCommand, error) {
req := &ListTemplates{ req := &ListTemplates{
Name: temp.Name, ID: template.ID,
Account: temp.Account, Name: template.Name,
DomainID: temp.DomainID, ZoneID: template.ZoneID,
ID: temp.ID,
ZoneID: temp.ZoneID,
Hypervisor: temp.Hypervisor,
//TODO Tags
} }
if temp.IsFeatured { if template.IsFeatured {
req.TemplateFilter = "featured" req.TemplateFilter = "featured"
} }
if temp.Removed != "" { if template.Removed != "" {
*req.ShowRemoved = true *req.ShowRemoved = true
} }
for i := range template.Tags {
req.Tags = append(req.Tags, template.Tags[i])
}
return req, nil return req, nil
} }
//go:generate go run generate/main.go -interface=Listable ListTemplates
// ListTemplates represents a template query filter // ListTemplates represents a template query filter
type ListTemplates struct { type ListTemplates struct {
TemplateFilter string `json:"templatefilter" doc:"possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". * featured : templates that have been marked as featured and public. * self : templates that have been registered or created by the calling user. * selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. * sharedexecutable : templates ready to be deployed that have been granted to the calling user by another user. * executable : templates that are owned by the calling user, or public templates, that can be used to deploy a VM. * community : templates that have been marked as public but not featured. * all : all templates (only usable by admins)."` TemplateFilter string `json:"templatefilter" doc:"Possible values are \"featured\", \"self\", \"selfexecutable\",\"sharedexecutable\",\"executable\", and \"community\". * featured : templates that have been marked as featured and public. * self : templates that have been registered or created by the calling user. * selfexecutable : same as self, but only returns templates that can be used to deploy a new VM. * sharedexecutable : templates ready to be deployed that have been granted to the calling user by another user. * executable : templates that are owned by the calling user, or public templates, that can be used to deploy a VM. * community : templates that have been marked as public but not featured."`
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor for which to restrict the search"`
ID *UUID `json:"id,omitempty" doc:"the template ID"` ID *UUID `json:"id,omitempty" doc:"the template ID"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Name string `json:"name,omitempty" doc:"the template name"` Name string `json:"name,omitempty" doc:"the template name"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
ShowRemoved *bool `json:"showremoved,omitempty" doc:"show removed templates as well"` ShowRemoved *bool `json:"showremoved,omitempty" doc:"Show removed templates as well"`
Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"list templates by zoneId"` ZoneID *UUID `json:"zoneid,omitempty" doc:"list templates by zoneid"`
_ bool `name:"listTemplates" description:"List all public, private, and privileged templates."` _ bool `name:"listTemplates" description:"List all public, private, and privileged templates."`
} }
@ -97,172 +85,27 @@ type ListTemplatesResponse struct {
Template []Template `json:"template"` Template []Template `json:"template"`
} }
func (ListTemplates) response() interface{} {
return new(ListTemplatesResponse)
}
func (ListTemplates) each(resp interface{}, callback IterateItemFunc) {
temps, ok := resp.(*ListTemplatesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListTemplatesResponse expected, got %T", resp))
return
}
for i := range temps.Template {
if !callback(&temps.Template[i], nil) {
break
}
}
}
// SetPage sets the current page
func (ls *ListTemplates) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListTemplates) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// CreateTemplate (Async) represents a template creation
type CreateTemplate struct {
Bits int `json:"bits,omitempty" doc:"32 or 64 bit"`
Details map[string]string `json:"details,omitempty" doc:"Template details in key/value pairs."`
DisplayText string `json:"displaytext" doc:"the display text of the template. This is usually used for display purposes."`
IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"`
IsFeatured *bool `json:"isfeatured,omitempty" doc:"true if this template is a featured template, false otherwise"`
IsPublic *bool `json:"ispublic,omitempty" doc:"true if this template is a public template, false otherwise"`
Name string `json:"name" doc:"the name of the template"`
OsTypeID *UUID `json:"ostypeid" doc:"the ID of the OS Type that best represents the OS of this template."`
PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the template supports the password reset feature; default is false"`
RequiresHVM *bool `json:"requireshvm,omitempty" doc:"true if the template requres HVM, false otherwise"`
SnapshotID *UUID `json:"snapshotid,omitempty" doc:"the ID of the snapshot the template is being created from. Either this parameter, or volumeId has to be passed in"`
TemplateTag string `json:"templatetag,omitempty" doc:"the tag for this template."`
URL string `json:"url,omitempty" doc:"Optional, only for baremetal hypervisor. The directory name where template stored on CIFS server"`
VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"Optional, VM ID. If this presents, it is going to create a baremetal template for VM this ID refers to. This is only for VM whose hypervisor type is BareMetal"`
VolumeID *UUID `json:"volumeid,omitempty" doc:"the ID of the disk volume the template is being created from. Either this parameter, or snapshotId has to be passed in"`
_ bool `name:"createTemplate" description:"Creates a template of a virtual machine. The virtual machine must be in a STOPPED state. A template created from this command is automatically designated as a private template visible to the account that created it."`
}
func (CreateTemplate) response() interface{} {
return new(AsyncJobResult)
}
func (CreateTemplate) asyncResponse() interface{} {
return new(Template)
}
// CopyTemplate (Async) represents a template copy
type CopyTemplate struct {
DestZoneID *UUID `json:"destzoneid" doc:"ID of the zone the template is being copied to."`
ID *UUID `json:"id" doc:"Template ID."`
SourceZoneID *UUID `json:"sourcezoneid,omitempty" doc:"ID of the zone the template is currently hosted on. If not specified and template is cross-zone, then we will sync this template to region wide image store."`
_ bool `name:"copyTemplate" description:"Copies a template from one zone to another."`
}
func (CopyTemplate) response() interface{} {
return new(AsyncJobResult)
}
func (CopyTemplate) asyncResponse() interface{} {
return new(Template)
}
// UpdateTemplate represents a template change
type UpdateTemplate struct {
Bootable *bool `json:"bootable,omitempty" doc:"true if image is bootable, false otherwise"`
Details map[string]string `json:"details,omitempty" doc:"Details in key/value pairs."`
DisplayText string `json:"displaytext,omitempty" doc:"the display text of the image"`
Format string `json:"format,omitempty" doc:"the format for the image"`
ID *UUID `json:"id" doc:"the ID of the image file"`
IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if template/ISO contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"`
IsRouting *bool `json:"isrouting,omitempty" doc:"true if the template type is routing i.e., if template is used to deploy router"`
Name string `json:"name,omitempty" doc:"the name of the image file"`
OsTypeID *UUID `json:"ostypeid,omitempty" doc:"the ID of the OS type that best represents the OS of this image."`
PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the image supports the password reset feature; default is false"`
SortKey int `json:"sortkey,omitempty" doc:"sort key of the template, integer"`
_ bool `name:"updateTemplate" description:"Updates attributes of a template."`
}
func (UpdateTemplate) response() interface{} {
return new(AsyncJobResult)
}
func (UpdateTemplate) asyncResponse() interface{} {
return new(Template)
}
// DeleteTemplate (Async) represents the deletion of a template
type DeleteTemplate struct {
ID *UUID `json:"id" doc:"the ID of the template"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of zone of the template"`
_ bool `name:"deleteTemplate" description:"Deletes a template from the system. All virtual machines using the deleted template will not be affected."`
}
func (DeleteTemplate) response() interface{} {
return new(AsyncJobResult)
}
func (DeleteTemplate) asyncResponse() interface{} {
return new(booleanResponse)
}
// PrepareTemplate represents a template preparation
type PrepareTemplate struct {
TemplateID *UUID `json:"templateid" doc:"template ID of the template to be prepared in primary storage(s)."`
ZoneID *UUID `json:"zoneid" doc:"zone ID of the template to be prepared in primary storage(s)."`
_ bool `name:"prepareTemplate" description:"load template into primary storage"`
}
func (PrepareTemplate) response() interface{} {
return new(AsyncJobResult)
}
func (PrepareTemplate) asyncResponse() interface{} {
return new(Template)
}
// RegisterTemplate represents a template registration
type RegisterTemplate struct {
Account string `json:"account,omitempty" doc:"an optional accountName. Must be used with domainId."`
Bits int `json:"bits,omitempty" doc:"32 or 64 bits support. 64 by default"`
Checksum string `json:"checksum,omitempty" doc:"the MD5 checksum value of this template"`
Details map[string]string `json:"details,omitempty" doc:"Template details in key/value pairs."`
DisplayText string `json:"displaytext" doc:"the display text of the template. This is usually used for display purposes."`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainId. If the account parameter is used, domainId must also be used."`
Format string `json:"format" doc:"the format for the template. Possible values include QCOW2, RAW, and VHD."`
Hypervisor string `json:"hypervisor" doc:"the target hypervisor for the template"`
IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"`
IsExtractable *bool `json:"isextractable,omitempty" doc:"true if the template or its derivatives are extractable; default is false"`
IsFeatured *bool `json:"isfeatured,omitempty" doc:"true if this template is a featured template, false otherwise"`
IsPublic *bool `json:"ispublic,omitempty" doc:"true if the template is available to all accounts; default is true"`
IsRouting *bool `json:"isrouting,omitempty" doc:"true if the template type is routing i.e., if template is used to deploy router"`
IsSystem *bool `json:"issystem,omitempty" doc:"true if the template type is system i.e., if template is used to deploy system VM"`
Name string `json:"name" doc:"the name of the template"`
OsTypeID *UUID `json:"ostypeid" doc:"the ID of the OS Type that best represents the OS of this template."`
PasswordEnabled *bool `json:"passwordenabled,omitempty" doc:"true if the template supports the password reset feature; default is false"`
RequiresHVM *bool `json:"requireshvm,omitempty" doc:"true if this template requires HVM"`
SSHKeyEnabled *bool `json:"sshkeyenabled,omitempty" doc:"true if the template supports the sshkey upload feature; default is false"`
TemplateTag string `json:"templatetag,omitempty" doc:"the tag for this template."`
URL string `json:"url" doc:"the URL of where the template is hosted. Possible URL include http:// and https://"`
ZoneID *UUID `json:"zoneid" doc:"the ID of the zone the template is to be hosted on"`
_ bool `name:"registerTemplate" description:"Registers an existing template into the CloudStack cloud."`
}
func (RegisterTemplate) response() interface{} {
return new(Template)
}
// OSCategory represents an OS category // OSCategory represents an OS category
type OSCategory struct { type OSCategory struct {
ID string `json:"id,omitempty" doc:"the ID of the OS category"` ID *UUID `json:"id,omitempty" doc:"the ID of the OS category"`
Name string `json:"name,omitempty" doc:"the name of the OS category"` Name string `json:"name,omitempty" doc:"the name of the OS category"`
} }
// ListRequest builds the ListOSCategories request
func (osCat OSCategory) ListRequest() (ListCommand, error) {
req := &ListOSCategories{
Name: osCat.Name,
ID: osCat.ID,
}
return req, nil
}
//go:generate go run generate/main.go -interface=Listable ListOSCategories
// ListOSCategories lists the OS categories // ListOSCategories lists the OS categories
type ListOSCategories struct { type ListOSCategories struct {
ID string `json:"id,omitempty" doc:"list Os category by id"` ID *UUID `json:"id,omitempty" doc:"list Os category by id"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"list os category by name"` Name string `json:"name,omitempty" doc:"list os category by name"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
@ -275,7 +118,3 @@ type ListOSCategoriesResponse struct {
Count int `json:"count"` Count int `json:"count"`
OSCategory []OSCategory `json:"oscategory"` OSCategory []OSCategory `json:"oscategory"`
} }
func (ListOSCategories) response() interface{} {
return new(ListOSCategoriesResponse)
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListTemplates) Response() interface{} {
return new(ListTemplatesResponse)
}
// ListRequest returns itself
func (ls *ListTemplates) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListTemplates) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListTemplates) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListTemplates) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListTemplatesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListTemplatesResponse was expected, got %T", resp))
return
}
for i := range items.Template {
if !callback(&items.Template[i], nil) {
break
}
}
}

View file

@ -2,26 +2,32 @@ package egoscale
// User represents a User // User represents a User
type User struct { type User struct {
APIKey string `json:"apikey,omitempty" doc:"the api key of the user"` APIKey string `json:"apikey,omitempty" doc:"the api key of the user"`
Account string `json:"account,omitempty" doc:"the account name of the user"` Account string `json:"account,omitempty" doc:"the account name of the user"`
AccountID *UUID `json:"accountid,omitempty" doc:"the account ID of the user"` AccountID *UUID `json:"accountid,omitempty" doc:"the account ID of the user"`
AccountType int16 `json:"accounttype,omitempty" doc:"the account type of the user"` Created string `json:"created,omitempty" doc:"the date and time the user account was created"`
Created string `json:"created,omitempty" doc:"the date and time the user account was created"` Email string `json:"email,omitempty" doc:"the user email address"`
Domain string `json:"domain,omitempty" doc:"the domain name of the user"` FirstName string `json:"firstname,omitempty" doc:"the user firstname"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of the user"` ID *UUID `json:"id,omitempty" doc:"the user ID"`
Email string `json:"email,omitempty" doc:"the user email address"` IsDefault bool `json:"isdefault,omitempty" doc:"true if user is default, false otherwise"`
FirstName string `json:"firstname,omitempty" doc:"the user firstname"` LastName string `json:"lastname,omitempty" doc:"the user lastname"`
ID *UUID `json:"id,omitempty" doc:"the user ID"` RoleID *UUID `json:"roleid,omitempty" doc:"the ID of the role"`
IsCallerChildDomain bool `json:"iscallerchilddomain,omitempty" doc:"the boolean value representing if the updating target is in caller's child domain"` RoleName string `json:"rolename,omitempty" doc:"the name of the role"`
IsDefault bool `json:"isdefault,omitempty" doc:"true if user is default, false otherwise"` RoleType string `json:"roletype,omitempty" doc:"the type of the role"`
LastName string `json:"lastname,omitempty" doc:"the user lastname"` SecretKey string `json:"secretkey,omitempty" doc:"the secret key of the user"`
RoleID *UUID `json:"roleid,omitempty" doc:"the ID of the role"` State string `json:"state,omitempty" doc:"the user state"`
RoleName string `json:"rolename,omitempty" doc:"the name of the role"` Timezone string `json:"timezone,omitempty" doc:"the timezone user was created in"`
RoleType string `json:"roletype,omitempty" doc:"the type of the role"` UserName string `json:"username,omitempty" doc:"the user name"`
SecretKey string `json:"secretkey,omitempty" doc:"the secret key of the user"` }
State string `json:"state,omitempty" doc:"the user state"`
Timezone string `json:"timezone,omitempty" doc:"the timezone user was created in"` // ListRequest builds the ListUsers request
UserName string `json:"username,omitempty" doc:"the user name"` func (user User) ListRequest() (ListCommand, error) {
req := &ListUsers{
ID: user.ID,
UserName: user.UserName,
}
return req, nil
} }
// RegisterUserKeys registers a new set of key of the given user // RegisterUserKeys registers a new set of key of the given user
@ -32,60 +38,22 @@ type RegisterUserKeys struct {
_ bool `name:"registerUserKeys" description:"This command allows a user to register for the developer API, returning a secret key and an API key. This request is made through the integration API port, so it is a privileged command and must be made on behalf of a user. It is up to the implementer just how the username and password are entered, and then how that translates to an integration API request. Both secret key and API key should be returned to the user"` _ bool `name:"registerUserKeys" description:"This command allows a user to register for the developer API, returning a secret key and an API key. This request is made through the integration API port, so it is a privileged command and must be made on behalf of a user. It is up to the implementer just how the username and password are entered, and then how that translates to an integration API request. Both secret key and API key should be returned to the user"`
} }
func (RegisterUserKeys) response() interface{} { // Response returns the struct to unmarshal
func (RegisterUserKeys) Response() interface{} {
return new(User) return new(User)
} }
// CreateUser represents the creation of a User //go:generate go run generate/main.go -interface=Listable ListUsers
type CreateUser struct {
Account string `json:"account" doc:"Creates the user under the specified account. If no account is specified, the username will be used as the account name."`
Email string `json:"email" doc:"email"`
FirstName string `json:"firstname" doc:"firstname"`
LastName string `json:"lastname" doc:"lastname"`
Password string `json:"password" doc:"Clear text password (Default hashed to SHA256SALT). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter See Docs section."`
UserName string `json:"username" doc:"Unique username."`
DomainID *UUID `json:"domainid,omitempty" doc:"Creates the user under the specified domain. Has to be accompanied with the account parameter"`
Timezone string `json:"timezone,omitempty" doc:"Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format."`
UserID *UUID `json:"userid,omitempty" doc:"User UUID, required for adding account from external provisioning system"`
_ bool `name:"createUser" description:"Creates a user for an account that already exists"`
}
func (CreateUser) response() interface{} {
return new(User)
}
// UpdateUser represents the modification of a User
type UpdateUser struct {
ID *UUID `json:"id" doc:"User uuid"`
Email string `json:"email,omitempty" doc:"email"`
FirstName string `json:"firstname,omitempty" doc:"first name"`
LastName string `json:"lastname,omitempty" doc:"last name"`
Password string `json:"password,omitempty" doc:"Clear text password (default hashed to SHA256SALT). If you wish to use any other hashing algorithm, you would need to write a custom authentication adapter"`
Timezone string `json:"timezone,omitempty" doc:"Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format."`
UserAPIKey string `json:"userapikey,omitempty" doc:"The API key for the user. Must be specified with userSecretKey"`
UserName string `json:"username,omitempty" doc:"Unique username"`
UserSecretKey string `json:"usersecretkey,omitempty" doc:"The secret key for the user. Must be specified with userApiKey"`
_ bool `name:"updateUser" description:"Updates a user account"`
}
func (UpdateUser) response() interface{} {
return new(User)
}
// ListUsers represents the search for Users // ListUsers represents the search for Users
type ListUsers struct { type ListUsers struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` ID *UUID `json:"id,omitempty" doc:"List user by ID."`
AccountType int64 `json:"accounttype,omitempty" doc:"List users by account type. Valid types include admin, domain-admin, read-only-admin, or user."` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"` Page int `json:"page,omitempty"`
ID *UUID `json:"id,omitempty" doc:"List user by ID."` PageSize int `json:"pagesize,omitempty"`
IsRecursive bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."` State string `json:"state,omitempty" doc:"List users by state of the user account."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` UserName string `json:"username,omitempty" doc:"List user by the username"`
ListAll bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` _ bool `name:"listUsers" description:"Lists user accounts"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
State string `json:"state,omitempty" doc:"List users by state of the user account."`
Username string `json:"username,omitempty" doc:"List user by the username"`
_ bool `name:"listUsers" description:"Lists user accounts"`
} }
// ListUsersResponse represents a list of users // ListUsersResponse represents a list of users
@ -93,17 +61,3 @@ type ListUsersResponse struct {
Count int `json:"count"` Count int `json:"count"`
User []User `json:"user"` User []User `json:"user"`
} }
func (ListUsers) response() interface{} {
return new(ListUsersResponse)
}
// DeleteUser deletes a user for an account
type DeleteUser struct {
ID *UUID `json:"id" doc:"id of the user to be deleted"`
_ bool `name:"deleteUser" description:"Deletes a user for an account"`
}
func (DeleteUser) response() interface{} {
return new(booleanResponse)
}

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

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListUsers) Response() interface{} {
return new(ListUsersResponse)
}
// ListRequest returns itself
func (ls *ListUsers) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListUsers) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListUsers) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListUsers) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListUsersResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListUsersResponse was expected, got %T", resp))
return
}
for i := range items.User {
if !callback(&items.User[i], nil) {
break
}
}
}

View file

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
) )
// UUID holds a UUID v4 // UUID holds a UUID v4
@ -12,12 +12,36 @@ type UUID struct {
uuid.UUID uuid.UUID
} }
// Equal returns true if itself is equal to other // DeepCopy create a true copy of the receiver.
func (u *UUID) DeepCopy() *UUID {
if u == nil {
return nil
}
out := [uuid.Size]byte{}
copy(out[:], u.Bytes())
return &UUID{
(uuid.UUID)(out),
}
}
// DeepCopyInto copies the receiver into out.
//
// In must be non nil.
func (u *UUID) DeepCopyInto(out *UUID) {
o := [uuid.Size]byte{}
copy(o[:], u.Bytes())
out.UUID = (uuid.UUID)(o)
}
// Equal returns true if itself is equal to other.
func (u UUID) Equal(other UUID) bool { func (u UUID) Equal(other UUID) bool {
return uuid.Equal(u.UUID, other.UUID) return uuid.Equal(u.UUID, other.UUID)
} }
// UnmarshalJSON unmarshals the raw JSON into the MAC address // UnmarshalJSON unmarshals the raw JSON into the UUID.
func (u *UUID) UnmarshalJSON(b []byte) error { func (u *UUID) UnmarshalJSON(b []byte) error {
var s string var s string
if err := json.Unmarshal(b, &s); err != nil { if err := json.Unmarshal(b, &s); err != nil {
@ -31,12 +55,12 @@ func (u *UUID) UnmarshalJSON(b []byte) error {
return err return err
} }
// MarshalJSON converts the UUID to a string representation // MarshalJSON converts the UUID to a string representation.
func (u UUID) MarshalJSON() ([]byte, error) { func (u UUID) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("%q", u.String())), nil return []byte(fmt.Sprintf("%q", u.String())), nil
} }
// ParseUUID parses a string into a UUID // ParseUUID parses a string into a UUID.
func ParseUUID(s string) (*UUID, error) { func ParseUUID(s string) (*UUID, error) {
u, err := uuid.FromString(s) u, err := uuid.FromString(s)
if err != nil { if err != nil {
@ -45,7 +69,7 @@ func ParseUUID(s string) (*UUID, error) {
return &UUID{u}, nil return &UUID{u}, nil
} }
// MustParseUUID acts like ParseUUID but panic in case of a failure // MustParseUUID acts like ParseUUID but panic in case of a failure.
func MustParseUUID(s string) *UUID { func MustParseUUID(s string) *UUID {
u, e := ParseUUID(s) u, e := ParseUUID(s)
if e != nil { if e != nil {

View file

@ -1,4 +1,4 @@
package egoscale package egoscale
// Version of the library // Version of the library
const Version = "0.11.6" const Version = "0.14.0"

View file

@ -29,8 +29,10 @@ const (
VirtualMachineDestroyed VirtualMachineState = "Destroyed" VirtualMachineDestroyed VirtualMachineState = "Destroyed"
// VirtualMachineExpunging "VM is being expunged // VirtualMachineExpunging "VM is being expunged
VirtualMachineExpunging VirtualMachineState = "Expunging" VirtualMachineExpunging VirtualMachineState = "Expunging"
// VirtualMachineMigrating VM is being migrated. host id holds to from host // VirtualMachineMigrating VM is being live migrated. host id holds destination host, last host id holds source host
VirtualMachineMigrating VirtualMachineState = "Migrating" VirtualMachineMigrating VirtualMachineState = "Migrating"
// VirtualMachineMoving VM is being migrated offline (volume is being moved).
VirtualMachineMoving VirtualMachineState = "Moving"
// VirtualMachineError VM is in error // VirtualMachineError VM is in error
VirtualMachineError VirtualMachineState = "Error" VirtualMachineError VirtualMachineState = "Error"
// VirtualMachineUnknown VM state is unknown // VirtualMachineUnknown VM state is unknown
@ -43,67 +45,62 @@ const (
// //
// See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html // See: http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/stable/virtual_machines.html
type VirtualMachine struct { type VirtualMachine struct {
Account string `json:"account,omitempty" doc:"the account associated with the virtual machine"` Account string `json:"account,omitempty" doc:"the account associated with the virtual machine"`
AccountID *UUID `json:"accountid,omitempty" doc:"the account ID associated with the virtual machine"` AccountID *UUID `json:"accountid,omitempty" doc:"the account ID associated with the virtual machine"`
AffinityGroup []AffinityGroup `json:"affinitygroup,omitempty" doc:"list of affinity groups associated with the virtual machine"` AffinityGroup []AffinityGroup `json:"affinitygroup,omitempty" doc:"list of affinity groups associated with the virtual machine"`
ClusterID *UUID `json:"clusterid,omitempty" doc:"the ID of the vm's cluster"` ClusterID *UUID `json:"clusterid,omitempty" doc:"the ID of the vm's cluster"`
ClusterName string `json:"clustername,omitempty" doc:"the name of the vm's cluster"` ClusterName string `json:"clustername,omitempty" doc:"the name of the vm's cluster"`
CPUNumber int `json:"cpunumber,omitempty" doc:"the number of cpu this virtual machine is running with"` CPUNumber int `json:"cpunumber,omitempty" doc:"the number of cpu this virtual machine is running with"`
CPUSpeed int `json:"cpuspeed,omitempty" doc:"the speed of each cpu"` CPUSpeed int `json:"cpuspeed,omitempty" doc:"the speed of each cpu"`
CPUUsed string `json:"cpuused,omitempty" doc:"the amount of the vm's CPU currently used"` CPUUsed string `json:"cpuused,omitempty" doc:"the amount of the vm's CPU currently used"`
Created string `json:"created,omitempty" doc:"the date when this virtual machine was created"` Created string `json:"created,omitempty" doc:"the date when this virtual machine was created"`
Details map[string]string `json:"details,omitempty" doc:"Vm details in key/value pairs."` Details map[string]string `json:"details,omitempty" doc:"Vm details in key/value pairs."`
DiskIoRead int64 `json:"diskioread,omitempty" doc:"the read (io) of disk on the vm"` DiskIoRead int64 `json:"diskioread,omitempty" doc:"the read (io) of disk on the vm"`
DiskIoWrite int64 `json:"diskiowrite,omitempty" doc:"the write (io) of disk on the vm"` DiskIoWrite int64 `json:"diskiowrite,omitempty" doc:"the write (io) of disk on the vm"`
DiskKbsRead int64 `json:"diskkbsread,omitempty" doc:"the read (bytes) of disk on the vm"` DiskKbsRead int64 `json:"diskkbsread,omitempty" doc:"the read (bytes) of disk on the vm"`
DiskKbsWrite int64 `json:"diskkbswrite,omitempty" doc:"the write (bytes) of disk on the vm"` DiskKbsWrite int64 `json:"diskkbswrite,omitempty" doc:"the write (bytes) of disk on the vm"`
DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"the ID of the disk offering of the virtual machine"` DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"the ID of the disk offering of the virtual machine"`
DiskOfferingName string `json:"diskofferingname,omitempty" doc:"the name of the disk offering of the virtual machine"` DiskOfferingName string `json:"diskofferingname,omitempty" doc:"the name of the disk offering of the virtual machine"`
DisplayName string `json:"displayname,omitempty" doc:"user generated name. The name of the virtual machine is returned if no displayname exists."` DisplayName string `json:"displayname,omitempty" doc:"user generated name. The name of the virtual machine is returned if no displayname exists."`
DisplayVM bool `json:"displayvm,omitempty" doc:"an optional field whether to the display the vm to the end user or not."` ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the service offering"`
Domain string `json:"domain,omitempty" doc:"the name of the domain in which the virtual machine exists"` Group string `json:"group,omitempty" doc:"the group name of the virtual machine"`
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain in which the virtual machine exists"` GroupID *UUID `json:"groupid,omitempty" doc:"the group ID of the virtual machine"`
ForVirtualNetwork bool `json:"forvirtualnetwork,omitempty" doc:"the virtual network for the service offering"` HAEnable bool `json:"haenable,omitempty" doc:"true if high-availability is enabled, false otherwise"`
Group string `json:"group,omitempty" doc:"the group name of the virtual machine"` HostName string `json:"hostname,omitempty" doc:"the name of the host for the virtual machine"`
GroupID *UUID `json:"groupid,omitempty" doc:"the group ID of the virtual machine"` ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"`
HAEnable bool `json:"haenable,omitempty" doc:"true if high-availability is enabled, false otherwise"` InstanceName string `json:"instancename,omitempty" doc:"instance name of the user vm; this parameter is returned to the ROOT admin only"`
HostID *UUID `json:"hostid,omitempty" doc:"the ID of the host for the virtual machine"` IsoDisplayText string `json:"isodisplaytext,omitempty" doc:"an alternate display text of the ISO attached to the virtual machine"`
HostName string `json:"hostname,omitempty" doc:"the name of the host for the virtual machine"` IsoID *UUID `json:"isoid,omitempty" doc:"the ID of the ISO attached to the virtual machine"`
Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor on which the template runs"` IsoName string `json:"isoname,omitempty" doc:"the name of the ISO attached to the virtual machine"`
ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` KeyPair string `json:"keypair,omitempty" doc:"ssh key-pair"`
InstanceName string `json:"instancename,omitempty" doc:"instance name of the user vm; this parameter is returned to the ROOT admin only"` Memory int `json:"memory,omitempty" doc:"the memory allocated for the virtual machine"`
IsDynamicallyScalable bool `json:"isdynamicallyscalable,omitempty" doc:"true if vm contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory."` Name string `json:"name,omitempty" doc:"the name of the virtual machine"`
IsoDisplayText string `json:"isodisplaytext,omitempty" doc:"an alternate display text of the ISO attached to the virtual machine"` NetworkKbsRead int64 `json:"networkkbsread,omitempty" doc:"the incoming network traffic on the vm"`
IsoID *UUID `json:"isoid,omitempty" doc:"the ID of the ISO attached to the virtual machine"` NetworkKbsWrite int64 `json:"networkkbswrite,omitempty" doc:"the outgoing network traffic on the host"`
IsoName string `json:"isoname,omitempty" doc:"the name of the ISO attached to the virtual machine"` Nic []Nic `json:"nic,omitempty" doc:"the list of nics associated with vm"`
KeyPair string `json:"keypair,omitempty" doc:"ssh key-pair"` OSCategoryID *UUID `json:"oscategoryid,omitempty" doc:"Os category ID of the virtual machine"`
Memory int `json:"memory,omitempty" doc:"the memory allocated for the virtual machine"` OSCategoryName string `json:"oscategoryname,omitempty" doc:"Os category name of the virtual machine"`
Name string `json:"name,omitempty" doc:"the name of the virtual machine"` OSTypeID *UUID `json:"ostypeid,omitempty" doc:"OS type id of the vm"`
NetworkKbsRead int64 `json:"networkkbsread,omitempty" doc:"the incoming network traffic on the vm"` Password string `json:"password,omitempty" doc:"the password (if exists) of the virtual machine"`
NetworkKbsWrite int64 `json:"networkkbswrite,omitempty" doc:"the outgoing network traffic on the host"` PasswordEnabled bool `json:"passwordenabled,omitempty" doc:"true if the password rest feature is enabled, false otherwise"`
Nic []Nic `json:"nic,omitempty" doc:"the list of nics associated with vm"` PCIDevices []PCIDevice `json:"pcidevices,omitempty" doc:"list of PCI devices"`
OSCategoryID *UUID `json:"oscategoryid,omitempty" doc:"Os category ID of the virtual machine"` PodID *UUID `json:"podid,omitempty" doc:"the ID of the vm's pod"`
OSCategoryName string `json:"oscategoryname,omitempty" doc:"Os category name of the virtual machine"` PodName string `json:"podname,omitempty" doc:"the name of the vm's pod"`
Password string `json:"password,omitempty" doc:"the password (if exists) of the virtual machine"` PublicIP string `json:"publicip,omitempty" doc:"public IP address id associated with vm via Static nat rule"`
PasswordEnabled bool `json:"passwordenabled,omitempty" doc:"true if the password rest feature is enabled, false otherwise"` PublicIPID *UUID `json:"publicipid,omitempty" doc:"public IP address id associated with vm via Static nat rule"`
PCIDevices []PCIDevice `json:"pcidevices,omitempty" doc:"list of PCI devices"` RootDeviceID int64 `json:"rootdeviceid,omitempty" doc:"device ID of the root volume"`
PodID *UUID `json:"podid,omitempty" doc:"the ID of the vm's pod"` RootDeviceType string `json:"rootdevicetype,omitempty" doc:"device type of the root volume"`
PodName string `json:"podname,omitempty" doc:"the name of the vm's pod"` SecurityGroup []SecurityGroup `json:"securitygroup,omitempty" doc:"list of security groups associated with the virtual machine"`
PublicIP string `json:"publicip,omitempty" doc:"public IP address id associated with vm via Static nat rule"` ServiceOfferingID *UUID `json:"serviceofferingid,omitempty" doc:"the ID of the service offering of the virtual machine"`
PublicIPID *UUID `json:"publicipid,omitempty" doc:"public IP address id associated with vm via Static nat rule"` ServiceOfferingName string `json:"serviceofferingname,omitempty" doc:"the name of the service offering of the virtual machine"`
RootDeviceID int64 `json:"rootdeviceid,omitempty" doc:"device ID of the root volume"` ServiceState string `json:"servicestate,omitempty" doc:"State of the Service from LB rule"`
RootDeviceType string `json:"rootdevicetype,omitempty" doc:"device type of the root volume"` State string `json:"state,omitempty" doc:"the state of the virtual machine"`
SecurityGroup []SecurityGroup `json:"securitygroup,omitempty" doc:"list of security groups associated with the virtual machine"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with vm"`
ServiceOfferingID *UUID `json:"serviceofferingid,omitempty" doc:"the ID of the service offering of the virtual machine"` TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"`
ServiceOfferingName string `json:"serviceofferingname,omitempty" doc:"the name of the service offering of the virtual machine"` TemplateID *UUID `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."`
ServiceState string `json:"servicestate,omitempty" doc:"State of the Service from LB rule"` TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"`
State string `json:"state,omitempty" doc:"the state of the virtual machine"` ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availablility zone for the virtual machine"`
Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with vm"` ZoneName string `json:"zonename,omitempty" doc:"the name of the availability zone for the virtual machine"`
TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"`
TemplateID *UUID `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."`
TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availablility zone for the virtual machine"`
ZoneName string `json:"zonename,omitempty" doc:"the name of the availability zone for the virtual machine"`
} }
// ResourceType returns the type of the resource // ResourceType returns the type of the resource
@ -122,11 +119,9 @@ func (vm VirtualMachine) Delete(ctx context.Context, client *Client) error {
// ListRequest builds the ListVirtualMachines request // ListRequest builds the ListVirtualMachines request
func (vm VirtualMachine) ListRequest() (ListCommand, error) { func (vm VirtualMachine) ListRequest() (ListCommand, error) {
// XXX: AffinityGroupID, SecurityGroupID, Tags // XXX: AffinityGroupID, SecurityGroupID
req := &ListVirtualMachines{ req := &ListVirtualMachines{
Account: vm.Account,
DomainID: vm.DomainID,
GroupID: vm.GroupID, GroupID: vm.GroupID,
ID: vm.ID, ID: vm.ID,
Name: vm.Name, Name: vm.Name,
@ -140,14 +135,18 @@ func (vm VirtualMachine) ListRequest() (ListCommand, error) {
req.IPAddress = nic.IPAddress req.IPAddress = nic.IPAddress
} }
for i := range vm.Tags {
req.Tags = append(req.Tags, vm.Tags[i])
}
return req, nil return req, nil
} }
// DefaultNic returns the default nic // DefaultNic returns the default nic
func (vm VirtualMachine) DefaultNic() *Nic { func (vm VirtualMachine) DefaultNic() *Nic {
for _, nic := range vm.Nic { for i, nic := range vm.Nic {
if nic.IsDefault { if nic.IsDefault {
return &nic return &vm.Nic[i]
} }
} }
@ -171,8 +170,9 @@ func (vm VirtualMachine) NicsByType(nicType string) []Nic {
for _, nic := range vm.Nic { for _, nic := range vm.Nic {
if nic.Type == nicType { if nic.Type == nicType {
// XXX The API forgets to specify it // XXX The API forgets to specify it
nic.VirtualMachineID = vm.ID n := nic
nics = append(nics, nic) n.VirtualMachineID = vm.ID
nics = append(nics, n)
} }
} }
return nics return nics
@ -184,8 +184,9 @@ func (vm VirtualMachine) NicsByType(nicType string) []Nic {
func (vm VirtualMachine) NicByNetworkID(networkID UUID) *Nic { func (vm VirtualMachine) NicByNetworkID(networkID UUID) *Nic {
for _, nic := range vm.Nic { for _, nic := range vm.Nic {
if nic.NetworkID.Equal(networkID) { if nic.NetworkID.Equal(networkID) {
nic.VirtualMachineID = vm.ID n := nic
return &nic n.VirtualMachineID = vm.ID
return &n
} }
} }
return nil return nil
@ -195,8 +196,9 @@ func (vm VirtualMachine) NicByNetworkID(networkID UUID) *Nic {
func (vm VirtualMachine) NicByID(nicID UUID) *Nic { func (vm VirtualMachine) NicByID(nicID UUID) *Nic {
for _, nic := range vm.Nic { for _, nic := range vm.Nic {
if nic.ID.Equal(nicID) { if nic.ID.Equal(nicID) {
nic.VirtualMachineID = vm.ID n := nic
return &nic n.VirtualMachineID = vm.ID
return &n
} }
} }
@ -213,10 +215,10 @@ type IPToNetwork struct {
// PCIDevice represents a PCI card present in the host // PCIDevice represents a PCI card present in the host
type PCIDevice struct { type PCIDevice struct {
PCIVendorName string `json:"pcivendorname,omitempty" doc:"Device vendor name of pci card"` PCIVendorName string `json:"pcivendorname,omitempty" doc:"Device vendor name of pci card"`
DeviceID *UUID `json:"deviceid,omitempty" doc:"Device model ID of pci card"` DeviceID string `json:"deviceid,omitempty" doc:"Device model ID of pci card"`
RemainingCapacity int `json:"remainingcapacity,omitempty" doc:"Remaining capacity in terms of no. of more VMs that can be deployped with this vGPU type"` RemainingCapacity int `json:"remainingcapacity,omitempty" doc:"Remaining capacity in terms of no. of more VMs that can be deployped with this vGPU type"`
MaxCapacity int `json:"maxcapacity,omitempty" doc:"Maximum vgpu can be created with this vgpu type on the given pci group"` MaxCapacity int `json:"maxcapacity,omitempty" doc:"Maximum vgpu can be created with this vgpu type on the given pci group"`
PCIVendorID *UUID `json:"pcivendorid,omitempty" doc:"Device vendor ID of pci card"` PCIVendorID string `json:"pcivendorid,omitempty" doc:"Device vendor ID of pci card"`
PCIDeviceName string `json:"pcidevicename,omitempty" doc:"Device model name of pci card"` PCIDeviceName string `json:"pcidevicename,omitempty" doc:"Device model name of pci card"`
} }
@ -229,8 +231,8 @@ type Password struct {
// VirtualMachineUserData represents the base64 encoded user-data // VirtualMachineUserData represents the base64 encoded user-data
type VirtualMachineUserData struct { type VirtualMachineUserData struct {
UserData string `json:"userdata,omitempty" doc:"Base 64 encoded VM user data"` UserData string `json:"userdata" doc:"Base 64 encoded VM user data"`
VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the virtual machine"` VirtualMachineID *UUID `json:"virtualmachineid" doc:"the ID of the virtual machine"`
} }
// Decode decodes as a readable string the content of the user-data (base64 · gzip) // Decode decodes as a readable string the content of the user-data (base64 · gzip)
@ -260,24 +262,16 @@ func (userdata VirtualMachineUserData) Decode() (string, error) {
// //
// Regarding the UserData field, the client is responsible to base64 (and probably gzip) it. Doing it within this library would make the integration with other tools, e.g. Terraform harder. // Regarding the UserData field, the client is responsible to base64 (and probably gzip) it. Doing it within this library would make the integration with other tools, e.g. Terraform harder.
type DeployVirtualMachine struct { type DeployVirtualMachine struct {
Account string `json:"account,omitempty" doc:"an optional account for the virtual machine. Must be used with domainId."`
AffinityGroupIDs []UUID `json:"affinitygroupids,omitempty" doc:"comma separated list of affinity groups id that are going to be applied to the virtual machine. Mutually exclusive with affinitygroupnames parameter"` AffinityGroupIDs []UUID `json:"affinitygroupids,omitempty" doc:"comma separated list of affinity groups id that are going to be applied to the virtual machine. Mutually exclusive with affinitygroupnames parameter"`
AffinityGroupNames []string `json:"affinitygroupnames,omitempty" doc:"comma separated list of affinity groups names that are going to be applied to the virtual machine.Mutually exclusive with affinitygroupids parameter"` AffinityGroupNames []string `json:"affinitygroupnames,omitempty" doc:"comma separated list of affinity groups names that are going to be applied to the virtual machine.Mutually exclusive with affinitygroupids parameter"`
CustomID *UUID `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"`
DeploymentPlanner string `json:"deploymentplanner,omitempty" doc:"Deployment planner to use for vm allocation. Available to ROOT admin only"`
Details map[string]string `json:"details,omitempty" doc:"used to specify the custom parameters."` Details map[string]string `json:"details,omitempty" doc:"used to specify the custom parameters."`
DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"the ID of the disk offering for the virtual machine. If the template is of ISO format, the diskOfferingId is for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk volume. If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk Volume created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT Disk Volume created."` DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"the ID of the disk offering for the virtual machine. If the template is of ISO format, the diskofferingid is for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk volume. If the templateid parameter passed is from a Template object, the diskofferingid refers to a DATA Disk Volume created. If the templateid parameter passed is from an ISO object, the diskofferingid refers to a ROOT Disk Volume created."`
DisplayName string `json:"displayname,omitempty" doc:"an optional user generated name for the virtual machine"` DisplayName string `json:"displayname,omitempty" doc:"an optional user generated name for the virtual machine"`
DisplayVM *bool `json:"displayvm,omitempty" doc:"an optional field, whether to the display the vm to the end user or not."`
DomainID *UUID `json:"domainid,omitempty" doc:"an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used."`
Group string `json:"group,omitempty" doc:"an optional group for the virtual machine"` Group string `json:"group,omitempty" doc:"an optional group for the virtual machine"`
HostID *UUID `json:"hostid,omitempty" doc:"destination Host ID to deploy the VM to - parameter available for root admin only"`
Hypervisor string `json:"hypervisor,omitempty" doc:"the hypervisor on which to deploy the virtual machine"`
IP4 *bool `json:"ip4,omitempty" doc:"True to set an IPv4 to the default interface"` IP4 *bool `json:"ip4,omitempty" doc:"True to set an IPv4 to the default interface"`
IP6 *bool `json:"ip6,omitempty" doc:"True to set an IPv6 to the default interface"` IP6 *bool `json:"ip6,omitempty" doc:"True to set an IPv6 to the default interface"`
IP6Address net.IP `json:"ip6address,omitempty" doc:"the ipv6 address for default vm's network"` IP6Address net.IP `json:"ip6address,omitempty" doc:"the ipv6 address for default vm's network"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"the ip address for default vm's network"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"the ip address for default vm's network"`
IPToNetworkList []IPToNetwork `json:"iptonetworklist,omitempty" doc:"ip to network mapping. Can't be specified with networkIds parameter. Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].ipv6=fc00:1234:5678::abcd&iptonetworklist[0].networkid=uuid - requests to use ip 10.10.10.11 in network id=uuid"`
Keyboard string `json:"keyboard,omitempty" doc:"an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us"` Keyboard string `json:"keyboard,omitempty" doc:"an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us"`
KeyPair string `json:"keypair,omitempty" doc:"name of the ssh key pair used to login to the virtual machine"` KeyPair string `json:"keypair,omitempty" doc:"name of the ssh key pair used to login to the virtual machine"`
Name string `json:"name,omitempty" doc:"host name for the virtual machine"` Name string `json:"name,omitempty" doc:"host name for the virtual machine"`
@ -286,7 +280,7 @@ type DeployVirtualMachine struct {
SecurityGroupIDs []UUID `json:"securitygroupids,omitempty" doc:"comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter"` SecurityGroupIDs []UUID `json:"securitygroupids,omitempty" doc:"comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter"`
SecurityGroupNames []string `json:"securitygroupnames,omitempty" doc:"comma separated list of security groups names that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter"` SecurityGroupNames []string `json:"securitygroupnames,omitempty" doc:"comma separated list of security groups names that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter"`
ServiceOfferingID *UUID `json:"serviceofferingid" doc:"the ID of the service offering for the virtual machine"` ServiceOfferingID *UUID `json:"serviceofferingid" doc:"the ID of the service offering for the virtual machine"`
Size int64 `json:"size,omitempty" doc:"the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId"` Size int64 `json:"size,omitempty" doc:"the arbitrary size for the DATADISK volume. Mutually exclusive with diskofferingid"`
StartVM *bool `json:"startvm,omitempty" doc:"true if start vm after creating. Default value is true"` StartVM *bool `json:"startvm,omitempty" doc:"true if start vm after creating. Default value is true"`
TemplateID *UUID `json:"templateid" doc:"the ID of the template for the virtual machine"` TemplateID *UUID `json:"templateid" doc:"the ID of the template for the virtual machine"`
UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."` UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."`
@ -294,7 +288,7 @@ type DeployVirtualMachine struct {
_ bool `name:"deployVirtualMachine" description:"Creates and automatically starts a virtual machine based on a service offering, disk offering, and template."` _ bool `name:"deployVirtualMachine" description:"Creates and automatically starts a virtual machine based on a service offering, disk offering, and template."`
} }
func (req DeployVirtualMachine) onBeforeSend(params url.Values) error { func (req DeployVirtualMachine) onBeforeSend(_ url.Values) error {
// Either AffinityGroupIDs or AffinityGroupNames must be set // Either AffinityGroupIDs or AffinityGroupNames must be set
if len(req.AffinityGroupIDs) > 0 && len(req.AffinityGroupNames) > 0 { if len(req.AffinityGroupIDs) > 0 && len(req.AffinityGroupNames) > 0 {
return fmt.Errorf("either AffinityGroupIDs or AffinityGroupNames must be set") return fmt.Errorf("either AffinityGroupIDs or AffinityGroupNames must be set")
@ -308,27 +302,29 @@ func (req DeployVirtualMachine) onBeforeSend(params url.Values) error {
return nil return nil
} }
func (DeployVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (DeployVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DeployVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (DeployVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
// StartVirtualMachine (Async) represents the creation of the virtual machine // StartVirtualMachine (Async) represents the creation of the virtual machine
type StartVirtualMachine struct { type StartVirtualMachine struct {
ID *UUID `json:"id" doc:"The ID of the virtual machine"` ID *UUID `json:"id" doc:"The ID of the virtual machine"`
DeploymentPlanner string `json:"deploymentplanner,omitempty" doc:"Deployment planner to use for vm allocation. Available to ROOT admin only"` _ bool `name:"startVirtualMachine" description:"Starts a virtual machine."`
HostID *UUID `json:"hostid,omitempty" doc:"destination Host ID to deploy the VM to - parameter available for root admin only"`
_ bool `name:"startVirtualMachine" description:"Starts a virtual machine."`
} }
func (StartVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (StartVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (StartVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (StartVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -339,11 +335,13 @@ type StopVirtualMachine struct {
_ bool `name:"stopVirtualMachine" description:"Stops a virtual machine."` _ bool `name:"stopVirtualMachine" description:"Stops a virtual machine."`
} }
func (StopVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (StopVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (StopVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (StopVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -353,11 +351,13 @@ type RebootVirtualMachine struct {
_ bool `name:"rebootVirtualMachine" description:"Reboots a virtual machine."` _ bool `name:"rebootVirtualMachine" description:"Reboots a virtual machine."`
} }
func (RebootVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (RebootVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RebootVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (RebootVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -369,11 +369,13 @@ type RestoreVirtualMachine struct {
_ bool `name:"restoreVirtualMachine" description:"Restore a VM to original template/ISO or new template/ISO"` _ bool `name:"restoreVirtualMachine" description:"Restore a VM to original template/ISO or new template/ISO"`
} }
func (RestoreVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (RestoreVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RestoreVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (RestoreVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -383,42 +385,41 @@ type RecoverVirtualMachine struct {
_ bool `name:"recoverVirtualMachine" description:"Recovers a virtual machine."` _ bool `name:"recoverVirtualMachine" description:"Recovers a virtual machine."`
} }
func (RecoverVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (RecoverVirtualMachine) Response() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
// DestroyVirtualMachine (Async) represents the destruction of the virtual machine // DestroyVirtualMachine (Async) represents the destruction of the virtual machine
type DestroyVirtualMachine struct { type DestroyVirtualMachine struct {
ID *UUID `json:"id" doc:"The ID of the virtual machine"` ID *UUID `json:"id" doc:"The ID of the virtual machine"`
Expunge *bool `json:"expunge,omitempty" doc:"If true is passed, the vm is expunged immediately. False by default."` _ bool `name:"destroyVirtualMachine" description:"Destroys a virtual machine."`
_ bool `name:"destroyVirtualMachine" description:"Destroys a virtual machine."`
} }
func (DestroyVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (DestroyVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (DestroyVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (DestroyVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
// UpdateVirtualMachine represents the update of the virtual machine // UpdateVirtualMachine represents the update of the virtual machine
type UpdateVirtualMachine struct { type UpdateVirtualMachine struct {
ID *UUID `json:"id" doc:"The ID of the virtual machine"` ID *UUID `json:"id" doc:"The ID of the virtual machine"`
CustomID *UUID `json:"customid,omitempty" doc:"an optional field, in case you want to set a custom id to the resource. Allowed to Root Admins only"` Details map[string]string `json:"details,omitempty" doc:"Details in key/value pairs."`
Details map[string]string `json:"details,omitempty" doc:"Details in key/value pairs."` DisplayName string `json:"displayname,omitempty" doc:"user generated name"`
DisplayName string `json:"displayname,omitempty" doc:"user generated name"` Group string `json:"group,omitempty" doc:"group of the virtual machine"`
DisplayVM *bool `json:"displayvm,omitempty" doc:"an optional field, whether to the display the vm to the end user or not."` Name string `json:"name,omitempty" doc:"new host name of the vm. The VM has to be stopped/started for this update to take affect"`
Group string `json:"group,omitempty" doc:"group of the virtual machine"` SecurityGroupIDs []UUID `json:"securitygroupids,omitempty" doc:"list of security group ids to be applied on the virtual machine."`
HAEnable *bool `json:"haenable,omitempty" doc:"true if high-availability is enabled for the virtual machine, false otherwise"` UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."`
IsDynamicallyScalable *bool `json:"isdynamicallyscalable,omitempty" doc:"true if VM contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory"` _ bool `name:"updateVirtualMachine" description:"Updates properties of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. Therefore, stop the VM manually before issuing this call."`
Name string `json:"name,omitempty" doc:"new host name of the vm. The VM has to be stopped/started for this update to take affect"`
SecurityGroupIDs []UUID `json:"securitygroupids,omitempty" doc:"list of security group ids to be applied on the virtual machine."`
UserData string `json:"userdata,omitempty" doc:"an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 2KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 32K of data after base64 encoding."`
_ bool `name:"updateVirtualMachine" description:"Updates properties of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. Therefore, stop the VM manually before issuing this call."`
} }
func (UpdateVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (UpdateVirtualMachine) Response() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -428,12 +429,14 @@ type ExpungeVirtualMachine struct {
_ bool `name:"expungeVirtualMachine" description:"Expunge a virtual machine. Once expunged, it cannot be recoverd."` _ bool `name:"expungeVirtualMachine" description:"Expunge a virtual machine. Once expunged, it cannot be recoverd."`
} }
func (ExpungeVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (ExpungeVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (ExpungeVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (ExpungeVirtualMachine) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// ScaleVirtualMachine (Async) scales the virtual machine to a new service offering. // ScaleVirtualMachine (Async) scales the virtual machine to a new service offering.
@ -447,12 +450,14 @@ type ScaleVirtualMachine struct {
_ bool `name:"scaleVirtualMachine" description:"Scales the virtual machine to a new service offering."` _ bool `name:"scaleVirtualMachine" description:"Scales the virtual machine to a new service offering."`
} }
func (ScaleVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (ScaleVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (ScaleVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
return new(booleanResponse) func (ScaleVirtualMachine) AsyncResponse() interface{} {
return new(BooleanResponse)
} }
// ChangeServiceForVirtualMachine changes the service offering for a virtual machine. The virtual machine must be in a "Stopped" state for this command to take effect. // ChangeServiceForVirtualMachine changes the service offering for a virtual machine. The virtual machine must be in a "Stopped" state for this command to take effect.
@ -463,7 +468,8 @@ type ChangeServiceForVirtualMachine struct {
_ bool `name:"changeServiceForVirtualMachine" description:"Changes the service offering for a virtual machine. The virtual machine must be in a \"Stopped\" state for this command to take effect."` _ bool `name:"changeServiceForVirtualMachine" description:"Changes the service offering for a virtual machine. The virtual machine must be in a \"Stopped\" state for this command to take effect."`
} }
func (ChangeServiceForVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (ChangeServiceForVirtualMachine) Response() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -473,10 +479,13 @@ type ResetPasswordForVirtualMachine struct {
_ bool `name:"resetPasswordForVirtualMachine" description:"Resets the password for virtual machine. The virtual machine must be in a \"Stopped\" state and the template must already support this feature for this command to take effect."` _ bool `name:"resetPasswordForVirtualMachine" description:"Resets the password for virtual machine. The virtual machine must be in a \"Stopped\" state and the template must already support this feature for this command to take effect."`
} }
func (ResetPasswordForVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (ResetPasswordForVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (ResetPasswordForVirtualMachine) asyncResponse() interface{} {
// AsyncResponse returns the struct to unmarshal the async job
func (ResetPasswordForVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -486,28 +495,24 @@ type GetVMPassword struct {
_ bool `name:"getVMPassword" description:"Returns an encrypted password for the VM"` _ bool `name:"getVMPassword" description:"Returns an encrypted password for the VM"`
} }
func (GetVMPassword) response() interface{} { // Response returns the struct to unmarshal
func (GetVMPassword) Response() interface{} {
return new(Password) return new(Password)
} }
//go:generate go run generate/main.go -interface=Listable ListVirtualMachines
// ListVirtualMachines represents a search for a VM // ListVirtualMachines represents a search for a VM
type ListVirtualMachines struct { type ListVirtualMachines struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
AffinityGroupID *UUID `json:"affinitygroupid,omitempty" doc:"list vms by affinity group"` AffinityGroupID *UUID `json:"affinitygroupid,omitempty" doc:"list vms by affinity group"`
Details []string `json:"details,omitempty" doc:"comma separated list of host details requested, value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, diskoff, iso, volume, min, affgrp]. If no parameter is passed in, the details will be defaulted to all"` Details []string `json:"details,omitempty" doc:"comma separated list of host details requested, value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, diskoff, iso, volume, min, affgrp]. If no parameter is passed in, the details will be defaulted to all"`
DisplayVM *bool `json:"displayvm,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"list by network type; true if need to list vms using Virtual Network, false otherwise"` ForVirtualNetwork *bool `json:"forvirtualnetwork,omitempty" doc:"list by network type; true if need to list vms using Virtual Network, false otherwise"`
GroupID *UUID `json:"groupid,omitempty" doc:"the group ID"` GroupID *UUID `json:"groupid,omitempty" doc:"the group ID"`
HostID *UUID `json:"hostid,omitempty" doc:"the host ID"`
Hypervisor string `json:"hypervisor,omitempty" doc:"the target hypervisor for the template"`
ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"` ID *UUID `json:"id,omitempty" doc:"the ID of the virtual machine"`
IDs []string `json:"ids,omitempty" doc:"the IDs of the virtual machines, mutually exclusive with id"` IDs []string `json:"ids,omitempty" doc:"the IDs of the virtual machines, mutually exclusive with id"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"an IP address to filter the result"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"an IP address to filter the result"`
IsoID *UUID `json:"isoid,omitempty" doc:"list vms by iso"` IsoID *UUID `json:"isoid,omitempty" doc:"list vms by iso"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Name string `json:"name,omitempty" doc:"name of the virtual machine"` Name string `json:"name,omitempty" doc:"name of the virtual machine"`
NetworkID *UUID `json:"networkid,omitempty" doc:"list by network id"` NetworkID *UUID `json:"networkid,omitempty" doc:"list by network id"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
@ -526,47 +531,21 @@ type ListVirtualMachinesResponse struct {
VirtualMachine []VirtualMachine `json:"virtualmachine"` VirtualMachine []VirtualMachine `json:"virtualmachine"`
} }
func (ListVirtualMachines) response() interface{} {
return new(ListVirtualMachinesResponse)
}
// SetPage sets the current page
func (ls *ListVirtualMachines) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListVirtualMachines) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListVirtualMachines) each(resp interface{}, callback IterateItemFunc) {
vms, ok := resp.(*ListVirtualMachinesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListVirtualMachinesResponse expected, got %T", resp))
return
}
for i := range vms.VirtualMachine {
if !callback(&vms.VirtualMachine[i], nil) {
break
}
}
}
// AddNicToVirtualMachine (Async) adds a NIC to a VM // AddNicToVirtualMachine (Async) adds a NIC to a VM
type AddNicToVirtualMachine struct { type AddNicToVirtualMachine struct {
NetworkID *UUID `json:"networkid" doc:"Network ID"` NetworkID *UUID `json:"networkid" doc:"Network ID"`
VirtualMachineID *UUID `json:"virtualmachineid" doc:"Virtual Machine ID"` VirtualMachineID *UUID `json:"virtualmachineid" doc:"Virtual Machine ID"`
IPAddress net.IP `json:"ipaddress,omitempty" doc:"IP Address for the new network"` IPAddress net.IP `json:"ipaddress,omitempty" doc:"Static IP address lease for the corresponding NIC and network which should be in the range defined in the network"`
_ bool `name:"addNicToVirtualMachine" description:"Adds VM to specified network by creating a NIC"` _ bool `name:"addNicToVirtualMachine" description:"Adds VM to specified network by creating a NIC"`
} }
func (AddNicToVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (AddNicToVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (AddNicToVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (AddNicToVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -577,11 +556,13 @@ type RemoveNicFromVirtualMachine struct {
_ bool `name:"removeNicFromVirtualMachine" description:"Removes VM from specified network by deleting a NIC"` _ bool `name:"removeNicFromVirtualMachine" description:"Removes VM from specified network by deleting a NIC"`
} }
func (RemoveNicFromVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (RemoveNicFromVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (RemoveNicFromVirtualMachine) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (RemoveNicFromVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -592,10 +573,13 @@ type UpdateDefaultNicForVirtualMachine struct {
_ bool `name:"updateDefaultNicForVirtualMachine" description:"Changes the default NIC on a VM"` _ bool `name:"updateDefaultNicForVirtualMachine" description:"Changes the default NIC on a VM"`
} }
func (UpdateDefaultNicForVirtualMachine) response() interface{} { // Response returns the struct to unmarshal
func (UpdateDefaultNicForVirtualMachine) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (UpdateDefaultNicForVirtualMachine) asyncResponse() interface{} {
// AsyncResponse returns the struct to unmarshal the async job
func (UpdateDefaultNicForVirtualMachine) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }
@ -605,35 +589,24 @@ type GetVirtualMachineUserData struct {
_ bool `name:"getVirtualMachineUserData" description:"Returns user data associated with the VM"` _ bool `name:"getVirtualMachineUserData" description:"Returns user data associated with the VM"`
} }
func (GetVirtualMachineUserData) response() interface{} { // Response returns the struct to unmarshal
func (GetVirtualMachineUserData) Response() interface{} {
return new(VirtualMachineUserData) return new(VirtualMachineUserData)
} }
// Decode decodes the base64 / gzipped encoded user data
// MigrateVirtualMachine (Async) attempts migration of a VM to a different host or Root volume of the vm to a different storage pool
type MigrateVirtualMachine struct {
HostID *UUID `json:"hostid,omitempty" doc:"Destination Host ID to migrate VM to. Required for live migrating a VM from host to host"`
StorageID *UUID `json:"storageid,omitempty" doc:"Destination storage pool ID to migrate VM volumes to. Required for migrating the root disk volume"`
VirtualMachineID *UUID `json:"virtualmachineid" doc:"the ID of the virtual machine"`
_ bool `name:"migrateVirtualMachine" description:"Attempts Migration of a VM to a different host or Root volume of the vm to a different storage pool"`
}
func (MigrateVirtualMachine) response() interface{} {
return new(AsyncJobResult)
}
func (MigrateVirtualMachine) asyncResponse() interface{} {
return new(VirtualMachine)
}
// UpdateVMNicIP updates the default IP address of a VM Nic // UpdateVMNicIP updates the default IP address of a VM Nic
type UpdateVMNicIP struct { type UpdateVMNicIP struct {
_ bool `name:"updateVmNicIp" description:"Update the default Ip of a VM Nic"` _ bool `name:"updateVmNicIp" description:"Update the default Ip of a VM Nic"`
IPAddress net.IP `json:"ipaddress" doc:"Static IP address lease for the corresponding NIC and network which should be in the range defined in the network. Also, the last IP of the network is reserved by the DHCP server."` IPAddress net.IP `json:"ipaddress,omitempty" doc:"Static IP address lease for the corresponding NIC and network which should be in the range defined in the network. If absent, the call removes the lease associated with the nic."`
NicID *UUID `json:"nicid" doc:"the ID of the nic."` NicID *UUID `json:"nicid" doc:"the ID of the nic."`
} }
func (UpdateVMNicIP) response() interface{} { // Response returns the struct to unmarshal
func (UpdateVMNicIP) Response() interface{} {
return new(AsyncJobResult)
}
// AsyncResponse returns the struct to unmarshal the async job
func (UpdateVMNicIP) AsyncResponse() interface{} {
return new(VirtualMachine) return new(VirtualMachine)
} }

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListVirtualMachines) Response() interface{} {
return new(ListVirtualMachinesResponse)
}
// ListRequest returns itself
func (ls *ListVirtualMachines) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListVirtualMachines) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListVirtualMachines) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListVirtualMachines) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListVirtualMachinesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListVirtualMachinesResponse was expected, got %T", resp))
return
}
for i := range items.VirtualMachine {
if !callback(&items.VirtualMachine[i], nil) {
break
}
}
}

View file

@ -1,68 +0,0 @@
package egoscale
// InstanceGroup represents a group of VM
type InstanceGroup struct {
Account string `json:"account,omitempty" doc:"the account owning the instance group"`
Created string `json:"created,omitempty" doc:"time and date the instance group was created"`
Domain string `json:"domain,omitempty" doc:"the domain name of the instance group"`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of the instance group"`
ID *UUID `json:"id,omitempty" doc:"the id of the instance group"`
Name string `json:"name,omitempty" doc:"the name of the instance group"`
}
// CreateInstanceGroup creates a VM group
type CreateInstanceGroup struct {
Name string `json:"name" doc:"the name of the instance group"`
Account string `json:"account,omitempty" doc:"the account of the instance group. The account parameter must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"the domain ID of account owning the instance group"`
_ bool `name:"createInstanceGroup" description:"Creates a vm group"`
}
func (CreateInstanceGroup) response() interface{} {
return new(InstanceGroup)
}
// UpdateInstanceGroup updates a VM group
type UpdateInstanceGroup struct {
ID *UUID `json:"id" doc:"Instance group ID"`
Name string `json:"name,omitempty" doc:"new instance group name"`
_ bool `name:"updateInstanceGroup" description:"Updates a vm group"`
}
func (UpdateInstanceGroup) response() interface{} {
return new(InstanceGroup)
}
// DeleteInstanceGroup deletes a VM group
type DeleteInstanceGroup struct {
ID *UUID `json:"id" doc:"the ID of the instance group"`
_ bool `name:"deleteInstanceGroup" description:"Deletes a vm group"`
}
func (DeleteInstanceGroup) response() interface{} {
return new(booleanResponse)
}
// ListInstanceGroups lists VM groups
type ListInstanceGroups struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
ID *UUID `json:"id,omitempty" doc:"list instance groups by ID"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"`
Name string `json:"name,omitempty" doc:"list instance groups by name"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
_ bool `name:"listInstanceGroups" description:"Lists vm groups"`
}
// ListInstanceGroupsResponse represents a list of instance groups
type ListInstanceGroupsResponse struct {
Count int `json:"count"`
InstanceGroup []InstanceGroup `json:"instancegroup"`
}
func (ListInstanceGroups) response() interface{} {
return new(ListInstanceGroupsResponse)
}

View file

@ -1,9 +1,5 @@
package egoscale package egoscale
import (
"fmt"
)
// Volume represents a volume linked to a VM // Volume represents a volume linked to a VM
type Volume struct { type Volume struct {
Account string `json:"account,omitempty" doc:"the account associated with the disk volume"` Account string `json:"account,omitempty" doc:"the account associated with the disk volume"`
@ -22,8 +18,6 @@ type Volume struct {
DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"ID of the disk offering"` DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"ID of the disk offering"`
DiskOfferingName string `json:"diskofferingname,omitempty" doc:"name of the disk offering"` DiskOfferingName string `json:"diskofferingname,omitempty" doc:"name of the disk offering"`
DisplayVolume bool `json:"displayvolume,omitempty" doc:"an optional field whether to the display the volume to the end user or not."` DisplayVolume bool `json:"displayvolume,omitempty" doc:"an optional field whether to the display the volume to the end user or not."`
Domain string `json:"domain,omitempty" doc:"the domain associated with the disk volume"`
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain associated with the disk volume"`
Hypervisor string `json:"hypervisor,omitempty" doc:"Hypervisor the volume belongs to"` Hypervisor string `json:"hypervisor,omitempty" doc:"Hypervisor the volume belongs to"`
ID *UUID `json:"id,omitempty" doc:"ID of the disk volume"` ID *UUID `json:"id,omitempty" doc:"ID of the disk volume"`
IsExtractable *bool `json:"isextractable,omitempty" doc:"true if the volume is extractable, false otherwise"` IsExtractable *bool `json:"isextractable,omitempty" doc:"true if the volume is extractable, false otherwise"`
@ -49,7 +43,7 @@ type Volume struct {
StorageType string `json:"storagetype,omitempty" doc:"shared or local storage"` StorageType string `json:"storagetype,omitempty" doc:"shared or local storage"`
Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with volume"` Tags []ResourceTag `json:"tags,omitempty" doc:"the list of resource tags associated with volume"`
TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"` TemplateDisplayText string `json:"templatedisplaytext,omitempty" doc:"an alternate display text of the template for the virtual machine"`
TemplateID string `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."` // no *UUID because of the -1 thingy... TemplateID *UUID `json:"templateid,omitempty" doc:"the ID of the template for the virtual machine. A -1 is returned if the virtual machine was created from an ISO file."` // no *UUID because of the -1 thingy...
TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"` TemplateName string `json:"templatename,omitempty" doc:"the name of the template for the virtual machine"`
Type string `json:"type,omitempty" doc:"type of the disk volume (ROOT or DATADISK)"` Type string `json:"type,omitempty" doc:"type of the disk volume (ROOT or DATADISK)"`
VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"id of the virtual machine"` VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"id of the virtual machine"`
@ -68,8 +62,6 @@ func (Volume) ResourceType() string {
// ListRequest builds the ListVolumes request // ListRequest builds the ListVolumes request
func (vol Volume) ListRequest() (ListCommand, error) { func (vol Volume) ListRequest() (ListCommand, error) {
req := &ListVolumes{ req := &ListVolumes{
Account: vol.Account,
DomainID: vol.DomainID,
Name: vol.Name, Name: vol.Name,
Type: vol.Type, Type: vol.Type,
VirtualMachineID: vol.VirtualMachineID, VirtualMachineID: vol.VirtualMachineID,
@ -83,39 +75,34 @@ func (vol Volume) ListRequest() (ListCommand, error) {
type ResizeVolume struct { type ResizeVolume struct {
ID *UUID `json:"id" doc:"the ID of the disk volume"` ID *UUID `json:"id" doc:"the ID of the disk volume"`
DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"new disk offering id"` DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"new disk offering id"`
ShrinkOk *bool `json:"shrinkok,omitempty" doc:"Verify OK to Shrink"` Size int64 `json:"size,omitempty" doc:"New volume size in G (must be larger than current size since shrinking the disk is not supported)"`
Size int64 `json:"size,omitempty" doc:"New volume size in G"`
_ bool `name:"resizeVolume" description:"Resizes a volume"` _ bool `name:"resizeVolume" description:"Resizes a volume"`
} }
func (ResizeVolume) response() interface{} { // Response returns the struct to unmarshal
func (ResizeVolume) Response() interface{} {
return new(AsyncJobResult) return new(AsyncJobResult)
} }
func (ResizeVolume) asyncResponse() interface{} { // AsyncResponse returns the struct to unmarshal the async job
func (ResizeVolume) AsyncResponse() interface{} {
return new(Volume) return new(Volume)
} }
//go:generate go run generate/main.go -interface=Listable ListVolumes
// ListVolumes represents a query listing volumes // ListVolumes represents a query listing volumes
type ListVolumes struct { type ListVolumes struct {
Account string `json:"account,omitempty" doc:"list resources by account. Must be used with the domainId parameter."` DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"List volumes by disk offering"`
DiskOfferingID *UUID `json:"diskofferingid,omitempty" doc:"list volumes by disk offering"` ID *UUID `json:"id,omitempty" doc:"The ID of the disk volume"`
DisplayVolume *bool `json:"displayvolume,omitempty" doc:"list resources by display flag; only ROOT admin is eligible to pass this parameter"`
DomainID *UUID `json:"domainid,omitempty" doc:"list only resources belonging to the domain specified"`
HostID *UUID `json:"hostid,omitempty" doc:"list volumes on specified host"`
ID *UUID `json:"id,omitempty" doc:"the ID of the disk volume"`
IsRecursive *bool `json:"isrecursive,omitempty" doc:"defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves."`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
ListAll *bool `json:"listall,omitempty" doc:"If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false"` Name string `json:"name,omitempty" doc:"The name of the disk volume"`
Name string `json:"name,omitempty" doc:"the name of the disk volume"`
Page int `json:"page,omitempty"` Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"` PageSize int `json:"pagesize,omitempty"`
PodID *UUID `json:"podid,omitempty" doc:"the pod id the disk volume belongs to"`
StorageID *UUID `json:"storageid,omitempty" doc:"the ID of the storage pool, available to ROOT admin only"`
Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"` Tags []ResourceTag `json:"tags,omitempty" doc:"List resources by tags (key/value pairs)"`
Type string `json:"type,omitempty" doc:"the type of disk volume"` Type string `json:"type,omitempty" doc:"The type of disk volume"`
VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"the ID of the virtual machine"` VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"The ID of the virtual machine"`
ZoneID *UUID `json:"zoneid,omitempty" doc:"the ID of the availability zone"` ZoneID *UUID `json:"zoneid,omitempty" doc:"The ID of the availability zone"`
_ bool `name:"listVolumes" description:"Lists all volumes."` _ bool `name:"listVolumes" description:"Lists all volumes."`
} }
@ -124,31 +111,3 @@ type ListVolumesResponse struct {
Count int `json:"count"` Count int `json:"count"`
Volume []Volume `json:"volume"` Volume []Volume `json:"volume"`
} }
func (ListVolumes) response() interface{} {
return new(ListVolumesResponse)
}
// SetPage sets the current page
func (ls *ListVolumes) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListVolumes) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListVolumes) each(resp interface{}, callback IterateItemFunc) {
volumes, ok := resp.(*ListVolumesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListVolumesResponse expected, got %T", resp))
return
}
for i := range volumes.Volume {
if !callback(&volumes.Volume[i], nil) {
break
}
}
}

View file

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListVolumes) Response() interface{} {
return new(ListVolumesResponse)
}
// ListRequest returns itself
func (ls *ListVolumes) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListVolumes) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListVolumes) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListVolumes) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListVolumesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListVolumesResponse was expected, got %T", resp))
return
}
for i := range items.Volume {
if !callback(&items.Volume[i], nil) {
break
}
}
}

View file

@ -1,7 +1,6 @@
package egoscale package egoscale
import ( import (
"fmt"
"net" "net"
) )
@ -15,9 +14,6 @@ type Zone struct {
DisplayText string `json:"displaytext,omitempty" doc:"the display text of the zone"` DisplayText string `json:"displaytext,omitempty" doc:"the display text of the zone"`
DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the Zone"` DNS1 net.IP `json:"dns1,omitempty" doc:"the first DNS for the Zone"`
DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the Zone"` DNS2 net.IP `json:"dns2,omitempty" doc:"the second DNS for the Zone"`
Domain string `json:"domain,omitempty" doc:"Network domain name for the networks in the zone"`
DomainID *UUID `json:"domainid,omitempty" doc:"the UUID of the containing domain, null for public zones"`
DomainName string `json:"domainname,omitempty" doc:"the name of the containing domain, null for public zones"`
GuestCIDRAddress *CIDR `json:"guestcidraddress,omitempty" doc:"the guest CIDR address for the Zone"` GuestCIDRAddress *CIDR `json:"guestcidraddress,omitempty" doc:"the guest CIDR address for the Zone"`
ID *UUID `json:"id,omitempty" doc:"Zone id"` ID *UUID `json:"id,omitempty" doc:"Zone id"`
InternalDNS1 net.IP `json:"internaldns1,omitempty" doc:"the first internal DNS for the Zone"` InternalDNS1 net.IP `json:"internaldns1,omitempty" doc:"the first internal DNS for the Zone"`
@ -37,18 +33,18 @@ type Zone struct {
// ListRequest builds the ListZones request // ListRequest builds the ListZones request
func (zone Zone) ListRequest() (ListCommand, error) { func (zone Zone) ListRequest() (ListCommand, error) {
req := &ListZones{ req := &ListZones{
DomainID: zone.DomainID, ID: zone.ID,
ID: zone.ID, Name: zone.Name,
Name: zone.Name,
} }
return req, nil return req, nil
} }
//go:generate go run generate/main.go -interface=Listable ListZones
// ListZones represents a query for zones // ListZones represents a query for zones
type ListZones struct { type ListZones struct {
Available *bool `json:"available,omitempty" doc:"true if you want to retrieve all available Zones. False if you only want to return the Zones from which you have at least one VM. Default is false."` Available *bool `json:"available,omitempty" doc:"true if you want to retrieve all available Zones. False if you only want to return the Zones from which you have at least one VM. Default is false."`
DomainID *UUID `json:"domainid,omitempty" doc:"the ID of the domain associated with the zone"`
ID *UUID `json:"id,omitempty" doc:"the ID of the zone"` ID *UUID `json:"id,omitempty" doc:"the ID of the zone"`
Keyword string `json:"keyword,omitempty" doc:"List by keyword"` Keyword string `json:"keyword,omitempty" doc:"List by keyword"`
Name string `json:"name,omitempty" doc:"the name of the zone"` Name string `json:"name,omitempty" doc:"the name of the zone"`
@ -64,31 +60,3 @@ type ListZonesResponse struct {
Count int `json:"count"` Count int `json:"count"`
Zone []Zone `json:"zone"` Zone []Zone `json:"zone"`
} }
func (ListZones) response() interface{} {
return new(ListZonesResponse)
}
// SetPage sets the current page
func (ls *ListZones) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListZones) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
func (ListZones) each(resp interface{}, callback IterateItemFunc) {
zones, ok := resp.(*ListZonesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type. ListZonesResponse was expected, got %T", resp))
return
}
for i := range zones.Zone {
if !callback(&zones.Zone[i], nil) {
break
}
}
}

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

@ -0,0 +1,43 @@
// code generated; DO NOT EDIT.
package egoscale
import "fmt"
// Response returns the struct to unmarshal
func (ListZones) Response() interface{} {
return new(ListZonesResponse)
}
// ListRequest returns itself
func (ls *ListZones) ListRequest() (ListCommand, error) {
if ls == nil {
return nil, fmt.Errorf("%T cannot be nil", ls)
}
return ls, nil
}
// SetPage sets the current apge
func (ls *ListZones) SetPage(page int) {
ls.Page = page
}
// SetPageSize sets the page size
func (ls *ListZones) SetPageSize(pageSize int) {
ls.PageSize = pageSize
}
// Each triggers the callback for each, valid answer or any non 404 issue
func (ListZones) Each(resp interface{}, callback IterateItemFunc) {
items, ok := resp.(*ListZonesResponse)
if !ok {
callback(nil, fmt.Errorf("wrong type, ListZonesResponse was expected, got %T", resp))
return
}
for i := range items.Zone {
if !callback(&items.Zone[i], nil) {
break
}
}
}