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