Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add loadbalancer additional vips feature #21

Open
wants to merge 5 commits into
base: v1.5.0-ovh
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,11 @@ func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointO
// NewBareMetalV1 creates a ServiceClient that may be used with the v1
// bare metal package.
func NewBareMetalV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
return initClientOpts(client, eo, "baremetal")
sc, err := initClientOpts(client, eo, "baremetal")
if !strings.HasSuffix(sc.Endpoint, "v1/") {
sc.ResourceBase = sc.Endpoint + "v1/"
}
return sc, err
}

// NewBareMetalIntrospectionV1 creates a ServiceClient that may be used with the v1
Expand Down
7 changes: 7 additions & 0 deletions openstack/identity/v3/endpoints/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pa
})
}

// Get retrieves details on a single endpoint, by ID.
func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
resp, err := client.Get(endpointURL(client, id), &r.Body, nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// UpdateOptsBuilder allows extensions to add parameters to the Update request.
type UpdateOptsBuilder interface {
ToEndpointUpdateMap() (map[string]interface{}, error)
Expand Down
6 changes: 6 additions & 0 deletions openstack/identity/v3/endpoints/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ func (r commonResult) Extract() (*Endpoint, error) {
return s.Endpoint, err
}

// GetResult is the response from a Get operation. Call its Extract method
// to interpret it as an Endpoint.
type GetResult struct {
commonResult
}

// CreateResult is the response from a Create operation. Call its Extract
// method to interpret it as an Endpoint.
type CreateResult struct {
Expand Down
91 changes: 91 additions & 0 deletions openstack/identity/v3/extensions/endpointgroups/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,94 @@ func DeleteProjectAssociation(client *gophercloud.ServiceClient, id string, proj
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// CreateOptsBuilder allows extensions to add additional parameters to
// the Create request.
type CreateOptsBuilder interface {
ToGroupCreateMap() (map[string]interface{}, error)
}

// CreateOpts provides options used to create a group.
type CreateOpts struct {
// Name is the name of the new endpoint group.
Name string `json:"name" required:"true"`

// Description is a description of the endpoint group.
Description *string `json:"description,omitempty"`

// Filters are the filters of the endpoint group.
Filters map[string]interface{} `json:"filters,omitempty"`
}

// ToGroupCreateMap formats a CreateOpts into a create request.
func (opts CreateOpts) ToGroupCreateMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "endpoint_group")
if err != nil {
return nil, err
}

return b, nil
}

// Create creates a new endpoint group.
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
b, err := opts.ToGroupCreateMap()
if err != nil {
r.Err = err
return
}
resp, err := client.Post(createURL(client), &b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{201},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// UpdateOptsBuilder allows extensions to add additional parameters to
// the Update request.
type UpdateOptsBuilder interface {
ToGroupUpdateMap() (map[string]interface{}, error)
}

// UpdateOpts provides options for updating an endpoint group.
type UpdateOpts struct {
// Name is the name of the endpoint group.
Name string `json:"name,omitempty"`

// Description is a description of the endpoint group.
Description *string `json:"description,omitempty"`

// Filters are the filters of the endpoint group.
Filters map[string]interface{} `json:"filters,omitempty"`
}

// ToGroupUpdateMap formats a UpdateOpts into an update request.
func (opts UpdateOpts) ToGroupUpdateMap() (map[string]interface{}, error) {
b, err := gophercloud.BuildRequestBody(opts, "endpoint_group")
if err != nil {
return nil, err
}

return b, nil
}

// Update updates an existing Endpoint Group.
func Update(client *gophercloud.ServiceClient, groupID string, opts UpdateOptsBuilder) (r UpdateResult) {
b, err := opts.ToGroupUpdateMap()
if err != nil {
r.Err = err
return
}
resp, err := client.Patch(updateURL(client, groupID), &b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// Delete deletes an endpoint group.
func Delete(client *gophercloud.ServiceClient, groupID string) (r DeleteResult) {
resp, err := client.Delete(deleteURL(client, groupID), nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
18 changes: 18 additions & 0 deletions openstack/identity/v3/extensions/endpointgroups/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,21 @@ type CheckProjectAssociationResult struct {
type DeleteProjectAssociationResult struct {
gophercloud.ErrResult
}

// CreateResult is the response from a Create operation. Call its Extract method
// to interpret it as an Endpoint Group.
type CreateResult struct {
commonResult
}

// UpdateResult is the response from an Update operation. Call its Extract
// method to interpret it as an Endpoint Group.
type UpdateResult struct {
commonResult
}

// DeleteResult is the response from a Delete operation. Call its ExtractErr to
// determine if the request succeeded or failed.
type DeleteResult struct {
gophercloud.ErrResult
}
24 changes: 18 additions & 6 deletions openstack/identity/v3/extensions/endpointgroups/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,26 @@ func rootURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL(endpointGroupPath)
}

func resourceURL(client *gophercloud.ServiceClient, endointGroupID string) string {
return client.ServiceURL(endpointGroupPath, endointGroupID)
func resourceURL(client *gophercloud.ServiceClient, endpointGroupID string) string {
return client.ServiceURL(endpointGroupPath, endpointGroupID)
}

func projectAssociationURL(client *gophercloud.ServiceClient, endpointGroupId string, projectId string) string {
return client.ServiceURL(endpointGroupPath, endpointGroupId, "projects", projectId)
func projectAssociationURL(client *gophercloud.ServiceClient, endpointGroupID string, projectID string) string {
return client.ServiceURL(endpointGroupPath, endpointGroupID, "projects", projectID)
}

func listEndpointGroupsAssociationURL(client *gophercloud.ServiceClient, projectId string) string {
return client.ServiceURL(endpointGroupsAssociationPath, projectId, "endpoint_groups")
func listEndpointGroupsAssociationURL(client *gophercloud.ServiceClient, projectID string) string {
return client.ServiceURL(endpointGroupsAssociationPath, projectID, "endpoint_groups")
}

func createURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL(endpointGroupPath)
}

func updateURL(client *gophercloud.ServiceClient, endpointGroupID string) string {
return client.ServiceURL(endpointGroupPath, endpointGroupID)
}

func deleteURL(client *gophercloud.ServiceClient, endpointGroupID string) string {
return client.ServiceURL(endpointGroupPath, endpointGroupID)
}
4 changes: 4 additions & 0 deletions openstack/loadbalancer/v2/loadbalancers/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ type CreateOpts struct {

// Tags is a set of resource tags.
Tags []string `json:"tags,omitempty"`

// The additional ips of the loadbalancer. Subnets must all belong to the same network as the primary VIP.
// New in version 2.26
AdditionalVIps []AdditionalVip `json:"additional_vips,omitempty"`
}

// ToLoadBalancerCreateMap builds a request body from CreateOpts.
Expand Down
10 changes: 10 additions & 0 deletions openstack/loadbalancer/v2/loadbalancers/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ type LoadBalancer struct {
// Tags is a list of resource tags. Tags are arbitrarily defined strings
// attached to the resource.
Tags []string `json:"tags"`

// The additional ips of the loadbalancer. Subnets must all belong to the same network as the primary VIP.
// New in version 2.26
AdditionalVIps []AdditionalVip `json:"additional_vips"`
}

// AdditionalVip represent additional ip of a loadbalancer. IpAddress field is optional.
type AdditionalVip struct {
SubnetID string `json:"subnet_id"`
IPAddress string `json:"ip_address,omitempty"`
}

func (r *LoadBalancer) UnmarshalJSON(b []byte) error {
Expand Down
18 changes: 13 additions & 5 deletions openstack/loadbalancer/v2/loadbalancers/testing/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
const LoadbalancersListBody = `
{
"loadbalancers":[
{
{
"id": "c331058c-6a40-4144-948e-b9fb1df9db4b",
"project_id": "54030507-44f7-473c-9342-b4d14a95f692",
"created_at": "2019-06-30T04:15:37",
Expand Down Expand Up @@ -52,7 +52,8 @@ const LoadbalancersListBody = `
"admin_state_up": true,
"provisioning_status": "PENDING_CREATE",
"operating_status": "OFFLINE",
"tags": ["test", "stage"]
"tags": ["test", "stage"],
"additional_vips": [{"subnet_id": "0d4f6a08-60b7-44ab-8903-f7d76ec54095", "ip_address" : "192.168.10.10"}]
}
]
}
Expand All @@ -77,7 +78,8 @@ const SingleLoadbalancerBody = `
"admin_state_up": true,
"provisioning_status": "PENDING_CREATE",
"operating_status": "OFFLINE",
"tags": ["test", "stage"]
"tags": ["test", "stage"],
"additional_vips": [{"subnet_id": "0d4f6a08-60b7-44ab-8903-f7d76ec54095", "ip_address" : "192.168.10.10"}]
}
}
`
Expand Down Expand Up @@ -289,7 +291,12 @@ var (
ProvisioningStatus: "PENDING_CREATE",
OperatingStatus: "OFFLINE",
Tags: []string{"test", "stage"},
}
AdditionalVIps: []loadbalancers.AdditionalVip{
{
SubnetID: "0d4f6a08-60b7-44ab-8903-f7d76ec54095",
IPAddress: "192.168.10.10",
},
}}
LoadbalancerUpdated = loadbalancers.LoadBalancer{
ID: "36e08a3e-a78f-4b40-a229-1e7e23eee1ab",
ProjectID: "54030507-44f7-473c-9342-b4d14a95f692",
Expand Down Expand Up @@ -546,7 +553,8 @@ func HandleLoadbalancerCreationSuccessfully(t *testing.T, response string) {
"flavor_id": "bba40eb2-ee8c-11e9-81b4-2a2ae2dbcce4",
"provider": "haproxy",
"admin_state_up": true,
"tags": ["test", "stage"]
"tags": ["test", "stage"],
"additional_vips": [{"subnet_id": "0d4f6a08-60b7-44ab-8903-f7d76ec54095", "ip_address" : "192.168.10.10"}]
}
}`)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ func TestCreateLoadbalancer(t *testing.T) {
FlavorID: "bba40eb2-ee8c-11e9-81b4-2a2ae2dbcce4",
Provider: "haproxy",
Tags: []string{"test", "stage"},
AdditionalVIps: []loadbalancers.AdditionalVip{
{
SubnetID: "0d4f6a08-60b7-44ab-8903-f7d76ec54095",
IPAddress: "192.168.10.10",
},
},
}).Extract()
th.AssertNoErr(t, err)

Expand Down
34 changes: 18 additions & 16 deletions openstack/networking/v2/networks/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,24 @@ type ListOptsBuilder interface {
// by a particular network attribute. SortDir sets the direction, and is either
// `asc' or `desc'. Marker and Limit are used for pagination.
type ListOpts struct {
Status string `q:"status"`
Name string `q:"name"`
Description string `q:"description"`
AdminStateUp *bool `q:"admin_state_up"`
TenantID string `q:"tenant_id"`
ProjectID string `q:"project_id"`
Shared *bool `q:"shared"`
ID string `q:"id"`
Marker string `q:"marker"`
Limit int `q:"limit"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
Tags string `q:"tags"`
TagsAny string `q:"tags-any"`
NotTags string `q:"not-tags"`
NotTagsAny string `q:"not-tags-any"`
Status string `q:"status"`
Name string `q:"name"`
Description string `q:"description"`
AdminStateUp *bool `q:"admin_state_up"`
TenantID string `q:"tenant_id"`
ProjectID string `q:"project_id"`
Shared *bool `q:"shared"`
ID string `q:"id"`
Marker string `q:"marker"`
Limit int `q:"limit"`
SortKey string `q:"sort_key"`
SortDir string `q:"sort_dir"`
Tags string `q:"tags"`
TagsAny string `q:"tags-any"`
NotTags string `q:"not-tags"`
NotTagsAny string `q:"not-tags-any"`
NetworkType string `q:"provider:network_type"`
SegmentationID int `q:"provider:segmentation_id"`
}

// ToNetworkListQuery formats a ListOpts into a query string.
Expand Down