1
0
mirror of https://github.com/openshift/installer.git synced 2026-02-06 00:48:45 +01:00

OpenStack: vendor loadbalancer v2 deps

This pulls in the latest gophercloud support for
openstack loadbalancer, and so enables interaction
with those resources.
This commit is contained in:
Maysa Macedo
2019-06-26 10:10:28 -04:00
parent 26c5e504fc
commit bf64e3de1a
25 changed files with 3325 additions and 1 deletions

10
Gopkg.lock generated
View File

@@ -306,7 +306,7 @@
[[projects]]
branch = "master"
digest = "1:fc872d4e11767301113bddded780fa5b44a3dec90afa6c26fcaaf641ff758dad"
digest = "1:fafce8bcd6b10bcf75556a9649010fbfed5772302c1bf24fbc347558ccfa9c63"
name = "github.com/gophercloud/gophercloud"
packages = [
".",
@@ -320,6 +320,12 @@
"openstack/identity/v2/tokens",
"openstack/identity/v3/regions",
"openstack/identity/v3/tokens",
"openstack/loadbalancer/v2/apiversions",
"openstack/loadbalancer/v2/l7policies",
"openstack/loadbalancer/v2/listeners",
"openstack/loadbalancer/v2/loadbalancers",
"openstack/loadbalancer/v2/monitors",
"openstack/loadbalancer/v2/pools",
"openstack/networking/v2/extensions",
"openstack/networking/v2/extensions/layer3/floatingips",
"openstack/networking/v2/extensions/layer3/routers",
@@ -1202,6 +1208,8 @@
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
"github.com/gophercloud/gophercloud/openstack/identity/v3/regions",
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/apiversions",
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers",
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",

View File

@@ -0,0 +1,22 @@
/*
Package apiversions provides information and interaction with the different
API versions for the OpenStack Load Balancer service. This functionality is not
restricted to this particular version.
Example to List API Versions
allPages, err := apiversions.List(loadbalancerClient).AllPages()
if err != nil {
panic(err)
}
allVersions, err := apiversions.ExtractAPIVersions(allPages)
if err != nil {
panic(err)
}
for _, version := range allVersions {
fmt.Printf("%+v\n", version)
}
*/
package apiversions

View File

@@ -0,0 +1,13 @@
package apiversions
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// List lists all the load balancer API versions available to end-users.
func List(c *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(c, listURL(c), func(r pagination.PageResult) pagination.Page {
return APIVersionPage{pagination.SinglePageBase(r)}
})
}

View File

@@ -0,0 +1,32 @@
package apiversions
import "github.com/gophercloud/gophercloud/pagination"
// APIVersion represents an API version for load balancer. It contains
// the status of the API, and its unique ID.
type APIVersion struct {
Status string `son:"status"`
ID string `json:"id"`
}
// APIVersionPage is the page returned by a pager when traversing over a
// collection of API versions.
type APIVersionPage struct {
pagination.SinglePageBase
}
// IsEmpty checks whether an APIVersionPage struct is empty.
func (r APIVersionPage) IsEmpty() (bool, error) {
is, err := ExtractAPIVersions(r)
return len(is) == 0, err
}
// ExtractAPIVersions takes a collection page, extracts all of the elements,
// and returns them a slice of APIVersion structs. It is effectively a cast.
func ExtractAPIVersions(r pagination.Page) ([]APIVersion, error) {
var s struct {
Versions []APIVersion `json:"versions"`
}
err := (r.(APIVersionPage)).ExtractInto(&s)
return s.Versions, err
}

View File

@@ -0,0 +1,14 @@
package apiversions
import (
"strings"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/utils"
)
func listURL(c *gophercloud.ServiceClient) string {
baseEndpoint, _ := utils.BaseEndpoint(c.Endpoint)
endpoint := strings.TrimRight(baseEndpoint, "/") + "/"
return endpoint
}

View File

@@ -0,0 +1,123 @@
/*
Package l7policies provides information and interaction with L7Policies and
Rules of the LBaaS v2 extension for the OpenStack Networking service.
Example to Create a L7Policy
createOpts := l7policies.CreateOpts{
Name: "redirect-example.com",
ListenerID: "023f2e34-7806-443b-bfae-16c324569a3d",
Action: l7policies.ActionRedirectToURL,
RedirectURL: "http://www.example.com",
}
l7policy, err := l7policies.Create(lbClient, createOpts).Extract()
if err != nil {
panic(err)
}
Example to List L7Policies
listOpts := l7policies.ListOpts{
ListenerID: "c79a4468-d788-410c-bf79-9a8ef6354852",
}
allPages, err := l7policies.List(lbClient, listOpts).AllPages()
if err != nil {
panic(err)
}
allL7Policies, err := l7policies.ExtractL7Policies(allPages)
if err != nil {
panic(err)
}
for _, l7policy := range allL7Policies {
fmt.Printf("%+v\n", l7policy)
}
Example to Get a L7Policy
l7policy, err := l7policies.Get(lbClient, "023f2e34-7806-443b-bfae-16c324569a3d").Extract()
if err != nil {
panic(err)
}
Example to Delete a L7Policy
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
err := l7policies.Delete(lbClient, l7policyID).ExtractErr()
if err != nil {
panic(err)
}
Example to Update a L7Policy
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
name := "new-name"
updateOpts := l7policies.UpdateOpts{
Name: &name,
}
l7policy, err := l7policies.Update(lbClient, l7policyID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Create a Rule
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
createOpts := l7policies.CreateRuleOpts{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareTypeRegex,
Value: "/images*",
}
rule, err := l7policies.CreateRule(lbClient, l7policyID, createOpts).Extract()
if err != nil {
panic(err)
}
Example to List L7 Rules
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
listOpts := l7policies.ListRulesOpts{
RuleType: l7policies.TypePath,
}
allPages, err := l7policies.ListRules(lbClient, l7policyID, listOpts).AllPages()
if err != nil {
panic(err)
}
allRules, err := l7policies.ExtractRules(allPages)
if err != nil {
panic(err)
}
for _, rule := allRules {
fmt.Printf("%+v\n", rule)
}
Example to Get a l7 rule
l7rule, err := l7policies.GetRule(lbClient, "023f2e34-7806-443b-bfae-16c324569a3d", "53ad8ab8-40fa-11e8-a508-00224d6b7bc1").Extract()
if err != nil {
panic(err)
}
Example to Delete a l7 rule
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
ruleID := "64dba99f-8af8-4200-8882-e32a0660f23e"
err := l7policies.DeleteRule(lbClient, l7policyID, ruleID).ExtractErr()
if err != nil {
panic(err)
}
Example to Update a Rule
l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64"
ruleID := "64dba99f-8af8-4200-8882-e32a0660f23e"
updateOpts := l7policies.UpdateRuleOpts{
RuleType: l7policies.TypePath,
CompareType: l7policies.CompareTypeRegex,
Value: "/images/special*",
}
rule, err := l7policies.UpdateRule(lbClient, l7policyID, ruleID, updateOpts).Extract()
if err != nil {
panic(err)
}
*/
package l7policies

View File

@@ -0,0 +1,376 @@
package l7policies
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
ToL7PolicyCreateMap() (map[string]interface{}, error)
}
type Action string
type RuleType string
type CompareType string
const (
ActionRedirectToPool Action = "REDIRECT_TO_POOL"
ActionRedirectToURL Action = "REDIRECT_TO_URL"
ActionReject Action = "REJECT"
TypeCookie RuleType = "COOKIE"
TypeFileType RuleType = "FILE_TYPE"
TypeHeader RuleType = "HEADER"
TypeHostName RuleType = "HOST_NAME"
TypePath RuleType = "PATH"
CompareTypeContains CompareType = "CONTAINS"
CompareTypeEndWith CompareType = "ENDS_WITH"
CompareTypeEqual CompareType = "EQUAL_TO"
CompareTypeRegex CompareType = "REGEX"
CompareTypeStartWith CompareType = "STARTS_WITH"
)
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts struct {
// Name of the L7 policy.
Name string `json:"name,omitempty"`
// The ID of the listener.
ListenerID string `json:"listener_id" required:"true"`
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
Action Action `json:"action" required:"true"`
// The position of this policy on the listener.
Position int32 `json:"position,omitempty"`
// A human-readable description for the resource.
Description string `json:"description,omitempty"`
// ProjectID is the UUID of the project who owns the L7 policy in octavia.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id,omitempty"`
// Requests matching this policy will be redirected to the pool with this ID.
// Only valid if action is REDIRECT_TO_POOL.
RedirectPoolID string `json:"redirect_pool_id,omitempty"`
// Requests matching this policy will be redirected to this URL.
// Only valid if action is REDIRECT_TO_URL.
RedirectURL string `json:"redirect_url,omitempty"`
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToL7PolicyCreateMap builds a request body from CreateOpts.
func (opts CreateOpts) ToL7PolicyCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "l7policy")
}
// Create accepts a CreateOpts struct and uses the values to create a new l7policy.
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToL7PolicyCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
return
}
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToL7PolicyListQuery() (string, error)
}
// ListOpts allows the filtering and sorting of paginated collections through
// the API.
type ListOpts struct {
Name string `q:"name"`
Description string `q:"description"`
ListenerID string `q:"listener_id"`
Action string `q:"action"`
ProjectID string `q:"project_id"`
RedirectPoolID string `q:"redirect_pool_id"`
RedirectURL string `q:"redirect_url"`
Position int32 `q:"position"`
AdminStateUp bool `q:"admin_state_up"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToL7PolicyListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToL7PolicyListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
// l7policies. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
//
// Default policy settings return only those l7policies that are owned by the
// project 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.ToL7PolicyListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return L7PolicyPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a particular l7policy based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
return
}
// Delete will permanently delete a particular l7policy based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
_, r.Err = c.Delete(resourceURL(c, id), nil)
return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
ToL7PolicyUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts is the common options struct used in this package's Update
// operation.
type UpdateOpts struct {
// Name of the L7 policy, empty string is allowed.
Name *string `json:"name,omitempty"`
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
Action Action `json:"action,omitempty"`
// The position of this policy on the listener.
Position int32 `json:"position,omitempty"`
// A human-readable description for the resource, empty string is allowed.
Description *string `json:"description,omitempty"`
// Requests matching this policy will be redirected to the pool with this ID.
// Only valid if action is REDIRECT_TO_POOL.
RedirectPoolID *string `json:"redirect_pool_id,omitempty"`
// Requests matching this policy will be redirected to this URL.
// Only valid if action is REDIRECT_TO_URL.
RedirectURL *string `json:"redirect_url,omitempty"`
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToL7PolicyUpdateMap builds a request body from UpdateOpts.
func (opts UpdateOpts) ToL7PolicyUpdateMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "l7policy")
if err != nil {
return nil, err
}
m := b["l7policy"].(map[string]interface{})
if m["redirect_pool_id"] == "" {
m["redirect_pool_id"] = nil
}
if m["redirect_url"] == "" {
m["redirect_url"] = nil
}
return b, nil
}
// Update allows l7policy to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
b, err := opts.ToL7PolicyUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return
}
// CreateRuleOpts is the common options struct used in this package's CreateRule
// operation.
type CreateRuleOpts struct {
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
RuleType RuleType `json:"type" required:"true"`
// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
CompareType CompareType `json:"compare_type" required:"true"`
// The value to use for the comparison. For example, the file type to compare.
Value string `json:"value" required:"true"`
// ProjectID is the UUID of the project who owns the rule in octavia.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id,omitempty"`
// The key to use for the comparison. For example, the name of the cookie to evaluate.
Key string `json:"key,omitempty"`
// When true the logic of the rule is inverted. For example, with invert true,
// equal to would become not equal to. Default is false.
Invert bool `json:"invert,omitempty"`
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToRuleCreateMap builds a request body from CreateRuleOpts.
func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "rule")
}
// CreateRule will create and associate a Rule with a particular L7Policy.
func CreateRule(c *gophercloud.ServiceClient, policyID string, opts CreateRuleOpts) (r CreateRuleResult) {
b, err := opts.ToRuleCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(ruleRootURL(c, policyID), b, &r.Body, nil)
return
}
// ListRulesOptsBuilder allows extensions to add additional parameters to the
// ListRules request.
type ListRulesOptsBuilder interface {
ToRulesListQuery() (string, error)
}
// ListRulesOpts allows the filtering and sorting of paginated collections
// through the API.
type ListRulesOpts struct {
RuleType RuleType `q:"type"`
ProjectID string `q:"project_id"`
CompareType CompareType `q:"compare_type"`
Value string `q:"value"`
Key string `q:"key"`
Invert bool `q:"invert"`
AdminStateUp bool `q:"admin_state_up"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
}
// ToRulesListQuery formats a ListOpts into a query string.
func (opts ListRulesOpts) ToRulesListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// ListRules returns a Pager which allows you to iterate over a collection of
// rules. It accepts a ListRulesOptsBuilder, which allows you to filter and
// sort the returned collection for greater efficiency.
//
// Default policy settings return only those rules that are owned by the
// project who submits the request, unless an admin user submits the request.
func ListRules(c *gophercloud.ServiceClient, policyID string, opts ListRulesOptsBuilder) pagination.Pager {
url := ruleRootURL(c, policyID)
if opts != nil {
query, err := opts.ToRulesListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return RulePage{pagination.LinkedPageBase{PageResult: r}}
})
}
// GetRule retrieves a particular L7Policy Rule based on its unique ID.
func GetRule(c *gophercloud.ServiceClient, policyID string, ruleID string) (r GetRuleResult) {
_, r.Err = c.Get(ruleResourceURL(c, policyID, ruleID), &r.Body, nil)
return
}
// DeleteRule will remove a Rule from a particular L7Policy.
func DeleteRule(c *gophercloud.ServiceClient, policyID string, ruleID string) (r DeleteRuleResult) {
_, r.Err = c.Delete(ruleResourceURL(c, policyID, ruleID), nil)
return
}
// UpdateRuleOptsBuilder allows to add additional parameters to the PUT request.
type UpdateRuleOptsBuilder interface {
ToRuleUpdateMap() (map[string]interface{}, error)
}
// UpdateRuleOpts is the common options struct used in this package's Update
// operation.
type UpdateRuleOpts struct {
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
RuleType RuleType `json:"type,omitempty"`
// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
CompareType CompareType `json:"compare_type,omitempty"`
// The value to use for the comparison. For example, the file type to compare.
Value string `json:"value,omitempty"`
// The key to use for the comparison. For example, the name of the cookie to evaluate.
Key *string `json:"key,omitempty"`
// When true the logic of the rule is inverted. For example, with invert true,
// equal to would become not equal to. Default is false.
Invert *bool `json:"invert,omitempty"`
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToRuleUpdateMap builds a request body from UpdateRuleOpts.
func (opts UpdateRuleOpts) ToRuleUpdateMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "rule")
if err != nil {
return nil, err
}
if m := b["rule"].(map[string]interface{}); m["key"] == "" {
m["key"] = nil
}
return b, nil
}
// UpdateRule allows Rule to be updated.
func UpdateRule(c *gophercloud.ServiceClient, policyID string, ruleID string, opts UpdateRuleOptsBuilder) (r UpdateRuleResult) {
b, err := opts.ToRuleUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(ruleResourceURL(c, policyID, ruleID), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201, 202},
})
return
}

View File

@@ -0,0 +1,237 @@
package l7policies
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// L7Policy is a collection of L7 rules associated with a Listener, and which
// may also have an association to a back-end pool.
type L7Policy struct {
// The unique ID for the L7 policy.
ID string `json:"id"`
// Name of the L7 policy.
Name string `json:"name"`
// The ID of the listener.
ListenerID string `json:"listener_id"`
// The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT.
Action string `json:"action"`
// The position of this policy on the listener.
Position int32 `json:"position"`
// A human-readable description for the resource.
Description string `json:"description"`
// ProjectID is the UUID of the project who owns the L7 policy in octavia.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id"`
// Requests matching this policy will be redirected to the pool with this ID.
// Only valid if action is REDIRECT_TO_POOL.
RedirectPoolID string `json:"redirect_pool_id"`
// Requests matching this policy will be redirected to this URL.
// Only valid if action is REDIRECT_TO_URL.
RedirectURL string `json:"redirect_url"`
// The administrative state of the L7 policy, which is up (true) or down (false).
AdminStateUp bool `json:"admin_state_up"`
// The provisioning status of the L7 policy.
// This value is ACTIVE, PENDING_* or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// The operating status of the L7 policy.
OperatingStatus string `json:"operating_status"`
// Rules are List of associated L7 rule IDs.
Rules []Rule `json:"rules"`
}
// Rule represents layer 7 load balancing rule.
type Rule struct {
// The unique ID for the L7 rule.
ID string `json:"id"`
// The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH.
RuleType string `json:"type"`
// The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH.
CompareType string `json:"compare_type"`
// The value to use for the comparison. For example, the file type to compare.
Value string `json:"value"`
// ProjectID is the UUID of the project who owns the rule in octavia.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id"`
// The key to use for the comparison. For example, the name of the cookie to evaluate.
Key string `json:"key"`
// When true the logic of the rule is inverted. For example, with invert true,
// equal to would become not equal to. Default is false.
Invert bool `json:"invert"`
// The administrative state of the L7 rule, which is up (true) or down (false).
AdminStateUp bool `json:"admin_state_up"`
// The provisioning status of the L7 rule.
// This value is ACTIVE, PENDING_* or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// The operating status of the L7 policy.
OperatingStatus string `json:"operating_status"`
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a l7policy.
func (r commonResult) Extract() (*L7Policy, error) {
var s struct {
L7Policy *L7Policy `json:"l7policy"`
}
err := r.ExtractInto(&s)
return s.L7Policy, err
}
// CreateResult represents the result of a Create operation. Call its Extract
// method to interpret the result as a L7Policy.
type CreateResult struct {
commonResult
}
// L7PolicyPage is the page returned by a pager when traversing over a
// collection of l7policies.
type L7PolicyPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of l7policies 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 (r L7PolicyPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"l7policies_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a L7PolicyPage struct is empty.
func (r L7PolicyPage) IsEmpty() (bool, error) {
is, err := ExtractL7Policies(r)
return len(is) == 0, err
}
// ExtractL7Policies accepts a Page struct, specifically a L7PolicyPage struct,
// and extracts the elements into a slice of L7Policy structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractL7Policies(r pagination.Page) ([]L7Policy, error) {
var s struct {
L7Policies []L7Policy `json:"l7policies"`
}
err := (r.(L7PolicyPage)).ExtractInto(&s)
return s.L7Policies, err
}
// GetResult represents the result of a Get operation. Call its Extract
// method to interpret the result as a L7Policy.
type GetResult struct {
commonResult
}
// DeleteResult represents the result of a Delete operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
// UpdateResult represents the result of an Update operation. Call its Extract
// method to interpret the result as a L7Policy.
type UpdateResult struct {
commonResult
}
type commonRuleResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a rule.
func (r commonRuleResult) Extract() (*Rule, error) {
var s struct {
Rule *Rule `json:"rule"`
}
err := r.ExtractInto(&s)
return s.Rule, err
}
// CreateRuleResult represents the result of a CreateRule operation.
// Call its Extract method to interpret it as a Rule.
type CreateRuleResult struct {
commonRuleResult
}
// RulePage is the page returned by a pager when traversing over a
// collection of Rules in a L7Policy.
type RulePage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of rules 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 (r RulePage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"rules_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a RulePage struct is empty.
func (r RulePage) IsEmpty() (bool, error) {
is, err := ExtractRules(r)
return len(is) == 0, err
}
// ExtractRules accepts a Page struct, specifically a RulePage struct,
// and extracts the elements into a slice of Rules structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractRules(r pagination.Page) ([]Rule, error) {
var s struct {
Rules []Rule `json:"rules"`
}
err := (r.(RulePage)).ExtractInto(&s)
return s.Rules, err
}
// GetRuleResult represents the result of a GetRule operation.
// Call its Extract method to interpret it as a Rule.
type GetRuleResult struct {
commonRuleResult
}
// DeleteRuleResult represents the result of a DeleteRule operation.
// Call its ExtractErr method to determine if the request succeeded or failed.
type DeleteRuleResult struct {
gophercloud.ErrResult
}
// UpdateRuleResult represents the result of an UpdateRule operation.
// Call its Extract method to interpret it as a Rule.
type UpdateRuleResult struct {
commonRuleResult
}

View File

@@ -0,0 +1,25 @@
package l7policies
import "github.com/gophercloud/gophercloud"
const (
rootPath = "lbaas"
resourcePath = "l7policies"
rulePath = "rules"
)
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 ruleRootURL(c *gophercloud.ServiceClient, policyID string) string {
return c.ServiceURL(rootPath, resourcePath, policyID, rulePath)
}
func ruleResourceURL(c *gophercloud.ServiceClient, policyID string, ruleID string) string {
return c.ServiceURL(rootPath, resourcePath, policyID, rulePath, ruleID)
}

View File

@@ -0,0 +1,74 @@
/*
Package listeners provides information and interaction with Listeners of the
LBaaS v2 extension for the OpenStack Networking service.
Example to List Listeners
listOpts := listeners.ListOpts{
LoadbalancerID : "ca430f80-1737-4712-8dc6-3f640d55594b",
}
allPages, err := listeners.List(networkClient, listOpts).AllPages()
if err != nil {
panic(err)
}
allListeners, err := listeners.ExtractListeners(allPages)
if err != nil {
panic(err)
}
for _, listener := range allListeners {
fmt.Printf("%+v\n", listener)
}
Example to Create a Listener
createOpts := listeners.CreateOpts{
Protocol: "TCP",
Name: "db",
LoadbalancerID: "79e05663-7f03-45d2-a092-8b94062f22ab",
AdminStateUp: gophercloud.Enabled,
DefaultPoolID: "41efe233-7591-43c5-9cf7-923964759f9e",
ProtocolPort: 3306,
}
listener, err := listeners.Create(networkClient, createOpts).Extract()
if err != nil {
panic(err)
}
Example to Update a Listener
listenerID := "d67d56a6-4a86-4688-a282-f46444705c64"
i1001 := 1001
i181000 := 181000
updateOpts := listeners.UpdateOpts{
ConnLimit: &i1001,
TimeoutClientData: &i181000,
TimeoutMemberData: &i181000,
}
listener, err := listeners.Update(networkClient, listenerID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Delete a Listener
listenerID := "d67d56a6-4a86-4688-a282-f46444705c64"
err := listeners.Delete(networkClient, listenerID).ExtractErr()
if err != nil {
panic(err)
}
Example to Get the Statistics of a Listener
listenerID := "d67d56a6-4a86-4688-a282-f46444705c64"
stats, err := listeners.GetStats(networkClient, listenerID).Extract()
if err != nil {
panic(err)
}
*/
package listeners

View File

@@ -0,0 +1,245 @@
package listeners
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// Type Protocol represents a listener protocol.
type Protocol string
// Supported attributes for create/update operations.
const (
ProtocolTCP Protocol = "TCP"
ProtocolUDP Protocol = "UDP"
ProtocolPROXY Protocol = "PROXY"
ProtocolHTTP Protocol = "HTTP"
ProtocolHTTPS Protocol = "HTTPS"
)
// 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"`
ProjectID string `q:"project_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"`
TimeoutClientData *int `q:"timeout_client_data"`
TimeoutMemberData *int `q:"timeout_member_data"`
TimeoutMemberConnect *int `q:"timeout_member_connect"`
TimeoutTCPInspect *int `q:"timeout_tcp_inspect"`
}
// ToListenerListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToListenerListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
// listeners. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
//
// Default policy settings return only those listeners that are owned by the
// project 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}}
})
}
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
ToListenerCreateMap() (map[string]interface{}, error)
}
// CreateOpts represents options for creating a listener.
type CreateOpts struct {
// The load balancer on which to provision this listener.
LoadbalancerID string `json:"loadbalancer_id" required:"true"`
// The protocol - can either be TCP, HTTP or HTTPS.
Protocol Protocol `json:"protocol" required:"true"`
// The port on which to listen for client traffic.
ProtocolPort int `json:"protocol_port" required:"true"`
// ProjectID is only required if the caller has an admin role and wants
// to create a pool for another project.
ProjectID string `json:"project_id,omitempty"`
// Human-readable name for the Listener. Does not have to be unique.
Name string `json:"name,omitempty"`
// The ID of the default pool with which the Listener is associated.
DefaultPoolID string `json:"default_pool_id,omitempty"`
// Human-readable description for the Listener.
Description string `json:"description,omitempty"`
// The maximum number of connections allowed for the Listener.
ConnLimit *int `json:"connection_limit,omitempty"`
// A reference to a Barbican container of TLS secrets.
DefaultTlsContainerRef string `json:"default_tls_container_ref,omitempty"`
// A list of references to TLS secrets.
SniContainerRefs []string `json:"sni_container_refs,omitempty"`
// The administrative state of the Listener. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Frontend client inactivity timeout in milliseconds
TimeoutClientData *int `json:"timeout_client_data,omitempty"`
// Backend member inactivity timeout in milliseconds
TimeoutMemberData *int `json:"timeout_member_data,omitempty"`
// Backend member connection timeout in milliseconds
TimeoutMemberConnect *int `json:"timeout_member_connect,omitempty"`
// Time, in milliseconds, to wait for additional TCP packets for content inspection
TimeoutTCPInspect *int `json:"timeout_tcp_inspect,omitempty"`
// A dictionary of optional headers to insert into the request before it is sent to the backend member.
InsertHeaders map[string]string `json:"insert_headers,omitempty"`
}
// ToListenerCreateMap builds a request body from CreateOpts.
func (opts CreateOpts) ToListenerCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "listener")
}
// 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 projects by
// specifying a ProjectID attribute different than their own.
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToListenerCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
return
}
// Get retrieves a particular Listeners based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
ToListenerUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts represents options for updating a Listener.
type UpdateOpts struct {
// Human-readable name for the Listener. Does not have to be unique.
Name *string `json:"name,omitempty"`
// The ID of the default pool with which the Listener is associated.
DefaultPoolID *string `json:"default_pool_id,omitempty"`
// Human-readable description for the Listener.
Description *string `json:"description,omitempty"`
// The maximum number of connections allowed for the Listener.
ConnLimit *int `json:"connection_limit,omitempty"`
// A reference to a Barbican container of TLS secrets.
DefaultTlsContainerRef string `json:"default_tls_container_ref,omitempty"`
// A list of references to TLS secrets.
SniContainerRefs []string `json:"sni_container_refs,omitempty"`
// The administrative state of the Listener. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Frontend client inactivity timeout in milliseconds
TimeoutClientData *int `json:"timeout_client_data,omitempty"`
// Backend member inactivity timeout in milliseconds
TimeoutMemberData *int `json:"timeout_member_data,omitempty"`
// Backend member connection timeout in milliseconds
TimeoutMemberConnect *int `json:"timeout_member_connect,omitempty"`
// Time, in milliseconds, to wait for additional TCP packets for content inspection
TimeoutTCPInspect *int `json:"timeout_tcp_inspect,omitempty"`
}
// ToListenerUpdateMap builds a request body from UpdateOpts.
func (opts UpdateOpts) ToListenerUpdateMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "listener")
if err != nil {
return nil, err
}
if m := b["listener"].(map[string]interface{}); m["default_pool_id"] == "" {
m["default_pool_id"] = nil
}
return b, nil
}
// Update is an operation which modifies the attributes of the specified
// Listener.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) {
b, err := opts.ToListenerUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
return
}
// Delete will permanently delete a particular Listeners based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
_, r.Err = c.Delete(resourceURL(c, id), nil)
return
}
// GetStats will return the shows the current statistics of a particular Listeners.
func GetStats(c *gophercloud.ServiceClient, id string) (r StatsResult) {
_, r.Err = c.Get(statisticsRootURL(c, id), &r.Body, nil)
return
}

View File

@@ -0,0 +1,187 @@
package listeners
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/gophercloud/pagination"
)
type LoadBalancerID struct {
ID string `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 `json:"id"`
// Owner of the Listener.
ProjectID string `json:"project_id"`
// Human-readable name for the Listener. Does not have to be unique.
Name string `json:"name"`
// Human-readable description for the Listener.
Description string `json:"description"`
// The protocol to loadbalance. A valid value is TCP, HTTP, or HTTPS.
Protocol string `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 `json:"protocol_port"`
// The UUID of default pool. Must have compatible protocol with listener.
DefaultPoolID string `json:"default_pool_id"`
// A list of load balancer IDs.
Loadbalancers []LoadBalancerID `json:"loadbalancers"`
// The maximum number of connections allowed for the Loadbalancer.
// Default is -1, meaning no limit.
ConnLimit int `json:"connection_limit"`
// The list of references to TLS secrets.
SniContainerRefs []string `json:"sni_container_refs"`
// A reference to a Barbican container of TLS secrets.
DefaultTlsContainerRef string `json:"default_tls_container_ref"`
// The administrative state of the Listener. A valid value is true (UP) or false (DOWN).
AdminStateUp bool `json:"admin_state_up"`
// Pools are the pools which are part of this listener.
Pools []pools.Pool `json:"pools"`
// L7policies are the L7 policies which are part of this listener.
L7Policies []l7policies.L7Policy `json:"l7policies"`
// The provisioning status of the Listener.
// This value is ACTIVE, PENDING_* or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// Frontend client inactivity timeout in milliseconds
TimeoutClientData int `json:"timeout_client_data"`
// Backend member inactivity timeout in milliseconds
TimeoutMemberData int `json:"timeout_member_data"`
// Backend member connection timeout in milliseconds
TimeoutMemberConnect int `json:"timeout_member_connect"`
// Time, in milliseconds, to wait for additional TCP packets for content inspection
TimeoutTCPInspect int `json:"timeout_tcp_inspect"`
// A dictionary of optional headers to insert into the request before it is sent to the backend member.
InsertHeaders map[string]string `json:"insert_headers"`
}
type Stats struct {
// The currently active connections.
ActiveConnections int `json:"active_connections"`
// The total bytes received.
BytesIn int `json:"bytes_in"`
// The total bytes sent.
BytesOut int `json:"bytes_out"`
// The total requests that were unable to be fulfilled.
RequestErrors int `json:"request_errors"`
// The total connections handled.
TotalConnections int `json:"total_connections"`
}
// ListenerPage is the page returned by a pager when traversing over a
// collection of listeners.
type ListenerPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of listeners 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 (r ListenerPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"listeners_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a ListenerPage struct is empty.
func (r ListenerPage) IsEmpty() (bool, error) {
is, err := ExtractListeners(r)
return len(is) == 0, err
}
// 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(r pagination.Page) ([]Listener, error) {
var s struct {
Listeners []Listener `json:"listeners"`
}
err := (r.(ListenerPage)).ExtractInto(&s)
return s.Listeners, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a listener.
func (r commonResult) Extract() (*Listener, error) {
var s struct {
Listener *Listener `json:"listener"`
}
err := r.ExtractInto(&s)
return s.Listener, err
}
// CreateResult represents the result of a create operation. Call its Extract
// method to interpret it as a Listener.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation. Call its Extract
// method to interpret it as a Listener.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation. Call its Extract
// method to interpret it as a Listener.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
// StatsResult represents the result of a GetStats operation.
// Call its Extract method to interpret it as a Stats.
type StatsResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts the status of
// a Listener.
func (r StatsResult) Extract() (*Stats, error) {
var s struct {
Stats *Stats `json:"stats"`
}
err := r.ExtractInto(&s)
return s.Stats, err
}

View File

@@ -0,0 +1,21 @@
package listeners
import "github.com/gophercloud/gophercloud"
const (
rootPath = "lbaas"
resourcePath = "listeners"
statisticsPath = "stats"
)
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 statisticsRootURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id, statisticsPath)
}

