Merge pull request #529 from kwapik/fix/reauth_in_v3_tokens
[rfr] Fix reauth in v3 tokens
diff --git a/acceptance/openstack/networking/v2/port_test.go b/acceptance/openstack/networking/v2/port_test.go
index 03e8e27..91bf5bd 100644
--- a/acceptance/openstack/networking/v2/port_test.go
+++ b/acceptance/openstack/networking/v2/port_test.go
@@ -45,10 +45,20 @@
th.AssertEquals(t, p.ID, portID)
// Update port
- p, err = ports.Update(Client, portID, ports.UpdateOpts{Name: "new_port_name"}).Extract()
+ updateOpts := ports.UpdateOpts{
+ Name: "new_port_name",
+ AllowedAddressPairs: []ports.AddressPair{
+ ports.AddressPair{IPAddress: "192.168.199.201"},
+ },
+ }
+ p, err = ports.Update(Client, portID, updateOpts).Extract()
+
th.AssertNoErr(t, err)
th.AssertEquals(t, p.Name, "new_port_name")
+ updatedPort, err := ports.Get(Client, portID).Extract()
+ th.AssertEquals(t, updatedPort.AllowedAddressPairs[0].IPAddress, "192.168.199.201")
+
// Delete port
res := ports.Delete(Client, portID)
th.AssertNoErr(t, res.Err)
@@ -82,8 +92,8 @@
th.AssertNoErr(t, err)
for _, p := range portList {
- t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v]",
- p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups)
+ t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v] Allowed Address Pairs [%#v]",
+ p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups, p.AllowedAddressPairs)
}
return true, nil
@@ -108,6 +118,9 @@
IPVersion: subnets.IPv4,
Name: "my_subnet",
EnableDHCP: subnets.Down,
+ AllocationPools: []subnets.AllocationPool{
+ subnets.AllocationPool{Start: "192.168.199.2", End: "192.168.199.200"},
+ },
}).Extract()
return s.ID, err
}
diff --git a/openstack/networking/v2/extensions/layer3/routers/requests.go b/openstack/networking/v2/extensions/layer3/routers/requests.go
index 8b6e73d..1ffc136 100644
--- a/openstack/networking/v2/extensions/layer3/routers/requests.go
+++ b/openstack/networking/v2/extensions/layer3/routers/requests.go
@@ -16,6 +16,7 @@
ID string `q:"id"`
Name string `q:"name"`
AdminStateUp *bool `q:"admin_state_up"`
+ Distributed *bool `q:"distributed"`
Status string `q:"status"`
TenantID string `q:"tenant_id"`
Limit int `q:"limit"`
@@ -46,6 +47,7 @@
type CreateOpts struct {
Name string
AdminStateUp *bool
+ Distributed *bool
TenantID string
GatewayInfo *GatewayInfo
}
@@ -62,6 +64,7 @@
type router struct {
Name *string `json:"name,omitempty"`
AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Distributed *bool `json:"distributed,omitempty"`
TenantID *string `json:"tenant_id,omitempty"`
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
}
@@ -73,6 +76,7 @@
reqBody := request{Router: router{
Name: gophercloud.MaybeString(opts.Name),
AdminStateUp: opts.AdminStateUp,
+ Distributed: opts.Distributed,
TenantID: gophercloud.MaybeString(opts.TenantID),
}}
@@ -96,6 +100,7 @@
type UpdateOpts struct {
Name string
AdminStateUp *bool
+ Distributed *bool
GatewayInfo *GatewayInfo
Routes []Route
}
@@ -109,6 +114,7 @@
type router struct {
Name *string `json:"name,omitempty"`
AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Distributed *bool `json:"distributed,omitempty"`
GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
Routes []Route `json:"routes"`
}
@@ -120,6 +126,7 @@
reqBody := request{Router: router{
Name: gophercloud.MaybeString(opts.Name),
AdminStateUp: opts.AdminStateUp,
+ Distributed: opts.Distributed,
}}
if opts.GatewayInfo != nil {
diff --git a/openstack/networking/v2/extensions/layer3/routers/requests_test.go b/openstack/networking/v2/extensions/layer3/routers/requests_test.go
index 1981733..dbdc6fa 100644
--- a/openstack/networking/v2/extensions/layer3/routers/requests_test.go
+++ b/openstack/networking/v2/extensions/layer3/routers/requests_test.go
@@ -37,6 +37,7 @@
"name": "second_routers",
"admin_state_up": true,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b"
},
{
@@ -47,6 +48,7 @@
"name": "router1",
"admin_state_up": true,
"tenant_id": "33a40233088643acb66ff6eb0ebea679",
+ "distributed": false,
"id": "a9254bdb-2613-4a13-ac4c-adc581fba50d"
}
]
@@ -69,6 +71,7 @@
Status: "ACTIVE",
GatewayInfo: GatewayInfo{NetworkID: ""},
AdminStateUp: true,
+ Distributed: false,
Name: "second_routers",
ID: "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b",
TenantID: "6b96ff0cb17a4b859e1e575d221683d3",
@@ -77,6 +80,7 @@
Status: "ACTIVE",
GatewayInfo: GatewayInfo{NetworkID: "3c5bcddd-6af9-4e6b-9c3e-c153e521cab8"},
AdminStateUp: true,
+ Distributed: false,
Name: "router1",
ID: "a9254bdb-2613-4a13-ac4c-adc581fba50d",
TenantID: "33a40233088643acb66ff6eb0ebea679",
@@ -127,6 +131,7 @@
"name": "foo_router",
"admin_state_up": false,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e"
}
}
@@ -176,6 +181,7 @@
"name": "router1",
"admin_state_up": true,
"tenant_id": "d6554fe62e2f41efbb6e026fad5c1542",
+ "distributed": false,
"id": "a07eea83-7710-4860-931b-5fe220fae533"
}
}
@@ -233,6 +239,7 @@
"name": "new_name",
"admin_state_up": true,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e",
"routes": [
{
@@ -287,6 +294,7 @@
"name": "name",
"admin_state_up": true,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e",
"routes": []
}
diff --git a/openstack/networking/v2/extensions/layer3/routers/results.go b/openstack/networking/v2/extensions/layer3/routers/results.go
index 5e297ab..4534123 100644
--- a/openstack/networking/v2/extensions/layer3/routers/results.go
+++ b/openstack/networking/v2/extensions/layer3/routers/results.go
@@ -35,6 +35,9 @@
// Administrative state of the router.
AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
+ // Whether router is disitrubted or not..
+ Distributed bool `json:"distributed" mapstructure:"distributed"`
+
// Human readable name for the router. Does not have to be unique.
Name string `json:"name" mapstructure:"name"`
diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go
index 2caf1ca..e73e10a 100644
--- a/openstack/networking/v2/ports/requests.go
+++ b/openstack/networking/v2/ports/requests.go
@@ -95,15 +95,16 @@
// CreateOpts represents the attributes used when creating a new port.
type CreateOpts struct {
- NetworkID string
- Name string
- AdminStateUp *bool
- MACAddress string
- FixedIPs interface{}
- DeviceID string
- DeviceOwner string
- TenantID string
- SecurityGroups []string
+ NetworkID string
+ Name string
+ AdminStateUp *bool
+ MACAddress string
+ FixedIPs interface{}
+ DeviceID string
+ DeviceOwner string
+ TenantID string
+ SecurityGroups []string
+ AllowedAddressPairs []AddressPair
}
// ToPortCreateMap casts a CreateOpts struct to a map.
@@ -139,6 +140,9 @@
if opts.MACAddress != "" {
p["mac_address"] = opts.MACAddress
}
+ if opts.AllowedAddressPairs != nil {
+ p["allowed_address_pairs"] = opts.AllowedAddressPairs
+ }
return map[string]interface{}{"port": p}, nil
}
@@ -168,12 +172,13 @@
// UpdateOpts represents the attributes used when updating an existing port.
type UpdateOpts struct {
- Name string
- AdminStateUp *bool
- FixedIPs interface{}
- DeviceID string
- DeviceOwner string
- SecurityGroups []string
+ Name string
+ AdminStateUp *bool
+ FixedIPs interface{}
+ DeviceID string
+ DeviceOwner string
+ SecurityGroups []string
+ AllowedAddressPairs []AddressPair
}
// ToPortUpdateMap casts an UpdateOpts struct to a map.
@@ -198,6 +203,9 @@
if opts.Name != "" {
p["name"] = opts.Name
}
+ if opts.AllowedAddressPairs != nil {
+ p["allowed_address_pairs"] = opts.AllowedAddressPairs
+ }
return map[string]interface{}{"port": p}, nil
}
diff --git a/openstack/networking/v2/ports/requests_test.go b/openstack/networking/v2/ports/requests_test.go
index 9e323ef..b442996 100644
--- a/openstack/networking/v2/ports/requests_test.go
+++ b/openstack/networking/v2/ports/requests_test.go
@@ -164,7 +164,13 @@
"ip_address": "10.0.0.2"
}
],
- "security_groups": ["foo"]
+ "security_groups": ["foo"],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ]
}
}
`)
@@ -177,7 +183,6 @@
"port": {
"status": "DOWN",
"name": "private-port",
- "allowed_address_pairs": [],
"admin_state_up": true,
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
@@ -193,6 +198,12 @@
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"device_id": ""
}
}
@@ -208,6 +219,9 @@
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.2"},
},
SecurityGroups: []string{"foo"},
+ AllowedAddressPairs: []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ },
}
n, err := Create(fake.ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
@@ -224,6 +238,9 @@
})
th.AssertEquals(t, n.ID, "65c0ee9f-d634-4522-8954-51021b570b0d")
th.AssertDeepEquals(t, n.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
+ th.AssertDeepEquals(t, n.AllowedAddressPairs, []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ })
}
func TestRequiredCreateOpts(t *testing.T) {
@@ -252,6 +269,12 @@
"ip_address": "10.0.0.3"
}
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
]
@@ -278,6 +301,12 @@
"ip_address": "10.0.0.3"
}
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
@@ -294,6 +323,9 @@
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
},
SecurityGroups: []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"},
+ AllowedAddressPairs: []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ },
}
s, err := Update(fake.ServiceClient(), "65c0ee9f-d634-4522-8954-51021b570b0d", options).Extract()
@@ -303,6 +335,9 @@
th.AssertDeepEquals(t, s.FixedIPs, []IP{
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
})
+ th.AssertDeepEquals(t, s.AllowedAddressPairs, []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ })
th.AssertDeepEquals(t, s.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
}
diff --git a/openstack/networking/v2/ports/results.go b/openstack/networking/v2/ports/results.go
index 2511ff5..1f7eea1 100644
--- a/openstack/networking/v2/ports/results.go
+++ b/openstack/networking/v2/ports/results.go
@@ -19,7 +19,6 @@
var res struct {
Port *Port `json:"port"`
}
-
err := mapstructure.Decode(r.Body, &res)
return res.Port, err
@@ -51,6 +50,11 @@
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
}
+type AddressPair struct {
+ IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
+ MACAddress string `mapstructure:"mac_address" json:"mac_address,omitempty"`
+}
+
// Port represents a Neutron port. See package documentation for a top-level
// description of what this is.
type Port struct {
@@ -78,6 +82,8 @@
SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
// Identifies the device (e.g., virtual server) using this port.
DeviceID string `mapstructure:"device_id" json:"device_id"`
+ // Identifies the list of IP addresses the port will recognize/accept
+ AllowedAddressPairs []AddressPair `mapstructure:"allowed_address_pairs" json:"allowed_address_pairs"`
}
// PortPage is the page returned by a pager when traversing over a collection
diff --git a/provider_client.go b/provider_client.go
index 9264355..152a091 100644
--- a/provider_client.go
+++ b/provider_client.go
@@ -246,6 +246,8 @@
return []int{201, 202}
case method == "PUT":
return []int{201, 202}
+ case method == "PATCH":
+ return []int{200, 204}
case method == "DELETE":
return []int{202, 204}
}
@@ -299,6 +301,24 @@
return client.Request("PUT", url, *opts)
}
+func (client *ProviderClient) Patch(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) {
+ if opts == nil {
+ opts = &RequestOpts{}
+ }
+
+ if v, ok := (JSONBody).(io.ReadSeeker); ok {
+ opts.RawBody = v
+ } else if JSONBody != nil {
+ opts.JSONBody = JSONBody
+ }
+
+ if JSONResponse != nil {
+ opts.JSONResponse = JSONResponse
+ }
+
+ return client.Request("PATCH", url, *opts)
+}
+
func (client *ProviderClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = &RequestOpts{}