diff --git a/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go b/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go index 351020410e..b38d7283ca 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go +++ b/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go @@ -3,6 +3,7 @@ package layer3 import ( + "os" "testing" "github.com/gophercloud/gophercloud/acceptance/clients" @@ -10,6 +11,7 @@ import ( "github.com/gophercloud/gophercloud/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" + "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" ) func TestLayer3FloatingIPsList(t *testing.T) { @@ -98,3 +100,48 @@ func TestLayer3FloatingIPsCreateDelete(t *testing.T) { t.Fatalf("Unable to disassociate floating IP: %v", err) } } + +func TestLayer3FloatingIPsCreateDeleteBySubnetID(t *testing.T) { + username := os.Getenv("OS_USERNAME") + if username != "admin" { + t.Skip("must be admin to run this test") + } + + client, err := clients.NewNetworkV2Client() + if err != nil { + t.Fatalf("Unable to create a compute client: %v", err) + } + + choices, err := clients.AcceptanceTestChoicesFromEnv() + if err != nil { + t.Fatalf("Unable to get choices: %v", err) + } + + listOpts := subnets.ListOpts{ + NetworkID: choices.ExternalNetworkID, + } + + subnetPages, err := subnets.List(client, listOpts).AllPages() + if err != nil { + t.Fatalf("Unable to list subnets: %v", err) + } + + allSubnets, err := subnets.ExtractSubnets(subnetPages) + if err != nil { + t.Fatalf("Unable to extract subnets: %v", err) + } + + createOpts := floatingips.CreateOpts{ + FloatingNetworkID: choices.ExternalNetworkID, + SubnetID: allSubnets[0].ID, + } + + fip, err := floatingips.Create(client, createOpts).Extract() + if err != nil { + t.Fatalf("Unable to create floating IP: %v") + } + + tools.PrintResource(t, fip) + + DeleteFloatingIP(t, client, fip.ID) +} diff --git a/openstack/networking/v2/extensions/layer3/floatingips/requests.go b/openstack/networking/v2/extensions/layer3/floatingips/requests.go index 1c8a8b2f13..0a6eb62cb6 100644 --- a/openstack/networking/v2/extensions/layer3/floatingips/requests.go +++ b/openstack/networking/v2/extensions/layer3/floatingips/requests.go @@ -53,6 +53,7 @@ type CreateOpts struct { FloatingIP string `json:"floating_ip_address,omitempty"` PortID string `json:"port_id,omitempty"` FixedIP string `json:"fixed_ip_address,omitempty"` + SubnetID string `json:"subnet_id,omitempty"` TenantID string `json:"tenant_id,omitempty"` } diff --git a/openstack/networking/v2/extensions/layer3/floatingips/testing/requests_test.go b/openstack/networking/v2/extensions/layer3/floatingips/testing/requests_test.go index c665a2ef18..89c028e8a7 100644 --- a/openstack/networking/v2/extensions/layer3/floatingips/testing/requests_test.go +++ b/openstack/networking/v2/extensions/layer3/floatingips/testing/requests_test.go @@ -224,6 +224,58 @@ func TestCreateEmptyPort(t *testing.T) { th.AssertEquals(t, "10.0.0.3", ip.FixedIP) } +func TestCreateWithSubnetID(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v2.0/floatingips", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, ` +{ + "floatingip": { + "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", + "subnet_id": "37adf01c-24db-467a-b845-7ab1e8216c01" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + + fmt.Fprintf(w, ` +{ + "floatingip": { + "router_id": null, + "tenant_id": "4969c491a3c74ee4af974e6d800c62de", + "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", + "fixed_ip_address": null, + "floating_ip_address": "172.24.4.3", + "port_id": null, + "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7" + } +} + `) + }) + + options := floatingips.CreateOpts{ + FloatingNetworkID: "376da547-b977-4cfe-9cba-275c80debf57", + SubnetID: "37adf01c-24db-467a-b845-7ab1e8216c01", + } + + ip, err := floatingips.Create(fake.ServiceClient(), options).Extract() + th.AssertNoErr(t, err) + + th.AssertEquals(t, "2f245a7b-796b-4f26-9cf9-9e82d248fda7", ip.ID) + th.AssertEquals(t, "4969c491a3c74ee4af974e6d800c62de", ip.TenantID) + th.AssertEquals(t, "376da547-b977-4cfe-9cba-275c80debf57", ip.FloatingNetworkID) + th.AssertEquals(t, "172.24.4.3", ip.FloatingIP) + th.AssertEquals(t, "", ip.PortID) + th.AssertEquals(t, "", ip.FixedIP) +} + func TestGet(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP()