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 }