github.com/gophercloud/gophercloud@v1.11.0/openstack/networking/v2/extensions/layer3/routers/testing/requests_test.go (about) 1 package testing 2 3 import ( 4 "fmt" 5 "net/http" 6 "testing" 7 "time" 8 9 fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common" 10 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" 11 "github.com/gophercloud/gophercloud/pagination" 12 th "github.com/gophercloud/gophercloud/testhelper" 13 ) 14 15 func TestList(t *testing.T) { 16 th.SetupHTTP() 17 defer th.TeardownHTTP() 18 19 th.Mux.HandleFunc("/v2.0/routers", func(w http.ResponseWriter, r *http.Request) { 20 th.TestMethod(t, r, "GET") 21 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 22 23 w.Header().Add("Content-Type", "application/json") 24 w.WriteHeader(http.StatusOK) 25 26 fmt.Fprintf(w, ` 27 { 28 "routers": [ 29 { 30 "status": "ACTIVE", 31 "external_gateway_info": null, 32 "name": "second_routers", 33 "admin_state_up": true, 34 "tenant_id": "6b96ff0cb17a4b859e1e575d221683d3", 35 "distributed": false, 36 "id": "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b" 37 }, 38 { 39 "status": "ACTIVE", 40 "external_gateway_info": { 41 "network_id": "3c5bcddd-6af9-4e6b-9c3e-c153e521cab8" 42 }, 43 "name": "router1", 44 "admin_state_up": true, 45 "tenant_id": "33a40233088643acb66ff6eb0ebea679", 46 "distributed": false, 47 "id": "a9254bdb-2613-4a13-ac4c-adc581fba50d" 48 }, 49 { 50 "status": "ACTIVE", 51 "external_gateway_info": { 52 "network_id": "2b37576e-b050-4891-8b20-e1e37a93942a", 53 "external_fixed_ips": [ 54 {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"}, 55 {"ip_address": "198.51.100.33", "subnet_id": "1d699529-bdfd-43f8-bcaa-bff00c547af2"} 56 ] 57 }, 58 "name": "gateway", 59 "admin_state_up": true, 60 "tenant_id": "a3e881e0a6534880c5473d95b9442099", 61 "distributed": false, 62 "id": "308a035c-005d-4452-a9fe-6f8f2f0c28d8" 63 } 64 ] 65 } 66 `) 67 }) 68 69 count := 0 70 71 routers.List(fake.ServiceClient(), routers.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { 72 count++ 73 actual, err := routers.ExtractRouters(page) 74 if err != nil { 75 t.Errorf("Failed to extract routers: %v", err) 76 return false, err 77 } 78 79 expected := []routers.Router{ 80 { 81 Status: "ACTIVE", 82 GatewayInfo: routers.GatewayInfo{NetworkID: ""}, 83 AdminStateUp: true, 84 Distributed: false, 85 Name: "second_routers", 86 ID: "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b", 87 TenantID: "6b96ff0cb17a4b859e1e575d221683d3", 88 }, 89 { 90 Status: "ACTIVE", 91 GatewayInfo: routers.GatewayInfo{NetworkID: "3c5bcddd-6af9-4e6b-9c3e-c153e521cab8"}, 92 AdminStateUp: true, 93 Distributed: false, 94 Name: "router1", 95 ID: "a9254bdb-2613-4a13-ac4c-adc581fba50d", 96 TenantID: "33a40233088643acb66ff6eb0ebea679", 97 }, 98 { 99 Status: "ACTIVE", 100 GatewayInfo: routers.GatewayInfo{ 101 NetworkID: "2b37576e-b050-4891-8b20-e1e37a93942a", 102 ExternalFixedIPs: []routers.ExternalFixedIP{ 103 {IPAddress: "192.0.2.17", SubnetID: "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"}, 104 {IPAddress: "198.51.100.33", SubnetID: "1d699529-bdfd-43f8-bcaa-bff00c547af2"}, 105 }, 106 }, 107 AdminStateUp: true, 108 Distributed: false, 109 Name: "gateway", 110 ID: "308a035c-005d-4452-a9fe-6f8f2f0c28d8", 111 TenantID: "a3e881e0a6534880c5473d95b9442099", 112 }, 113 } 114 115 th.CheckDeepEquals(t, expected, actual) 116 117 return true, nil 118 }) 119 120 if count != 1 { 121 t.Errorf("Expected 1 page, got %d", count) 122 } 123 } 124 125 func TestCreate(t *testing.T) { 126 th.SetupHTTP() 127 defer th.TeardownHTTP() 128 129 th.Mux.HandleFunc("/v2.0/routers", func(w http.ResponseWriter, r *http.Request) { 130 th.TestMethod(t, r, "POST") 131 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 132 th.TestHeader(t, r, "Content-Type", "application/json") 133 th.TestHeader(t, r, "Accept", "application/json") 134 th.TestJSONRequest(t, r, ` 135 { 136 "router":{ 137 "name": "foo_router", 138 "admin_state_up": false, 139 "external_gateway_info":{ 140 "enable_snat": false, 141 "network_id":"8ca37218-28ff-41cb-9b10-039601ea7e6b", 142 "external_fixed_ips": [ 143 {"subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} 144 ] 145 }, 146 "availability_zone_hints": ["zone1", "zone2"] 147 } 148 } 149 `) 150 151 w.Header().Add("Content-Type", "application/json") 152 w.WriteHeader(http.StatusCreated) 153 154 fmt.Fprintf(w, ` 155 { 156 "router": { 157 "status": "ACTIVE", 158 "external_gateway_info": { 159 "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b", 160 "enable_snat": false, 161 "external_fixed_ips": [ 162 {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} 163 ] 164 }, 165 "name": "foo_router", 166 "admin_state_up": false, 167 "tenant_id": "6b96ff0cb17a4b859e1e575d221683d3", 168 "distributed": false, 169 "availability_zone_hints": ["zone1", "zone2"], 170 "id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e" 171 } 172 } 173 `) 174 }) 175 176 asu := false 177 enableSNAT := false 178 efi := []routers.ExternalFixedIP{ 179 { 180 SubnetID: "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def", 181 }, 182 } 183 gwi := routers.GatewayInfo{ 184 NetworkID: "8ca37218-28ff-41cb-9b10-039601ea7e6b", 185 EnableSNAT: &enableSNAT, 186 ExternalFixedIPs: efi, 187 } 188 options := routers.CreateOpts{ 189 Name: "foo_router", 190 AdminStateUp: &asu, 191 GatewayInfo: &gwi, 192 AvailabilityZoneHints: []string{"zone1", "zone2"}, 193 } 194 r, err := routers.Create(fake.ServiceClient(), options).Extract() 195 th.AssertNoErr(t, err) 196 197 gwi.ExternalFixedIPs = []routers.ExternalFixedIP{{ 198 IPAddress: "192.0.2.17", 199 SubnetID: "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def", 200 }} 201 202 th.AssertEquals(t, "foo_router", r.Name) 203 th.AssertEquals(t, false, r.AdminStateUp) 204 th.AssertDeepEquals(t, gwi, r.GatewayInfo) 205 th.AssertDeepEquals(t, []string{"zone1", "zone2"}, r.AvailabilityZoneHints) 206 } 207 208 func TestGet(t *testing.T) { 209 th.SetupHTTP() 210 defer th.TeardownHTTP() 211 212 th.Mux.HandleFunc("/v2.0/routers/a07eea83-7710-4860-931b-5fe220fae533", func(w http.ResponseWriter, r *http.Request) { 213 th.TestMethod(t, r, "GET") 214 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 215 216 w.Header().Add("Content-Type", "application/json") 217 w.WriteHeader(http.StatusOK) 218 219 fmt.Fprintf(w, ` 220 { 221 "router": { 222 "status": "ACTIVE", 223 "external_gateway_info": { 224 "network_id": "85d76829-6415-48ff-9c63-5c5ca8c61ac6", 225 "external_fixed_ips": [ 226 {"ip_address": "198.51.100.33", "subnet_id": "1d699529-bdfd-43f8-bcaa-bff00c547af2"} 227 ] 228 }, 229 "routes": [ 230 { 231 "nexthop": "10.1.0.10", 232 "destination": "40.0.1.0/24" 233 } 234 ], 235 "name": "router1", 236 "admin_state_up": true, 237 "tenant_id": "d6554fe62e2f41efbb6e026fad5c1542", 238 "distributed": false, 239 "availability_zone_hints": ["zone1", "zone2"], 240 "id": "a07eea83-7710-4860-931b-5fe220fae533" 241 } 242 } 243 `) 244 }) 245 246 n, err := routers.Get(fake.ServiceClient(), "a07eea83-7710-4860-931b-5fe220fae533").Extract() 247 th.AssertNoErr(t, err) 248 249 th.AssertEquals(t, n.Status, "ACTIVE") 250 th.AssertDeepEquals(t, n.GatewayInfo, routers.GatewayInfo{ 251 NetworkID: "85d76829-6415-48ff-9c63-5c5ca8c61ac6", 252 ExternalFixedIPs: []routers.ExternalFixedIP{ 253 {IPAddress: "198.51.100.33", SubnetID: "1d699529-bdfd-43f8-bcaa-bff00c547af2"}, 254 }, 255 }) 256 th.AssertEquals(t, n.Name, "router1") 257 th.AssertEquals(t, n.AdminStateUp, true) 258 th.AssertEquals(t, n.TenantID, "d6554fe62e2f41efbb6e026fad5c1542") 259 th.AssertEquals(t, n.ID, "a07eea83-7710-4860-931b-5fe220fae533") 260 th.AssertDeepEquals(t, n.Routes, []routers.Route{{DestinationCIDR: "40.0.1.0/24", NextHop: "10.1.0.10"}}) 261 th.AssertDeepEquals(t, n.AvailabilityZoneHints, []string{"zone1", "zone2"}) 262 } 263 264 func TestUpdate(t *testing.T) { 265 th.SetupHTTP() 266 defer th.TeardownHTTP() 267 268 th.Mux.HandleFunc("/v2.0/routers/4e8e5957-649f-477b-9e5b-f1f75b21c03c", func(w http.ResponseWriter, r *http.Request) { 269 th.TestMethod(t, r, "PUT") 270 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 271 th.TestHeader(t, r, "Content-Type", "application/json") 272 th.TestHeader(t, r, "Accept", "application/json") 273 th.TestJSONRequest(t, r, ` 274 { 275 "router": { 276 "name": "new_name", 277 "external_gateway_info": { 278 "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b" 279 }, 280 "routes": [ 281 { 282 "nexthop": "10.1.0.10", 283 "destination": "40.0.1.0/24" 284 } 285 ] 286 } 287 } 288 `) 289 290 w.Header().Add("Content-Type", "application/json") 291 w.WriteHeader(http.StatusOK) 292 293 fmt.Fprintf(w, ` 294 { 295 "router": { 296 "status": "ACTIVE", 297 "external_gateway_info": { 298 "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b", 299 "external_fixed_ips": [ 300 {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} 301 ] 302 }, 303 "name": "new_name", 304 "admin_state_up": true, 305 "tenant_id": "6b96ff0cb17a4b859e1e575d221683d3", 306 "distributed": false, 307 "id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e", 308 "routes": [ 309 { 310 "nexthop": "10.1.0.10", 311 "destination": "40.0.1.0/24" 312 } 313 ] 314 } 315 } 316 `) 317 }) 318 319 gwi := routers.GatewayInfo{NetworkID: "8ca37218-28ff-41cb-9b10-039601ea7e6b"} 320 r := []routers.Route{{DestinationCIDR: "40.0.1.0/24", NextHop: "10.1.0.10"}} 321 options := routers.UpdateOpts{Name: "new_name", GatewayInfo: &gwi, Routes: &r} 322 323 n, err := routers.Update(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options).Extract() 324 th.AssertNoErr(t, err) 325 326 gwi.ExternalFixedIPs = []routers.ExternalFixedIP{ 327 {IPAddress: "192.0.2.17", SubnetID: "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"}, 328 } 329 330 th.AssertEquals(t, n.Name, "new_name") 331 th.AssertDeepEquals(t, n.GatewayInfo, gwi) 332 th.AssertDeepEquals(t, n.Routes, []routers.Route{{DestinationCIDR: "40.0.1.0/24", NextHop: "10.1.0.10"}}) 333 } 334 335 func TestUpdateWithoutRoutes(t *testing.T) { 336 th.SetupHTTP() 337 defer th.TeardownHTTP() 338 339 th.Mux.HandleFunc("/v2.0/routers/4e8e5957-649f-477b-9e5b-f1f75b21c03c", func(w http.ResponseWriter, r *http.Request) { 340 th.TestMethod(t, r, "PUT") 341 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 342 th.TestHeader(t, r, "Content-Type", "application/json") 343 th.TestHeader(t, r, "Accept", "application/json") 344 th.TestJSONRequest(t, r, ` 345 { 346 "router": { 347 "name": "new_name" 348 } 349 } 350 `) 351 352 w.Header().Add("Content-Type", "application/json") 353 w.WriteHeader(http.StatusOK) 354 355 fmt.Fprintf(w, ` 356 { 357 "router": { 358 "status": "ACTIVE", 359 "external_gateway_info": { 360 "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b", 361 "external_fixed_ips": [ 362 {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} 363 ] 364 }, 365 "name": "new_name", 366 "admin_state_up": true, 367 "tenant_id": "6b96ff0cb17a4b859e1e575d221683d3", 368 "distributed": false, 369 "id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e", 370 "routes": [ 371 { 372 "nexthop": "10.1.0.10", 373 "destination": "40.0.1.0/24" 374 } 375 ] 376 } 377 } 378 `) 379 }) 380 381 options := routers.UpdateOpts{Name: "new_name"} 382 383 n, err := routers.Update(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options).Extract() 384 th.AssertNoErr(t, err) 385 386 th.AssertEquals(t, n.Name, "new_name") 387 th.AssertDeepEquals(t, n.Routes, []routers.Route{{DestinationCIDR: "40.0.1.0/24", NextHop: "10.1.0.10"}}) 388 } 389 390 func TestAllRoutesRemoved(t *testing.T) { 391 th.SetupHTTP() 392 defer th.TeardownHTTP() 393 394 th.Mux.HandleFunc("/v2.0/routers/4e8e5957-649f-477b-9e5b-f1f75b21c03c", func(w http.ResponseWriter, r *http.Request) { 395 th.TestMethod(t, r, "PUT") 396 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 397 th.TestHeader(t, r, "Content-Type", "application/json") 398 th.TestHeader(t, r, "Accept", "application/json") 399 th.TestJSONRequest(t, r, ` 400 { 401 "router": { 402 "routes": [] 403 } 404 } 405 `) 406 407 w.Header().Add("Content-Type", "application/json") 408 w.WriteHeader(http.StatusOK) 409 410 fmt.Fprintf(w, ` 411 { 412 "router": { 413 "status": "ACTIVE", 414 "external_gateway_info": { 415 "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b" 416 }, 417 "name": "name", 418 "admin_state_up": true, 419 "tenant_id": "6b96ff0cb17a4b859e1e575d221683d3", 420 "distributed": false, 421 "id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e", 422 "routes": [] 423 } 424 } 425 `) 426 }) 427 428 r := []routers.Route{} 429 options := routers.UpdateOpts{Routes: &r} 430 431 n, err := routers.Update(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options).Extract() 432 th.AssertNoErr(t, err) 433 434 th.AssertDeepEquals(t, n.Routes, []routers.Route{}) 435 } 436 437 func TestDelete(t *testing.T) { 438 th.SetupHTTP() 439 defer th.TeardownHTTP() 440 441 th.Mux.HandleFunc("/v2.0/routers/4e8e5957-649f-477b-9e5b-f1f75b21c03c", func(w http.ResponseWriter, r *http.Request) { 442 th.TestMethod(t, r, "DELETE") 443 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 444 w.WriteHeader(http.StatusNoContent) 445 }) 446 447 res := routers.Delete(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c") 448 th.AssertNoErr(t, res.Err) 449 } 450 451 func TestAddInterface(t *testing.T) { 452 th.SetupHTTP() 453 defer th.TeardownHTTP() 454 455 th.Mux.HandleFunc("/v2.0/routers/4e8e5957-649f-477b-9e5b-f1f75b21c03c/add_router_interface", func(w http.ResponseWriter, r *http.Request) { 456 th.TestMethod(t, r, "PUT") 457 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 458 th.TestHeader(t, r, "Content-Type", "application/json") 459 th.TestHeader(t, r, "Accept", "application/json") 460 th.TestJSONRequest(t, r, ` 461 { 462 "subnet_id": "a2f1f29d-571b-4533-907f-5803ab96ead1" 463 } 464 `) 465 466 w.Header().Add("Content-Type", "application/json") 467 w.WriteHeader(http.StatusOK) 468 469 fmt.Fprintf(w, ` 470 { 471 "subnet_id": "0d32a837-8069-4ec3-84c4-3eef3e10b188", 472 "tenant_id": "017d8de156df4177889f31a9bd6edc00", 473 "port_id": "3f990102-4485-4df1-97a0-2c35bdb85b31", 474 "id": "9a83fa11-8da5-436e-9afe-3d3ac5ce7770" 475 } 476 `) 477 }) 478 479 opts := routers.AddInterfaceOpts{SubnetID: "a2f1f29d-571b-4533-907f-5803ab96ead1"} 480 res, err := routers.AddInterface(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", opts).Extract() 481 th.AssertNoErr(t, err) 482 483 th.AssertEquals(t, "0d32a837-8069-4ec3-84c4-3eef3e10b188", res.SubnetID) 484 th.AssertEquals(t, "017d8de156df4177889f31a9bd6edc00", res.TenantID) 485 th.AssertEquals(t, "3f990102-4485-4df1-97a0-2c35bdb85b31", res.PortID) 486 th.AssertEquals(t, "9a83fa11-8da5-436e-9afe-3d3ac5ce7770", res.ID) 487 } 488 489 func TestAddInterfaceRequiredOpts(t *testing.T) { 490 _, err := routers.AddInterface(fake.ServiceClient(), "foo", routers.AddInterfaceOpts{}).Extract() 491 if err == nil { 492 t.Fatalf("Expected error, got none") 493 } 494 _, err = routers.AddInterface(fake.ServiceClient(), "foo", routers.AddInterfaceOpts{SubnetID: "bar", PortID: "baz"}).Extract() 495 if err == nil { 496 t.Fatalf("Expected error, got none") 497 } 498 } 499 500 func TestRemoveInterface(t *testing.T) { 501 th.SetupHTTP() 502 defer th.TeardownHTTP() 503 504 th.Mux.HandleFunc("/v2.0/routers/4e8e5957-649f-477b-9e5b-f1f75b21c03c/remove_router_interface", func(w http.ResponseWriter, r *http.Request) { 505 th.TestMethod(t, r, "PUT") 506 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 507 th.TestHeader(t, r, "Content-Type", "application/json") 508 th.TestHeader(t, r, "Accept", "application/json") 509 th.TestJSONRequest(t, r, ` 510 { 511 "subnet_id": "a2f1f29d-571b-4533-907f-5803ab96ead1" 512 } 513 `) 514 515 w.Header().Add("Content-Type", "application/json") 516 w.WriteHeader(http.StatusOK) 517 518 fmt.Fprintf(w, ` 519 { 520 "subnet_id": "0d32a837-8069-4ec3-84c4-3eef3e10b188", 521 "tenant_id": "017d8de156df4177889f31a9bd6edc00", 522 "port_id": "3f990102-4485-4df1-97a0-2c35bdb85b31", 523 "id": "9a83fa11-8da5-436e-9afe-3d3ac5ce7770" 524 } 525 `) 526 }) 527 528 opts := routers.RemoveInterfaceOpts{SubnetID: "a2f1f29d-571b-4533-907f-5803ab96ead1"} 529 res, err := routers.RemoveInterface(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", opts).Extract() 530 th.AssertNoErr(t, err) 531 532 th.AssertEquals(t, "0d32a837-8069-4ec3-84c4-3eef3e10b188", res.SubnetID) 533 th.AssertEquals(t, "017d8de156df4177889f31a9bd6edc00", res.TenantID) 534 th.AssertEquals(t, "3f990102-4485-4df1-97a0-2c35bdb85b31", res.PortID) 535 th.AssertEquals(t, "9a83fa11-8da5-436e-9afe-3d3ac5ce7770", res.ID) 536 } 537 538 func TestListL3Agents(t *testing.T) { 539 th.SetupHTTP() 540 defer th.TeardownHTTP() 541 542 th.Mux.HandleFunc("/v2.0/routers/fa3a4aaa-c73f-48aa-a603-8c8bf642b7c0/l3-agents", func(w http.ResponseWriter, r *http.Request) { 543 th.TestMethod(t, r, "GET") 544 th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) 545 546 w.Header().Add("Content-Type", "application/json") 547 w.WriteHeader(http.StatusOK) 548 549 fmt.Fprintf(w, ` 550 { 551 "agents": [ 552 { 553 "id": "ddbf087c-e38f-4a73-bcb3-c38f2a719a03", 554 "agent_type": "L3 agent", 555 "binary": "neutron-l3-agent", 556 "topic": "l3_agent", 557 "host": "os-ctrl-02", 558 "admin_state_up": true, 559 "created_at": "2017-07-26 23:15:44", 560 "started_at": "2018-06-26 21:46:19", 561 "heartbeat_timestamp": "2019-01-09 10:28:53", 562 "description": "My L3 agent for OpenStack", 563 "resources_synced": true, 564 "availability_zone": "nova", 565 "alive": true, 566 "configurations": { 567 "agent_mode": "legacy", 568 "ex_gw_ports": 2, 569 "floating_ips": 2, 570 "handle_internal_only_routers": true, 571 "interface_driver": "linuxbridge", 572 "interfaces": 1, 573 "log_agent_heartbeats": false, 574 "routers": 2 575 }, 576 "resource_versions": {}, 577 "ha_state": "standby" 578 }, 579 { 580 "id": "4541cc6c-87bc-4cee-bad2-36ca78836c91", 581 "agent_type": "L3 agent", 582 "binary": "neutron-l3-agent", 583 "topic": "l3_agent", 584 "host": "os-ctrl-03", 585 "admin_state_up": true, 586 "created_at": "2017-01-22 14:00:50", 587 "started_at": "2018-11-06 12:09:17", 588 "heartbeat_timestamp": "2019-01-09 10:28:50", 589 "description": "My L3 agent for OpenStack", 590 "resources_synced": true, 591 "availability_zone": "nova", 592 "alive": true, 593 "configurations": { 594 "agent_mode": "legacy", 595 "ex_gw_ports": 2, 596 "floating_ips": 2, 597 "handle_internal_only_routers": true, 598 "interface_driver": "linuxbridge", 599 "interfaces": 1, 600 "log_agent_heartbeats": false, 601 "routers": 2 602 }, 603 "resource_versions": {}, 604 "ha_state": "active" 605 } 606 ] 607 } 608 `) 609 }) 610 611 l3AgentsPages, err := routers.ListL3Agents(fake.ServiceClient(), "fa3a4aaa-c73f-48aa-a603-8c8bf642b7c0").AllPages() 612 th.AssertNoErr(t, err) 613 actual, err := routers.ExtractL3Agents(l3AgentsPages) 614 th.AssertNoErr(t, err) 615 616 expected := []routers.L3Agent{ 617 { 618 ID: "ddbf087c-e38f-4a73-bcb3-c38f2a719a03", 619 AdminStateUp: true, 620 AgentType: "L3 agent", 621 Description: "My L3 agent for OpenStack", 622 Alive: true, 623 ResourcesSynced: true, 624 Binary: "neutron-l3-agent", 625 AvailabilityZone: "nova", 626 Configurations: map[string]interface{}{ 627 "agent_mode": "legacy", 628 "ex_gw_ports": float64(2), 629 "floating_ips": float64(2), 630 "handle_internal_only_routers": true, 631 "interface_driver": "linuxbridge", 632 "interfaces": float64(1), 633 "log_agent_heartbeats": false, 634 "routers": float64(2), 635 }, 636 CreatedAt: time.Date(2017, 7, 26, 23, 15, 44, 0, time.UTC), 637 StartedAt: time.Date(2018, 6, 26, 21, 46, 19, 0, time.UTC), 638 HeartbeatTimestamp: time.Date(2019, 1, 9, 10, 28, 53, 0, time.UTC), 639 Host: "os-ctrl-02", 640 Topic: "l3_agent", 641 HAState: "standby", 642 ResourceVersions: map[string]interface{}{}, 643 }, 644 { 645 ID: "4541cc6c-87bc-4cee-bad2-36ca78836c91", 646 AdminStateUp: true, 647 AgentType: "L3 agent", 648 Description: "My L3 agent for OpenStack", 649 Alive: true, 650 ResourcesSynced: true, 651 Binary: "neutron-l3-agent", 652 AvailabilityZone: "nova", 653 Configurations: map[string]interface{}{ 654 "agent_mode": "legacy", 655 "ex_gw_ports": float64(2), 656 "floating_ips": float64(2), 657 "handle_internal_only_routers": true, 658 "interface_driver": "linuxbridge", 659 "interfaces": float64(1), 660 "log_agent_heartbeats": false, 661 "routers": float64(2), 662 }, 663 CreatedAt: time.Date(2017, 1, 22, 14, 00, 50, 0, time.UTC), 664 StartedAt: time.Date(2018, 11, 6, 12, 9, 17, 0, time.UTC), 665 HeartbeatTimestamp: time.Date(2019, 1, 9, 10, 28, 50, 0, time.UTC), 666 Host: "os-ctrl-03", 667 Topic: "l3_agent", 668 HAState: "active", 669 ResourceVersions: map[string]interface{}{}, 670 }, 671 } 672 th.CheckDeepEquals(t, expected, actual) 673 }