1
2
3
4
19
20 package iptables
21
22 import (
23 "bytes"
24 "fmt"
25 "net"
26 "os"
27 "reflect"
28 "strings"
29 "testing"
30 "time"
31
32 "k8s.io/apimachinery/pkg/util/sets"
33 utilversion "k8s.io/apimachinery/pkg/util/version"
34 "k8s.io/apimachinery/pkg/util/wait"
35 "k8s.io/utils/exec"
36 fakeexec "k8s.io/utils/exec/testing"
37 )
38
39 func getLockPaths() (string, string) {
40 lock14x := fmt.Sprintf("@xtables-%d", time.Now().Nanosecond())
41 lock16x := fmt.Sprintf("xtables-%d.lock", time.Now().Nanosecond())
42 return lock14x, lock16x
43 }
44
45 func testIPTablesVersionCmds(t *testing.T, protocol Protocol) {
46 version := " v1.4.22"
47 iptablesCmd := iptablesCommand(protocol)
48 iptablesRestoreCmd := iptablesRestoreCommand(protocol)
49
50 fcmd := fakeexec.FakeCmd{
51 CombinedOutputScript: []fakeexec.FakeAction{
52
53 func() ([]byte, []byte, error) { return []byte(iptablesCmd + version), nil, nil },
54
55 func() ([]byte, []byte, error) { return []byte(iptablesRestoreCmd + version), nil, nil },
56 },
57 }
58 fexec := &fakeexec.FakeExec{
59 CommandScript: []fakeexec.FakeCommandAction{
60 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
61 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
62 },
63 }
64 _ = New(fexec, protocol)
65
66
67 if !sets.New(fcmd.CombinedOutputLog[0]...).HasAll(iptablesCmd, "--version") {
68 t.Errorf("%s runner instantiate: Expected cmd '%s --version', Got '%s'", protocol, iptablesCmd, fcmd.CombinedOutputLog[0])
69 }
70
71
72 if !sets.New(fcmd.CombinedOutputLog[1]...).HasAll(iptablesRestoreCmd, "--version") {
73 t.Errorf("%s runner instantiate: Expected cmd '%s --version', Got '%s'", protocol, iptablesRestoreCmd, fcmd.CombinedOutputLog[1])
74 }
75 }
76
77 func TestIPTablesVersionCmdsIPv4(t *testing.T) {
78 testIPTablesVersionCmds(t, ProtocolIPv4)
79 }
80
81 func TestIPTablesVersionCmdsIPv6(t *testing.T) {
82 testIPTablesVersionCmds(t, ProtocolIPv6)
83 }
84
85 func testEnsureChain(t *testing.T, protocol Protocol) {
86 fcmd := fakeexec.FakeCmd{
87 CombinedOutputScript: []fakeexec.FakeAction{
88
89 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
90
91 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
92
93 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
94
95 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 2} },
96 },
97 }
98 fexec := &fakeexec.FakeExec{
99 CommandScript: []fakeexec.FakeCommandAction{
100 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
101 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
102 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
103 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
104 },
105 }
106 runner := New(fexec, protocol)
107
108 exists, err := runner.EnsureChain(TableNAT, Chain("FOOBAR"))
109 if err != nil {
110 t.Errorf("%s new chain: Expected success, got %v", protocol, err)
111 }
112 if exists {
113 t.Errorf("%s new chain: Expected exists = false", protocol)
114 }
115 if fcmd.CombinedOutputCalls != 2 {
116 t.Errorf("%s new chain: Expected 2 CombinedOutput() calls, got %d", protocol, fcmd.CombinedOutputCalls)
117 }
118 cmd := iptablesCommand(protocol)
119 if !sets.New(fcmd.CombinedOutputLog[1]...).HasAll(cmd, "-t", "nat", "-N", "FOOBAR") {
120 t.Errorf("%s new chain: Expected cmd containing '%s -t nat -N FOOBAR', got %s", protocol, cmd, fcmd.CombinedOutputLog[2])
121 }
122
123 exists, err = runner.EnsureChain(TableNAT, Chain("FOOBAR"))
124 if err != nil {
125 t.Errorf("%s existing chain: Expected success, got %v", protocol, err)
126 }
127 if !exists {
128 t.Errorf("%s existing chain: Expected exists = true", protocol)
129 }
130
131 _, err = runner.EnsureChain(TableNAT, Chain("FOOBAR"))
132 if err == nil {
133 t.Errorf("%s: Expected failure", protocol)
134 }
135 }
136
137 func TestEnsureChainIPv4(t *testing.T) {
138 testEnsureChain(t, ProtocolIPv4)
139 }
140
141 func TestEnsureChainIPv6(t *testing.T) {
142 testEnsureChain(t, ProtocolIPv6)
143 }
144
145 func TestFlushChain(t *testing.T) {
146 fcmd := fakeexec.FakeCmd{
147 CombinedOutputScript: []fakeexec.FakeAction{
148
149 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
150
151 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
152
153 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
154 },
155 }
156 fexec := &fakeexec.FakeExec{
157 CommandScript: []fakeexec.FakeCommandAction{
158 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
159 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
160 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
161 },
162 }
163 runner := New(fexec, ProtocolIPv4)
164
165 err := runner.FlushChain(TableNAT, Chain("FOOBAR"))
166 if err != nil {
167 t.Errorf("expected success, got %v", err)
168 }
169 if fcmd.CombinedOutputCalls != 2 {
170 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
171 }
172 if !sets.New(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-F", "FOOBAR") {
173 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
174 }
175
176 err = runner.FlushChain(TableNAT, Chain("FOOBAR"))
177 if err == nil {
178 t.Errorf("expected failure")
179 }
180 }
181
182 func TestDeleteChain(t *testing.T) {
183 fcmd := fakeexec.FakeCmd{
184 CombinedOutputScript: []fakeexec.FakeAction{
185
186 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
187
188 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
189
190 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
191 },
192 }
193 fexec := &fakeexec.FakeExec{
194 CommandScript: []fakeexec.FakeCommandAction{
195 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
196 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
197 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
198 },
199 }
200 runner := New(fexec, ProtocolIPv4)
201
202 err := runner.DeleteChain(TableNAT, Chain("FOOBAR"))
203 if err != nil {
204 t.Errorf("expected success, got %v", err)
205 }
206 if fcmd.CombinedOutputCalls != 2 {
207 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
208 }
209 if !sets.New(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-X", "FOOBAR") {
210 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
211 }
212
213 err = runner.DeleteChain(TableNAT, Chain("FOOBAR"))
214 if err == nil {
215 t.Errorf("expected failure")
216 }
217 }
218
219 func TestEnsureRuleAlreadyExists(t *testing.T) {
220 fcmd := fakeexec.FakeCmd{
221 CombinedOutputScript: []fakeexec.FakeAction{
222
223 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
224
225 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
226 },
227 }
228 fexec := &fakeexec.FakeExec{
229 CommandScript: []fakeexec.FakeCommandAction{
230
231 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
232
233 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
234 },
235 }
236 runner := New(fexec, ProtocolIPv4)
237 exists, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123")
238 if err != nil {
239 t.Errorf("expected success, got %v", err)
240 }
241 if !exists {
242 t.Errorf("expected exists = true")
243 }
244 if fcmd.CombinedOutputCalls != 2 {
245 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
246 }
247 if !sets.New(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") {
248 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
249 }
250 }
251
252 func TestEnsureRuleNew(t *testing.T) {
253 fcmd := fakeexec.FakeCmd{
254 CombinedOutputScript: []fakeexec.FakeAction{
255
256 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
257
258 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
259
260 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
261 },
262 }
263 fexec := &fakeexec.FakeExec{
264 CommandScript: []fakeexec.FakeCommandAction{
265
266 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
267
268 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
269 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
270 },
271 }
272 runner := New(fexec, ProtocolIPv4)
273 exists, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123")
274 if err != nil {
275 t.Errorf("expected success, got %v", err)
276 }
277 if exists {
278 t.Errorf("expected exists = false")
279 }
280 if fcmd.CombinedOutputCalls != 3 {
281 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
282 }
283 if !sets.New(fcmd.CombinedOutputLog[2]...).HasAll("iptables", "-t", "nat", "-A", "OUTPUT", "abc", "123") {
284 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[3])
285 }
286 }
287
288 func TestEnsureRuleErrorChecking(t *testing.T) {
289 fcmd := fakeexec.FakeCmd{
290 CombinedOutputScript: []fakeexec.FakeAction{
291
292 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
293
294 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 2} },
295 },
296 }
297 fexec := &fakeexec.FakeExec{
298 CommandScript: []fakeexec.FakeCommandAction{
299
300 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
301
302 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
303 },
304 }
305 runner := New(fexec, ProtocolIPv4)
306 _, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123")
307 if err == nil {
308 t.Errorf("expected failure")
309 }
310 if fcmd.CombinedOutputCalls != 2 {
311 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
312 }
313 }
314
315 func TestEnsureRuleErrorCreating(t *testing.T) {
316 fcmd := fakeexec.FakeCmd{
317 CombinedOutputScript: []fakeexec.FakeAction{
318
319 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
320
321 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
322
323 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
324 },
325 }
326 fexec := &fakeexec.FakeExec{
327 CommandScript: []fakeexec.FakeCommandAction{
328
329 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
330
331 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
332 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
333 },
334 }
335 runner := New(fexec, ProtocolIPv4)
336 _, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123")
337 if err == nil {
338 t.Errorf("expected failure")
339 }
340 if fcmd.CombinedOutputCalls != 3 {
341 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
342 }
343 }
344
345 func TestDeleteRuleDoesNotExist(t *testing.T) {
346 fcmd := fakeexec.FakeCmd{
347 CombinedOutputScript: []fakeexec.FakeAction{
348
349 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
350
351 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
352 },
353 }
354 fexec := &fakeexec.FakeExec{
355 CommandScript: []fakeexec.FakeCommandAction{
356
357 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
358
359 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
360 },
361 }
362 runner := New(fexec, ProtocolIPv4)
363 err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123")
364 if err != nil {
365 t.Errorf("expected success, got %v", err)
366 }
367 if fcmd.CombinedOutputCalls != 2 {
368 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
369 }
370 if !sets.New(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") {
371 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
372 }
373 }
374
375 func TestDeleteRuleExists(t *testing.T) {
376 fcmd := fakeexec.FakeCmd{
377 CombinedOutputScript: []fakeexec.FakeAction{
378
379 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
380
381 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
382
383 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
384 },
385 }
386 fexec := &fakeexec.FakeExec{
387 CommandScript: []fakeexec.FakeCommandAction{
388
389 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
390
391 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
392 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
393 },
394 }
395 runner := New(fexec, ProtocolIPv4)
396 err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123")
397 if err != nil {
398 t.Errorf("expected success, got %v", err)
399 }
400 if fcmd.CombinedOutputCalls != 3 {
401 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
402 }
403 if !sets.New(fcmd.CombinedOutputLog[2]...).HasAll("iptables", "-t", "nat", "-D", "OUTPUT", "abc", "123") {
404 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[3])
405 }
406 }
407
408 func TestDeleteRuleErrorChecking(t *testing.T) {
409 fcmd := fakeexec.FakeCmd{
410 CombinedOutputScript: []fakeexec.FakeAction{
411
412 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
413
414 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 2} },
415 },
416 }
417 fexec := &fakeexec.FakeExec{
418 CommandScript: []fakeexec.FakeCommandAction{
419
420 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
421
422 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
423 },
424 }
425 runner := New(fexec, ProtocolIPv4)
426 err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123")
427 if err == nil {
428 t.Errorf("expected failure")
429 }
430 if fcmd.CombinedOutputCalls != 2 {
431 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
432 }
433 }
434
435 func TestDeleteRuleErrorDeleting(t *testing.T) {
436 fcmd := fakeexec.FakeCmd{
437 CombinedOutputScript: []fakeexec.FakeAction{
438
439 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
440
441 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
442
443 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
444 },
445 }
446 fexec := &fakeexec.FakeExec{
447 CommandScript: []fakeexec.FakeCommandAction{
448
449 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
450
451 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
452 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
453 },
454 }
455 runner := New(fexec, ProtocolIPv4)
456 err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123")
457 if err == nil {
458 t.Errorf("expected failure")
459 }
460 if fcmd.CombinedOutputCalls != 3 {
461 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
462 }
463 }
464
465 func TestGetIPTablesHasCheckCommand(t *testing.T) {
466 testCases := []struct {
467 Version string
468 Expected bool
469 }{
470 {"iptables v1.4.7", false},
471 {"iptables v1.4.11", true},
472 {"iptables v1.4.19.1", true},
473 {"iptables v2.0.0", true},
474 {"total junk", true},
475 }
476
477 for _, testCase := range testCases {
478 fcmd := fakeexec.FakeCmd{
479 CombinedOutputScript: []fakeexec.FakeAction{
480 func() ([]byte, []byte, error) { return []byte(testCase.Version), nil, nil },
481 func() ([]byte, []byte, error) { return []byte(testCase.Version), nil, nil },
482 },
483 }
484 fexec := &fakeexec.FakeExec{
485 CommandScript: []fakeexec.FakeCommandAction{
486 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
487 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
488 },
489 }
490 ipt := New(fexec, ProtocolIPv4)
491 runner := ipt.(*runner)
492 if testCase.Expected != runner.hasCheck {
493 t.Errorf("Expected result: %v, Got result: %v", testCase.Expected, runner.hasCheck)
494 }
495 }
496 }
497
498 func TestIPTablesCommands(t *testing.T) {
499 testCases := []struct {
500 funcName string
501 protocol Protocol
502 expectedCmd string
503 }{
504 {"iptablesCommand", ProtocolIPv4, cmdIPTables},
505 {"iptablesCommand", ProtocolIPv6, cmdIP6Tables},
506 {"iptablesSaveCommand", ProtocolIPv4, cmdIPTablesSave},
507 {"iptablesSaveCommand", ProtocolIPv6, cmdIP6TablesSave},
508 {"iptablesRestoreCommand", ProtocolIPv4, cmdIPTablesRestore},
509 {"iptablesRestoreCommand", ProtocolIPv6, cmdIP6TablesRestore},
510 }
511 for _, testCase := range testCases {
512 var cmd string
513 switch testCase.funcName {
514 case "iptablesCommand":
515 cmd = iptablesCommand(testCase.protocol)
516 case "iptablesSaveCommand":
517 cmd = iptablesSaveCommand(testCase.protocol)
518 case "iptablesRestoreCommand":
519 cmd = iptablesRestoreCommand(testCase.protocol)
520 }
521 if cmd != testCase.expectedCmd {
522 t.Errorf("Function: %s, Expected result: %s, Actual result: %s", testCase.funcName, testCase.expectedCmd, cmd)
523 }
524 }
525 }
526
527 func TestCheckRuleWithoutCheckPresent(t *testing.T) {
528 iptablesSaveOutput := `# Generated by iptables-save v1.4.7 on Wed Oct 29 14:56:01 2014
529 *nat
530 :PREROUTING ACCEPT [2136997:197881818]
531 :POSTROUTING ACCEPT [4284525:258542680]
532 :OUTPUT ACCEPT [5901660:357267963]
533 -A PREROUTING -m addrtype --dst-type LOCAL -m mark --mark 0x00004000/0x00004000 -j DOCKER
534 COMMIT
535 # Completed on Wed Oct 29 14:56:01 2014`
536
537 fcmd := fakeexec.FakeCmd{
538 CombinedOutputScript: []fakeexec.FakeAction{
539
540 func() ([]byte, []byte, error) { return []byte(iptablesSaveOutput), nil, nil },
541 },
542 }
543 fexec := &fakeexec.FakeExec{
544 CommandScript: []fakeexec.FakeCommandAction{
545
546 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
547 },
548 }
549 runner := &runner{exec: fexec}
550 exists, err := runner.checkRuleWithoutCheck(
551 TableNAT, ChainPrerouting,
552 "-m", "addrtype",
553 "-m", "mark", "--mark", "0x4000/0x4000",
554 "-j", "DOCKER",
555 "--dst-type", "LOCAL")
556 if err != nil {
557 t.Errorf("expected success, got %v", err)
558 }
559 if !exists {
560 t.Errorf("expected exists = true")
561 }
562 if fcmd.CombinedOutputCalls != 1 {
563 t.Errorf("expected 1 CombinedOutput() call, got %d", fcmd.CombinedOutputCalls)
564 }
565 if !sets.New(fcmd.CombinedOutputLog[0]...).HasAll("iptables-save", "-t", "nat") {
566 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0])
567 }
568 }
569
570 func TestCheckRuleWithoutCheckAbsent(t *testing.T) {
571 iptablesSaveOutput := `# Generated by iptables-save v1.4.7 on Wed Oct 29 14:56:01 2014
572 *nat
573 :PREROUTING ACCEPT [2136997:197881818]
574 :POSTROUTING ACCEPT [4284525:258542680]
575 :OUTPUT ACCEPT [5901660:357267963]
576 -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
577 COMMIT
578 # Completed on Wed Oct 29 14:56:01 2014`
579
580 fcmd := fakeexec.FakeCmd{
581 CombinedOutputScript: []fakeexec.FakeAction{
582
583 func() ([]byte, []byte, error) { return []byte(iptablesSaveOutput), nil, nil },
584 },
585 }
586 fexec := &fakeexec.FakeExec{
587 CommandScript: []fakeexec.FakeCommandAction{
588
589 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
590 },
591 }
592 runner := &runner{exec: fexec}
593 exists, err := runner.checkRuleWithoutCheck(TableNAT, ChainPrerouting, "-m", "addrtype", "-j", "DOCKER")
594 if err != nil {
595 t.Errorf("expected success, got %v", err)
596 }
597 if exists {
598 t.Errorf("expected exists = false")
599 }
600 if fcmd.CombinedOutputCalls != 1 {
601 t.Errorf("expected 1 CombinedOutput() call, got %d", fcmd.CombinedOutputCalls)
602 }
603 if !sets.New(fcmd.CombinedOutputLog[0]...).HasAll("iptables-save", "-t", "nat") {
604 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0])
605 }
606 }
607
608 func TestIPTablesWaitFlag(t *testing.T) {
609 testCases := []struct {
610 Version string
611 Result []string
612 }{
613 {"0.55.55", nil},
614 {"1.0.55", nil},
615 {"1.4.19", nil},
616 {"1.4.20", []string{WaitString}},
617 {"1.4.21", []string{WaitString}},
618 {"1.4.22", []string{WaitString, WaitSecondsValue}},
619 {"1.5.0", []string{WaitString, WaitSecondsValue}},
620 {"2.0.0", []string{WaitString, WaitSecondsValue, WaitIntervalString, WaitIntervalUsecondsValue}},
621 }
622
623 for _, testCase := range testCases {
624 result := getIPTablesWaitFlag(utilversion.MustParseGeneric(testCase.Version))
625 if !reflect.DeepEqual(result, testCase.Result) {
626 t.Errorf("For %s expected %v got %v", testCase.Version, testCase.Result, result)
627 }
628 }
629 }
630
631 func TestWaitFlagUnavailable(t *testing.T) {
632 fcmd := fakeexec.FakeCmd{
633 CombinedOutputScript: []fakeexec.FakeAction{
634
635 func() ([]byte, []byte, error) { return []byte("iptables v1.4.19"), nil, nil },
636
637 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
638
639 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
640 },
641 }
642 fexec := &fakeexec.FakeExec{
643 CommandScript: []fakeexec.FakeCommandAction{
644
645 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
646
647 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
648 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
649 },
650 }
651 runner := New(fexec, ProtocolIPv4)
652 err := runner.DeleteChain(TableNAT, Chain("FOOBAR"))
653 if err != nil {
654 t.Errorf("expected success, got %v", err)
655 }
656 if fcmd.CombinedOutputCalls != 3 {
657 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
658 }
659 if sets.New(fcmd.CombinedOutputLog[2]...).Has(WaitString) {
660 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
661 }
662 }
663
664 func TestWaitFlagOld(t *testing.T) {
665 fcmd := fakeexec.FakeCmd{
666 CombinedOutputScript: []fakeexec.FakeAction{
667
668 func() ([]byte, []byte, error) { return []byte("iptables v1.4.20"), nil, nil },
669
670 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
671
672 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
673 },
674 }
675 fexec := &fakeexec.FakeExec{
676 CommandScript: []fakeexec.FakeCommandAction{
677 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
678 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
679 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
680 },
681 }
682 runner := New(fexec, ProtocolIPv4)
683 err := runner.DeleteChain(TableNAT, Chain("FOOBAR"))
684 if err != nil {
685 t.Errorf("expected success, got %v", err)
686 }
687 if fcmd.CombinedOutputCalls != 3 {
688 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
689 }
690 if !sets.New(fcmd.CombinedOutputLog[2]...).HasAll("iptables", WaitString) {
691 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
692 }
693 if sets.New(fcmd.CombinedOutputLog[2]...).Has(WaitSecondsValue) {
694 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
695 }
696 }
697
698 func TestWaitFlagNew(t *testing.T) {
699 fcmd := fakeexec.FakeCmd{
700 CombinedOutputScript: []fakeexec.FakeAction{
701
702 func() ([]byte, []byte, error) { return []byte("iptables v1.4.22"), nil, nil },
703
704 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
705
706 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
707 },
708 }
709 fexec := &fakeexec.FakeExec{
710 CommandScript: []fakeexec.FakeCommandAction{
711 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
712 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
713 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
714 },
715 }
716 runner := New(fexec, ProtocolIPv4)
717 err := runner.DeleteChain(TableNAT, Chain("FOOBAR"))
718 if err != nil {
719 t.Errorf("expected success, got %v", err)
720 }
721 if fcmd.CombinedOutputCalls != 3 {
722 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
723 }
724 if !sets.New(fcmd.CombinedOutputLog[2]...).HasAll("iptables", WaitString, WaitSecondsValue) {
725 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
726 }
727 }
728
729 func TestWaitIntervalFlagNew(t *testing.T) {
730 fcmd := fakeexec.FakeCmd{
731 CombinedOutputScript: []fakeexec.FakeAction{
732
733 func() ([]byte, []byte, error) { return []byte("iptables v1.6.1"), nil, nil },
734
735 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
736
737 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
738 },
739 }
740 fexec := &fakeexec.FakeExec{
741 CommandScript: []fakeexec.FakeCommandAction{
742 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
743 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
744 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
745 },
746 }
747 runner := New(fexec, ProtocolIPv4)
748 err := runner.DeleteChain(TableNAT, Chain("FOOBAR"))
749 if err != nil {
750 t.Errorf("expected success, got %v", err)
751 }
752 if fcmd.CombinedOutputCalls != 3 {
753 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
754 }
755 if !sets.New(fcmd.CombinedOutputLog[2]...).HasAll("iptables", WaitString, WaitSecondsValue, WaitIntervalString, WaitIntervalUsecondsValue) {
756 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
757 }
758 }
759
760 func testSaveInto(t *testing.T, protocol Protocol) {
761 version := " v1.9.22"
762 iptablesCmd := iptablesCommand(protocol)
763 iptablesSaveCmd := iptablesSaveCommand(protocol)
764
765 output := fmt.Sprintf(`# Generated by %s on Thu Jan 19 11:38:09 2017
766 *filter
767 :INPUT ACCEPT [15079:38410730]
768 :FORWARD ACCEPT [0:0]
769 :OUTPUT ACCEPT [11045:521562]
770 COMMIT
771 # Completed on Thu Jan 19 11:38:09 2017`, iptablesSaveCmd+version)
772
773 stderrOutput := "#STDERR OUTPUT"
774
775 fcmd := fakeexec.FakeCmd{
776 CombinedOutputScript: []fakeexec.FakeAction{
777
778 func() ([]byte, []byte, error) { return []byte(iptablesCmd + version), nil, nil },
779 },
780 RunScript: []fakeexec.FakeAction{
781 func() ([]byte, []byte, error) { return []byte(output), []byte(stderrOutput), nil },
782 func() ([]byte, []byte, error) { return nil, []byte(stderrOutput), &fakeexec.FakeExitError{Status: 1} },
783 },
784 }
785 fexec := &fakeexec.FakeExec{
786 CommandScript: []fakeexec.FakeCommandAction{
787 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
788 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
789 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
790 },
791 }
792 runner := New(fexec, protocol)
793 buffer := bytes.NewBuffer(nil)
794
795
796 err := runner.SaveInto(TableNAT, buffer)
797 if err != nil {
798 t.Fatalf("%s: Expected success, got %v", protocol, err)
799 }
800
801 if buffer.String() != output {
802 t.Errorf("%s: Expected output '%s', got '%v'", protocol, output, buffer.String())
803 }
804
805 if fcmd.CombinedOutputCalls != 1 {
806 t.Errorf("%s: Expected 1 CombinedOutput() calls, got %d", protocol, fcmd.CombinedOutputCalls)
807 }
808 if fcmd.RunCalls != 1 {
809 t.Errorf("%s: Expected 1 Run() call, got %d", protocol, fcmd.RunCalls)
810 }
811 if !sets.New(fcmd.RunLog[0]...).HasAll(iptablesSaveCmd, "-t", "nat") {
812 t.Errorf("%s: Expected cmd containing '%s -t nat', got '%s'", protocol, iptablesSaveCmd, fcmd.RunLog[0])
813 }
814
815
816 buffer.Reset()
817 err = runner.SaveInto(TableNAT, buffer)
818 if err == nil {
819 t.Errorf("%s: Expected failure", protocol)
820 }
821 if buffer.String() != stderrOutput {
822 t.Errorf("%s: Expected output '%s', got '%v'", protocol, stderrOutput, buffer.String())
823 }
824 }
825
826 func TestSaveIntoIPv4(t *testing.T) {
827 testSaveInto(t, ProtocolIPv4)
828 }
829
830 func TestSaveIntoIPv6(t *testing.T) {
831 testSaveInto(t, ProtocolIPv6)
832 }
833
834 func testRestore(t *testing.T, protocol Protocol) {
835 version := " v1.9.22"
836 iptablesCmd := iptablesCommand(protocol)
837 iptablesRestoreCmd := iptablesRestoreCommand(protocol)
838
839 fcmd := fakeexec.FakeCmd{
840 CombinedOutputScript: []fakeexec.FakeAction{
841
842 func() ([]byte, []byte, error) { return []byte(iptablesCmd + version), nil, nil },
843 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
844 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
845 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
846 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
847 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
848 },
849 }
850 fexec := &fakeexec.FakeExec{
851 CommandScript: []fakeexec.FakeCommandAction{
852 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
853 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
854 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
855 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
856 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
857 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
858 },
859 }
860 runner := New(fexec, protocol)
861
862
863 err := runner.Restore(TableNAT, []byte{}, FlushTables, RestoreCounters)
864 if err != nil {
865 t.Errorf("%s flush,restore: Expected success, got %v", protocol, err)
866 }
867
868 commandSet := sets.New(fcmd.CombinedOutputLog[1]...)
869 if !commandSet.HasAll(iptablesRestoreCmd, "-T", string(TableNAT), "--counters") || commandSet.HasAny("--noflush") {
870 t.Errorf("%s flush, restore: Expected cmd containing '%s -T %s --counters', got '%s'", protocol, iptablesRestoreCmd, string(TableNAT), fcmd.CombinedOutputLog[1])
871 }
872
873
874 err = runner.Restore(TableNAT, []byte{}, FlushTables, NoRestoreCounters)
875 if err != nil {
876 t.Errorf("%s flush, no restore: Expected success, got %v", protocol, err)
877 }
878
879 commandSet = sets.New(fcmd.CombinedOutputLog[2]...)
880 if !commandSet.HasAll(iptablesRestoreCmd, "-T", string(TableNAT)) || commandSet.HasAny("--noflush", "--counters") {
881 t.Errorf("%s flush, no restore: Expected cmd containing '--noflush' or '--counters', got '%s'", protocol, fcmd.CombinedOutputLog[2])
882 }
883
884
885 err = runner.Restore(TableNAT, []byte{}, NoFlushTables, RestoreCounters)
886 if err != nil {
887 t.Errorf("%s no flush, restore: Expected success, got %v", protocol, err)
888 }
889
890 commandSet = sets.New(fcmd.CombinedOutputLog[3]...)
891 if !commandSet.HasAll(iptablesRestoreCmd, "-T", string(TableNAT), "--noflush", "--counters") {
892 t.Errorf("%s no flush, restore: Expected cmd containing '--noflush' and '--counters', got '%s'", protocol, fcmd.CombinedOutputLog[3])
893 }
894
895
896 err = runner.Restore(TableNAT, []byte{}, NoFlushTables, NoRestoreCounters)
897 if err != nil {
898 t.Errorf("%s no flush, no restore: Expected success, got %v", protocol, err)
899 }
900
901 commandSet = sets.New(fcmd.CombinedOutputLog[4]...)
902 if !commandSet.HasAll(iptablesRestoreCmd, "-T", string(TableNAT), "--noflush") || commandSet.HasAny("--counters") {
903 t.Errorf("%s no flush, no restore: Expected cmd containing '%s -T %s --noflush', got '%s'", protocol, iptablesRestoreCmd, string(TableNAT), fcmd.CombinedOutputLog[4])
904 }
905
906 if fcmd.CombinedOutputCalls != 5 {
907 t.Errorf("%s: Expected 5 total CombinedOutput() calls, got %d", protocol, fcmd.CombinedOutputCalls)
908 }
909
910
911 err = runner.Restore(TableNAT, []byte{}, FlushTables, RestoreCounters)
912 if err == nil {
913 t.Errorf("%s Expected a failure", protocol)
914 }
915 }
916
917 func TestRestoreIPv4(t *testing.T) {
918 testRestore(t, ProtocolIPv4)
919 }
920
921 func TestRestoreIPv6(t *testing.T) {
922 testRestore(t, ProtocolIPv6)
923 }
924
925
926 func TestRestoreAll(t *testing.T) {
927 fcmd := fakeexec.FakeCmd{
928 CombinedOutputScript: []fakeexec.FakeAction{
929
930 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
931 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
932 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
933 },
934 }
935 fexec := &fakeexec.FakeExec{
936 CommandScript: []fakeexec.FakeCommandAction{
937 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
938 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
939 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
940 },
941 }
942 lockPath14x, lockPath16x := getLockPaths()
943 runner := newInternal(fexec, ProtocolIPv4, lockPath14x, lockPath16x)
944
945 err := runner.RestoreAll([]byte{}, NoFlushTables, RestoreCounters)
946 if err != nil {
947 t.Fatalf("expected success, got %v", err)
948 }
949
950 commandSet := sets.New(fcmd.CombinedOutputLog[1]...)
951 if !commandSet.HasAll("iptables-restore", "--counters", "--noflush") {
952 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
953 }
954
955 if fcmd.CombinedOutputCalls != 2 {
956 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
957 }
958
959
960 err = runner.Restore(TableNAT, []byte{}, FlushTables, RestoreCounters)
961 if err == nil {
962 t.Errorf("expected failure")
963 }
964 }
965
966
967 func TestRestoreAllWait(t *testing.T) {
968 fcmd := fakeexec.FakeCmd{
969 CombinedOutputScript: []fakeexec.FakeAction{
970
971 func() ([]byte, []byte, error) { return []byte("iptables v1.9.22"), nil, nil },
972 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
973 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
974 },
975 }
976 fexec := &fakeexec.FakeExec{
977 CommandScript: []fakeexec.FakeCommandAction{
978 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
979 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
980 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
981 },
982 }
983 lockPath14x, lockPath16x := getLockPaths()
984 runner := newInternal(fexec, ProtocolIPv4, lockPath14x, lockPath16x)
985
986 err := runner.RestoreAll([]byte{}, NoFlushTables, RestoreCounters)
987 if err != nil {
988 t.Fatalf("expected success, got %v", err)
989 }
990
991 commandSet := sets.New(fcmd.CombinedOutputLog[1]...)
992 if !commandSet.HasAll("iptables-restore", WaitString, WaitSecondsValue, WaitIntervalString, WaitIntervalUsecondsValue, "--counters", "--noflush") {
993 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1])
994 }
995
996 if fcmd.CombinedOutputCalls != 2 {
997 t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
998 }
999
1000
1001 err = runner.Restore(TableNAT, []byte{}, FlushTables, RestoreCounters)
1002 if err == nil {
1003 t.Errorf("expected failure")
1004 }
1005 }
1006
1007
1008
1009 func TestRestoreAllWaitOldIptablesRestore(t *testing.T) {
1010 fcmd := fakeexec.FakeCmd{
1011 CombinedOutputScript: []fakeexec.FakeAction{
1012
1013 func() ([]byte, []byte, error) { return []byte("iptables v1.4.22"), nil, nil },
1014
1015 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
1016 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
1017 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
1018 },
1019 }
1020 fexec := &fakeexec.FakeExec{
1021 CommandScript: []fakeexec.FakeCommandAction{
1022 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1023 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1024 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1025 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1026 },
1027 }
1028 lockPath14x, lockPath16x := getLockPaths()
1029
1030
1031 defer os.Remove(lockPath16x)
1032 runner := newInternal(fexec, ProtocolIPv4, lockPath14x, lockPath16x)
1033
1034 err := runner.RestoreAll([]byte{}, NoFlushTables, RestoreCounters)
1035 if err != nil {
1036 t.Fatalf("expected success, got %v", err)
1037 }
1038
1039 commandSet := sets.New(fcmd.CombinedOutputLog[2]...)
1040 if !commandSet.HasAll("iptables-restore", "--counters", "--noflush") {
1041 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
1042 }
1043 if commandSet.HasAll(WaitString) {
1044 t.Errorf("wrong CombinedOutput() log (unexpected %s option), got %s", WaitString, fcmd.CombinedOutputLog[1])
1045 }
1046
1047 if fcmd.CombinedOutputCalls != 3 {
1048 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
1049 }
1050
1051
1052 err = runner.Restore(TableNAT, []byte{}, FlushTables, RestoreCounters)
1053 if err == nil {
1054 t.Errorf("expected failure")
1055 }
1056 }
1057
1058
1059
1060
1061 func TestRestoreAllGrabNewLock(t *testing.T) {
1062 fcmd := fakeexec.FakeCmd{
1063 CombinedOutputScript: []fakeexec.FakeAction{
1064
1065 func() ([]byte, []byte, error) { return []byte("iptables v1.4.22"), nil, nil },
1066
1067 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
1068 },
1069 }
1070 fexec := &fakeexec.FakeExec{
1071 CommandScript: []fakeexec.FakeCommandAction{
1072 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1073 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1074 },
1075 }
1076 lockPath14x, lockPath16x := getLockPaths()
1077 runner := newInternal(fexec, ProtocolIPv4, lockPath14x, lockPath16x)
1078
1079
1080 runLock, err := os.OpenFile(lockPath16x, os.O_CREATE, 0600)
1081 if err != nil {
1082 t.Fatalf("expected to open %s, got %v", lockPath16x, err)
1083 }
1084 defer func() {
1085 runLock.Close()
1086 os.Remove(lockPath16x)
1087 }()
1088
1089 if err := grabIptablesFileLock(runLock); err != nil {
1090 t.Errorf("expected to lock %s, got %v", lockPath16x, err)
1091 }
1092
1093 err = runner.RestoreAll([]byte{}, NoFlushTables, RestoreCounters)
1094 if err == nil {
1095 t.Fatal("expected failure, got success instead")
1096 }
1097 if !strings.Contains(err.Error(), "failed to acquire new iptables lock: timed out waiting for the condition") {
1098 t.Errorf("expected timeout error, got %v", err)
1099 }
1100 }
1101
1102
1103
1104
1105 func TestRestoreAllGrabOldLock(t *testing.T) {
1106 fcmd := fakeexec.FakeCmd{
1107 CombinedOutputScript: []fakeexec.FakeAction{
1108
1109 func() ([]byte, []byte, error) { return []byte("iptables v1.4.22"), nil, nil },
1110
1111 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
1112 },
1113 }
1114 fexec := &fakeexec.FakeExec{
1115 CommandScript: []fakeexec.FakeCommandAction{
1116 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1117 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1118 },
1119 }
1120 lockPath14x, lockPath16x := getLockPaths()
1121
1122
1123 defer os.Remove(lockPath16x)
1124 runner := newInternal(fexec, ProtocolIPv4, lockPath14x, lockPath16x)
1125
1126 var runLock *net.UnixListener
1127
1128 err := wait.PollImmediate(time.Second, wait.ForeverTestTimeout, func() (done bool, err error) {
1129 runLock, err = net.ListenUnix("unix", &net.UnixAddr{Name: lockPath14x, Net: "unix"})
1130 if err != nil {
1131 t.Logf("Failed to lock %s: %v, will retry.", lockPath14x, err)
1132 return false, nil
1133 }
1134 return true, nil
1135 })
1136 if err != nil {
1137 t.Fatalf("Timed out locking %s", lockPath14x)
1138 }
1139 if runLock == nil {
1140 t.Fatal("Unexpected nil runLock")
1141 }
1142
1143 defer runLock.Close()
1144
1145 err = runner.RestoreAll([]byte{}, NoFlushTables, RestoreCounters)
1146 if err == nil {
1147 t.Fatal("expected failure, got success instead")
1148 }
1149 if !strings.Contains(err.Error(), "failed to acquire old iptables lock: timed out waiting for the condition") {
1150 t.Errorf("expected timeout error, got %v", err)
1151 }
1152 }
1153
1154
1155
1156 func TestRestoreAllWaitBackportedIptablesRestore(t *testing.T) {
1157 fcmd := fakeexec.FakeCmd{
1158 CombinedOutputScript: []fakeexec.FakeAction{
1159
1160 func() ([]byte, []byte, error) { return []byte("iptables v1.4.22"), nil, nil },
1161
1162 func() ([]byte, []byte, error) { return []byte("iptables v1.4.22"), nil, nil },
1163 func() ([]byte, []byte, error) { return []byte{}, nil, nil },
1164 func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
1165 },
1166 }
1167 fexec := &fakeexec.FakeExec{
1168 CommandScript: []fakeexec.FakeCommandAction{
1169 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1170 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1171 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1172 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
1173 },
1174 }
1175 lockPath14x, lockPath16x := getLockPaths()
1176 runner := newInternal(fexec, ProtocolIPv4, lockPath14x, lockPath16x)
1177
1178 err := runner.RestoreAll([]byte{}, NoFlushTables, RestoreCounters)
1179 if err != nil {
1180 t.Fatalf("expected success, got %v", err)
1181 }
1182
1183 commandSet := sets.New(fcmd.CombinedOutputLog[2]...)
1184 if !commandSet.HasAll("iptables-restore", "--counters", "--noflush") {
1185 t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2])
1186 }
1187 if !commandSet.HasAll(WaitString) {
1188 t.Errorf("wrong CombinedOutput() log (expected %s option), got %s", WaitString, fcmd.CombinedOutputLog[1])
1189 }
1190
1191 if fcmd.CombinedOutputCalls != 3 {
1192 t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
1193 }
1194
1195
1196 err = runner.Restore(TableNAT, []byte{}, FlushTables, RestoreCounters)
1197 if err == nil {
1198 t.Errorf("expected failure")
1199 }
1200 }
1201
1202
1203 func TestExtractLines(t *testing.T) {
1204 mkLines := func(lines ...LineData) []LineData {
1205 return lines
1206 }
1207 lines := "Line1: 1\nLine2: 2\nLine3: 3\nLine4: 4\nLine5: 5\nLine6: 6\nLine7: 7\nLine8: 8\nLine9: 9\nLine10: 10"
1208 tests := []struct {
1209 count int
1210 line int
1211 name string
1212 want []LineData
1213 }{{
1214 name: "test-line-0",
1215 count: 3,
1216 line: 0,
1217 want: nil,
1218 }, {
1219 name: "test-count-0",
1220 count: 0,
1221 line: 3,
1222 want: mkLines(LineData{3, "Line3: 3"}),
1223 }, {
1224 name: "test-common-cases",
1225 count: 3,
1226 line: 6,
1227 want: mkLines(
1228 LineData{3, "Line3: 3"},
1229 LineData{4, "Line4: 4"},
1230 LineData{5, "Line5: 5"},
1231 LineData{6, "Line6: 6"},
1232 LineData{7, "Line7: 7"},
1233 LineData{8, "Line8: 8"},
1234 LineData{9, "Line9: 9"}),
1235 }, {
1236 name: "test4-bound-cases",
1237 count: 11,
1238 line: 10,
1239 want: mkLines(
1240 LineData{1, "Line1: 1"},
1241 LineData{2, "Line2: 2"},
1242 LineData{3, "Line3: 3"},
1243 LineData{4, "Line4: 4"},
1244 LineData{5, "Line5: 5"},
1245 LineData{6, "Line6: 6"},
1246 LineData{7, "Line7: 7"},
1247 LineData{8, "Line8: 8"},
1248 LineData{9, "Line9: 9"},
1249 LineData{10, "Line10: 10"}),
1250 }}
1251
1252 for _, tt := range tests {
1253 t.Run(tt.name, func(t *testing.T) {
1254 got := ExtractLines([]byte(lines), tt.line, tt.count)
1255 if !reflect.DeepEqual(got, tt.want) {
1256 t.Errorf("got = %v, want = %v", got, tt.want)
1257 }
1258 })
1259 }
1260 }
1261
View as plain text