View File

@@ -0,0 +1,92 @@
/*
Package loadbalancers provides information and interaction with Load Balancers
of the LBaaS v2 extension for the OpenStack Networking service.
Example to List Load Balancers
listOpts := loadbalancers.ListOpts{
Provider: "haproxy",
}
allPages, err := loadbalancers.List(networkClient, listOpts).AllPages()
if err != nil {
panic(err)
}
allLoadbalancers, err := loadbalancers.ExtractLoadBalancers(allPages)
if err != nil {
panic(err)
}
for _, lb := range allLoadbalancers {
fmt.Printf("%+v\n", lb)
}
Example to Create a Load Balancer
createOpts := loadbalancers.CreateOpts{
Name: "db_lb",
AdminStateUp: gophercloud.Enabled,
VipSubnetID: "9cedb85d-0759-4898-8a4b-fa5a5ea10086",
VipAddress: "10.30.176.48",
Flavor: "medium",
Provider: "haproxy",
Tags: []string{"test", "stage"},
}
lb, err := loadbalancers.Create(networkClient, createOpts).Extract()
if err != nil {
panic(err)
}
Example to Update a Load Balancer
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"
name := "new-name"
updateOpts := loadbalancers.UpdateOpts{
Name: &name,
}
lb, err := loadbalancers.Update(networkClient, lbID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Delete a Load Balancers
deleteOpts := loadbalancers.DeleteOpts{
Cascade: true,
}
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"
err := loadbalancers.Delete(networkClient, lbID, deleteOpts).ExtractErr()
if err != nil {
panic(err)
}
Example to Get the Status of a Load Balancer
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"
status, err := loadbalancers.GetStatuses(networkClient, LBID).Extract()
if err != nil {
panic(err)
}
Example to Get the Statistics of a Load Balancer
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"
stats, err := loadbalancers.GetStats(networkClient, LBID).Extract()
if err != nil {
panic(err)
}
Example to Failover a Load Balancers
lbID := "d67d56a6-4a86-4688-a282-f46444705c64"
err := loadbalancers.Failover(networkClient, lbID).ExtractErr()
if err != nil {
panic(err)
}
*/
package loadbalancers

View File

@@ -0,0 +1,241 @@
package loadbalancers
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// 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"`
ProjectID string `q:"project_id"`
ProvisioningStatus string `q:"provisioning_status"`
VipAddress string `q:"vip_address"`
VipPortID string `q:"vip_port_id"`
VipSubnetID string `q:"vip_subnet_id"`
VipNetworkID string `q:"vip_network_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"`
Tags []string `q:"tags"`
TagsAny []string `q:"tags-any"`
TagsNot []string `q:"not-tags"`
TagsNotAny []string `q:"not-tags-any"`
}
// ToLoadBalancerListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToLoadBalancerListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
// load balancers. It accepts a ListOpts struct, which allows you to filter
// and sort the returned collection for greater efficiency.
//
// Default policy settings return only those load balancers that are owned by
// the project 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}}
})
}
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
ToLoadBalancerCreateMap() (map[string]interface{}, error)
}
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts struct {
// Human-readable name for the Loadbalancer. Does not have to be unique.
Name string `json:"name,omitempty"`
// Human-readable description for the Loadbalancer.
Description string `json:"description,omitempty"`
// Providing a neutron port ID for the vip_port_id tells Octavia to use this
// port for the VIP. If the port has more than one subnet you must specify
// either the vip_subnet_id or vip_address to clarify which address should
// be used for the VIP.
VipPortID string `json:"vip_port_id,omitempty"`
// The subnet on which to allocate the Loadbalancer's address. A project can
// only create Loadbalancers on networks authorized by policy (e.g. networks
// that belong to them or networks that are shared).
VipSubnetID string `json:"vip_subnet_id,omitempty"`
// 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).
VipNetworkID string `json:"vip_network_id,omitempty"`
// ProjectID is the UUID of the project who owns the Loadbalancer.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id,omitempty"`
// The IP address of the Loadbalancer.
VipAddress string `json:"vip_address,omitempty"`
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// The UUID of a flavor.
Flavor string `json:"flavor,omitempty"`
// The name of the provider.
Provider string `json:"provider,omitempty"`
// Tags is a set of resource tags.
Tags []string `json:"tags,omitempty"`
}
// ToLoadBalancerCreateMap builds a request body from CreateOpts.
func (opts CreateOpts) ToLoadBalancerCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "loadbalancer")
}
// 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.
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToLoadBalancerCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
return
}
// Get retrieves a particular Loadbalancer based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
ToLoadBalancerUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts is the common options struct used in this package's Update
// operation.
type UpdateOpts struct {
// Human-readable name for the Loadbalancer. Does not have to be unique.
Name *string `json:"name,omitempty"`
// Human-readable description for the Loadbalancer.
Description *string `json:"description,omitempty"`
// The administrative state of the Loadbalancer. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
// Tags is a set of resource tags.
Tags *[]string `json:"tags,omitempty"`
}
// ToLoadBalancerUpdateMap builds a request body from UpdateOpts.
func (opts UpdateOpts) ToLoadBalancerUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "loadbalancer")
}
// Update is an operation which modifies the attributes of the specified
// LoadBalancer.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) {
b, err := opts.ToLoadBalancerUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
return
}
// DeleteOptsBuilder allows extensions to add additional parameters to the
// Delete request.
type DeleteOptsBuilder interface {
ToLoadBalancerDeleteQuery() (string, error)
}
// DeleteOpts is the common options struct used in this package's Delete
// operation.
type DeleteOpts struct {
// Cascade will delete all children of the load balancer (listners, monitors, etc).
Cascade bool `q:"cascade"`
}
// ToLoadBalancerDeleteQuery formats a DeleteOpts into a query string.
func (opts DeleteOpts) ToLoadBalancerDeleteQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// Delete will permanently delete a particular LoadBalancer based on its
// unique ID.
func Delete(c *gophercloud.ServiceClient, id string, opts DeleteOptsBuilder) (r DeleteResult) {
url := resourceURL(c, id)
if opts != nil {
query, err := opts.ToLoadBalancerDeleteQuery()
if err != nil {
r.Err = err
return
}
url += query
}
_, r.Err = c.Delete(url, nil)
return
}
// GetStatuses will return the status of a particular LoadBalancer.
func GetStatuses(c *gophercloud.ServiceClient, id string) (r GetStatusesResult) {
_, r.Err = c.Get(statusRootURL(c, id), &r.Body, nil)
return
}
// GetStats will return the shows the current statistics of a particular LoadBalancer.
func GetStats(c *gophercloud.ServiceClient, id string) (r StatsResult) {
_, r.Err = c.Get(statisticsRootURL(c, id), &r.Body, nil)
return
}
// Failover performs a failover of a load balancer.
func Failover(c *gophercloud.ServiceClient, id string) (r FailoverResult) {
_, r.Err = c.Put(failoverRootURL(c, id), nil, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
return
}

View File

@@ -0,0 +1,200 @@
package loadbalancers
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"github.com/gophercloud/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 `json:"description"`
// The administrative state of the Loadbalancer.
// A valid value is true (UP) or false (DOWN).
AdminStateUp bool `json:"admin_state_up"`
// Owner of the LoadBalancer.
ProjectID string `json:"project_id"`
// The provisioning status of the LoadBalancer.
// This value is ACTIVE, PENDING_CREATE or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// The IP address of the Loadbalancer.
VipAddress string `json:"vip_address"`
// The UUID of the port associated with the IP address.
VipPortID string `json:"vip_port_id"`
// The UUID of the subnet on which to allocate the virtual IP for the
// Loadbalancer address.
VipSubnetID string `json:"vip_subnet_id"`
// The UUID of the network on which to allocate the virtual IP for the
// Loadbalancer address.
VipNetworkID string `json:"vip_network_id"`
// The unique ID for the LoadBalancer.
ID string `json:"id"`
// The operating status of the LoadBalancer. This value is ONLINE or OFFLINE.
OperatingStatus string `json:"operating_status"`
// Human-readable name for the LoadBalancer. Does not have to be unique.
Name string `json:"name"`
// The UUID of a flavor if set.
Flavor string `json:"flavor"`
// The name of the provider.
Provider string `json:"provider"`
// Listeners are the listeners related to this Loadbalancer.
Listeners []listeners.Listener `json:"listeners"`
// Pools are the pools related to this Loadbalancer.
Pools []pools.Pool `json:"pools"`
// Tags is a list of resource tags. Tags are arbitrarily defined strings
// attached to the resource.
Tags []string `json:"tags"`
}
// StatusTree represents the status of a loadbalancer.
type StatusTree struct {
Loadbalancer *LoadBalancer `json:"loadbalancer"`
}
type Stats struct {
// The currently active connections.
ActiveConnections int `json:"active_connections"`
// The total bytes received.
BytesIn int `json:"bytes_in"`
// The total bytes sent.
BytesOut int `json:"bytes_out"`
// The total requests that were unable to be fulfilled.
RequestErrors int `json:"request_errors"`
// The total connections handled.
TotalConnections int `json:"total_connections"`
}
// LoadBalancerPage is the page returned by a pager when traversing over a
// collection of load balancers.
type LoadBalancerPage struct {
pagination.LinkedPageBase
}
// NextPageURL is invoked when a paginated collection of load balancers 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 (r LoadBalancerPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"loadbalancers_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a LoadBalancerPage struct is empty.
func (r LoadBalancerPage) IsEmpty() (bool, error) {
is, err := ExtractLoadBalancers(r)
return len(is) == 0, err
}
// 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(r pagination.Page) ([]LoadBalancer, error) {
var s struct {
LoadBalancers []LoadBalancer `json:"loadbalancers"`
}
err := (r.(LoadBalancerPage)).ExtractInto(&s)
return s.LoadBalancers, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a loadbalancer.
func (r commonResult) Extract() (*LoadBalancer, error) {
var s struct {
LoadBalancer *LoadBalancer `json:"loadbalancer"`
}
err := r.ExtractInto(&s)
return s.LoadBalancer, err
}
// GetStatusesResult represents the result of a GetStatuses operation.
// Call its Extract method to interpret it as a StatusTree.
type GetStatusesResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts the status of
// a Loadbalancer.
func (r GetStatusesResult) Extract() (*StatusTree, error) {
var s struct {
Statuses *StatusTree `json:"statuses"`
}
err := r.ExtractInto(&s)
return s.Statuses, err
}
// StatsResult represents the result of a GetStats operation.
// Call its Extract method to interpret it as a Stats.
type StatsResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts the status of
// a Loadbalancer.
func (r StatsResult) Extract() (*Stats, error) {
var s struct {
Stats *Stats `json:"stats"`
}
err := r.ExtractInto(&s)
return s.Stats, err
}
// CreateResult represents the result of a create operation. Call its Extract
// method to interpret it as a LoadBalancer.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation. Call its Extract
// method to interpret it as a LoadBalancer.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation. Call its Extract
// method to interpret it as a LoadBalancer.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
// FailoverResult represents the result of a failover operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type FailoverResult struct {
gophercloud.ErrResult
}

