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  }