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