Handle Unmarshaling Compute Floating IP IDs (#217)
diff --git a/openstack/compute/v2/extensions/floatingips/results.go b/openstack/compute/v2/extensions/floatingips/results.go
index 753f3af..2f5b338 100644
--- a/openstack/compute/v2/extensions/floatingips/results.go
+++ b/openstack/compute/v2/extensions/floatingips/results.go
@@ -1,6 +1,9 @@
package floatingips
import (
+ "encoding/json"
+ "strconv"
+
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
@@ -8,7 +11,7 @@
// A FloatingIP is an IP that can be associated with an instance
type FloatingIP struct {
// ID is a unique ID of the Floating IP
- ID string `json:"id"`
+ ID string `json:"-"`
// FixedIP is the IP of the instance related to the Floating IP
FixedIP string `json:"fixed_ip,omitempty"`
@@ -23,6 +26,29 @@
Pool string `json:"pool"`
}
+func (r *FloatingIP) UnmarshalJSON(b []byte) error {
+ type tmp FloatingIP
+ var s struct {
+ tmp
+ ID interface{} `json:"id"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+
+ *r = FloatingIP(s.tmp)
+
+ switch t := s.ID.(type) {
+ case float64:
+ r.ID = strconv.FormatFloat(t, 'f', -1, 64)
+ case string:
+ r.ID = t
+ }
+
+ return err
+}
+
// FloatingIPPage stores a single, only page of FloatingIPs
// results from a List call.
type FloatingIPPage struct {
diff --git a/openstack/compute/v2/extensions/floatingips/testing/fixtures.go b/openstack/compute/v2/extensions/floatingips/testing/fixtures.go
index e372606..6866e26 100644
--- a/openstack/compute/v2/extensions/floatingips/testing/fixtures.go
+++ b/openstack/compute/v2/extensions/floatingips/testing/fixtures.go
@@ -58,6 +58,20 @@
}
`
+// CreateOutputWithNumericID is a sample response to a Post call
+// with a legacy nova-network-based numeric ID.
+const CreateOutputWithNumericID = `
+{
+ "floating_ip": {
+ "fixed_ip": null,
+ "id": 1,
+ "instance_id": null,
+ "ip": "10.10.10.1",
+ "pool": "nova"
+ }
+}
+`
+
// FirstFloatingIP is the first result in ListOutput.
var FirstFloatingIP = floatingips.FloatingIP{
ID: "1",
@@ -125,6 +139,23 @@
})
}
+// HandleCreateWithNumericIDSuccessfully configures the test server to respond to a Create request
+// for a new floating ip
+func HandleCreateWithNumericIDSuccessfully(t *testing.T) {
+ th.Mux.HandleFunc("/os-floating-ips", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "POST")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.TestJSONRequest(t, r, `
+{
+ "pool": "nova"
+}
+`)
+
+ w.Header().Add("Content-Type", "application/json")
+ fmt.Fprintf(w, CreateOutputWithNumericID)
+ })
+}
+
// HandleDeleteSuccessfully configures the test server to respond to a Delete request for a
// an existing floating ip
func HandleDeleteSuccessfully(t *testing.T) {
diff --git a/openstack/compute/v2/extensions/floatingips/testing/requests_test.go b/openstack/compute/v2/extensions/floatingips/testing/requests_test.go
index e53da91..2356671 100644
--- a/openstack/compute/v2/extensions/floatingips/testing/requests_test.go
+++ b/openstack/compute/v2/extensions/floatingips/testing/requests_test.go
@@ -39,6 +39,18 @@
th.CheckDeepEquals(t, &CreatedFloatingIP, actual)
}
+func TestCreateWithNumericID(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleCreateWithNumericIDSuccessfully(t)
+
+ actual, err := floatingips.Create(client.ServiceClient(), floatingips.CreateOpts{
+ Pool: "nova",
+ }).Extract()
+ th.AssertNoErr(t, err)
+ th.CheckDeepEquals(t, &CreatedFloatingIP, actual)
+}
+
func TestGet(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()