View File

@@ -0,0 +1,31 @@
package loadbalancers
import "github.com/gophercloud/gophercloud"
const (
rootPath = "lbaas"
resourcePath = "loadbalancers"
statusPath = "status"
statisticsPath = "stats"
failoverPath = "failover"
)
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)
}
func statisticsRootURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id, statisticsPath)
}
func failoverRootURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL(rootPath, resourcePath, id, failoverPath)
}

View File

@@ -0,0 +1,69 @@
/*
Package monitors provides information and interaction with Monitors
of the LBaaS v2 extension for the OpenStack Networking service.
Example to List Monitors
listOpts := monitors.ListOpts{
PoolID: "c79a4468-d788-410c-bf79-9a8ef6354852",
}
allPages, err := monitors.List(networkClient, listOpts).AllPages()
if err != nil {
panic(err)
}
allMonitors, err := monitors.ExtractMonitors(allPages)
if err != nil {
panic(err)
}
for _, monitor := range allMonitors {
fmt.Printf("%+v\n", monitor)
}
Example to Create a Monitor
createOpts := monitors.CreateOpts{
Type: "HTTP",
Name: "db",
PoolID: "84f1b61f-58c4-45bf-a8a9-2dafb9e5214d",
Delay: 20,
Timeout: 10,
MaxRetries: 5,
URLPath: "/check",
ExpectedCodes: "200-299",
}
monitor, err := monitors.Create(networkClient, createOpts).Extract()
if err != nil {
panic(err)
}
Example to Update a Monitor
monitorID := "d67d56a6-4a86-4688-a282-f46444705c64"
updateOpts := monitors.UpdateOpts{
Name: "NewHealthmonitorName",
Delay: 3,
Timeout: 20,
MaxRetries: 10,
URLPath: "/another_check",
ExpectedCodes: "301",
}
monitor, err := monitors.Update(networkClient, monitorID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Delete a Monitor
monitorID := "d67d56a6-4a86-4688-a282-f46444705c64"
err := monitors.Delete(networkClient, monitorID).ExtractErr()
if err != nil {
panic(err)
}
*/
package monitors

