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