github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/libnetwork/sandbox_unix_test.go (about)

     1  //go:build !windows
     2  
     3  package libnetwork
     4  
     5  import (
     6  	"strconv"
     7  	"testing"
     8  
     9  	"github.com/docker/docker/errdefs"
    10  	"github.com/docker/docker/internal/testutils/netnsutils"
    11  	"github.com/docker/docker/libnetwork/config"
    12  	"github.com/docker/docker/libnetwork/ipamapi"
    13  	"github.com/docker/docker/libnetwork/netlabel"
    14  	"github.com/docker/docker/libnetwork/options"
    15  	"github.com/docker/docker/libnetwork/osl"
    16  	"gotest.tools/v3/assert"
    17  	is "gotest.tools/v3/assert/cmp"
    18  )
    19  
    20  func getTestEnv(t *testing.T, opts ...[]NetworkOption) (*Controller, []*Network) {
    21  	const netType = "bridge"
    22  	c, err := New(
    23  		OptionBoltdbWithRandomDBFile(t),
    24  		config.OptionDriverConfig(netType, map[string]any{
    25  			netlabel.GenericData: options.Generic{"EnableIPForwarding": true},
    26  		}),
    27  	)
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  	t.Cleanup(c.Stop)
    32  
    33  	if len(opts) == 0 {
    34  		return c, nil
    35  	}
    36  
    37  	nwList := make([]*Network, 0, len(opts))
    38  	for i, opt := range opts {
    39  		name := "test_nw_" + strconv.Itoa(i)
    40  		newOptions := []NetworkOption{
    41  			NetworkOptionGeneric(options.Generic{
    42  				netlabel.GenericData: options.Generic{"BridgeName": name},
    43  			}),
    44  		}
    45  		newOptions = append(newOptions, opt...)
    46  		n, err := c.NewNetwork(netType, name, "", newOptions...)
    47  		if err != nil {
    48  			t.Fatal(err)
    49  		}
    50  
    51  		nwList = append(nwList, n)
    52  	}
    53  
    54  	return c, nwList
    55  }
    56  
    57  func TestControllerGetSandbox(t *testing.T) {
    58  	ctrlr, _ := getTestEnv(t)
    59  	t.Run("invalid id", func(t *testing.T) {
    60  		const cID = ""
    61  		sb, err := ctrlr.GetSandbox(cID)
    62  		_, ok := err.(ErrInvalidID)
    63  		assert.Check(t, ok, "expected ErrInvalidID, got %[1]v (%[1]T)", err)
    64  		assert.Check(t, is.Nil(sb))
    65  	})
    66  	t.Run("not found", func(t *testing.T) {
    67  		const cID = "container-id-with-no-sandbox"
    68  		sb, err := ctrlr.GetSandbox(cID)
    69  		assert.Check(t, errdefs.IsNotFound(err), "expected  a ErrNotFound, got %[1]v (%[1]T)", err)
    70  		assert.Check(t, is.Nil(sb))
    71  	})
    72  	t.Run("existing sandbox", func(t *testing.T) {
    73  		const cID = "test-container-id"
    74  		expected, err := ctrlr.NewSandbox(cID)
    75  		assert.Check(t, err)
    76  
    77  		sb, err := ctrlr.GetSandbox(cID)
    78  		assert.Check(t, err)
    79  		assert.Check(t, is.Equal(sb.ContainerID(), cID))
    80  		assert.Check(t, is.Equal(sb.ID(), expected.ID()))
    81  		assert.Check(t, is.Equal(sb.Key(), expected.Key()))
    82  		assert.Check(t, is.Equal(sb.ContainerID(), expected.ContainerID()))
    83  
    84  		err = sb.Delete()
    85  		assert.Check(t, err)
    86  
    87  		sb, err = ctrlr.GetSandbox(cID)
    88  		assert.Check(t, errdefs.IsNotFound(err), "expected  a ErrNotFound, got %[1]v (%[1]T)", err)
    89  		assert.Check(t, is.Nil(sb))
    90  	})
    91  }
    92  
    93  func TestSandboxAddEmpty(t *testing.T) {
    94  	ctrlr, _ := getTestEnv(t)
    95  
    96  	sbx, err := ctrlr.NewSandbox("sandbox0")
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  
   101  	if err := sbx.Delete(); err != nil {
   102  		t.Fatal(err)
   103  	}
   104  
   105  	if len(ctrlr.sandboxes) != 0 {
   106  		t.Fatalf("controller sandboxes is not empty. len = %d", len(ctrlr.sandboxes))
   107  	}
   108  
   109  	osl.GC()
   110  }
   111  
   112  // // If different priorities are specified, internal option and ipv6 addresses mustn't influence endpoint order
   113  func TestSandboxAddMultiPrio(t *testing.T) {
   114  	defer netnsutils.SetupTestOSContext(t)()
   115  
   116  	opts := [][]NetworkOption{
   117  		{NetworkOptionEnableIPv6(true), NetworkOptionIpam(ipamapi.DefaultIPAM, "", nil, []*IpamConf{{PreferredPool: "fe90::/64"}}, nil)},
   118  		{NetworkOptionInternalNetwork()},
   119  		{},
   120  	}
   121  
   122  	ctrlr, nws := getTestEnv(t, opts...)
   123  
   124  	sbx, err := ctrlr.NewSandbox("sandbox1")
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  	sid := sbx.ID()
   129  
   130  	ep1, err := nws[0].CreateEndpoint("ep1")
   131  	if err != nil {
   132  		t.Fatal(err)
   133  	}
   134  	ep2, err := nws[1].CreateEndpoint("ep2")
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	ep3, err := nws[2].CreateEndpoint("ep3")
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  
   143  	if err := ep1.Join(sbx, JoinOptionPriority(1)); err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	if err := ep2.Join(sbx, JoinOptionPriority(2)); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	if err := ep3.Join(sbx, JoinOptionPriority(3)); err != nil {
   152  		t.Fatal(err)
   153  	}
   154  
   155  	if ctrlr.sandboxes[sid].endpoints[0].ID() != ep3.ID() {
   156  		t.Fatal("Expected ep3 to be at the top of the heap. But did not find ep3 at the top of the heap")
   157  	}
   158  
   159  	if len(sbx.Endpoints()) != 3 {
   160  		t.Fatal("Expected 3 endpoints to be connected to the sandbox.")
   161  	}
   162  
   163  	if err := ep3.Leave(sbx); err != nil {
   164  		t.Fatal(err)
   165  	}
   166  	if ctrlr.sandboxes[sid].endpoints[0].ID() != ep2.ID() {
   167  		t.Fatal("Expected ep2 to be at the top of the heap after removing ep3. But did not find ep2 at the top of the heap")
   168  	}
   169  
   170  	if err := ep2.Leave(sbx); err != nil {
   171  		t.Fatal(err)
   172  	}
   173  	if ctrlr.sandboxes[sid].endpoints[0].ID() != ep1.ID() {
   174  		t.Fatal("Expected ep1 to be at the top of the heap after removing ep2. But did not find ep1 at the top of the heap")
   175  	}
   176  
   177  	// Re-add ep3 back
   178  	if err := ep3.Join(sbx, JoinOptionPriority(3)); err != nil {
   179  		t.Fatal(err)
   180  	}
   181  
   182  	if ctrlr.sandboxes[sid].endpoints[0].ID() != ep3.ID() {
   183  		t.Fatal("Expected ep3 to be at the top of the heap after adding ep3 back. But did not find ep3 at the top of the heap")
   184  	}
   185  
   186  	if err := sbx.Delete(); err != nil {
   187  		t.Fatal(err)
   188  	}
   189  
   190  	if len(ctrlr.sandboxes) != 0 {
   191  		t.Fatalf("controller sandboxes is not empty. len = %d", len(ctrlr.sandboxes))
   192  	}
   193  
   194  	osl.GC()
   195  }
   196  
   197  func TestSandboxAddSamePrio(t *testing.T) {
   198  	defer netnsutils.SetupTestOSContext(t)()
   199  
   200  	opts := [][]NetworkOption{
   201  		{},
   202  		{},
   203  		{NetworkOptionEnableIPv6(true), NetworkOptionIpam(ipamapi.DefaultIPAM, "", nil, []*IpamConf{{PreferredPool: "fe90::/64"}}, nil)},
   204  		{NetworkOptionInternalNetwork()},
   205  	}
   206  
   207  	ctrlr, nws := getTestEnv(t, opts...)
   208  
   209  	sbx, err := ctrlr.NewSandbox("sandbox1")
   210  	if err != nil {
   211  		t.Fatal(err)
   212  	}
   213  	sid := sbx.ID()
   214  
   215  	epNw1, err := nws[1].CreateEndpoint("ep1")
   216  	if err != nil {
   217  		t.Fatal(err)
   218  	}
   219  	epIPv6, err := nws[2].CreateEndpoint("ep2")
   220  	if err != nil {
   221  		t.Fatal(err)
   222  	}
   223  
   224  	epInternal, err := nws[3].CreateEndpoint("ep3")
   225  	if err != nil {
   226  		t.Fatal(err)
   227  	}
   228  
   229  	epNw0, err := nws[0].CreateEndpoint("ep4")
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  
   234  	if err := epNw1.Join(sbx); err != nil {
   235  		t.Fatal(err)
   236  	}
   237  
   238  	if err := epIPv6.Join(sbx); err != nil {
   239  		t.Fatal(err)
   240  	}
   241  
   242  	if err := epInternal.Join(sbx); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	if err := epNw0.Join(sbx); err != nil {
   247  		t.Fatal(err)
   248  	}
   249  
   250  	// order should now be: epIPv6, epNw0, epNw1, epInternal
   251  	if len(sbx.Endpoints()) != 4 {
   252  		t.Fatal("Expected 4 endpoints to be connected to the sandbox.")
   253  	}
   254  
   255  	// IPv6 has precedence over IPv4
   256  	if ctrlr.sandboxes[sid].endpoints[0].ID() != epIPv6.ID() {
   257  		t.Fatal("Expected epIPv6 to be at the top of the heap. But did not find epIPv6 at the top of the heap")
   258  	}
   259  
   260  	// internal network has lowest precedence
   261  	if ctrlr.sandboxes[sid].endpoints[3].ID() != epInternal.ID() {
   262  		t.Fatal("Expected epInternal to be at the bottom of the heap. But did not find epInternal at the bottom of the heap")
   263  	}
   264  
   265  	if err := epIPv6.Leave(sbx); err != nil {
   266  		t.Fatal(err)
   267  	}
   268  
   269  	// 'test_nw_0' has precedence over 'test_nw_1'
   270  	if ctrlr.sandboxes[sid].endpoints[0].ID() != epNw0.ID() {
   271  		t.Fatal("Expected epNw0 to be at the top of the heap after removing epIPv6. But did not find epNw0 at the top of the heap")
   272  	}
   273  
   274  	if err := epNw1.Leave(sbx); err != nil {
   275  		t.Fatal(err)
   276  	}
   277  
   278  	if err := sbx.Delete(); err != nil {
   279  		t.Fatal(err)
   280  	}
   281  
   282  	if len(ctrlr.sandboxes) != 0 {
   283  		t.Fatalf("controller containers is not empty. len = %d", len(ctrlr.sandboxes))
   284  	}
   285  
   286  	osl.GC()
   287  }