github.com/bdwilliams/libcompose@v0.3.1-0.20160826154243-d81a9bdacff0/docker/network/network_test.go (about) 1 package network 2 3 import ( 4 "fmt" 5 "testing" 6 7 "golang.org/x/net/context" 8 9 "github.com/docker/engine-api/types" 10 "github.com/docker/engine-api/types/network" 11 "github.com/docker/libcompose/config" 12 "github.com/docker/libcompose/test" 13 "github.com/docker/libcompose/yaml" 14 ) 15 16 type networkNotFound struct { 17 network string 18 } 19 20 func (e networkNotFound) Error() string { 21 return fmt.Sprintf("network %s not found", e.network) 22 } 23 24 func (e networkNotFound) NotFound() bool { 25 return true 26 } 27 28 func TestNetworksFromServices(t *testing.T) { 29 cases := []struct { 30 networkConfigs map[string]*config.NetworkConfig 31 services map[string]*config.ServiceConfig 32 networkEnabled bool 33 expectedNetworks []*Network 34 expectedError bool 35 }{ 36 { 37 expectedNetworks: []*Network{}, 38 }, 39 { 40 networkConfigs: map[string]*config.NetworkConfig{ 41 "net1": {}, 42 }, 43 services: map[string]*config.ServiceConfig{}, 44 expectedNetworks: []*Network{ 45 { 46 name: "net1", 47 projectName: "prj", 48 }, 49 }, 50 expectedError: true, 51 }, 52 { 53 networkConfigs: map[string]*config.NetworkConfig{ 54 "net1": {}, 55 "net2": {}, 56 }, 57 services: map[string]*config.ServiceConfig{ 58 "svc1": { 59 Networks: &yaml.Networks{ 60 Networks: []*yaml.Network{ 61 { 62 Name: "net1", 63 }, 64 }, 65 }, 66 }, 67 }, 68 expectedNetworks: []*Network{ 69 { 70 name: "default", 71 projectName: "prj", 72 }, 73 { 74 name: "net1", 75 projectName: "prj", 76 }, 77 { 78 name: "net2", 79 projectName: "prj", 80 }, 81 }, 82 expectedError: true, 83 }, 84 { 85 networkConfigs: map[string]*config.NetworkConfig{ 86 "net1": {}, 87 "net2": {}, 88 }, 89 services: map[string]*config.ServiceConfig{ 90 "svc1": { 91 Networks: &yaml.Networks{ 92 Networks: []*yaml.Network{ 93 { 94 Name: "net1", 95 }, 96 }, 97 }, 98 }, 99 "svc2": { 100 Networks: &yaml.Networks{ 101 Networks: []*yaml.Network{ 102 { 103 Name: "net1", 104 }, 105 { 106 Name: "net2", 107 }, 108 }, 109 }, 110 }, 111 }, 112 expectedNetworks: []*Network{ 113 { 114 name: "net1", 115 projectName: "prj", 116 }, 117 { 118 name: "net2", 119 projectName: "prj", 120 }, 121 }, 122 expectedError: false, 123 }, 124 { 125 networkConfigs: map[string]*config.NetworkConfig{ 126 "net1": {}, 127 "net2": {}, 128 }, 129 services: map[string]*config.ServiceConfig{ 130 "svc1": { 131 Networks: &yaml.Networks{ 132 Networks: []*yaml.Network{ 133 { 134 Name: "net1", 135 }, 136 }, 137 }, 138 }, 139 "svc2": { 140 Networks: &yaml.Networks{ 141 Networks: []*yaml.Network{ 142 { 143 Name: "net1", 144 }, 145 { 146 Name: "net2", 147 }, 148 }, 149 }, 150 }, 151 "svc3": { 152 NetworkMode: "host", 153 Networks: &yaml.Networks{ 154 Networks: []*yaml.Network{ 155 { 156 Name: "net3", 157 }, 158 }, 159 }, 160 }, 161 }, 162 expectedNetworks: []*Network{ 163 { 164 name: "net1", 165 projectName: "prj", 166 }, 167 { 168 name: "net2", 169 projectName: "prj", 170 }, 171 }, 172 expectedError: false, 173 }, 174 } 175 for index, c := range cases { 176 services := config.NewServiceConfigs() 177 for name, service := range c.services { 178 services.Add(name, service) 179 } 180 networks, err := NetworksFromServices(&networkClient{}, "prj", c.networkConfigs, services, c.networkEnabled) 181 if c.expectedError { 182 if err == nil { 183 t.Fatalf("%d: expected an error, got nothing", index) 184 } 185 } else { 186 if err != nil { 187 t.Fatalf("%d: didn't expect an error, got one %s", index, err.Error()) 188 } 189 if networks.networkEnabled != c.networkEnabled { 190 t.Fatalf("%d: expected network enabled %v, got %v", index, c.networkEnabled, networks.networkEnabled) 191 } 192 if len(networks.networks) != len(c.expectedNetworks) { 193 t.Fatalf("%d: expected %v, got %v", index, c.expectedNetworks, networks.networks) 194 } 195 for _, network := range networks.networks { 196 testExpectedContainsNetwork(t, index, c.expectedNetworks, network) 197 } 198 } 199 } 200 } 201 202 func testExpectedContainsNetwork(t *testing.T, index int, expected []*Network, network *Network) { 203 found := false 204 for _, e := range expected { 205 if e.name == network.name && e.projectName == network.projectName { 206 found = true 207 break 208 } 209 } 210 if !found { 211 t.Fatalf("%d: network %v not found in %v", index, network, expected) 212 } 213 } 214 215 type networkClient struct { 216 test.NopClient 217 expectedNetworkCreate types.NetworkCreate 218 expectedRemoveNetworkID string 219 expectedName string 220 inspectError error 221 inspectNetworkDriver string 222 inspectNetworkOptions map[string]string 223 removeError error 224 } 225 226 func (c *networkClient) NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) { 227 if c.inspectError != nil { 228 return types.NetworkResource{}, c.inspectError 229 } 230 return types.NetworkResource{ 231 ID: "network_id", 232 Driver: c.inspectNetworkDriver, 233 Options: c.inspectNetworkOptions, 234 }, nil 235 } 236 237 func (c *networkClient) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { 238 if c.expectedName != "" { 239 if options.Driver != c.expectedNetworkCreate.Driver { 240 return types.NetworkCreateResponse{}, fmt.Errorf("Invalid network create, expected driver %q, got %q", c.expectedNetworkCreate.Driver, options.Driver) 241 } 242 if options.IPAM.Driver != c.expectedNetworkCreate.IPAM.Driver { 243 return types.NetworkCreateResponse{}, fmt.Errorf("Invalid network create, expected ipam %q, got %q", c.expectedNetworkCreate.IPAM, options.IPAM) 244 } 245 if len(options.IPAM.Config) != len(c.expectedNetworkCreate.IPAM.Config) { 246 return types.NetworkCreateResponse{}, fmt.Errorf("Invalid network create, expected ipam %q, got %q", c.expectedNetworkCreate.Driver, options.Driver) 247 } 248 return types.NetworkCreateResponse{ 249 ID: c.expectedName, 250 }, nil 251 } 252 return c.NopClient.NetworkCreate(ctx, name, options) 253 } 254 255 func (c *networkClient) NetworkRemove(ctx context.Context, networkID string) error { 256 if c.expectedRemoveNetworkID != "" { 257 if networkID != c.expectedRemoveNetworkID { 258 return fmt.Errorf("Invalid network id for removing, expected %q, got %q", c.expectedRemoveNetworkID, networkID) 259 } 260 return nil 261 } 262 return c.NopClient.NetworkRemove(ctx, networkID) 263 } 264 265 func TestNetworksInitialize(t *testing.T) { 266 errorCases := []struct { 267 networkEnabled bool 268 network *Network 269 inspectError error 270 inspectNetworkDriver string 271 inspectNetworkOptions map[string]string 272 expectedNetworkCreate types.NetworkCreate 273 expectedName string 274 }{ 275 // NetworkNotEnabled, never an error 276 { 277 networkEnabled: false, 278 network: &Network{ 279 name: "net1", 280 driver: "driver1", 281 }, 282 inspectError: networkNotFound{ 283 network: "net1", 284 }, 285 }, 286 // External 287 { 288 networkEnabled: true, 289 network: &Network{ 290 name: "net1", 291 external: true, 292 }, 293 }, 294 // NotFound, will create a new one 295 { 296 networkEnabled: true, 297 network: &Network{ 298 name: "net1", 299 driver: "driver1", 300 }, 301 inspectError: networkNotFound{ 302 network: "net1", 303 }, 304 expectedName: "net1", 305 expectedNetworkCreate: types.NetworkCreate{ 306 Driver: "driver1", 307 }, 308 }, 309 // NotFound, will create a new one 310 // with IPAM 311 { 312 networkEnabled: true, 313 network: &Network{ 314 name: "net1", 315 driver: "driver1", 316 ipam: config.Ipam{ 317 Driver: "ipamDriver", 318 Config: []config.IpamConfig{ 319 { 320 Subnet: "subnet", 321 IPRange: "iprange", 322 }, 323 }, 324 }, 325 }, 326 inspectError: networkNotFound{ 327 network: "net1", 328 }, 329 expectedName: "net1", 330 expectedNetworkCreate: types.NetworkCreate{ 331 Driver: "driver1", 332 IPAM: network.IPAM{ 333 Driver: "ipamDriver", 334 Config: []network.IPAMConfig{ 335 { 336 Subnet: "subnet", 337 IPRange: "iprange", 338 }, 339 }, 340 }, 341 }, 342 }, 343 { 344 networkEnabled: true, 345 network: &Network{ 346 name: "net1", 347 driver: "driver1", 348 }, 349 inspectNetworkDriver: "driver1", 350 }, 351 { 352 networkEnabled: true, 353 network: &Network{ 354 name: "net1", 355 driver: "driver1", 356 driverOptions: map[string]string{ 357 "key1": "value1", 358 "key2": "value2", 359 }, 360 }, 361 inspectNetworkDriver: "driver1", 362 inspectNetworkOptions: map[string]string{ 363 "key1": "value1", 364 "key2": "value2", 365 }, 366 }, 367 } 368 for _, e := range errorCases { 369 cli := &networkClient{ 370 expectedName: e.expectedName, 371 expectedNetworkCreate: e.expectedNetworkCreate, 372 inspectError: e.inspectError, 373 inspectNetworkDriver: e.inspectNetworkDriver, 374 inspectNetworkOptions: e.inspectNetworkOptions, 375 } 376 e.network.client = cli 377 networks := &Networks{ 378 networkEnabled: e.networkEnabled, 379 networks: []*Network{ 380 e.network, 381 }, 382 } 383 err := networks.Initialize(context.Background()) 384 if err != nil { 385 t.Error(err) 386 } 387 } 388 } 389 390 func TestNetworksInitializeErrors(t *testing.T) { 391 errorCases := []struct { 392 network *Network 393 inspectError error 394 inspectNetworkDriver string 395 inspectNetworkOptions map[string]string 396 expectedNetworkCreate types.NetworkCreate 397 expectedName string 398 expectedError string 399 }{ 400 { 401 network: &Network{ 402 projectName: "prj", 403 name: "net1", 404 }, 405 inspectError: fmt.Errorf("any error"), 406 expectedError: "any error", 407 }, 408 { 409 network: &Network{ 410 projectName: "prj", 411 name: "net1", 412 external: true, 413 }, 414 inspectError: networkNotFound{ 415 network: "net1", 416 }, 417 expectedError: "Network net1 declared as external, but could not be found. Please create the network manually using docker network create net1 and try again", 418 }, 419 { 420 network: &Network{ 421 projectName: "prj", 422 name: "net1", 423 }, 424 inspectError: networkNotFound{ 425 network: "net1", 426 }, 427 expectedError: "Engine no longer exists", // default error 428 }, 429 { 430 network: &Network{ 431 projectName: "prj", 432 name: "net1", 433 driver: "driver1", 434 }, 435 inspectNetworkDriver: "driver2", 436 expectedError: `Network "prj_net1" needs to be recreated - driver has changed`, 437 }, 438 { 439 network: &Network{ 440 projectName: "prj", 441 name: "net1", 442 driver: "driver1", 443 driverOptions: map[string]string{ 444 "key1": "value1", 445 "key2": "value2", 446 }, 447 }, 448 inspectNetworkDriver: "driver1", 449 inspectNetworkOptions: map[string]string{ 450 "key1": "value1", 451 "key2": "anothervalue", 452 }, 453 expectedError: `Network "prj_net1" needs to be recreated - options have changed`, 454 }, 455 } 456 for index, e := range errorCases { 457 cli := &networkClient{ 458 expectedName: e.expectedName, 459 expectedNetworkCreate: e.expectedNetworkCreate, 460 inspectError: e.inspectError, 461 inspectNetworkDriver: e.inspectNetworkDriver, 462 inspectNetworkOptions: e.inspectNetworkOptions, 463 } 464 e.network.client = cli 465 networks := &Networks{ 466 networkEnabled: true, 467 networks: []*Network{ 468 e.network, 469 }, 470 } 471 err := networks.Initialize(context.Background()) 472 if err == nil || err.Error() != e.expectedError { 473 t.Errorf("%d: expected an error %v, got %v", index, e.expectedError, err) 474 } 475 } 476 } 477 478 func TestNetworksRemove(t *testing.T) { 479 removeCases := []struct { 480 networkEnabled bool 481 expectedRemoveNetworkID string 482 network *Network 483 }{ 484 // Network not enabled, always no error 485 { 486 networkEnabled: false, 487 network: &Network{ 488 projectName: "prj", 489 name: "net1", 490 driver: "driver1", 491 }, 492 }, 493 // Network enabled 494 { 495 networkEnabled: true, 496 expectedRemoveNetworkID: "prj_net1", 497 network: &Network{ 498 projectName: "prj", 499 name: "net1", 500 driver: "driver1", 501 }, 502 }, 503 } 504 for _, c := range removeCases { 505 cli := &networkClient{ 506 expectedRemoveNetworkID: c.expectedRemoveNetworkID, 507 } 508 c.network.client = cli 509 networks := &Networks{ 510 networkEnabled: c.networkEnabled, 511 networks: []*Network{ 512 c.network, 513 }, 514 } 515 err := networks.Remove(context.Background()) 516 if err != nil { 517 t.Error(err) 518 } 519 } 520 } 521 522 func TestNetworksRemoveErrors(t *testing.T) { 523 cli := &networkClient{} 524 networks := &Networks{ 525 networkEnabled: true, 526 networks: []*Network{ 527 { 528 client: cli, 529 projectName: "prj", 530 name: "net1", 531 }, 532 }, 533 } 534 err := networks.Remove(context.Background()) 535 if err == nil { 536 t.Errorf("Expected a error, got nothing.") 537 } 538 }