View File

@@ -0,0 +1,257 @@
package monitors
import (
"fmt"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// 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"`
ProjectID string `q:"project_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 (
errDelayMustGETimeout = fmt.Errorf("Delay must be greater than or equal to timeout")
)
// CreateOptsBuilder allows extensions to add additional parameters to the
// List request.
type CreateOptsBuilder interface {
ToMonitorCreateMap() (map[string]interface{}, error)
}
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts struct {
// The Pool to Monitor.
PoolID string `json:"pool_id" required:"true"`
// 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 `json:"type" required:"true"`
// The time, in seconds, between sending probes to members.
Delay int `json:"delay" required:"true"`
// 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 `json:"timeout" required:"true"`
// Number of permissible ping failures before changing the member's
// status to INACTIVE. Must be a number between 1 and 10.
MaxRetries int `json:"max_retries" required:"true"`
// URI path that will be accessed if Monitor type is HTTP or HTTPS.
// Required for HTTP(S) types.
URLPath string `json:"url_path,omitempty"`
// The HTTP method used for requests by the Monitor. If this attribute
// is not specified, it defaults to "GET". Required for HTTP(S) types.
HTTPMethod string `json:"http_method,omitempty"`
// Expected HTTP codes for a passing HTTP(S) Monitor. You can either specify
// a single status like "200", or a range like "200-202". Required for HTTP(S)
// types.
ExpectedCodes string `json:"expected_codes,omitempty"`
// TenantID is the UUID of the project who owns the Monitor.
// Only administrative users can specify a project UUID other than their own.
TenantID string `json:"tenant_id,omitempty"`
// ProjectID is the UUID of the project who owns the Monitor.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id,omitempty"`
// The Name of the Monitor.
Name string `json:"name,omitempty"`
// The administrative state of the Monitor. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToMonitorCreateMap builds a request body from CreateOpts.
func (opts CreateOpts) ToMonitorCreateMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "healthmonitor")
if err != nil {
return nil, err
}
switch opts.Type {
case TypeHTTP, TypeHTTPS:
switch opts.URLPath {
case "":
return nil, fmt.Errorf("URLPath must be provided for HTTP and HTTPS")
}
switch opts.ExpectedCodes {
case "":
return nil, fmt.Errorf("ExpectedCodes must be provided for HTTP and HTTPS")
}
}
return b, 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) (r CreateResult) {
b, err := opts.ToMonitorCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
return
}
// Get retrieves a particular Health Monitor based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
ToMonitorUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts is the common options struct used in this package's Update
// operation.
type UpdateOpts struct {
// The time, in seconds, between sending probes to members.
Delay int `json:"delay,omitempty"`
// 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 `json:"timeout,omitempty"`
// Number of permissible ping failures before changing the member's
// status to INACTIVE. Must be a number between 1 and 10.
MaxRetries int `json:"max_retries,omitempty"`
// URI path that will be accessed if Monitor type is HTTP or HTTPS.
// Required for HTTP(S) types.
URLPath string `json:"url_path,omitempty"`
// The HTTP method used for requests by the Monitor. If this attribute
// is not specified, it defaults to "GET". Required for HTTP(S) types.
HTTPMethod string `json:"http_method,omitempty"`
// Expected HTTP codes for a passing HTTP(S) Monitor. You can either specify
// a single status like "200", or a range like "200-202". Required for HTTP(S)
// types.
ExpectedCodes string `json:"expected_codes,omitempty"`
// The Name of the Monitor.
Name *string `json:"name,omitempty"`
// The administrative state of the Monitor. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToMonitorUpdateMap builds a request body from UpdateOpts.
func (opts UpdateOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "healthmonitor")
}
// Update is an operation which modifies the attributes of the specified
// Monitor.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
b, err := opts.ToMonitorUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
return
}
// Delete will permanently delete a particular Monitor based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
_, r.Err = c.Delete(resourceURL(c, id), nil)
return
}

View File

@@ -0,0 +1,156 @@
package monitors
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
type PoolID struct {
ID string `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 `json:"id"`
// The Name of the Monitor.
Name string `json:"name"`
// The owner of the Monitor.
ProjectID string `json:"project_id"`
// The type of probe sent by the load balancer to verify the member state,
// which is PING, TCP, HTTP, or HTTPS.
Type string `json:"type"`
// The time, in seconds, between sending probes to members.
Delay int `json:"delay"`
// 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 `json:"timeout"`
// 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"`
// The HTTP method that the monitor uses for requests.
HTTPMethod string `json:"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" `
// Expected HTTP codes for a passing HTTP(S) monitor.
ExpectedCodes string `json:"expected_codes"`
// The administrative state of the health monitor, which is up (true) or
// down (false).
AdminStateUp bool `json:"admin_state_up"`
// The status of the health monitor. Indicates whether the health monitor is
// operational.
Status string `json:"status"`
// List of pools that are associated with the health monitor.
Pools []PoolID `json:"pools"`
// The provisioning status of the Monitor.
// This value is ACTIVE, PENDING_* or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// The operating status of the monitor.
OperatingStatus string `json:"operating_status"`
}
// 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 (r MonitorPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"healthmonitors_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a MonitorPage struct is empty.
func (r MonitorPage) IsEmpty() (bool, error) {
is, err := ExtractMonitors(r)
return len(is) == 0, err
}
// 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(r pagination.Page) ([]Monitor, error) {
var s struct {
Monitors []Monitor `json:"healthmonitors"`
}
err := (r.(MonitorPage)).ExtractInto(&s)
return s.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) {
var s struct {
Monitor *Monitor `json:"healthmonitor"`
}
err := r.ExtractInto(&s)
return s.Monitor, err
}
// CreateResult represents the result of a create operation. Call its Extract
// method to interpret it as a Monitor.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a get operation. Call its Extract
// method to interpret it as a Monitor.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an update operation. Call its Extract
// method to interpret it as a Monitor.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a delete operation. Call its
// ExtractErr method to determine if the result succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}

View File

@@ -0,0 +1,16 @@
package monitors
import "github.com/gophercloud/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)
}

View File

