mirror of https://github.com/k3s-io/k3s
Vendor/Godep updates
parent
eb32bf55ef
commit
bb1ae12906
|
@ -1615,133 +1615,158 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud",
|
"ImportPath": "github.com/rackspace/gophercloud",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/flavors",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/flavors",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/images",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/images",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/servers",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/compute/v2/servers",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tenants",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tenants",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tokens",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v2/tokens",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/tokens",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/identity/v3/tokens",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
|
||||||
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
|
||||||
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
|
||||||
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
|
||||||
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/networking/v2/ports",
|
||||||
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/openstack/utils",
|
"ImportPath": "github.com/rackspace/gophercloud/openstack/utils",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/pagination",
|
"ImportPath": "github.com/rackspace/gophercloud/pagination",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/rackspace",
|
"ImportPath": "github.com/rackspace/gophercloud/rackspace",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes",
|
"ImportPath": "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/rackspace/compute/v2/servers",
|
"ImportPath": "github.com/rackspace/gophercloud/rackspace/compute/v2/servers",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach",
|
"ImportPath": "github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens",
|
"ImportPath": "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/testhelper",
|
"ImportPath": "github.com/rackspace/gophercloud/testhelper",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/rackspace/gophercloud/testhelper/client",
|
"ImportPath": "github.com/rackspace/gophercloud/testhelper/client",
|
||||||
"Comment": "v1.0.0-842-g8992d74",
|
"Comment": "v1.0.0-920-g934dbf8",
|
||||||
"Rev": "8992d7483a06748dea706e4716d042a4a9e73918"
|
"Rev": "934dbf81977c67c521c75492dc1f55ca74dc5b04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/robfig/cron",
|
"ImportPath": "github.com/robfig/cron",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
0
vendor/github.com/coreos/go-oidc/jose/sig_hmac.go
generated
vendored
Normal file → Executable file
0
vendor/github.com/coreos/go-oidc/jose/sig_hmac.go
generated
vendored
Normal file → Executable file
0
vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py
generated
vendored
Normal file → Executable file
0
vendor/github.com/hashicorp/go-msgpack/codec/msgpack_test.py
generated
vendored
Normal file → Executable file
|
@ -42,6 +42,11 @@ type AuthOptions struct {
|
||||||
// re-authenticate automatically if/when your token expires. If you set it to
|
// re-authenticate automatically if/when your token expires. If you set it to
|
||||||
// false, it will not cache these settings, but re-authentication will not be
|
// false, it will not cache these settings, but re-authentication will not be
|
||||||
// possible. This setting defaults to false.
|
// possible. This setting defaults to false.
|
||||||
|
//
|
||||||
|
// NOTE: The reauth function will try to re-authenticate endlessly if left unchecked.
|
||||||
|
// The way to limit the number of attempts is to provide a custom HTTP client to the provider client
|
||||||
|
// and provide a transport that implements the RoundTripper interface and stores the number of failed retries.
|
||||||
|
// For an example of this, see here: https://github.com/rackspace/rack/blob/1.0.0/auth/clients.go#L311
|
||||||
AllowReauth bool
|
AllowReauth bool
|
||||||
|
|
||||||
// TokenID allows users to authenticate (possibly as another user) with an
|
// TokenID allows users to authenticate (possibly as another user) with an
|
||||||
|
|
|
@ -134,13 +134,17 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||||
v3Client.Endpoint = endpoint
|
v3Client.Endpoint = endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy the auth options to a local variable that we can change. `options`
|
||||||
|
// needs to stay as-is for reauth purposes
|
||||||
|
v3Options := options
|
||||||
|
|
||||||
var scope *tokens3.Scope
|
var scope *tokens3.Scope
|
||||||
if options.TenantID != "" {
|
if options.TenantID != "" {
|
||||||
scope = &tokens3.Scope{
|
scope = &tokens3.Scope{
|
||||||
ProjectID: options.TenantID,
|
ProjectID: options.TenantID,
|
||||||
}
|
}
|
||||||
options.TenantID = ""
|
v3Options.TenantID = ""
|
||||||
options.TenantName = ""
|
v3Options.TenantName = ""
|
||||||
} else {
|
} else {
|
||||||
if options.TenantName != "" {
|
if options.TenantName != "" {
|
||||||
scope = &tokens3.Scope{
|
scope = &tokens3.Scope{
|
||||||
|
@ -148,11 +152,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
|
||||||
DomainID: options.DomainID,
|
DomainID: options.DomainID,
|
||||||
DomainName: options.DomainName,
|
DomainName: options.DomainName,
|
||||||
}
|
}
|
||||||
options.TenantName = ""
|
v3Options.TenantName = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := tokens3.Create(v3Client, options, scope)
|
result := tokens3.Create(v3Client, v3Options, scope)
|
||||||
|
|
||||||
token, err := result.ExtractToken()
|
token, err := result.ExtractToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -277,6 +281,29 @@ func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
|
||||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service.
|
||||||
|
func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||||
|
eo.ApplyDefaults("volume")
|
||||||
|
url, err := client.EndpointLocator(eo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force using v2 API
|
||||||
|
if strings.Contains(url, "/v1") {
|
||||||
|
url = strings.Replace(url, "/v1", "/v2", -1)
|
||||||
|
}
|
||||||
|
if !strings.Contains(url, "/v2") {
|
||||||
|
return nil, fmt.Errorf("Block Storage v2 endpoint not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &gophercloud.ServiceClient{
|
||||||
|
ProviderClient: client,
|
||||||
|
Endpoint: url,
|
||||||
|
ResourceBase: url,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
|
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
|
||||||
// CDN service.
|
// CDN service.
|
||||||
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||||
|
|
|
@ -51,6 +51,8 @@ type Image struct {
|
||||||
Status string
|
Status string
|
||||||
|
|
||||||
Updated string
|
Updated string
|
||||||
|
|
||||||
|
Metadata map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImagePage contains a single page of results from a List operation.
|
// ImagePage contains a single page of results from a List operation.
|
||||||
|
|
|
@ -25,6 +25,9 @@ type Monitor struct {
|
||||||
// The unique ID for the VIP.
|
// The unique ID for the VIP.
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
|
// Monitor name. Does not have to be unique.
|
||||||
|
Name string
|
||||||
|
|
||||||
// Owner of the VIP. Only an administrative user can specify a tenant ID
|
// Owner of the VIP. Only an administrative user can specify a tenant ID
|
||||||
// other than its own.
|
// other than its own.
|
||||||
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
|
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
|
||||||
|
|
|
@ -74,6 +74,9 @@ type CreateOpts struct {
|
||||||
// current specification supports LBMethodRoundRobin and
|
// current specification supports LBMethodRoundRobin and
|
||||||
// LBMethodLeastConnections as valid values for this attribute.
|
// LBMethodLeastConnections as valid values for this attribute.
|
||||||
LBMethod string
|
LBMethod string
|
||||||
|
|
||||||
|
// The provider of the pool
|
||||||
|
Provider string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create accepts a CreateOpts struct and uses the values to create a new
|
// Create accepts a CreateOpts struct and uses the values to create a new
|
||||||
|
@ -85,6 +88,7 @@ func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
SubnetID string `json:"subnet_id"`
|
SubnetID string `json:"subnet_id"`
|
||||||
LBMethod string `json:"lb_method"`
|
LBMethod string `json:"lb_method"`
|
||||||
|
Provider string `json:"provider,omitempty"`
|
||||||
}
|
}
|
||||||
type request struct {
|
type request struct {
|
||||||
Pool pool `json:"pool"`
|
Pool pool `json:"pool"`
|
||||||
|
@ -96,6 +100,7 @@ func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
Protocol: opts.Protocol,
|
Protocol: opts.Protocol,
|
||||||
SubnetID: opts.SubnetID,
|
SubnetID: opts.SubnetID,
|
||||||
LBMethod: opts.LBMethod,
|
LBMethod: opts.LBMethod,
|
||||||
|
Provider: opts.Provider,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
var res CreateResult
|
var res CreateResult
|
||||||
|
|
214
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/fixtures.go
generated
vendored
Normal file
214
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/fixtures.go
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
// +build fixtures
|
||||||
|
|
||||||
|
package listeners
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListenersListBody contains the canned body of a listeners list response.
|
||||||
|
const ListenersListBody = `
|
||||||
|
{
|
||||||
|
"listeners":[
|
||||||
|
{
|
||||||
|
"id": "db902c0c-d5ff-4753-b465-668ad9656918",
|
||||||
|
"tenant_id": "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
"name": "web",
|
||||||
|
"description": "listener config for the web tier",
|
||||||
|
"loadbalancers": [{"id": "53306cda-815d-4354-9444-59e09da9c3c5"}],
|
||||||
|
"protocol": "HTTP",
|
||||||
|
"protocol_port": 80,
|
||||||
|
"default_pool_id": "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"default_tls_container_ref": "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
"sni_container_refs": ["3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"tenant_id": "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
"name": "db",
|
||||||
|
"description": "listener config for the db tier",
|
||||||
|
"loadbalancers": [{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"protocol": "TCP",
|
||||||
|
"protocol_port": 3306,
|
||||||
|
"default_pool_id": "41efe233-7591-43c5-9cf7-923964759f9e",
|
||||||
|
"connection_limit": 2000,
|
||||||
|
"admin_state_up": true,
|
||||||
|
"default_tls_container_ref": "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
"sni_container_refs": ["3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SingleServerBody is the canned body of a Get request on an existing listener.
|
||||||
|
const SingleListenerBody = `
|
||||||
|
{
|
||||||
|
"listener": {
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"tenant_id": "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
"name": "db",
|
||||||
|
"description": "listener config for the db tier",
|
||||||
|
"loadbalancers": [{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"protocol": "TCP",
|
||||||
|
"protocol_port": 3306,
|
||||||
|
"default_pool_id": "41efe233-7591-43c5-9cf7-923964759f9e",
|
||||||
|
"connection_limit": 2000,
|
||||||
|
"admin_state_up": true,
|
||||||
|
"default_tls_container_ref": "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
"sni_container_refs": ["3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// PostUpdateListenerBody is the canned response body of a Update request on an existing listener.
|
||||||
|
const PostUpdateListenerBody = `
|
||||||
|
{
|
||||||
|
"listener": {
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"tenant_id": "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
"name": "NewListenerName",
|
||||||
|
"description": "listener config for the db tier",
|
||||||
|
"loadbalancers": [{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"protocol": "TCP",
|
||||||
|
"protocol_port": 3306,
|
||||||
|
"default_pool_id": "41efe233-7591-43c5-9cf7-923964759f9e",
|
||||||
|
"connection_limit": 1000,
|
||||||
|
"admin_state_up": true,
|
||||||
|
"default_tls_container_ref": "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
"sni_container_refs": ["3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
ListenerWeb = Listener{
|
||||||
|
ID: "db902c0c-d5ff-4753-b465-668ad9656918",
|
||||||
|
TenantID: "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
Name: "web",
|
||||||
|
Description: "listener config for the web tier",
|
||||||
|
Loadbalancers: []LoadBalancerID{{ID: "53306cda-815d-4354-9444-59e09da9c3c5"}},
|
||||||
|
Protocol: "HTTP",
|
||||||
|
ProtocolPort: 80,
|
||||||
|
DefaultPoolID: "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
AdminStateUp: true,
|
||||||
|
DefaultTlsContainerRef: "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
SniContainerRefs: []string{"3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"},
|
||||||
|
}
|
||||||
|
ListenerDb = Listener{
|
||||||
|
ID: "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
TenantID: "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
Name: "db",
|
||||||
|
Description: "listener config for the db tier",
|
||||||
|
Loadbalancers: []LoadBalancerID{{ID: "79e05663-7f03-45d2-a092-8b94062f22ab"}},
|
||||||
|
Protocol: "TCP",
|
||||||
|
ProtocolPort: 3306,
|
||||||
|
DefaultPoolID: "41efe233-7591-43c5-9cf7-923964759f9e",
|
||||||
|
ConnLimit: 2000,
|
||||||
|
AdminStateUp: true,
|
||||||
|
DefaultTlsContainerRef: "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
SniContainerRefs: []string{"3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"},
|
||||||
|
}
|
||||||
|
ListenerUpdated = Listener{
|
||||||
|
ID: "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
TenantID: "310df60f-2a10-4ee5-9554-98393092194c",
|
||||||
|
Name: "NewListenerName",
|
||||||
|
Description: "listener config for the db tier",
|
||||||
|
Loadbalancers: []LoadBalancerID{{ID: "79e05663-7f03-45d2-a092-8b94062f22ab"}},
|
||||||
|
Protocol: "TCP",
|
||||||
|
ProtocolPort: 3306,
|
||||||
|
DefaultPoolID: "41efe233-7591-43c5-9cf7-923964759f9e",
|
||||||
|
ConnLimit: 1000,
|
||||||
|
AdminStateUp: true,
|
||||||
|
DefaultTlsContainerRef: "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
SniContainerRefs: []string{"3d328d82-2547-4921-ac2f-61c3b452b5ff", "b3cfd7e3-8c19-455c-8ebb-d78dfd8f7e7d"},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleListenerListSuccessfully sets up the test server to respond to a listener List request.
|
||||||
|
func HandleListenerListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/listeners", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
r.ParseForm()
|
||||||
|
marker := r.Form.Get("marker")
|
||||||
|
switch marker {
|
||||||
|
case "":
|
||||||
|
fmt.Fprintf(w, ListenersListBody)
|
||||||
|
case "45e08a3e-a78f-4b40-a229-1e7e23eee1ab":
|
||||||
|
fmt.Fprintf(w, `{ "listeners": [] }`)
|
||||||
|
default:
|
||||||
|
t.Fatalf("/v2.0/lbaas/listeners invoked with unexpected marker=[%s]", marker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleListenerCreationSuccessfully sets up the test server to respond to a listener creation request
|
||||||
|
// with a given response.
|
||||||
|
func HandleListenerCreationSuccessfully(t *testing.T, response string) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/listeners", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"listener": {
|
||||||
|
"loadbalancer_id": "79e05663-7f03-45d2-a092-8b94062f22ab",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"name": "db",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"default_tls_container_ref": "2c433435-20de-4411-84ae-9cc8917def76",
|
||||||
|
"default_pool_id": "41efe233-7591-43c5-9cf7-923964759f9e",
|
||||||
|
"protocol_port": 3306
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleListenerGetSuccessfully sets up the test server to respond to a listener Get request.
|
||||||
|
func HandleListenerGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/listeners/4ec89087-d057-4e2c-911f-60a3b47ee304", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, SingleListenerBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleListenerDeletionSuccessfully sets up the test server to respond to a listener deletion request.
|
||||||
|
func HandleListenerDeletionSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/listeners/4ec89087-d057-4e2c-911f-60a3b47ee304", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleListenerUpdateSuccessfully sets up the test server to respond to a listener Update request.
|
||||||
|
func HandleListenerUpdateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/listeners/4ec89087-d057-4e2c-911f-60a3b47ee304", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "PUT")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"listener": {
|
||||||
|
"name": "NewListenerName",
|
||||||
|
"connection_limit": 1001
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, PostUpdateListenerBody)
|
||||||
|
})
|
||||||
|
}
|
279
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/requests.go
generated
vendored
Normal file
279
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
package listeners
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminState gives users a solid type to work with for create and update
|
||||||
|
// operations. It is recommended that users use the `Up` and `Down` enums.
|
||||||
|
type AdminState *bool
|
||||||
|
|
||||||
|
type listenerOpts struct {
|
||||||
|
// Required. The protocol - can either be TCP, HTTP or HTTPS.
|
||||||
|
Protocol Protocol
|
||||||
|
|
||||||
|
// Required. The port on which to listen for client traffic.
|
||||||
|
ProtocolPort int
|
||||||
|
|
||||||
|
// Required for admins. Indicates the owner of the Listener.
|
||||||
|
TenantID string
|
||||||
|
|
||||||
|
// Required. The load balancer on which to provision this listener.
|
||||||
|
LoadbalancerID string
|
||||||
|
|
||||||
|
// Human-readable name for the Listener. Does not have to be unique.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Optional. The ID of the default pool with which the Listener is associated.
|
||||||
|
DefaultPoolID string
|
||||||
|
|
||||||
|
// Optional. Human-readable description for the Listener.
|
||||||
|
Description string
|
||||||
|
|
||||||
|
// Optional. The maximum number of connections allowed for the Listener.
|
||||||
|
ConnLimit *int
|
||||||
|
|
||||||
|
// Optional. A reference to a container of TLS secrets.
|
||||||
|
DefaultTlsContainerRef string
|
||||||
|
|
||||||
|
// Optional. A list of references to TLS secrets.
|
||||||
|
SniContainerRefs []string
|
||||||
|
|
||||||
|
// Optional. The administrative state of the Listener. A valid value is true (UP)
|
||||||
|
// or false (DOWN).
|
||||||
|
AdminStateUp *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience vars for AdminStateUp values.
|
||||||
|
var (
|
||||||
|
iTrue = true
|
||||||
|
iFalse = false
|
||||||
|
|
||||||
|
Up AdminState = &iTrue
|
||||||
|
Down AdminState = &iFalse
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// List request.
|
||||||
|
type ListOptsBuilder interface {
|
||||||
|
ToListenerListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the floating IP attributes you want to see returned. SortKey allows you to
|
||||||
|
// sort by a particular listener attribute. SortDir sets the direction, and is
|
||||||
|
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type ListOpts struct {
|
||||||
|
ID string `q:"id"`
|
||||||
|
Name string `q:"name"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
LoadbalancerID string `q:"loadbalancer_id"`
|
||||||
|
DefaultPoolID string `q:"default_pool_id"`
|
||||||
|
Protocol string `q:"protocol"`
|
||||||
|
ProtocolPort int `q:"protocol_port"`
|
||||||
|
ConnectionLimit int `q:"connection_limit"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToListenerListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts ListOpts) ToListenerListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return q.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// routers. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those routers that are owned by the
|
||||||
|
// tenant who submits the request, unless an admin user submits the request.
|
||||||
|
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||||
|
url := rootURL(c)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToListenerListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return ListenerPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Protocol string
|
||||||
|
|
||||||
|
// Supported attributes for create/update operations.
|
||||||
|
const (
|
||||||
|
ProtocolTCP Protocol = "TCP"
|
||||||
|
ProtocolHTTP Protocol = "HTTP"
|
||||||
|
ProtocolHTTPS Protocol = "HTTPS"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errLoadbalancerIdRequired = fmt.Errorf("LoadbalancerID is required")
|
||||||
|
errProtocolRequired = fmt.Errorf("Protocol is required")
|
||||||
|
errProtocolPortRequired = fmt.Errorf("ProtocolPort is required")
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Create operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToListenerCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts is the common options struct used in this package's Create
|
||||||
|
// operation.
|
||||||
|
type CreateOpts listenerOpts
|
||||||
|
|
||||||
|
// ToListenerCreateMap casts a CreateOpts struct to a map.
|
||||||
|
func (opts CreateOpts) ToListenerCreateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.LoadbalancerID != "" {
|
||||||
|
l["loadbalancer_id"] = opts.LoadbalancerID
|
||||||
|
} else {
|
||||||
|
return nil, errLoadbalancerIdRequired
|
||||||
|
}
|
||||||
|
if opts.Protocol != "" {
|
||||||
|
l["protocol"] = opts.Protocol
|
||||||
|
} else {
|
||||||
|
return nil, errProtocolRequired
|
||||||
|
}
|
||||||
|
if opts.ProtocolPort != 0 {
|
||||||
|
l["protocol_port"] = opts.ProtocolPort
|
||||||
|
} else {
|
||||||
|
return nil, errProtocolPortRequired
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.TenantID != "" {
|
||||||
|
l["tenant_id"] = opts.TenantID
|
||||||
|
}
|
||||||
|
if opts.DefaultPoolID != "" {
|
||||||
|
l["default_pool_id"] = opts.DefaultPoolID
|
||||||
|
}
|
||||||
|
if opts.Description != "" {
|
||||||
|
l["description"] = opts.Description
|
||||||
|
}
|
||||||
|
if opts.ConnLimit != nil {
|
||||||
|
l["connection_limit"] = &opts.ConnLimit
|
||||||
|
}
|
||||||
|
if opts.DefaultTlsContainerRef != "" {
|
||||||
|
l["default_tls_container_ref"] = opts.DefaultTlsContainerRef
|
||||||
|
}
|
||||||
|
if opts.SniContainerRefs != nil {
|
||||||
|
l["sni_container_refs"] = opts.SniContainerRefs
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"listener": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create is an operation which provisions a new Listeners based on the
|
||||||
|
// configuration defined in the CreateOpts struct. Once the request is
|
||||||
|
// validated and progress has started on the provisioning process, a
|
||||||
|
// CreateResult will be returned.
|
||||||
|
//
|
||||||
|
// Users with an admin role can create Listeners on behalf of other tenants by
|
||||||
|
// specifying a TenantID attribute different than their own.
|
||||||
|
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToListenerCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a particular Listeners based on its unique ID.
|
||||||
|
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Update operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type UpdateOptsBuilder interface {
|
||||||
|
ToListenerUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts is the common options struct used in this package's Update
|
||||||
|
// operation.
|
||||||
|
type UpdateOpts listenerOpts
|
||||||
|
|
||||||
|
// ToListenerUpdateMap casts a UpdateOpts struct to a map.
|
||||||
|
func (opts UpdateOpts) ToListenerUpdateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.Description != "" {
|
||||||
|
l["description"] = opts.Description
|
||||||
|
}
|
||||||
|
if opts.ConnLimit != nil {
|
||||||
|
l["connection_limit"] = &opts.ConnLimit
|
||||||
|
}
|
||||||
|
if opts.DefaultTlsContainerRef != "" {
|
||||||
|
l["default_tls_container_ref"] = opts.DefaultTlsContainerRef
|
||||||
|
}
|
||||||
|
if opts.SniContainerRefs != nil {
|
||||||
|
l["sni_container_refs"] = opts.SniContainerRefs
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"listener": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is an operation which modifies the attributes of the specified Listener.
|
||||||
|
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
|
||||||
|
var res UpdateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToListenerUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200, 202},
|
||||||
|
})
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete will permanently delete a particular Listeners based on its unique ID.
|
||||||
|
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = c.Delete(resourceURL(c, id), nil)
|
||||||
|
return res
|
||||||
|
}
|
139
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/results.go
generated
vendored
Normal file
139
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/results.go
generated
vendored
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
package listeners
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoadBalancerID struct {
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listener is the primary load balancing configuration object that specifies
|
||||||
|
// the loadbalancer and port on which client traffic is received, as well
|
||||||
|
// as other details such as the load balancing method to be use, protocol, etc.
|
||||||
|
type Listener struct {
|
||||||
|
// The unique ID for the Listener.
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
|
||||||
|
// Owner of the Listener. Only an admin user can specify a tenant ID other than its own.
|
||||||
|
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
|
||||||
|
|
||||||
|
// Human-readable name for the Listener. Does not have to be unique.
|
||||||
|
Name string `mapstructure:"name" json:"name"`
|
||||||
|
|
||||||
|
// Human-readable description for the Listener.
|
||||||
|
Description string `mapstructure:"description" json:"description"`
|
||||||
|
|
||||||
|
// The protocol to loadbalance. A valid value is TCP, HTTP, or HTTPS.
|
||||||
|
Protocol string `mapstructure:"protocol" json:"protocol"`
|
||||||
|
|
||||||
|
// The port on which to listen to client traffic that is associated with the
|
||||||
|
// Loadbalancer. A valid value is from 0 to 65535.
|
||||||
|
ProtocolPort int `mapstructure:"protocol_port" json:"protocol_port"`
|
||||||
|
|
||||||
|
// The UUID of default pool. Must have compatible protocol with listener.
|
||||||
|
DefaultPoolID string `mapstructure:"default_pool_id" json:"default_pool_id"`
|
||||||
|
|
||||||
|
// A list of load balancer IDs.
|
||||||
|
Loadbalancers []LoadBalancerID `mapstructure:"loadbalancers" json:"loadbalancers"`
|
||||||
|
|
||||||
|
// The maximum number of connections allowed for the Loadbalancer. Default is -1,
|
||||||
|
// meaning no limit.
|
||||||
|
ConnLimit int `mapstructure:"connection_limit" json:"connection_limit"`
|
||||||
|
|
||||||
|
// The list of references to TLS secrets.
|
||||||
|
SniContainerRefs []string `mapstructure:"sni_container_refs" json:"sni_container_refs"`
|
||||||
|
|
||||||
|
// Optional. A reference to a container of TLS secrets.
|
||||||
|
DefaultTlsContainerRef string `mapstructure:"default_tls_container_ref" json:"default_tls_container_ref"`
|
||||||
|
|
||||||
|
// The administrative state of the Listener. A valid value is true (UP) or false (DOWN).
|
||||||
|
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
|
||||||
|
|
||||||
|
Pools []pools.Pool `mapstructure:"pools" json:"pools"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenerPage is the page returned by a pager when traversing over a
|
||||||
|
// collection of routers.
|
||||||
|
type ListenerPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of routers has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (p ListenerPage) NextPageURL() (string, error) {
|
||||||
|
type resp struct {
|
||||||
|
Links []gophercloud.Link `mapstructure:"listeners_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var r resp
|
||||||
|
err := mapstructure.Decode(p.Body, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gophercloud.ExtractNextURL(r.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a RouterPage struct is empty.
|
||||||
|
func (p ListenerPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractListeners(p)
|
||||||
|
if err != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return len(is) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractListeners accepts a Page struct, specifically a ListenerPage struct,
|
||||||
|
// and extracts the elements into a slice of Listener structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractListeners(page pagination.Page) ([]Listener, error) {
|
||||||
|
var resp struct {
|
||||||
|
Listeners []Listener `mapstructure:"listeners" json:"listeners"`
|
||||||
|
}
|
||||||
|
err := mapstructure.Decode(page.(ListenerPage).Body, &resp)
|
||||||
|
return resp.Listeners, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type commonResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a router.
|
||||||
|
func (r commonResult) Extract() (*Listener, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
Listener *Listener `mapstructure:"listener" json:"listener"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.Listener, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult represents the result of a create operation.
|
||||||
|
type CreateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult represents the result of a get operation.
|
||||||
|
type GetResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResult represents the result of an update operation.
|
||||||
|
type UpdateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult represents the result of a delete operation.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
16
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/urls.go
generated
vendored
Normal file
16
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package listeners
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
const (
|
||||||
|
rootPath = "lbaas"
|
||||||
|
resourcePath = "listeners"
|
||||||
|
)
|
||||||
|
|
||||||
|
func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, id)
|
||||||
|
}
|
278
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/fixtures.go
generated
vendored
Normal file
278
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/fixtures.go
generated
vendored
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
// +build fixtures
|
||||||
|
|
||||||
|
package loadbalancers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadbalancersListBody contains the canned body of a loadbalancer list response.
|
||||||
|
const LoadbalancersListBody = `
|
||||||
|
{
|
||||||
|
"loadbalancers":[
|
||||||
|
{
|
||||||
|
"id": "c331058c-6a40-4144-948e-b9fb1df9db4b",
|
||||||
|
"tenant_id": "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
"name": "web_lb",
|
||||||
|
"description": "lb config for the web tier",
|
||||||
|
"vip_subnet_id": "8a49c438-848f-467b-9655-ea1548708154",
|
||||||
|
"vip_address": "10.30.176.47",
|
||||||
|
"flavor": "small",
|
||||||
|
"provider": "haproxy",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"provisioning_status": "ACTIVE",
|
||||||
|
"operating_status": "ONLINE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"tenant_id": "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
"name": "db_lb",
|
||||||
|
"description": "lb config for the db tier",
|
||||||
|
"vip_subnet_id": "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
|
||||||
|
"vip_address": "10.30.176.48",
|
||||||
|
"flavor": "medium",
|
||||||
|
"provider": "haproxy",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"provisioning_status": "PENDING_CREATE",
|
||||||
|
"operating_status": "OFFLINE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SingleLoadbalancerBody is the canned body of a Get request on an existing loadbalancer.
|
||||||
|
const SingleLoadbalancerBody = `
|
||||||
|
{
|
||||||
|
"loadbalancer": {
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"tenant_id": "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
"name": "db_lb",
|
||||||
|
"description": "lb config for the db tier",
|
||||||
|
"vip_subnet_id": "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
|
||||||
|
"vip_address": "10.30.176.48",
|
||||||
|
"flavor": "medium",
|
||||||
|
"provider": "haproxy",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"provisioning_status": "PENDING_CREATE",
|
||||||
|
"operating_status": "OFFLINE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// PostUpdateLoadbalancerBody is the canned response body of a Update request on an existing loadbalancer.
|
||||||
|
const PostUpdateLoadbalancerBody = `
|
||||||
|
{
|
||||||
|
"loadbalancer": {
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"tenant_id": "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
"name": "NewLoadbalancerName",
|
||||||
|
"description": "lb config for the db tier",
|
||||||
|
"vip_subnet_id": "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
|
||||||
|
"vip_address": "10.30.176.48",
|
||||||
|
"flavor": "medium",
|
||||||
|
"provider": "haproxy",
|
||||||
|
"admin_state_up": true,
|
||||||
|
"provisioning_status": "PENDING_CREATE",
|
||||||
|
"operating_status": "OFFLINE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SingleLoadbalancerBody is the canned body of a Get request on an existing loadbalancer.
|
||||||
|
const LoadbalancerStatuesesTree = `
|
||||||
|
{
|
||||||
|
"statuses" : {
|
||||||
|
"loadbalancer": {
|
||||||
|
"id": "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
"name": "db_lb",
|
||||||
|
"provisioning_status": "PENDING_UPDATE",
|
||||||
|
"operating_status": "ACTIVE",
|
||||||
|
"listeners": [{
|
||||||
|
"id": "db902c0c-d5ff-4753-b465-668ad9656918",
|
||||||
|
"name": "db",
|
||||||
|
"pools": [{
|
||||||
|
"id": "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
"name": "db",
|
||||||
|
"healthmonitor": {
|
||||||
|
"id": "67306cda-815d-4354-9fe4-59e09da9c3c5",
|
||||||
|
"type":"PING"
|
||||||
|
},
|
||||||
|
"members":[{
|
||||||
|
"id": "2a280670-c202-4b0b-a562-34077415aabf",
|
||||||
|
"name": "db",
|
||||||
|
"address": "10.0.2.11",
|
||||||
|
"protocol_port": 80
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
LoadbalancerWeb = LoadBalancer{
|
||||||
|
ID: "c331058c-6a40-4144-948e-b9fb1df9db4b",
|
||||||
|
TenantID: "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
Name: "web_lb",
|
||||||
|
Description: "lb config for the web tier",
|
||||||
|
VipSubnetID: "8a49c438-848f-467b-9655-ea1548708154",
|
||||||
|
VipAddress: "10.30.176.47",
|
||||||
|
Flavor: "small",
|
||||||
|
Provider: "haproxy",
|
||||||
|
AdminStateUp: true,
|
||||||
|
ProvisioningStatus: "ACTIVE",
|
||||||
|
OperatingStatus: "ONLINE",
|
||||||
|
}
|
||||||
|
LoadbalancerDb = LoadBalancer{
|
||||||
|
ID: "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
TenantID: "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
Name: "db_lb",
|
||||||
|
Description: "lb config for the db tier",
|
||||||
|
VipSubnetID: "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
|
||||||
|
VipAddress: "10.30.176.48",
|
||||||
|
Flavor: "medium",
|
||||||
|
Provider: "haproxy",
|
||||||
|
AdminStateUp: true,
|
||||||
|
ProvisioningStatus: "PENDING_CREATE",
|
||||||
|
OperatingStatus: "OFFLINE",
|
||||||
|
}
|
||||||
|
LoadbalancerUpdated = LoadBalancer{
|
||||||
|
ID: "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
TenantID: "54030507-44f7-473c-9342-b4d14a95f692",
|
||||||
|
Name: "NewLoadbalancerName",
|
||||||
|
Description: "lb config for the db tier",
|
||||||
|
VipSubnetID: "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
|
||||||
|
VipAddress: "10.30.176.48",
|
||||||
|
Flavor: "medium",
|
||||||
|
Provider: "haproxy",
|
||||||
|
AdminStateUp: true,
|
||||||
|
ProvisioningStatus: "PENDING_CREATE",
|
||||||
|
OperatingStatus: "OFFLINE",
|
||||||
|
}
|
||||||
|
LoadbalancerStatusesTree = LoadBalancer{
|
||||||
|
ID: "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
|
||||||
|
Name: "db_lb",
|
||||||
|
ProvisioningStatus: "PENDING_UPDATE",
|
||||||
|
OperatingStatus: "ACTIVE",
|
||||||
|
Listeners: []listeners.Listener{{
|
||||||
|
ID: "db902c0c-d5ff-4753-b465-668ad9656918",
|
||||||
|
Name: "db",
|
||||||
|
Pools: []pools.Pool{{
|
||||||
|
ID: "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
Name: "db",
|
||||||
|
Monitor: monitors.Monitor{
|
||||||
|
ID: "67306cda-815d-4354-9fe4-59e09da9c3c5",
|
||||||
|
Type: "PING",
|
||||||
|
},
|
||||||
|
Members: []pools.Member{{
|
||||||
|
ID: "2a280670-c202-4b0b-a562-34077415aabf",
|
||||||
|
Name: "db",
|
||||||
|
Address: "10.0.2.11",
|
||||||
|
ProtocolPort: 80,
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleLoadbalancerListSuccessfully sets up the test server to respond to a loadbalancer List request.
|
||||||
|
func HandleLoadbalancerListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/loadbalancers", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
r.ParseForm()
|
||||||
|
marker := r.Form.Get("marker")
|
||||||
|
switch marker {
|
||||||
|
case "":
|
||||||
|
fmt.Fprintf(w, LoadbalancersListBody)
|
||||||
|
case "45e08a3e-a78f-4b40-a229-1e7e23eee1ab":
|
||||||
|
fmt.Fprintf(w, `{ "loadbalancers": [] }`)
|
||||||
|
default:
|
||||||
|
t.Fatalf("/v2.0/lbaas/loadbalancers invoked with unexpected marker=[%s]", marker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleLoadbalancerCreationSuccessfully sets up the test server to respond to a loadbalancer creation request
|
||||||
|
// with a given response.
|
||||||
|
func HandleLoadbalancerCreationSuccessfully(t *testing.T, response string) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/loadbalancers", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"loadbalancer": {
|
||||||
|
"name": "db_lb",
|
||||||
|
"vip_subnet_id": "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
|
||||||
|
"vip_address": "10.30.176.48",
|
||||||
|
"flavor": "medium",
|
||||||
|
"provider": "haproxy",
|
||||||
|
"admin_state_up": true
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleLoadbalancerGetSuccessfully sets up the test server to respond to a loadbalancer Get request.
|
||||||
|
func HandleLoadbalancerGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/loadbalancers/36e08a3e-a78f-4b40-a229-1e7e23eee1ab", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, SingleLoadbalancerBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleLoadbalancerGetStatusesTree sets up the test server to respond to a loadbalancer Get statuses tree request.
|
||||||
|
func HandleLoadbalancerGetStatusesTree(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/loadbalancers/36e08a3e-a78f-4b40-a229-1e7e23eee1ab/statuses", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, LoadbalancerStatuesesTree)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleLoadbalancerDeletionSuccessfully sets up the test server to respond to a loadbalancer deletion request.
|
||||||
|
func HandleLoadbalancerDeletionSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/loadbalancers/36e08a3e-a78f-4b40-a229-1e7e23eee1ab", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleLoadbalancerUpdateSuccessfully sets up the test server to respond to a loadbalancer Update request.
|
||||||
|
func HandleLoadbalancerUpdateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/loadbalancers/36e08a3e-a78f-4b40-a229-1e7e23eee1ab", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "PUT")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"loadbalancer": {
|
||||||
|
"name": "NewLoadbalancerName"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, PostUpdateLoadbalancerBody)
|
||||||
|
})
|
||||||
|
}
|
248
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/requests.go
generated
vendored
Normal file
248
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
package loadbalancers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminState gives users a solid type to work with for create and update
|
||||||
|
// operations. It is recommended that users use the `Up` and `Down` enums.
|
||||||
|
type AdminState *bool
|
||||||
|
|
||||||
|
type loadbalancerOpts struct {
|
||||||
|
// Optional. Human-readable name for the Loadbalancer. Does not have to be unique.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Optional. Human-readable description for the Loadbalancer.
|
||||||
|
Description string
|
||||||
|
|
||||||
|
// Required. The network on which to allocate the Loadbalancer's address. A tenant can
|
||||||
|
// only create Loadbalancers on networks authorized by policy (e.g. networks that
|
||||||
|
// belong to them or networks that are shared).
|
||||||
|
VipSubnetID string
|
||||||
|
|
||||||
|
// Required for admins. The UUID of the tenant who owns the Loadbalancer.
|
||||||
|
// Only administrative users can specify a tenant UUID other than their own.
|
||||||
|
TenantID string
|
||||||
|
|
||||||
|
// Optional. The IP address of the Loadbalancer.
|
||||||
|
VipAddress string
|
||||||
|
|
||||||
|
// Optional. The administrative state of the Loadbalancer. A valid value is true (UP)
|
||||||
|
// or false (DOWN).
|
||||||
|
AdminStateUp *bool
|
||||||
|
|
||||||
|
// Optional. The UUID of a flavor.
|
||||||
|
Flavor string
|
||||||
|
|
||||||
|
// Optional. The name of the provider.
|
||||||
|
Provider string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience vars for AdminStateUp values.
|
||||||
|
var (
|
||||||
|
iTrue = true
|
||||||
|
iFalse = false
|
||||||
|
|
||||||
|
Up AdminState = &iTrue
|
||||||
|
Down AdminState = &iFalse
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// List request.
|
||||||
|
type ListOptsBuilder interface {
|
||||||
|
ToLoadbalancerListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the Loadbalancer attributes you want to see returned. SortKey allows you to
|
||||||
|
// sort by a particular attribute. SortDir sets the direction, and is
|
||||||
|
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type ListOpts struct {
|
||||||
|
Description string `q:"description"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
ProvisioningStatus string `q:"provisioning_status"`
|
||||||
|
VipAddress string `q:"vip_address"`
|
||||||
|
VipSubnetID string `q:"vip_subnet_id"`
|
||||||
|
ID string `q:"id"`
|
||||||
|
OperatingStatus string `q:"operating_status"`
|
||||||
|
Name string `q:"name"`
|
||||||
|
Flavor string `q:"flavor"`
|
||||||
|
Provider string `q:"provider"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToLoadbalancerListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts ListOpts) ToLoadbalancerListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return q.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// routers. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those routers that are owned by the
|
||||||
|
// tenant who submits the request, unless an admin user submits the request.
|
||||||
|
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||||
|
url := rootURL(c)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToLoadbalancerListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return LoadbalancerPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errVipSubnetIDRequried = fmt.Errorf("VipSubnetID is required")
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Create operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToLoadbalancerCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts is the common options struct used in this package's Create
|
||||||
|
// operation.
|
||||||
|
type CreateOpts loadbalancerOpts
|
||||||
|
|
||||||
|
// ToLoadbalancerCreateMap casts a CreateOpts struct to a map.
|
||||||
|
func (opts CreateOpts) ToLoadbalancerCreateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.VipSubnetID != "" {
|
||||||
|
l["vip_subnet_id"] = opts.VipSubnetID
|
||||||
|
} else {
|
||||||
|
return nil, errVipSubnetIDRequried
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.TenantID != "" {
|
||||||
|
l["tenant_id"] = opts.TenantID
|
||||||
|
}
|
||||||
|
if opts.Description != "" {
|
||||||
|
l["description"] = opts.Description
|
||||||
|
}
|
||||||
|
if opts.VipAddress != "" {
|
||||||
|
l["vip_address"] = opts.VipAddress
|
||||||
|
}
|
||||||
|
if opts.Flavor != "" {
|
||||||
|
l["flavor"] = opts.Flavor
|
||||||
|
}
|
||||||
|
if opts.Provider != "" {
|
||||||
|
l["provider"] = opts.Provider
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"loadbalancer": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create is an operation which provisions a new loadbalancer based on the
|
||||||
|
// configuration defined in the CreateOpts struct. Once the request is
|
||||||
|
// validated and progress has started on the provisioning process, a
|
||||||
|
// CreateResult will be returned.
|
||||||
|
//
|
||||||
|
// Users with an admin role can create loadbalancers on behalf of other tenants by
|
||||||
|
// specifying a TenantID attribute different than their own.
|
||||||
|
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToLoadbalancerCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a particular Loadbalancer based on its unique ID.
|
||||||
|
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Update operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type UpdateOptsBuilder interface {
|
||||||
|
ToLoadbalancerUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts is the common options struct used in this package's Update
|
||||||
|
// operation.
|
||||||
|
type UpdateOpts loadbalancerOpts
|
||||||
|
|
||||||
|
// ToLoadbalancerUpdateMap casts a UpdateOpts struct to a map.
|
||||||
|
func (opts UpdateOpts) ToLoadbalancerUpdateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.Description != "" {
|
||||||
|
l["description"] = opts.Description
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"loadbalancer": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is an operation which modifies the attributes of the specified Loadbalancer.
|
||||||
|
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
|
||||||
|
var res UpdateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToLoadbalancerUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200, 202},
|
||||||
|
})
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete will permanently delete a particular Loadbalancer based on its unique ID.
|
||||||
|
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = c.Delete(resourceURL(c, id), nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStatuses(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(statusRootURL(c, id), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
146
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/results.go
generated
vendored
Normal file
146
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/results.go
generated
vendored
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
package loadbalancers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadBalancer is the primary load balancing configuration object that specifies
|
||||||
|
// the virtual IP address on which client traffic is received, as well
|
||||||
|
// as other details such as the load balancing method to be use, protocol, etc.
|
||||||
|
type LoadBalancer struct {
|
||||||
|
// Human-readable description for the Loadbalancer.
|
||||||
|
Description string `mapstructure:"description" json:"description"`
|
||||||
|
|
||||||
|
// The administrative state of the Loadbalancer. A valid value is true (UP) or false (DOWN).
|
||||||
|
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
|
||||||
|
|
||||||
|
// Owner of the LoadBalancer. Only an admin user can specify a tenant ID other than its own.
|
||||||
|
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
|
||||||
|
|
||||||
|
// The provisioning status of the LoadBalancer. This value is ACTIVE, PENDING_CREATE or ERROR.
|
||||||
|
ProvisioningStatus string `mapstructure:"provisioning_status" json:"provisioning_status"`
|
||||||
|
|
||||||
|
// The IP address of the Loadbalancer.
|
||||||
|
VipAddress string `mapstructure:"vip_address" json:"vip_address"`
|
||||||
|
|
||||||
|
// The UUID of the subnet on which to allocate the virtual IP for the Loadbalancer address.
|
||||||
|
VipSubnetID string `mapstructure:"vip_subnet_id" json:"vip_subnet_id"`
|
||||||
|
|
||||||
|
// The unique ID for the LoadBalancer.
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
|
||||||
|
// The operating status of the LoadBalancer. This value is ONLINE or OFFLINE.
|
||||||
|
OperatingStatus string `mapstructure:"operating_status" json:"operating_status"`
|
||||||
|
|
||||||
|
// Human-readable name for the LoadBalancer. Does not have to be unique.
|
||||||
|
Name string `mapstructure:"name" json:"name"`
|
||||||
|
|
||||||
|
// The UUID of a flavor if set.
|
||||||
|
Flavor string `mapstructure:"flavor" json:"flavor"`
|
||||||
|
|
||||||
|
// The name of the provider.
|
||||||
|
Provider string `mapstructure:"provider" json:"provider"`
|
||||||
|
|
||||||
|
Listeners []listeners.Listener `mapstructure:"listeners" json:"listeners"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatusTree struct {
|
||||||
|
Loadbalancer *LoadBalancer `mapstructure:"loadbalancer" json:"loadbalancer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadbalancerPage is the page returned by a pager when traversing over a
|
||||||
|
// collection of routers.
|
||||||
|
type LoadbalancerPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of routers has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (p LoadbalancerPage) NextPageURL() (string, error) {
|
||||||
|
type resp struct {
|
||||||
|
Links []gophercloud.Link `mapstructure:"loadbalancers_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var r resp
|
||||||
|
err := mapstructure.Decode(p.Body, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gophercloud.ExtractNextURL(r.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a RouterPage struct is empty.
|
||||||
|
func (p LoadbalancerPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractLoadbalancers(p)
|
||||||
|
if err != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return len(is) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractLoadbalancers accepts a Page struct, specifically a LoadbalancerPage struct,
|
||||||
|
// and extracts the elements into a slice of LoadBalancer structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractLoadbalancers(page pagination.Page) ([]LoadBalancer, error) {
|
||||||
|
var resp struct {
|
||||||
|
LoadBalancers []LoadBalancer `mapstructure:"loadbalancers" json:"loadbalancers"`
|
||||||
|
}
|
||||||
|
err := mapstructure.Decode(page.(LoadbalancerPage).Body, &resp)
|
||||||
|
|
||||||
|
return resp.LoadBalancers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type commonResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a router.
|
||||||
|
func (r commonResult) Extract() (*LoadBalancer, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
var res struct {
|
||||||
|
LoadBalancer *LoadBalancer `mapstructure:"loadbalancer" json:"loadbalancer"`
|
||||||
|
}
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.LoadBalancer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a Loadbalancer.
|
||||||
|
func (r commonResult) ExtractStatuses() (*StatusTree, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
var res struct {
|
||||||
|
LoadBalancer *StatusTree `mapstructure:"statuses" json:"statuses"`
|
||||||
|
}
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.LoadBalancer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult represents the result of a create operation.
|
||||||
|
type CreateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult represents the result of a get operation.
|
||||||
|
type GetResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResult represents the result of an update operation.
|
||||||
|
type UpdateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult represents the result of a delete operation.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
21
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/urls.go
generated
vendored
Normal file
21
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package loadbalancers
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
const (
|
||||||
|
rootPath = "lbaas"
|
||||||
|
resourcePath = "loadbalancers"
|
||||||
|
statusPath = "statuses"
|
||||||
|
)
|
||||||
|
|
||||||
|
func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func statusRootURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, id, statusPath)
|
||||||
|
}
|
216
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/fixtures.go
generated
vendored
Normal file
216
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/fixtures.go
generated
vendored
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
// +build fixtures
|
||||||
|
|
||||||
|
package monitors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HealthmonitorsListBody contains the canned body of a healthmonitor list response.
|
||||||
|
const HealthmonitorsListBody = `
|
||||||
|
{
|
||||||
|
"healthmonitors":[
|
||||||
|
{
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"delay":10,
|
||||||
|
"name":"web",
|
||||||
|
"max_retries":1,
|
||||||
|
"timeout":1,
|
||||||
|
"type":"PING",
|
||||||
|
"pools": [{"id": "84f1b61f-58c4-45bf-a8a9-2dafb9e5214d"}],
|
||||||
|
"id":"466c8345-28d8-4f84-a246-e04380b0461d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"delay":5,
|
||||||
|
"name":"db",
|
||||||
|
"expected_codes":"200",
|
||||||
|
"max_retries":2,
|
||||||
|
"http_method":"GET",
|
||||||
|
"timeout":2,
|
||||||
|
"url_path":"/",
|
||||||
|
"type":"HTTP",
|
||||||
|
"pools": [{"id": "d459f7d8-c6ee-439d-8713-d3fc08aeed8d"}],
|
||||||
|
"id":"5d4b5228-33b0-4e60-b225-9b727c1a20e7"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SingleHealthmonitorBody is the canned body of a Get request on an existing healthmonitor.
|
||||||
|
const SingleHealthmonitorBody = `
|
||||||
|
{
|
||||||
|
"healthmonitor": {
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"delay":5,
|
||||||
|
"name":"db",
|
||||||
|
"expected_codes":"200",
|
||||||
|
"max_retries":2,
|
||||||
|
"http_method":"GET",
|
||||||
|
"timeout":2,
|
||||||
|
"url_path":"/",
|
||||||
|
"type":"HTTP",
|
||||||
|
"pools": [{"id": "d459f7d8-c6ee-439d-8713-d3fc08aeed8d"}],
|
||||||
|
"id":"5d4b5228-33b0-4e60-b225-9b727c1a20e7"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// PostUpdateHealthmonitorBody is the canned response body of a Update request on an existing healthmonitor.
|
||||||
|
const PostUpdateHealthmonitorBody = `
|
||||||
|
{
|
||||||
|
"healthmonitor": {
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"delay":3,
|
||||||
|
"name":"NewHealthmonitorName",
|
||||||
|
"expected_codes":"301",
|
||||||
|
"max_retries":10,
|
||||||
|
"http_method":"GET",
|
||||||
|
"timeout":20,
|
||||||
|
"url_path":"/another_check",
|
||||||
|
"type":"HTTP",
|
||||||
|
"pools": [{"id": "d459f7d8-c6ee-439d-8713-d3fc08aeed8d"}],
|
||||||
|
"id":"5d4b5228-33b0-4e60-b225-9b727c1a20e7"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
HealthmonitorWeb = Monitor{
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "web",
|
||||||
|
TenantID: "83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
Delay: 10,
|
||||||
|
MaxRetries: 1,
|
||||||
|
Timeout: 1,
|
||||||
|
Type: "PING",
|
||||||
|
ID: "466c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
Pools: []PoolID{{ID: "84f1b61f-58c4-45bf-a8a9-2dafb9e5214d"}},
|
||||||
|
}
|
||||||
|
HealthmonitorDb = Monitor{
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "db",
|
||||||
|
TenantID: "83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
Delay: 5,
|
||||||
|
ExpectedCodes: "200",
|
||||||
|
MaxRetries: 2,
|
||||||
|
Timeout: 2,
|
||||||
|
URLPath: "/",
|
||||||
|
Type: "HTTP",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
ID: "5d4b5228-33b0-4e60-b225-9b727c1a20e7",
|
||||||
|
Pools: []PoolID{{ID: "d459f7d8-c6ee-439d-8713-d3fc08aeed8d"}},
|
||||||
|
}
|
||||||
|
HealthmonitorUpdated = Monitor{
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "NewHealthmonitorName",
|
||||||
|
TenantID: "83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
Delay: 3,
|
||||||
|
ExpectedCodes: "301",
|
||||||
|
MaxRetries: 10,
|
||||||
|
Timeout: 20,
|
||||||
|
URLPath: "/another_check",
|
||||||
|
Type: "HTTP",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
ID: "5d4b5228-33b0-4e60-b225-9b727c1a20e7",
|
||||||
|
Pools: []PoolID{{ID: "d459f7d8-c6ee-439d-8713-d3fc08aeed8d"}},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleHealthmonitorListSuccessfully sets up the test server to respond to a healthmonitor List request.
|
||||||
|
func HandleHealthmonitorListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/healthmonitors", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
r.ParseForm()
|
||||||
|
marker := r.Form.Get("marker")
|
||||||
|
switch marker {
|
||||||
|
case "":
|
||||||
|
fmt.Fprintf(w, HealthmonitorsListBody)
|
||||||
|
case "556c8345-28d8-4f84-a246-e04380b0461d":
|
||||||
|
fmt.Fprintf(w, `{ "healthmonitors": [] }`)
|
||||||
|
default:
|
||||||
|
t.Fatalf("/v2.0/lbaas/healthmonitors invoked with unexpected marker=[%s]", marker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleHealthmonitorCreationSuccessfully sets up the test server to respond to a healthmonitor creation request
|
||||||
|
// with a given response.
|
||||||
|
func HandleHealthmonitorCreationSuccessfully(t *testing.T, response string) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/healthmonitors", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"healthmonitor": {
|
||||||
|
"type":"HTTP",
|
||||||
|
"pool_id":"84f1b61f-58c4-45bf-a8a9-2dafb9e5214d",
|
||||||
|
"tenant_id":"453105b9-1754-413f-aab1-55f1af620750",
|
||||||
|
"delay":20,
|
||||||
|
"name":"db",
|
||||||
|
"timeout":10,
|
||||||
|
"max_retries":5,
|
||||||
|
"url_path":"/check",
|
||||||
|
"expected_codes":"200-299"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleHealthmonitorGetSuccessfully sets up the test server to respond to a healthmonitor Get request.
|
||||||
|
func HandleHealthmonitorGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/healthmonitors/5d4b5228-33b0-4e60-b225-9b727c1a20e7", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, SingleHealthmonitorBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleHealthmonitorDeletionSuccessfully sets up the test server to respond to a healthmonitor deletion request.
|
||||||
|
func HandleHealthmonitorDeletionSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/healthmonitors/5d4b5228-33b0-4e60-b225-9b727c1a20e7", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleHealthmonitorUpdateSuccessfully sets up the test server to respond to a healthmonitor Update request.
|
||||||
|
func HandleHealthmonitorUpdateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/healthmonitors/5d4b5228-33b0-4e60-b225-9b727c1a20e7", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "PUT")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"healthmonitor": {
|
||||||
|
"name": "NewHealthmonitorName",
|
||||||
|
"delay": 3,
|
||||||
|
"timeout": 20,
|
||||||
|
"max_retries": 10,
|
||||||
|
"url_path": "/another_check",
|
||||||
|
"expected_codes": "301"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, PostUpdateHealthmonitorBody)
|
||||||
|
})
|
||||||
|
}
|
304
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/requests.go
generated
vendored
Normal file
304
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
package monitors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
type monitorOpts struct {
|
||||||
|
// Required. The Pool to Monitor.
|
||||||
|
PoolID string
|
||||||
|
|
||||||
|
// Optional. The Name of the Monitor.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Required for admins. Indicates the owner of the Loadbalancer.
|
||||||
|
TenantID string
|
||||||
|
|
||||||
|
// Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
|
||||||
|
// sent by the load balancer to verify the member state.
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// Required. The time, in seconds, between sending probes to members.
|
||||||
|
Delay int
|
||||||
|
|
||||||
|
// Required. Maximum number of seconds for a Monitor to wait for a ping reply
|
||||||
|
// before it times out. The value must be less than the delay value.
|
||||||
|
Timeout int
|
||||||
|
|
||||||
|
// Required. Number of permissible ping failures before changing the member's
|
||||||
|
// status to INACTIVE. Must be a number between 1 and 10.
|
||||||
|
MaxRetries int
|
||||||
|
|
||||||
|
// Required for HTTP(S) types. URI path that will be accessed if Monitor type
|
||||||
|
// is HTTP or HTTPS.
|
||||||
|
URLPath string
|
||||||
|
|
||||||
|
// Required for HTTP(S) types. The HTTP method used for requests by the
|
||||||
|
// Monitor. If this attribute is not specified, it defaults to "GET".
|
||||||
|
HTTPMethod string
|
||||||
|
|
||||||
|
// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
|
||||||
|
// Monitor. You can either specify a single status like "200", or a range
|
||||||
|
// like "200-202".
|
||||||
|
ExpectedCodes string
|
||||||
|
|
||||||
|
AdminStateUp *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// List request.
|
||||||
|
type ListOptsBuilder interface {
|
||||||
|
ToMonitorListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the Monitor attributes you want to see returned. SortKey allows you to
|
||||||
|
// sort by a particular Monitor attribute. SortDir sets the direction, and is
|
||||||
|
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type ListOpts struct {
|
||||||
|
ID string `q:"id"`
|
||||||
|
Name string `q:"name"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
PoolID string `q:"pool_id"`
|
||||||
|
Type string `q:"type"`
|
||||||
|
Delay int `q:"delay"`
|
||||||
|
Timeout int `q:"timeout"`
|
||||||
|
MaxRetries int `q:"max_retries"`
|
||||||
|
HTTPMethod string `q:"http_method"`
|
||||||
|
URLPath string `q:"url_path"`
|
||||||
|
ExpectedCodes string `q:"expected_codes"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
Status string `q:"status"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMonitorListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts ListOpts) ToMonitorListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return q.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// health monitors. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those health monitors that are owned by the
|
||||||
|
// tenant who submits the request, unless an admin user submits the request.
|
||||||
|
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||||
|
url := rootURL(c)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToMonitorListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return MonitorPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constants that represent approved monitoring types.
|
||||||
|
const (
|
||||||
|
TypePING = "PING"
|
||||||
|
TypeTCP = "TCP"
|
||||||
|
TypeHTTP = "HTTP"
|
||||||
|
TypeHTTPS = "HTTPS"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errPoolIDRequired = fmt.Errorf("PoolID to monitor is required")
|
||||||
|
errValidTypeRequired = fmt.Errorf("A valid Type is required. Supported values are PING, TCP, HTTP and HTTPS")
|
||||||
|
errDelayRequired = fmt.Errorf("Delay is required")
|
||||||
|
errTimeoutRequired = fmt.Errorf("Timeout is required")
|
||||||
|
errMaxRetriesRequired = fmt.Errorf("MaxRetries is required")
|
||||||
|
errURLPathRequired = fmt.Errorf("URL path is required")
|
||||||
|
errExpectedCodesRequired = fmt.Errorf("ExpectedCodes is required")
|
||||||
|
errDelayMustGETimeout = fmt.Errorf("Delay must be greater than or equal to timeout")
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Create operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToMonitorCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts is the common options struct used in this package's Create
|
||||||
|
// operation.
|
||||||
|
type CreateOpts monitorOpts
|
||||||
|
|
||||||
|
// ToMonitorCreateMap casts a CreateOpts struct to a map.
|
||||||
|
func (opts CreateOpts) ToMonitorCreateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
allowed := map[string]bool{TypeHTTP: true, TypeHTTPS: true, TypeTCP: true, TypePING: true}
|
||||||
|
|
||||||
|
if allowed[opts.Type] {
|
||||||
|
l["type"] = opts.Type
|
||||||
|
} else {
|
||||||
|
return nil, errValidTypeRequired
|
||||||
|
}
|
||||||
|
if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
|
||||||
|
if opts.URLPath != "" {
|
||||||
|
l["url_path"] = opts.URLPath
|
||||||
|
} else {
|
||||||
|
return nil, errURLPathRequired
|
||||||
|
}
|
||||||
|
if opts.ExpectedCodes != "" {
|
||||||
|
l["expected_codes"] = opts.ExpectedCodes
|
||||||
|
} else {
|
||||||
|
return nil, errExpectedCodesRequired
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opts.PoolID != "" {
|
||||||
|
l["pool_id"] = opts.PoolID
|
||||||
|
} else {
|
||||||
|
return nil, errPoolIDRequired
|
||||||
|
}
|
||||||
|
if opts.Delay != 0 {
|
||||||
|
l["delay"] = opts.Delay
|
||||||
|
} else {
|
||||||
|
return nil, errDelayRequired
|
||||||
|
}
|
||||||
|
if opts.Timeout != 0 {
|
||||||
|
l["timeout"] = opts.Timeout
|
||||||
|
} else {
|
||||||
|
return nil, errMaxRetriesRequired
|
||||||
|
}
|
||||||
|
if opts.MaxRetries != 0 {
|
||||||
|
l["max_retries"] = opts.MaxRetries
|
||||||
|
} else {
|
||||||
|
return nil, errMaxRetriesRequired
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.TenantID != "" {
|
||||||
|
l["tenant_id"] = opts.TenantID
|
||||||
|
}
|
||||||
|
if opts.HTTPMethod != "" {
|
||||||
|
l["http_method"] = opts.HTTPMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"healthmonitor": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create is an operation which provisions a new Health Monitor. There are
|
||||||
|
different types of Monitor you can provision: PING, TCP or HTTP(S). Below
|
||||||
|
are examples of how to create each one.
|
||||||
|
|
||||||
|
Here is an example config struct to use when creating a PING or TCP Monitor:
|
||||||
|
|
||||||
|
CreateOpts{Type: TypePING, Delay: 20, Timeout: 10, MaxRetries: 3}
|
||||||
|
CreateOpts{Type: TypeTCP, Delay: 20, Timeout: 10, MaxRetries: 3}
|
||||||
|
|
||||||
|
Here is an example config struct to use when creating a HTTP(S) Monitor:
|
||||||
|
|
||||||
|
CreateOpts{Type: TypeHTTP, Delay: 20, Timeout: 10, MaxRetries: 3,
|
||||||
|
HttpMethod: "HEAD", ExpectedCodes: "200", PoolID: "2c946bfc-1804-43ab-a2ff-58f6a762b505"}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToMonitorCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a particular Health Monitor based on its unique ID.
|
||||||
|
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Update operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type UpdateOptsBuilder interface {
|
||||||
|
ToMonitorUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts is the common options struct used in this package's Update
|
||||||
|
// operation.
|
||||||
|
type UpdateOpts monitorOpts
|
||||||
|
|
||||||
|
// ToMonitorUpdateMap casts a UpdateOpts struct to a map.
|
||||||
|
func (opts UpdateOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.URLPath != "" {
|
||||||
|
l["url_path"] = opts.URLPath
|
||||||
|
}
|
||||||
|
if opts.ExpectedCodes != "" {
|
||||||
|
l["expected_codes"] = opts.ExpectedCodes
|
||||||
|
}
|
||||||
|
if opts.Delay != 0 {
|
||||||
|
l["delay"] = opts.Delay
|
||||||
|
}
|
||||||
|
if opts.Timeout != 0 {
|
||||||
|
l["timeout"] = opts.Timeout
|
||||||
|
}
|
||||||
|
if opts.MaxRetries != 0 {
|
||||||
|
l["max_retries"] = opts.MaxRetries
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.HTTPMethod != "" {
|
||||||
|
l["http_method"] = opts.HTTPMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"healthmonitor": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is an operation which modifies the attributes of the specified Monitor.
|
||||||
|
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
||||||
|
var res UpdateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToMonitorUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200, 202},
|
||||||
|
})
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete will permanently delete a particular Monitor based on its unique ID.
|
||||||
|
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = c.Delete(resourceURL(c, id), nil)
|
||||||
|
return res
|
||||||
|
}
|
160
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/results.go
generated
vendored
Normal file
160
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/results.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
package monitors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PoolID struct {
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor represents a load balancer health monitor. A health monitor is used
|
||||||
|
// to determine whether or not back-end members of the VIP's pool are usable
|
||||||
|
// for processing a request. A pool can have several health monitors associated
|
||||||
|
// with it. There are different types of health monitors supported:
|
||||||
|
//
|
||||||
|
// PING: used to ping the members using ICMP.
|
||||||
|
// TCP: used to connect to the members using TCP.
|
||||||
|
// HTTP: used to send an HTTP request to the member.
|
||||||
|
// HTTPS: used to send a secure HTTP request to the member.
|
||||||
|
//
|
||||||
|
// When a pool has several monitors associated with it, each member of the pool
|
||||||
|
// is monitored by all these monitors. If any monitor declares the member as
|
||||||
|
// unhealthy, then the member status is changed to INACTIVE and the member
|
||||||
|
// won't participate in its pool's load balancing. In other words, ALL monitors
|
||||||
|
// must declare the member to be healthy for it to stay ACTIVE.
|
||||||
|
type Monitor struct {
|
||||||
|
// The unique ID for the Monitor.
|
||||||
|
ID string
|
||||||
|
|
||||||
|
// The Name of the Monitor.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Only an administrative user can specify a tenant ID
|
||||||
|
// other than its own.
|
||||||
|
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
|
||||||
|
|
||||||
|
// The type of probe sent by the load balancer to verify the member state,
|
||||||
|
// which is PING, TCP, HTTP, or HTTPS.
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// The time, in seconds, between sending probes to members.
|
||||||
|
Delay int
|
||||||
|
|
||||||
|
// The maximum number of seconds for a monitor to wait for a connection to be
|
||||||
|
// established before it times out. This value must be less than the delay value.
|
||||||
|
Timeout int
|
||||||
|
|
||||||
|
// Number of allowed connection failures before changing the status of the
|
||||||
|
// member to INACTIVE. A valid value is from 1 to 10.
|
||||||
|
MaxRetries int `json:"max_retries" mapstructure:"max_retries"`
|
||||||
|
|
||||||
|
// The HTTP method that the monitor uses for requests.
|
||||||
|
HTTPMethod string `json:"http_method" mapstructure:"http_method"`
|
||||||
|
|
||||||
|
// The HTTP path of the request sent by the monitor to test the health of a
|
||||||
|
// member. Must be a string beginning with a forward slash (/).
|
||||||
|
URLPath string `json:"url_path" mapstructure:"url_path"`
|
||||||
|
|
||||||
|
// Expected HTTP codes for a passing HTTP(S) monitor.
|
||||||
|
ExpectedCodes string `json:"expected_codes" mapstructure:"expected_codes"`
|
||||||
|
|
||||||
|
// The administrative state of the health monitor, which is up (true) or down (false).
|
||||||
|
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
|
||||||
|
|
||||||
|
// The status of the health monitor. Indicates whether the health monitor is
|
||||||
|
// operational.
|
||||||
|
Status string
|
||||||
|
|
||||||
|
// List of pools that are associated with the health monitor.
|
||||||
|
Pools []PoolID `mapstructure:"pools" json:"pools"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pool struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// MonitorPage is the page returned by a pager when traversing over a
|
||||||
|
// collection of health monitors.
|
||||||
|
type MonitorPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of monitors has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (p MonitorPage) NextPageURL() (string, error) {
|
||||||
|
type resp struct {
|
||||||
|
Links []gophercloud.Link `mapstructure:"healthmonitors_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var r resp
|
||||||
|
err := mapstructure.Decode(p.Body, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gophercloud.ExtractNextURL(r.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a PoolPage struct is empty.
|
||||||
|
func (p MonitorPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractMonitors(p)
|
||||||
|
if err != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return len(is) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractMonitors accepts a Page struct, specifically a MonitorPage struct,
|
||||||
|
// and extracts the elements into a slice of Monitor structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractMonitors(page pagination.Page) ([]Monitor, error) {
|
||||||
|
var resp struct {
|
||||||
|
Monitors []Monitor `mapstructure:"healthmonitors" json:"healthmonitors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(page.(MonitorPage).Body, &resp)
|
||||||
|
|
||||||
|
return resp.Monitors, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type commonResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a monitor.
|
||||||
|
func (r commonResult) Extract() (*Monitor, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
Monitor *Monitor `json:"healthmonitor" mapstructure:"healthmonitor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.Monitor, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult represents the result of a create operation.
|
||||||
|
type CreateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult represents the result of a get operation.
|
||||||
|
type GetResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResult represents the result of an update operation.
|
||||||
|
type UpdateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult represents the result of a delete operation.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
16
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/urls.go
generated
vendored
Normal file
16
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package monitors
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
const (
|
||||||
|
rootPath = "lbaas"
|
||||||
|
resourcePath = "healthmonitors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, id)
|
||||||
|
}
|
389
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/fixtures.go
generated
vendored
Normal file
389
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/fixtures.go
generated
vendored
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
// +build fixtures
|
||||||
|
|
||||||
|
package pools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
th "github.com/rackspace/gophercloud/testhelper"
|
||||||
|
"github.com/rackspace/gophercloud/testhelper/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PoolsListBody contains the canned body of a pool list response.
|
||||||
|
const PoolsListBody = `
|
||||||
|
{
|
||||||
|
"pools":[
|
||||||
|
{
|
||||||
|
"lb_algorithm":"ROUND_ROBIN",
|
||||||
|
"protocol":"HTTP",
|
||||||
|
"description":"",
|
||||||
|
"healthmonitor_id": "466c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
"members":[{"id": "53306cda-815d-4354-9fe4-59e09da9c3c5"}],
|
||||||
|
"listeners":[{"id": "2a280670-c202-4b0b-a562-34077415aabf"}],
|
||||||
|
"loadbalancers":[{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"id":"72741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
"name":"web",
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"provider": "haproxy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lb_algorithm":"LEAST_CONNECTION",
|
||||||
|
"protocol":"HTTP",
|
||||||
|
"description":"",
|
||||||
|
"healthmonitor_id": "5f6c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
"members":[{"id": "67306cda-815d-4354-9fe4-59e09da9c3c5"}],
|
||||||
|
"listeners":[{"id": "2a280670-c202-4b0b-a562-34077415aabf"}],
|
||||||
|
"loadbalancers":[{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"id":"c3741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
"name":"db",
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"provider": "haproxy"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SinglePoolBody is the canned body of a Get request on an existing pool.
|
||||||
|
const SinglePoolBody = `
|
||||||
|
{
|
||||||
|
"pool": {
|
||||||
|
"lb_algorithm":"LEAST_CONNECTION",
|
||||||
|
"protocol":"HTTP",
|
||||||
|
"description":"",
|
||||||
|
"healthmonitor_id": "5f6c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
"members":[{"id": "67306cda-815d-4354-9fe4-59e09da9c3c5"}],
|
||||||
|
"listeners":[{"id": "2a280670-c202-4b0b-a562-34077415aabf"}],
|
||||||
|
"loadbalancers":[{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"id":"c3741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
"name":"db",
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"provider": "haproxy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// PostUpdatePoolBody is the canned response body of a Update request on an existing pool.
|
||||||
|
const PostUpdatePoolBody = `
|
||||||
|
{
|
||||||
|
"pool": {
|
||||||
|
"lb_algorithm":"LEAST_CONNECTION",
|
||||||
|
"protocol":"HTTP",
|
||||||
|
"description":"",
|
||||||
|
"healthmonitor_id": "5f6c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
"members":[{"id": "67306cda-815d-4354-9fe4-59e09da9c3c5"}],
|
||||||
|
"listeners":[{"id": "2a280670-c202-4b0b-a562-34077415aabf"}],
|
||||||
|
"loadbalancers":[{"id": "79e05663-7f03-45d2-a092-8b94062f22ab"}],
|
||||||
|
"id":"c3741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
"name":"db",
|
||||||
|
"admin_state_up":true,
|
||||||
|
"tenant_id":"83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
"provider": "haproxy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
PoolWeb = Pool{
|
||||||
|
LBMethod: "ROUND_ROBIN",
|
||||||
|
Protocol: "HTTP",
|
||||||
|
Description: "",
|
||||||
|
MonitorID: "466c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
TenantID: "83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "web",
|
||||||
|
Members: []Member{{ID: "53306cda-815d-4354-9fe4-59e09da9c3c5"}},
|
||||||
|
ID: "72741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
Loadbalancers: []LoadBalancerID{{ID: "79e05663-7f03-45d2-a092-8b94062f22ab"}},
|
||||||
|
Listeners: []ListenerID{{ID: "2a280670-c202-4b0b-a562-34077415aabf"}},
|
||||||
|
Provider: "haproxy",
|
||||||
|
}
|
||||||
|
PoolDb = Pool{
|
||||||
|
LBMethod: "LEAST_CONNECTION",
|
||||||
|
Protocol: "HTTP",
|
||||||
|
Description: "",
|
||||||
|
MonitorID: "5f6c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
TenantID: "83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "db",
|
||||||
|
Members: []Member{{ID: "67306cda-815d-4354-9fe4-59e09da9c3c5"}},
|
||||||
|
ID: "c3741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
Loadbalancers: []LoadBalancerID{{ID: "79e05663-7f03-45d2-a092-8b94062f22ab"}},
|
||||||
|
Listeners: []ListenerID{{ID: "2a280670-c202-4b0b-a562-34077415aabf"}},
|
||||||
|
Provider: "haproxy",
|
||||||
|
}
|
||||||
|
PoolUpdated = Pool{
|
||||||
|
LBMethod: "LEAST_CONNECTION",
|
||||||
|
Protocol: "HTTP",
|
||||||
|
Description: "",
|
||||||
|
MonitorID: "5f6c8345-28d8-4f84-a246-e04380b0461d",
|
||||||
|
TenantID: "83657cfcdfe44cd5920adaf26c48ceea",
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "db",
|
||||||
|
Members: []Member{{ID: "67306cda-815d-4354-9fe4-59e09da9c3c5"}},
|
||||||
|
ID: "c3741b06-df4d-4715-b142-276b6bce75ab",
|
||||||
|
Loadbalancers: []LoadBalancerID{{ID: "79e05663-7f03-45d2-a092-8b94062f22ab"}},
|
||||||
|
Listeners: []ListenerID{{ID: "2a280670-c202-4b0b-a562-34077415aabf"}},
|
||||||
|
Provider: "haproxy",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandlePoolListSuccessfully sets up the test server to respond to a pool List request.
|
||||||
|
func HandlePoolListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
r.ParseForm()
|
||||||
|
marker := r.Form.Get("marker")
|
||||||
|
switch marker {
|
||||||
|
case "":
|
||||||
|
fmt.Fprintf(w, PoolsListBody)
|
||||||
|
case "45e08a3e-a78f-4b40-a229-1e7e23eee1ab":
|
||||||
|
fmt.Fprintf(w, `{ "pools": [] }`)
|
||||||
|
default:
|
||||||
|
t.Fatalf("/v2.0/lbaas/pools invoked with unexpected marker=[%s]", marker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlePoolCreationSuccessfully sets up the test server to respond to a pool creation request
|
||||||
|
// with a given response.
|
||||||
|
func HandlePoolCreationSuccessfully(t *testing.T, response string) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"pool": {
|
||||||
|
"lb_algorithm": "ROUND_ROBIN",
|
||||||
|
"protocol": "HTTP",
|
||||||
|
"name": "Example pool",
|
||||||
|
"tenant_id": "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
"loadbalancer_id": "79e05663-7f03-45d2-a092-8b94062f22ab"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlePoolGetSuccessfully sets up the test server to respond to a pool Get request.
|
||||||
|
func HandlePoolGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/c3741b06-df4d-4715-b142-276b6bce75ab", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, SinglePoolBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlePoolDeletionSuccessfully sets up the test server to respond to a pool deletion request.
|
||||||
|
func HandlePoolDeletionSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/c3741b06-df4d-4715-b142-276b6bce75ab", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlePoolUpdateSuccessfully sets up the test server to respond to a pool Update request.
|
||||||
|
func HandlePoolUpdateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/c3741b06-df4d-4715-b142-276b6bce75ab", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "PUT")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"pool": {
|
||||||
|
"name": "NewPoolName",
|
||||||
|
"lb_algorithm": "LEAST_CONNECTIONS"
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, PostUpdatePoolBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MembersListBody contains the canned body of a member list response.
|
||||||
|
const MembersListBody = `
|
||||||
|
{
|
||||||
|
"members":[
|
||||||
|
{
|
||||||
|
"id": "2a280670-c202-4b0b-a562-34077415aabf",
|
||||||
|
"address": "10.0.2.10",
|
||||||
|
"weight": 5,
|
||||||
|
"name": "web",
|
||||||
|
"subnet_id": "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
"tenant_id": "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
"admin_state_up":true,
|
||||||
|
"protocol_port": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
"address": "10.0.2.11",
|
||||||
|
"weight": 10,
|
||||||
|
"name": "db",
|
||||||
|
"subnet_id": "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
"tenant_id": "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
"admin_state_up":false,
|
||||||
|
"protocol_port": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SingleMemberBody is the canned body of a Get request on an existing member.
|
||||||
|
const SingleMemberBody = `
|
||||||
|
{
|
||||||
|
"member": {
|
||||||
|
"id": "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
"address": "10.0.2.11",
|
||||||
|
"weight": 10,
|
||||||
|
"name": "db",
|
||||||
|
"subnet_id": "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
"tenant_id": "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
"admin_state_up":false,
|
||||||
|
"protocol_port": 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// PostUpdateMemberBody is the canned response body of a Update request on an existing member.
|
||||||
|
const PostUpdateMemberBody = `
|
||||||
|
{
|
||||||
|
"member": {
|
||||||
|
"id": "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
"address": "10.0.2.11",
|
||||||
|
"weight": 10,
|
||||||
|
"name": "db",
|
||||||
|
"subnet_id": "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
"tenant_id": "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
"admin_state_up":false,
|
||||||
|
"protocol_port": 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
MemberWeb = Member{
|
||||||
|
SubnetID: "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
TenantID: "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
AdminStateUp: true,
|
||||||
|
Name: "web",
|
||||||
|
ID: "2a280670-c202-4b0b-a562-34077415aabf",
|
||||||
|
Address: "10.0.2.10",
|
||||||
|
Weight: 5,
|
||||||
|
ProtocolPort: 80,
|
||||||
|
}
|
||||||
|
MemberDb = Member{
|
||||||
|
SubnetID: "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
TenantID: "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
AdminStateUp: false,
|
||||||
|
Name: "db",
|
||||||
|
ID: "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
Address: "10.0.2.11",
|
||||||
|
Weight: 10,
|
||||||
|
ProtocolPort: 80,
|
||||||
|
}
|
||||||
|
MemberUpdated = Member{
|
||||||
|
SubnetID: "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
TenantID: "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
AdminStateUp: false,
|
||||||
|
Name: "db",
|
||||||
|
ID: "fad389a3-9a4a-4762-a365-8c7038508b5d",
|
||||||
|
Address: "10.0.2.11",
|
||||||
|
Weight: 10,
|
||||||
|
ProtocolPort: 80,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleMemberListSuccessfully sets up the test server to respond to a member List request.
|
||||||
|
func HandleMemberListSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/332abe93-f488-41ba-870b-2ac66be7f853/members", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
r.ParseForm()
|
||||||
|
marker := r.Form.Get("marker")
|
||||||
|
switch marker {
|
||||||
|
case "":
|
||||||
|
fmt.Fprintf(w, MembersListBody)
|
||||||
|
case "45e08a3e-a78f-4b40-a229-1e7e23eee1ab":
|
||||||
|
fmt.Fprintf(w, `{ "members": [] }`)
|
||||||
|
default:
|
||||||
|
t.Fatalf("/v2.0/lbaas/pools/332abe93-f488-41ba-870b-2ac66be7f853/members invoked with unexpected marker=[%s]", marker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleMemberCreationSuccessfully sets up the test server to respond to a member creation request
|
||||||
|
// with a given response.
|
||||||
|
func HandleMemberCreationSuccessfully(t *testing.T, response string) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/332abe93-f488-41ba-870b-2ac66be7f853/members", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "POST")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"member": {
|
||||||
|
"address": "10.0.2.11",
|
||||||
|
"weight": 10,
|
||||||
|
"name": "db",
|
||||||
|
"subnet_id": "1981f108-3c48-48d2-b908-30f7d28532c9",
|
||||||
|
"tenant_id": "2ffc6e22aae24e4795f87155d24c896f",
|
||||||
|
"protocol_port": 80
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
fmt.Fprintf(w, response)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleMemberGetSuccessfully sets up the test server to respond to a member Get request.
|
||||||
|
func HandleMemberGetSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/332abe93-f488-41ba-870b-2ac66be7f853/members/2a280670-c202-4b0b-a562-34077415aabf", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "GET")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, SingleMemberBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleMemberDeletionSuccessfully sets up the test server to respond to a member deletion request.
|
||||||
|
func HandleMemberDeletionSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/332abe93-f488-41ba-870b-2ac66be7f853/members/2a280670-c202-4b0b-a562-34077415aabf", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "DELETE")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleMemberUpdateSuccessfully sets up the test server to respond to a member Update request.
|
||||||
|
func HandleMemberUpdateSuccessfully(t *testing.T) {
|
||||||
|
th.Mux.HandleFunc("/v2.0/lbaas/pools/332abe93-f488-41ba-870b-2ac66be7f853/members/2a280670-c202-4b0b-a562-34077415aabf", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
th.TestMethod(t, r, "PUT")
|
||||||
|
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
|
||||||
|
th.TestHeader(t, r, "Accept", "application/json")
|
||||||
|
th.TestHeader(t, r, "Content-Type", "application/json")
|
||||||
|
th.TestJSONRequest(t, r, `{
|
||||||
|
"member": {
|
||||||
|
"name": "newMemberName",
|
||||||
|
"weight": 4
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, PostUpdateMemberBody)
|
||||||
|
})
|
||||||
|
}
|
485
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/requests.go
generated
vendored
Normal file
485
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,485 @@
|
||||||
|
package pools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminState gives users a solid type to work with for create and update
|
||||||
|
// operations. It is recommended that users use the `Up` and `Down` enums.
|
||||||
|
type AdminState *bool
|
||||||
|
|
||||||
|
type poolOpts struct {
|
||||||
|
// Only required if the caller has an admin role and wants to create a pool
|
||||||
|
// for another tenant.
|
||||||
|
TenantID string
|
||||||
|
|
||||||
|
// Optional. Name of the pool.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Optional. Human-readable description for the pool.
|
||||||
|
Description string
|
||||||
|
|
||||||
|
// Required. The protocol used by the pool members, you can use either
|
||||||
|
// ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
|
||||||
|
Protocol Protocol
|
||||||
|
|
||||||
|
// The Loadbalancer on which the members of the pool will be associated with.
|
||||||
|
// Note: one of LoadbalancerID or ListenerID must be provided.
|
||||||
|
LoadbalancerID string
|
||||||
|
|
||||||
|
// The Listener on which the members of the pool will be associated with.
|
||||||
|
// Note: one of LoadbalancerID or ListenerID must be provided.
|
||||||
|
ListenerID string
|
||||||
|
|
||||||
|
// Required. The algorithm used to distribute load between the members of the pool. The
|
||||||
|
// current specification supports LBMethodRoundRobin, LBMethodLeastConnections
|
||||||
|
// and LBMethodSourceIp as valid values for this attribute.
|
||||||
|
LBMethod LBMethod
|
||||||
|
|
||||||
|
// Optional. Omit this field to prevent session persistence.
|
||||||
|
Persistence *SessionPersistence
|
||||||
|
|
||||||
|
// Optional. The administrative state of the Pool. A valid value is true (UP)
|
||||||
|
// or false (DOWN).
|
||||||
|
AdminStateUp *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience vars for AdminStateUp values.
|
||||||
|
var (
|
||||||
|
iTrue = true
|
||||||
|
iFalse = false
|
||||||
|
|
||||||
|
Up AdminState = &iTrue
|
||||||
|
Down AdminState = &iFalse
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// List request.
|
||||||
|
type ListOptsBuilder interface {
|
||||||
|
ToPoolListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the Pool attributes you want to see returned. SortKey allows you to
|
||||||
|
// sort by a particular Pool attribute. SortDir sets the direction, and is
|
||||||
|
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type ListOpts struct {
|
||||||
|
LBMethod string `q:"lb_algorithm"`
|
||||||
|
Protocol string `q:"protocol"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
Name string `q:"name"`
|
||||||
|
ID string `q:"id"`
|
||||||
|
LoadbalancerID string `q:"loadbalancer_id"`
|
||||||
|
ListenerID string `q:"listener_id"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPoolListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts ListOpts) ToPoolListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return q.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// pools. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those pools that are owned by the
|
||||||
|
// tenant who submits the request, unless an admin user submits the request.
|
||||||
|
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||||
|
url := rootURL(c)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToPoolListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return PoolPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type LBMethod string
|
||||||
|
type Protocol string
|
||||||
|
|
||||||
|
// Supported attributes for create/update operations.
|
||||||
|
const (
|
||||||
|
LBMethodRoundRobin LBMethod = "ROUND_ROBIN"
|
||||||
|
LBMethodLeastConnections LBMethod = "LEAST_CONNECTIONS"
|
||||||
|
LBMethodSourceIp LBMethod = "SOURCE_IP"
|
||||||
|
|
||||||
|
ProtocolTCP Protocol = "TCP"
|
||||||
|
ProtocolHTTP Protocol = "HTTP"
|
||||||
|
ProtocolHTTPS Protocol = "HTTPS"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errLoadbalancerOrListenerRequired = fmt.Errorf("A ListenerID or LoadbalancerID is required")
|
||||||
|
errValidLBMethodRequired = fmt.Errorf("A valid LBMethod is required. Supported values are ROUND_ROBIN, LEAST_CONNECTIONS, SOURCE_IP")
|
||||||
|
errValidProtocolRequired = fmt.Errorf("A valid Protocol is required. Supported values are TCP, HTTP, HTTPS")
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Create operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToPoolCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts is the common options struct used in this package's Create
|
||||||
|
// operation.
|
||||||
|
type CreateOpts poolOpts
|
||||||
|
|
||||||
|
// ToPoolCreateMap casts a CreateOpts struct to a map.
|
||||||
|
func (opts CreateOpts) ToPoolCreateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
allowedLBMethod := map[LBMethod]bool{LBMethodRoundRobin: true, LBMethodLeastConnections: true, LBMethodSourceIp: true}
|
||||||
|
allowedProtocol := map[Protocol]bool{ProtocolTCP: true, ProtocolHTTP: true, ProtocolHTTPS: true}
|
||||||
|
|
||||||
|
if allowedLBMethod[opts.LBMethod] {
|
||||||
|
l["lb_algorithm"] = opts.LBMethod
|
||||||
|
} else {
|
||||||
|
return nil, errValidLBMethodRequired
|
||||||
|
}
|
||||||
|
if allowedProtocol[opts.Protocol] {
|
||||||
|
l["protocol"] = opts.Protocol
|
||||||
|
} else {
|
||||||
|
return nil, errValidProtocolRequired
|
||||||
|
}
|
||||||
|
if opts.LoadbalancerID == "" && opts.ListenerID == "" {
|
||||||
|
return nil, errLoadbalancerOrListenerRequired
|
||||||
|
} else {
|
||||||
|
if opts.LoadbalancerID != "" {
|
||||||
|
l["loadbalancer_id"] = opts.LoadbalancerID
|
||||||
|
}
|
||||||
|
if opts.ListenerID != "" {
|
||||||
|
l["listener_id"] = opts.ListenerID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.TenantID != "" {
|
||||||
|
l["tenant_id"] = opts.TenantID
|
||||||
|
}
|
||||||
|
if opts.Persistence != nil {
|
||||||
|
l["session_persistence"] = &opts.Persistence
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"pool": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create accepts a CreateOpts struct and uses the values to create a new
|
||||||
|
// load balancer pool.
|
||||||
|
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToPoolCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a particular pool based on its unique ID.
|
||||||
|
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Update operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type UpdateOptsBuilder interface {
|
||||||
|
ToPoolUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts is the common options struct used in this package's Update
|
||||||
|
// operation.
|
||||||
|
type UpdateOpts poolOpts
|
||||||
|
|
||||||
|
// ToPoolUpdateMap casts a UpdateOpts struct to a map.
|
||||||
|
func (opts UpdateOpts) ToPoolUpdateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
allowedLBMethod := map[LBMethod]bool{LBMethodRoundRobin: true, LBMethodLeastConnections: true, LBMethodSourceIp: true}
|
||||||
|
|
||||||
|
if opts.LBMethod != "" {
|
||||||
|
if allowedLBMethod[opts.LBMethod] {
|
||||||
|
l["lb_algorithm"] = opts.LBMethod
|
||||||
|
} else {
|
||||||
|
return nil, errValidLBMethodRequired
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.Description != "" {
|
||||||
|
l["description"] = opts.Description
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"pool": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update allows pools to be updated.
|
||||||
|
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
||||||
|
var res UpdateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToPoolUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete will permanently delete a particular pool based on its unique ID.
|
||||||
|
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = c.Delete(resourceURL(c, id), nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts contains all the values needed to create a new Member for a Pool.
|
||||||
|
type memberOpts struct {
|
||||||
|
// Optional. Name of the Member.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Only required if the caller has an admin role and wants to create a Member
|
||||||
|
// for another tenant.
|
||||||
|
TenantID string
|
||||||
|
|
||||||
|
// Required. The IP address of the member to receive traffic from the load balancer.
|
||||||
|
Address string
|
||||||
|
|
||||||
|
// Required. The port on which to listen for client traffic.
|
||||||
|
ProtocolPort int
|
||||||
|
|
||||||
|
// Optional. A positive integer value that indicates the relative portion of
|
||||||
|
// traffic that this member should receive from the pool. For example, a
|
||||||
|
// member with a weight of 10 receives five times as much traffic as a member
|
||||||
|
// with a weight of 2.
|
||||||
|
Weight int
|
||||||
|
|
||||||
|
// Optional. If you omit this parameter, LBaaS uses the vip_subnet_id
|
||||||
|
// parameter value for the subnet UUID.
|
||||||
|
SubnetID string
|
||||||
|
|
||||||
|
// Optional. The administrative state of the Pool. A valid value is true (UP)
|
||||||
|
// or false (DOWN).
|
||||||
|
AdminStateUp *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// Member List request.
|
||||||
|
type MemberListOptsBuilder interface {
|
||||||
|
ToMemberListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the Member attributes you want to see returned. SortKey allows you to
|
||||||
|
// sort by a particular Member attribute. SortDir sets the direction, and is
|
||||||
|
// either `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type MemberListOpts struct {
|
||||||
|
Name string `q:"name"`
|
||||||
|
Weight int `q:"weight"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
Address string `q:"address"`
|
||||||
|
ProtocolPort int `q:"protocol_port"`
|
||||||
|
ID string `q:"id"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToMemberListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts MemberListOpts) ToMemberListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return q.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// members. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those members that are owned by the
|
||||||
|
// tenant who submits the request, unless an admin user submits the request.
|
||||||
|
func ListAssociateMembers(c *gophercloud.ServiceClient, poolID string, opts MemberListOptsBuilder) pagination.Pager {
|
||||||
|
url := memberRootURL(c, poolID)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToMemberListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return MemberPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errPoolIdRequired = fmt.Errorf("PoolID is required")
|
||||||
|
errAddressRequired = fmt.Errorf("Address is required")
|
||||||
|
errProtocolPortRequired = fmt.Errorf("ProtocolPort is required")
|
||||||
|
)
|
||||||
|
|
||||||
|
// MemberCreateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Create operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type MemberCreateOptsBuilder interface {
|
||||||
|
ToMemberCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberCreateOpts is the common options struct used in this package's Create
|
||||||
|
// operation.
|
||||||
|
type MemberCreateOpts memberOpts
|
||||||
|
|
||||||
|
// ToMemberCreateMap casts a CreateOpts struct to a map.
|
||||||
|
func (opts MemberCreateOpts) ToMemberCreateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.Address != "" {
|
||||||
|
l["address"] = opts.Address
|
||||||
|
} else {
|
||||||
|
return nil, errAddressRequired
|
||||||
|
}
|
||||||
|
if opts.ProtocolPort != 0 {
|
||||||
|
l["protocol_port"] = opts.ProtocolPort
|
||||||
|
} else {
|
||||||
|
return nil, errProtocolPortRequired
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.TenantID != "" {
|
||||||
|
l["tenant_id"] = opts.TenantID
|
||||||
|
}
|
||||||
|
if opts.SubnetID != "" {
|
||||||
|
l["subnet_id"] = opts.SubnetID
|
||||||
|
}
|
||||||
|
if opts.Weight != 0 {
|
||||||
|
l["weight"] = opts.Weight
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"member": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAssociateMember will create and associate a Member with a particular Pool.
|
||||||
|
func CreateAssociateMember(c *gophercloud.ServiceClient, poolID string, opts MemberCreateOpts) AssociateResult {
|
||||||
|
var res AssociateResult
|
||||||
|
|
||||||
|
if poolID == "" {
|
||||||
|
res.Err = errPoolIdRequired
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
reqBody, err := opts.ToMemberCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
_, res.Err = c.Post(memberRootURL(c, poolID), reqBody, &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a particular Pool Member based on its unique ID.
|
||||||
|
func GetAssociateMember(c *gophercloud.ServiceClient, poolID string, memberID string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(memberResourceURL(c, poolID, memberID), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberUpdateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Update operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type MemberUpdateOptsBuilder interface {
|
||||||
|
ToMemberUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts is the common options struct used in this package's Update
|
||||||
|
// operation.
|
||||||
|
type MemberUpdateOpts memberOpts
|
||||||
|
|
||||||
|
// ToMemberUpdateMap casts a UpdateOpts struct to a map.
|
||||||
|
func (opts MemberUpdateOpts) ToMemberUpdateMap() (map[string]interface{}, error) {
|
||||||
|
l := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
l["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
l["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.Weight != 0 {
|
||||||
|
l["weight"] = opts.Weight
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"member": l}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update allows Member to be updated.
|
||||||
|
func UpdateAssociateMember(c *gophercloud.ServiceClient, poolID string, memberID string, opts MemberUpdateOpts) UpdateResult {
|
||||||
|
var res UpdateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToMemberUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to API
|
||||||
|
_, res.Err = c.Put(memberResourceURL(c, poolID, memberID), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200, 201, 202},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisassociateMember will remove and disassociate a Member from a particular Pool.
|
||||||
|
func DeleteMember(c *gophercloud.ServiceClient, poolID string, memberID string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = c.Delete(memberResourceURL(c, poolID, memberID), nil)
|
||||||
|
return res
|
||||||
|
}
|
274
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/results.go
generated
vendored
Normal file
274
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/results.go
generated
vendored
Normal file
|
@ -0,0 +1,274 @@
|
||||||
|
package pools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SessionPersistence represents the session persistence feature of the load
|
||||||
|
// balancing service. It attempts to force connections or requests in the same
|
||||||
|
// session to be processed by the same member as long as it is ative. Three
|
||||||
|
// types of persistence are supported:
|
||||||
|
//
|
||||||
|
// SOURCE_IP: With this mode, all connections originating from the same source
|
||||||
|
// IP address, will be handled by the same Member of the Pool.
|
||||||
|
// HTTP_COOKIE: With this persistence mode, the load balancing function will
|
||||||
|
// create a cookie on the first request from a client. Subsequent
|
||||||
|
// requests containing the same cookie value will be handled by
|
||||||
|
// the same Member of the Pool.
|
||||||
|
// APP_COOKIE: With this persistence mode, the load balancing function will
|
||||||
|
// rely on a cookie established by the backend application. All
|
||||||
|
// requests carrying the same cookie value will be handled by the
|
||||||
|
// same Member of the Pool.
|
||||||
|
type SessionPersistence struct {
|
||||||
|
// The type of persistence mode
|
||||||
|
Type string `mapstructure:"type" json:"type"`
|
||||||
|
|
||||||
|
// Name of cookie if persistence mode is set appropriately
|
||||||
|
CookieName string `mapstructure:"cookie_name" json:"cookie_name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerID struct {
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListenerID struct {
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool represents a logical set of devices, such as web servers, that you
|
||||||
|
// group together to receive and process traffic. The load balancing function
|
||||||
|
// chooses a Member of the Pool according to the configured load balancing
|
||||||
|
// method to handle the new requests or connections received on the VIP address.
|
||||||
|
type Pool struct {
|
||||||
|
// The load-balancer algorithm, which is round-robin, least-connections, and
|
||||||
|
// so on. This value, which must be supported, is dependent on the provider.
|
||||||
|
// Round-robin must be supported.
|
||||||
|
LBMethod string `json:"lb_algorithm" mapstructure:"lb_algorithm"`
|
||||||
|
|
||||||
|
// The protocol of the Pool, which is TCP, HTTP, or HTTPS.
|
||||||
|
Protocol string
|
||||||
|
|
||||||
|
// Description for the Pool.
|
||||||
|
Description string
|
||||||
|
|
||||||
|
// A list of listeners objects IDs.
|
||||||
|
Listeners []ListenerID `mapstructure:"listeners" json:"listeners"` //[]map[string]interface{}
|
||||||
|
|
||||||
|
// A list of member objects IDs.
|
||||||
|
Members []Member `mapstructure:"members" json:"members"`
|
||||||
|
|
||||||
|
// The ID of associated health monitor.
|
||||||
|
MonitorID string `json:"healthmonitor_id" mapstructure:"healthmonitor_id"`
|
||||||
|
|
||||||
|
// The network on which the members of the Pool will be located. Only members
|
||||||
|
// that are on this network can be added to the Pool.
|
||||||
|
SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
|
||||||
|
|
||||||
|
// Owner of the Pool. Only an administrative user can specify a tenant ID
|
||||||
|
// other than its own.
|
||||||
|
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
|
||||||
|
|
||||||
|
// The administrative state of the Pool, which is up (true) or down (false).
|
||||||
|
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
|
||||||
|
|
||||||
|
// Pool name. Does not have to be unique.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// The unique ID for the Pool.
|
||||||
|
ID string
|
||||||
|
|
||||||
|
// A list of load balancer objects IDs.
|
||||||
|
Loadbalancers []LoadBalancerID `mapstructure:"loadbalancers" json:"loadbalancers"`
|
||||||
|
|
||||||
|
// Indicates whether connections in the same session will be processed by the
|
||||||
|
// same Pool member or not.
|
||||||
|
Persistence SessionPersistence `mapstructure:"session_persistence" json:"session_persistence"`
|
||||||
|
|
||||||
|
// The provider
|
||||||
|
Provider string
|
||||||
|
|
||||||
|
Monitor monitors.Monitor `mapstructure:"healthmonitor" json:"healthmonitor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PoolPage is the page returned by a pager when traversing over a
|
||||||
|
// collection of pools.
|
||||||
|
type PoolPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of pools has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (p PoolPage) NextPageURL() (string, error) {
|
||||||
|
type resp struct {
|
||||||
|
Links []gophercloud.Link `mapstructure:"pools_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var r resp
|
||||||
|
err := mapstructure.Decode(p.Body, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gophercloud.ExtractNextURL(r.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a PoolPage struct is empty.
|
||||||
|
func (p PoolPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractPools(p)
|
||||||
|
if err != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return len(is) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractPools accepts a Page struct, specifically a RouterPage struct,
|
||||||
|
// and extracts the elements into a slice of Router structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractPools(page pagination.Page) ([]Pool, error) {
|
||||||
|
var resp struct {
|
||||||
|
Pools []Pool `mapstructure:"pools" json:"pools"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(page.(PoolPage).Body, &resp)
|
||||||
|
|
||||||
|
return resp.Pools, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type commonResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a router.
|
||||||
|
func (r commonResult) Extract() (*Pool, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
Pool *Pool `json:"pool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.Pool, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member represents the application running on a backend server.
|
||||||
|
type Member struct {
|
||||||
|
// Name of the Member.
|
||||||
|
Name string `json:"name" mapstructure:"name"`
|
||||||
|
|
||||||
|
// Weight of Member.
|
||||||
|
Weight int `json:"weight" mapstructure:"weight"`
|
||||||
|
|
||||||
|
// The administrative state of the member, which is up (true) or down (false).
|
||||||
|
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
|
||||||
|
|
||||||
|
// Owner of the Member. Only an administrative user can specify a tenant ID
|
||||||
|
// other than its own.
|
||||||
|
TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
|
||||||
|
|
||||||
|
// parameter value for the subnet UUID.
|
||||||
|
SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
|
||||||
|
|
||||||
|
// The Pool to which the Member belongs.
|
||||||
|
PoolID string `json:"pool_id" mapstructure:"pool_id"`
|
||||||
|
|
||||||
|
// The IP address of the Member.
|
||||||
|
Address string `json:"address" mapstructure:"address"`
|
||||||
|
|
||||||
|
// The port on which the application is hosted.
|
||||||
|
ProtocolPort int `json:"protocol_port" mapstructure:"protocol_port"`
|
||||||
|
|
||||||
|
// The unique ID for the Member.
|
||||||
|
ID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberPage is the page returned by a pager when traversing over a
|
||||||
|
// collection of Members in a Pool.
|
||||||
|
type MemberPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of members has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (p MemberPage) NextPageURL() (string, error) {
|
||||||
|
type resp struct {
|
||||||
|
Links []gophercloud.Link `mapstructure:"members_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var r resp
|
||||||
|
err := mapstructure.Decode(p.Body, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gophercloud.ExtractNextURL(r.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a MemberPage struct is empty.
|
||||||
|
func (p MemberPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractMembers(p)
|
||||||
|
if err != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return len(is) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractMembers accepts a Page struct, specifically a RouterPage struct,
|
||||||
|
// and extracts the elements into a slice of Router structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractMembers(page pagination.Page) ([]Member, error) {
|
||||||
|
var resp struct {
|
||||||
|
Member []Member `mapstructure:"members" json:"members"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(page.(MemberPage).Body, &resp)
|
||||||
|
|
||||||
|
return resp.Member, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractMember is a function that accepts a result and extracts a router.
|
||||||
|
func (r commonResult) ExtractMember() (*Member, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
Member *Member `json:"member"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.Member, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult represents the result of a create operation.
|
||||||
|
type CreateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult represents the result of a get operation.
|
||||||
|
type GetResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResult represents the result of an update operation.
|
||||||
|
type UpdateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult represents the result of a delete operation.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssociateResult represents the result of an association operation.
|
||||||
|
type AssociateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
25
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/urls.go
generated
vendored
Normal file
25
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package pools
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
const (
|
||||||
|
rootPath = "lbaas"
|
||||||
|
resourcePath = "pools"
|
||||||
|
memberPath = "members"
|
||||||
|
)
|
||||||
|
|
||||||
|
func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func memberRootURL(c *gophercloud.ServiceClient, poolId string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, poolId, memberPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func memberResourceURL(c *gophercloud.ServiceClient, poolID string, memeberID string) string {
|
||||||
|
return c.ServiceURL(rootPath, resourcePath, poolID, memberPath, memeberID)
|
||||||
|
}
|
8
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/doc.go
generated
vendored
Normal file
8
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Package ports contains functionality for working with Neutron port resources.
|
||||||
|
// A port represents a virtual switch port on a logical network switch. Virtual
|
||||||
|
// instances attach their interfaces into ports. The logical port also defines
|
||||||
|
// the MAC address and the IP address(es) to be assigned to the interfaces
|
||||||
|
// plugged into them. When IP addresses are associated to a port, this also
|
||||||
|
// implies the port is associated with a subnet, as the IP address was taken
|
||||||
|
// from the allocation pool for a specific subnet.
|
||||||
|
package ports
|
11
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/errors.go
generated
vendored
Normal file
11
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func err(str string) error {
|
||||||
|
return fmt.Errorf("%s", str)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errNetworkIDRequired = err("A Network ID is required")
|
||||||
|
)
|
268
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
Normal file
268
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminState gives users a solid type to work with for create and update
|
||||||
|
// operations. It is recommended that users use the `Up` and `Down` enums.
|
||||||
|
type AdminState *bool
|
||||||
|
|
||||||
|
// Convenience vars for AdminStateUp values.
|
||||||
|
var (
|
||||||
|
iTrue = true
|
||||||
|
iFalse = false
|
||||||
|
|
||||||
|
Up AdminState = &iTrue
|
||||||
|
Down AdminState = &iFalse
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||||
|
// List request.
|
||||||
|
type ListOptsBuilder interface {
|
||||||
|
ToPortListQuery() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOpts allows the filtering and sorting of paginated collections through
|
||||||
|
// the API. Filtering is achieved by passing in struct field values that map to
|
||||||
|
// the port attributes you want to see returned. SortKey allows you to sort
|
||||||
|
// by a particular port attribute. SortDir sets the direction, and is either
|
||||||
|
// `asc' or `desc'. Marker and Limit are used for pagination.
|
||||||
|
type ListOpts struct {
|
||||||
|
Status string `q:"status"`
|
||||||
|
Name string `q:"name"`
|
||||||
|
AdminStateUp *bool `q:"admin_state_up"`
|
||||||
|
NetworkID string `q:"network_id"`
|
||||||
|
TenantID string `q:"tenant_id"`
|
||||||
|
DeviceOwner string `q:"device_owner"`
|
||||||
|
MACAddress string `q:"mac_address"`
|
||||||
|
ID string `q:"id"`
|
||||||
|
DeviceID string `q:"device_id"`
|
||||||
|
Limit int `q:"limit"`
|
||||||
|
Marker string `q:"marker"`
|
||||||
|
SortKey string `q:"sort_key"`
|
||||||
|
SortDir string `q:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPortListQuery formats a ListOpts into a query string.
|
||||||
|
func (opts ListOpts) ToPortListQuery() (string, error) {
|
||||||
|
q, err := gophercloud.BuildQueryString(opts)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return q.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List returns a Pager which allows you to iterate over a collection of
|
||||||
|
// ports. It accepts a ListOpts struct, which allows you to filter and sort
|
||||||
|
// the returned collection for greater efficiency.
|
||||||
|
//
|
||||||
|
// Default policy settings return only those ports that are owned by the tenant
|
||||||
|
// who submits the request, unless the request is submitted by a user with
|
||||||
|
// administrative rights.
|
||||||
|
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
|
||||||
|
url := listURL(c)
|
||||||
|
if opts != nil {
|
||||||
|
query, err := opts.ToPortListQuery()
|
||||||
|
if err != nil {
|
||||||
|
return pagination.Pager{Err: err}
|
||||||
|
}
|
||||||
|
url += query
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
|
||||||
|
return PortPage{pagination.LinkedPageBase{PageResult: r}}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves a specific port based on its unique ID.
|
||||||
|
func Get(c *gophercloud.ServiceClient, id string) GetResult {
|
||||||
|
var res GetResult
|
||||||
|
_, res.Err = c.Get(getURL(c, id), &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Create operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type CreateOptsBuilder interface {
|
||||||
|
ToPortCreateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOpts represents the attributes used when creating a new port.
|
||||||
|
type CreateOpts struct {
|
||||||
|
NetworkID string
|
||||||
|
Name string
|
||||||
|
AdminStateUp *bool
|
||||||
|
MACAddress string
|
||||||
|
FixedIPs interface{}
|
||||||
|
DeviceID string
|
||||||
|
DeviceOwner string
|
||||||
|
TenantID string
|
||||||
|
SecurityGroups []string
|
||||||
|
AllowedAddressPairs []AddressPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPortCreateMap casts a CreateOpts struct to a map.
|
||||||
|
func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
|
||||||
|
p := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.NetworkID == "" {
|
||||||
|
return nil, errNetworkIDRequired
|
||||||
|
}
|
||||||
|
p["network_id"] = opts.NetworkID
|
||||||
|
|
||||||
|
if opts.DeviceID != "" {
|
||||||
|
p["device_id"] = opts.DeviceID
|
||||||
|
}
|
||||||
|
if opts.DeviceOwner != "" {
|
||||||
|
p["device_owner"] = opts.DeviceOwner
|
||||||
|
}
|
||||||
|
if opts.FixedIPs != nil {
|
||||||
|
p["fixed_ips"] = opts.FixedIPs
|
||||||
|
}
|
||||||
|
if opts.SecurityGroups != nil {
|
||||||
|
p["security_groups"] = opts.SecurityGroups
|
||||||
|
}
|
||||||
|
if opts.TenantID != "" {
|
||||||
|
p["tenant_id"] = opts.TenantID
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
p["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
p["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.MACAddress != "" {
|
||||||
|
p["mac_address"] = opts.MACAddress
|
||||||
|
}
|
||||||
|
if opts.AllowedAddressPairs != nil {
|
||||||
|
p["allowed_address_pairs"] = opts.AllowedAddressPairs
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"port": p}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create accepts a CreateOpts struct and creates a new network using the values
|
||||||
|
// provided. You must remember to provide a NetworkID value.
|
||||||
|
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
|
||||||
|
var res CreateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToPortCreateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
_, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptsBuilder is the interface options structs have to satisfy in order
|
||||||
|
// to be used in the main Update operation in this package. Since many
|
||||||
|
// extensions decorate or modify the common logic, it is useful for them to
|
||||||
|
// satisfy a basic interface in order for them to be used.
|
||||||
|
type UpdateOptsBuilder interface {
|
||||||
|
ToPortUpdateMap() (map[string]interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOpts represents the attributes used when updating an existing port.
|
||||||
|
type UpdateOpts struct {
|
||||||
|
Name string
|
||||||
|
AdminStateUp *bool
|
||||||
|
FixedIPs interface{}
|
||||||
|
DeviceID string
|
||||||
|
DeviceOwner string
|
||||||
|
SecurityGroups []string
|
||||||
|
AllowedAddressPairs []AddressPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToPortUpdateMap casts an UpdateOpts struct to a map.
|
||||||
|
func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
|
||||||
|
p := make(map[string]interface{})
|
||||||
|
|
||||||
|
if opts.DeviceID != "" {
|
||||||
|
p["device_id"] = opts.DeviceID
|
||||||
|
}
|
||||||
|
if opts.DeviceOwner != "" {
|
||||||
|
p["device_owner"] = opts.DeviceOwner
|
||||||
|
}
|
||||||
|
if opts.FixedIPs != nil {
|
||||||
|
p["fixed_ips"] = opts.FixedIPs
|
||||||
|
}
|
||||||
|
if opts.SecurityGroups != nil {
|
||||||
|
p["security_groups"] = opts.SecurityGroups
|
||||||
|
}
|
||||||
|
if opts.AdminStateUp != nil {
|
||||||
|
p["admin_state_up"] = &opts.AdminStateUp
|
||||||
|
}
|
||||||
|
if opts.Name != "" {
|
||||||
|
p["name"] = opts.Name
|
||||||
|
}
|
||||||
|
if opts.AllowedAddressPairs != nil {
|
||||||
|
p["allowed_address_pairs"] = opts.AllowedAddressPairs
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{"port": p}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update accepts a UpdateOpts struct and updates an existing port using the
|
||||||
|
// values provided.
|
||||||
|
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
|
||||||
|
var res UpdateResult
|
||||||
|
|
||||||
|
reqBody, err := opts.ToPortUpdateMap()
|
||||||
|
if err != nil {
|
||||||
|
res.Err = err
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
_, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
|
||||||
|
OkCodes: []int{200, 201},
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete accepts a unique ID and deletes the port associated with it.
|
||||||
|
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
|
||||||
|
var res DeleteResult
|
||||||
|
_, res.Err = c.Delete(deleteURL(c, id), nil)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDFromName is a convenience function that returns a port's ID given its name.
|
||||||
|
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
|
||||||
|
portCount := 0
|
||||||
|
portID := ""
|
||||||
|
if name == "" {
|
||||||
|
return "", fmt.Errorf("A port name must be provided.")
|
||||||
|
}
|
||||||
|
pager := List(client, nil)
|
||||||
|
pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||||
|
portList, err := ExtractPorts(page)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range portList {
|
||||||
|
if p.Name == name {
|
||||||
|
portCount++
|
||||||
|
portID = p.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
switch portCount {
|
||||||
|
case 0:
|
||||||
|
return "", fmt.Errorf("Unable to find port: %s", name)
|
||||||
|
case 1:
|
||||||
|
return portID, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("Found %d ports matching %s", portCount, name)
|
||||||
|
}
|
||||||
|
}
|
132
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
Normal file
132
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/results.go
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/rackspace/gophercloud"
|
||||||
|
"github.com/rackspace/gophercloud/pagination"
|
||||||
|
)
|
||||||
|
|
||||||
|
type commonResult struct {
|
||||||
|
gophercloud.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract is a function that accepts a result and extracts a port resource.
|
||||||
|
func (r commonResult) Extract() (*Port, error) {
|
||||||
|
if r.Err != nil {
|
||||||
|
return nil, r.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
var res struct {
|
||||||
|
Port *Port `json:"port"`
|
||||||
|
}
|
||||||
|
err := mapstructure.Decode(r.Body, &res)
|
||||||
|
|
||||||
|
return res.Port, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateResult represents the result of a create operation.
|
||||||
|
type CreateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResult represents the result of a get operation.
|
||||||
|
type GetResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResult represents the result of an update operation.
|
||||||
|
type UpdateResult struct {
|
||||||
|
commonResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResult represents the result of a delete operation.
|
||||||
|
type DeleteResult struct {
|
||||||
|
gophercloud.ErrResult
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP is a sub-struct that represents an individual IP.
|
||||||
|
type IP struct {
|
||||||
|
SubnetID string `mapstructure:"subnet_id" json:"subnet_id"`
|
||||||
|
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddressPair struct {
|
||||||
|
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
|
||||||
|
MACAddress string `mapstructure:"mac_address" json:"mac_address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port represents a Neutron port. See package documentation for a top-level
|
||||||
|
// description of what this is.
|
||||||
|
type Port struct {
|
||||||
|
// UUID for the port.
|
||||||
|
ID string `mapstructure:"id" json:"id"`
|
||||||
|
// Network that this port is associated with.
|
||||||
|
NetworkID string `mapstructure:"network_id" json:"network_id"`
|
||||||
|
// Human-readable name for the port. Might not be unique.
|
||||||
|
Name string `mapstructure:"name" json:"name"`
|
||||||
|
// Administrative state of port. If false (down), port does not forward packets.
|
||||||
|
AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
|
||||||
|
// Indicates whether network is currently operational. Possible values include
|
||||||
|
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
|
||||||
|
Status string `mapstructure:"status" json:"status"`
|
||||||
|
// Mac address to use on this port.
|
||||||
|
MACAddress string `mapstructure:"mac_address" json:"mac_address"`
|
||||||
|
// Specifies IP addresses for the port thus associating the port itself with
|
||||||
|
// the subnets where the IP addresses are picked from
|
||||||
|
FixedIPs []IP `mapstructure:"fixed_ips" json:"fixed_ips"`
|
||||||
|
// Owner of network. Only admin users can specify a tenant_id other than its own.
|
||||||
|
TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
|
||||||
|
// Identifies the entity (e.g.: dhcp agent) using this port.
|
||||||
|
DeviceOwner string `mapstructure:"device_owner" json:"device_owner"`
|
||||||
|
// Specifies the IDs of any security groups associated with a port.
|
||||||
|
SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
|
||||||
|
// Identifies the device (e.g., virtual server) using this port.
|
||||||
|
DeviceID string `mapstructure:"device_id" json:"device_id"`
|
||||||
|
// Identifies the list of IP addresses the port will recognize/accept
|
||||||
|
AllowedAddressPairs []AddressPair `mapstructure:"allowed_address_pairs" json:"allowed_address_pairs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortPage is the page returned by a pager when traversing over a collection
|
||||||
|
// of network ports.
|
||||||
|
type PortPage struct {
|
||||||
|
pagination.LinkedPageBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPageURL is invoked when a paginated collection of ports has reached
|
||||||
|
// the end of a page and the pager seeks to traverse over a new one. In order
|
||||||
|
// to do this, it needs to construct the next page's URL.
|
||||||
|
func (p PortPage) NextPageURL() (string, error) {
|
||||||
|
type resp struct {
|
||||||
|
Links []gophercloud.Link `mapstructure:"ports_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var r resp
|
||||||
|
err := mapstructure.Decode(p.Body, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gophercloud.ExtractNextURL(r.Links)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks whether a PortPage struct is empty.
|
||||||
|
func (p PortPage) IsEmpty() (bool, error) {
|
||||||
|
is, err := ExtractPorts(p)
|
||||||
|
if err != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return len(is) == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtractPorts accepts a Page struct, specifically a PortPage struct,
|
||||||
|
// and extracts the elements into a slice of Port structs. In other words,
|
||||||
|
// a generic collection is mapped into a relevant slice.
|
||||||
|
func ExtractPorts(page pagination.Page) ([]Port, error) {
|
||||||
|
var resp struct {
|
||||||
|
Ports []Port `mapstructure:"ports" json:"ports"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mapstructure.Decode(page.(PortPage).Body, &resp)
|
||||||
|
|
||||||
|
return resp.Ports, err
|
||||||
|
}
|
31
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/urls.go
generated
vendored
Normal file
31
vendor/github.com/rackspace/gophercloud/openstack/networking/v2/ports/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package ports
|
||||||
|
|
||||||
|
import "github.com/rackspace/gophercloud"
|
||||||
|
|
||||||
|
func resourceURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return c.ServiceURL("ports", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return c.ServiceURL("ports")
|
||||||
|
}
|
||||||
|
|
||||||
|
func listURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return rootURL(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return resourceURL(c, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createURL(c *gophercloud.ServiceClient) string {
|
||||||
|
return rootURL(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return resourceURL(c, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteURL(c *gophercloud.ServiceClient, id string) string {
|
||||||
|
return resourceURL(c, id)
|
||||||
|
}
|
|
@ -138,6 +138,11 @@ func (p Pager) AllPages() (Page, error) {
|
||||||
// that type.
|
// that type.
|
||||||
pageType := reflect.TypeOf(testPage)
|
pageType := reflect.TypeOf(testPage)
|
||||||
|
|
||||||
|
// if it's a single page, just return the testPage (first page)
|
||||||
|
if _, found := pageType.FieldByName("SinglePageBase"); found {
|
||||||
|
return testPage, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Switch on the page body type. Recognized types are `map[string]interface{}`,
|
// Switch on the page body type. Recognized types are `map[string]interface{}`,
|
||||||
// `[]byte`, and `[]interface{}`.
|
// `[]byte`, and `[]interface{}`.
|
||||||
switch testPage.GetBody().(type) {
|
switch testPage.GetBody().(type) {
|
||||||
|
@ -153,7 +158,14 @@ func (p Pager) AllPages() (Page, error) {
|
||||||
key = k
|
key = k
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pagesSlice = append(pagesSlice, b[key].([]interface{})...)
|
switch keyType := b[key].(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
pagesSlice = append(pagesSlice, keyType)
|
||||||
|
case []interface{}:
|
||||||
|
pagesSlice = append(pagesSlice, b[key].([]interface{})...)
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("Unsupported page body type: %+v", keyType)
|
||||||
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -222,3 +222,13 @@ func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*
|
||||||
}
|
}
|
||||||
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAutoScaleV1 creates a ServiceClient that may be used to access the v1 Auto Scale service.
|
||||||
|
func NewAutoScaleV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
|
||||||
|
eo.ApplyDefaults("rax:autoscale")
|
||||||
|
url, err := client.EndpointLocator(eo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
|
||||||
|
}
|
||||||
|
|
0
vendor/golang.org/x/sys/unix/mksyscall_solaris.pl
generated
vendored
Normal file → Executable file
0
vendor/golang.org/x/sys/unix/mksyscall_solaris.pl
generated
vendored
Normal file → Executable file
0
vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl
generated
vendored
Normal file → Executable file
0
vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl
generated
vendored
Normal file → Executable file
Loading…
Reference in New Issue