@@ -0,0 +1,154 @@
/*
Package pools provides information and interaction with Pools and
Members of the LBaaS v2 extension for the OpenStack Networking service.
Example to List Pools
listOpts := pools.ListOpts{
LoadbalancerID: "c79a4468-d788-410c-bf79-9a8ef6354852",
}
allPages, err := pools.List(networkClient, listOpts).AllPages()
if err != nil {
panic(err)
}
allPools, err := pools.ExtractMonitors(allPages)
if err != nil {
panic(err)
}
for _, pools := range allPools {
fmt.Printf("%+v\n", pool)
}
Example to Create a Pool
createOpts := pools.CreateOpts{
LBMethod: pools.LBMethodRoundRobin,
Protocol: "HTTP",
Name: "Example pool",
LoadbalancerID: "79e05663-7f03-45d2-a092-8b94062f22ab",
}
pool, err := pools.Create(networkClient, createOpts).Extract()
if err != nil {
panic(err)
}
Example to Update a Pool
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
updateOpts := pools.UpdateOpts{
Name: "new-name",
}
pool, err := pools.Update(networkClient, poolID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Delete a Pool
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
err := pools.Delete(networkClient, poolID).ExtractErr()
if err != nil {
panic(err)
}
Example to List Pool Members
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
listOpts := pools.ListMemberOpts{
ProtocolPort: 80,
}
allPages, err := pools.ListMembers(networkClient, poolID, listOpts).AllPages()
if err != nil {
panic(err)
}
allMembers, err := pools.ExtractMembers(allPages)
if err != nil {
panic(err)
}
for _, member := allMembers {
fmt.Printf("%+v\n", member)
}
Example to Create a Member
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
weight := 10
createOpts := pools.CreateMemberOpts{
Name: "db",
SubnetID: "1981f108-3c48-48d2-b908-30f7d28532c9",
Address: "10.0.2.11",
ProtocolPort: 80,
Weight: &weight,
}
member, err := pools.CreateMember(networkClient, poolID, createOpts).Extract()
if err != nil {
panic(err)
}
Example to Update a Member
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
memberID := "64dba99f-8af8-4200-8882-e32a0660f23e"
weight := 4
updateOpts := pools.UpdateMemberOpts{
Name: "new-name",
Weight: &weight,
}
member, err := pools.UpdateMember(networkClient, poolID, memberID, updateOpts).Extract()
if err != nil {
panic(err)
}
Example to Delete a Member
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
memberID := "64dba99f-8af8-4200-8882-e32a0660f23e"
err := pools.DeleteMember(networkClient, poolID, memberID).ExtractErr()
if err != nil {
panic(err)
}
Example to Update Members:
poolID := "d67d56a6-4a86-4688-a282-f46444705c64"
weight_1 := 20
member1 := pools.BatchUpdateMemberOpts{
Address: "192.0.2.16",
ProtocolPort: 80,
Name: "web-server-1",
SubnetID: "bbb35f84-35cc-4b2f-84c2-a6a29bba68aa",
Weight: &weight_1,
}
weight_2 := 10
member2 := pools.BatchUpdateMemberOpts{
Address: "192.0.2.17",
ProtocolPort: 80,
Name: "web-server-2",
Weight: &weight_2,
SubnetID: "bbb35f84-35cc-4b2f-84c2-a6a29bba68aa",
}
members := []pools.BatchUpdateMemberOpts{member1, member2}
err := pools.BatchUpdateMembers(networkClient, poolID, members).ExtractErr()
if err != nil {
panic(err)
}
*/
package pools

View File

@@ -0,0 +1,378 @@
package pools
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
// 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"`
ProjectID string `q:"project_id"`
AdminStateUp *bool `q:"admin_state_up"`
Name string `q:"name"`
ID string `q:"id"`
LoadbalancerID string `q:"loadbalancer_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)
return q.String(), err
}
// 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
// project 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"
ProtocolUDP Protocol = "UDP"
ProtocolPROXY Protocol = "PROXY"
ProtocolHTTP Protocol = "HTTP"
ProtocolHTTPS Protocol = "HTTPS"
)
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
ToPoolCreateMap() (map[string]interface{}, error)
}
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts struct {
// 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 `json:"lb_algorithm" required:"true"`
// The protocol used by the pool members, you can use either
// ProtocolTCP, ProtocolUDP, ProtocolPROXY, ProtocolHTTP, or ProtocolHTTPS.
Protocol Protocol `json:"protocol" required:"true"`
// The Loadbalancer on which the members of the pool will be associated with.
// Note: one of LoadbalancerID or ListenerID must be provided.
LoadbalancerID string `json:"loadbalancer_id,omitempty" xor:"ListenerID"`
// The Listener on which the members of the pool will be associated with.
// Note: one of LoadbalancerID or ListenerID must be provided.
ListenerID string `json:"listener_id,omitempty" xor:"LoadbalancerID"`
// ProjectID is the UUID of the project who owns the Pool.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id,omitempty"`
// Name of the pool.
Name string `json:"name,omitempty"`
// Human-readable description for the pool.
Description string `json:"description,omitempty"`
// Persistence is the session persistence of the pool.
// Omit this field to prevent session persistence.
Persistence *SessionPersistence `json:"session_persistence,omitempty"`
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToPoolCreateMap builds a request body from CreateOpts.
func (opts CreateOpts) ToPoolCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "pool")
}
// Create accepts a CreateOpts struct and uses the values to create a new
// load balancer pool.
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToPoolCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
return
}
// Get retrieves a particular pool based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
ToPoolUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts is the common options struct used in this package's Update
// operation.
type UpdateOpts struct {
// Name of the pool.
Name *string `json:"name,omitempty"`
// Human-readable description for the pool.
Description *string `json:"description,omitempty"`
// 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 `json:"lb_algorithm,omitempty"`
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToPoolUpdateMap builds a request body from UpdateOpts.
func (opts UpdateOpts) ToPoolUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "pool")
}
// Update allows pools to be updated.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
b, err := opts.ToPoolUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return
}
// Delete will permanently delete a particular pool based on its unique ID.
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
_, r.Err = c.Delete(resourceURL(c, id), nil)
return
}
// ListMemberOptsBuilder allows extensions to add additional parameters to the
// ListMembers request.
type ListMembersOptsBuilder interface {
ToMembersListQuery() (string, error)
}
// ListMembersOpts 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 ListMembersOpts struct {
Name string `q:"name"`
Weight int `q:"weight"`
AdminStateUp *bool `q:"admin_state_up"`
ProjectID string `q:"project_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 ListMembersOpts) ToMembersListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
return q.String(), err
}
// ListMembers returns a Pager which allows you to iterate over a collection of
// members. It accepts a ListMembersOptsBuilder, 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
// project who submits the request, unless an admin user submits the request.
func ListMembers(c *gophercloud.ServiceClient, poolID string, opts ListMembersOptsBuilder) pagination.Pager {
url := memberRootURL(c, poolID)
if opts != nil {
query, err := opts.ToMembersListQuery()
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}}
})
}
// CreateMemberOptsBuilder allows extensions to add additional parameters to the
// CreateMember request.
type CreateMemberOptsBuilder interface {
ToMemberCreateMap() (map[string]interface{}, error)
}
// CreateMemberOpts is the common options struct used in this package's CreateMember
// operation.
type CreateMemberOpts struct {
// The IP address of the member to receive traffic from the load balancer.
Address string `json:"address" required:"true"`
// The port on which to listen for client traffic.
ProtocolPort int `json:"protocol_port" required:"true"`
// Name of the Member.
Name string `json:"name,omitempty"`
// ProjectID is the UUID of the project who owns the Member.
// Only administrative users can specify a project UUID other than their own.
ProjectID string `json:"project_id,omitempty"`
// 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 `json:"weight,omitempty"`
// If you omit this parameter, LBaaS uses the vip_subnet_id parameter value
// for the subnet UUID.
SubnetID string `json:"subnet_id,omitempty"`
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToMemberCreateMap builds a request body from CreateMemberOpts.
func (opts CreateMemberOpts) ToMemberCreateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "member")
}
// CreateMember will create and associate a Member with a particular Pool.
func CreateMember(c *gophercloud.ServiceClient, poolID string, opts CreateMemberOpts) (r CreateMemberResult) {
b, err := opts.ToMemberCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Post(memberRootURL(c, poolID), b, &r.Body, nil)
return
}
// GetMember retrieves a particular Pool Member based on its unique ID.
func GetMember(c *gophercloud.ServiceClient, poolID string, memberID string) (r GetMemberResult) {
_, r.Err = c.Get(memberResourceURL(c, poolID, memberID), &r.Body, nil)
return
}
// UpdateMemberOptsBuilder allows extensions to add additional parameters to the
// List request.
type UpdateMemberOptsBuilder interface {
ToMemberUpdateMap() (map[string]interface{}, error)
}
// UpdateMemberOpts is the common options struct used in this package's Update
// operation.
type UpdateMemberOpts struct {
// Name of the Member.
Name *string `json:"name,omitempty"`
// 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 `json:"weight,omitempty"`
// The administrative state of the Pool. A valid value is true (UP)
// or false (DOWN).
AdminStateUp *bool `json:"admin_state_up,omitempty"`
}
// ToMemberUpdateMap builds a request body from UpdateMemberOpts.
func (opts UpdateMemberOpts) ToMemberUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "member")
}
// Update allows Member to be updated.
func UpdateMember(c *gophercloud.ServiceClient, poolID string, memberID string, opts UpdateMemberOptsBuilder) (r UpdateMemberResult) {
b, err := opts.ToMemberUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(memberResourceURL(c, poolID, memberID), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201, 202},
})
return
}
// BatchUpdateMemberOptsBuilder allows extensions to add additional parameters to the BatchUpdateMembers request.
type BatchUpdateMemberOptsBuilder interface {
ToBatchMemberUpdateMap() (map[string]interface{}, error)
}
type BatchUpdateMemberOpts CreateMemberOpts
// ToBatchMemberUpdateMap builds a request body from BatchUpdateMemberOpts.
func (opts BatchUpdateMemberOpts) ToBatchMemberUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "")
}
// BatchUpdateMembers updates the pool members in batch
func BatchUpdateMembers(c *gophercloud.ServiceClient, poolID string, opts []BatchUpdateMemberOpts) (r UpdateMembersResult) {
var members []map[string]interface{}
for _, opt := range opts {
b, err := opt.ToBatchMemberUpdateMap()
if err != nil {
r.Err = err
return
}
members = append(members, b)
}
b := map[string]interface{}{"members": members}
_, r.Err = c.Put(memberRootURL(c, poolID), b, nil, &gophercloud.RequestOpts{OkCodes: []int{202}})
return
}
// DisassociateMember will remove and disassociate a Member from a particular
// Pool.
func DeleteMember(c *gophercloud.ServiceClient, poolID string, memberID string) (r DeleteMemberResult) {
_, r.Err = c.Delete(memberResourceURL(c, poolID, memberID), nil)
return
}

View File

@@ -0,0 +1,328 @@
package pools
import (
"encoding/json"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors"
"github.com/gophercloud/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 `json:"type"`
// Name of cookie if persistence mode is set appropriately.
CookieName string `json:"cookie_name,omitempty"`
}
// LoadBalancerID represents a load balancer.
type LoadBalancerID struct {
ID string `json:"id"`
}
// ListenerID represents a listener.
type ListenerID struct {
ID string `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"`
// The protocol of the Pool, which is TCP, HTTP, or HTTPS.
Protocol string `json:"protocol"`
// Description for the Pool.
Description string `json:"description"`
// A list of listeners objects IDs.
Listeners []ListenerID `json:"listeners"` //[]map[string]interface{}
// A list of member objects IDs.
Members []Member `json:"members"`
// The ID of associated health monitor.
MonitorID string `json:"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"`
// Owner of the Pool.
ProjectID string `json:"project_id"`
// The administrative state of the Pool, which is up (true) or down (false).
AdminStateUp bool `json:"admin_state_up"`
// Pool name. Does not have to be unique.
Name string `json:"name"`
// The unique ID for the Pool.
ID string `json:"id"`
// A list of load balancer objects IDs.
Loadbalancers []LoadBalancerID `json:"loadbalancers"`
// Indicates whether connections in the same session will be processed by the
// same Pool member or not.
Persistence SessionPersistence `json:"session_persistence"`
// The load balancer provider.
Provider string `json:"provider"`
// The Monitor associated with this Pool.
Monitor monitors.Monitor `json:"healthmonitor"`
// The provisioning status of the pool.
// This value is ACTIVE, PENDING_* or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// The operating status of the pool.
OperatingStatus string `json:"operating_status"`
}
// 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 (r PoolPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"pools_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a PoolPage struct is empty.
func (r PoolPage) IsEmpty() (bool, error) {
is, err := ExtractPools(r)
return len(is) == 0, err
}
// ExtractPools accepts a Page struct, specifically a PoolPage struct,
// and extracts the elements into a slice of Pool structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractPools(r pagination.Page) ([]Pool, error) {
var s struct {
Pools []Pool `json:"pools"`
}
err := (r.(PoolPage)).ExtractInto(&s)
return s.Pools, err
}
type commonResult struct {
gophercloud.Result
}
// Extract is a function that accepts a result and extracts a pool.
func (r commonResult) Extract() (*Pool, error) {
var s struct {
Pool *Pool `json:"pool"`
}
err := r.ExtractInto(&s)
return s.Pool, err
}
// CreateResult represents the result of a Create operation. Call its Extract
// method to interpret the result as a Pool.
type CreateResult struct {
commonResult
}
// GetResult represents the result of a Get operation. Call its Extract
// method to interpret the result as a Pool.
type GetResult struct {
commonResult
}
// UpdateResult represents the result of an Update operation. Call its Extract
// method to interpret the result as a Pool.
type UpdateResult struct {
commonResult
}
// DeleteResult represents the result of a Delete operation. Call its
// ExtractErr method to determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
// Member represents the application running on a backend server.
type Member struct {
// Name of the Member.
Name string `json:"name"`
// Weight of Member.
Weight int `json:"weight"`
// The administrative state of the member, which is up (true) or down (false).
AdminStateUp bool `json:"admin_state_up"`
// Owner of the Member.
ProjectID string `json:"project_id"`
// Parameter value for the subnet UUID.
SubnetID string `json:"subnet_id"`
// The Pool to which the Member belongs.
PoolID string `json:"pool_id"`
// The IP address of the Member.
Address string `json:"address"`
// The port on which the application is hosted.
ProtocolPort int `json:"protocol_port"`
// The unique ID for the Member.
ID string `json:"id"`
// The provisioning status of the pool.
// This value is ACTIVE, PENDING_* or ERROR.
ProvisioningStatus string `json:"provisioning_status"`
// DateTime when the member was created
CreatedAt time.Time `json:"-"`
// DateTime when the member was updated
UpdatedAt time.Time `json:"-"`
// The operating status of the member
OperatingStatus string `json:"operating_status"`
// Is the member a backup? Backup members only receive traffic when all non-backup members are down.
Backup bool `json:"backup"`
// An alternate IP address used for health monitoring a backend member.
MonitorAddress string `json:"monitor_address"`
// An alternate protocol port used for health monitoring a backend member.
MonitorPort int `json:"monitor_port"`
}
// 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 (r MemberPage) NextPageURL() (string, error) {
var s struct {
Links []gophercloud.Link `json:"members_links"`
}
err := r.ExtractInto(&s)
if err != nil {
return "", err
}
return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a MemberPage struct is empty.
func (r MemberPage) IsEmpty() (bool, error) {
is, err := ExtractMembers(r)
return len(is) == 0, err
}
// ExtractMembers accepts a Page struct, specifically a MemberPage struct,
// and extracts the elements into a slice of Members structs. In other words,
// a generic collection is mapped into a relevant slice.
func ExtractMembers(r pagination.Page) ([]Member, error) {
var s struct {
Members []Member `json:"members"`
}
err := (r.(MemberPage)).ExtractInto(&s)
return s.Members, err
}
type commonMemberResult struct {
gophercloud.Result
}
func (r *Member) UnmarshalJSON(b []byte) error {
type tmp Member
var s struct {
tmp
CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"`
UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = Member(s.tmp)
r.CreatedAt = time.Time(s.CreatedAt)
r.UpdatedAt = time.Time(s.UpdatedAt)
return nil
}
// ExtractMember is a function that accepts a result and extracts a member.
func (r commonMemberResult) Extract() (*Member, error) {
var s struct {
Member *Member `json:"member"`
}
err := r.ExtractInto(&s)
return s.Member, err
}
// CreateMemberResult represents the result of a CreateMember operation.
// Call its Extract method to interpret it as a Member.
type CreateMemberResult struct {
commonMemberResult
}
// GetMemberResult represents the result of a GetMember operation.
// Call its Extract method to interpret it as a Member.
type GetMemberResult struct {
commonMemberResult
}
// UpdateMemberResult represents the result of an UpdateMember operation.
// Call its Extract method to interpret it as a Member.
type UpdateMemberResult struct {
commonMemberResult
}
// UpdateMembersResult represents the result of an UpdateMembers operation.
// Call its ExtractErr method to determine if the request succeeded or failed.
type UpdateMembersResult struct {
gophercloud.ErrResult
}
// DeleteMemberResult represents the result of a DeleteMember operation.
// Call its ExtractErr method to determine if the request succeeded or failed.
type DeleteMemberResult struct {
gophercloud.ErrResult
}

View File

@@ -0,0 +1,25 @@
package pools
import "github.com/gophercloud/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, memberID string) string {
return c.ServiceURL(rootPath, resourcePath, poolID, memberPath, memberID)
}