1818package support
1919
2020import (
21+ "fmt"
2122 "os"
2223 "path/filepath"
2324 "testing"
@@ -27,6 +28,8 @@ import (
2728 "github.com/spf13/afero"
2829 "github.com/stretchr/testify/assert"
2930 "github.com/stretchr/testify/require"
31+ "k8s.io/utils/exec"
32+ testingexec "k8s.io/utils/exec/testing"
3033)
3134
3235func TestDumpLog (t * testing.T ) {
@@ -49,3 +52,162 @@ func TestDumpLog(t *testing.T) {
4952 require .NoError (t , err )
5053 assert .True (t , ok )
5154}
55+
56+ func TestDumpNFTables (t * testing.T ) {
57+ const nftV4Output = "table ip antrea { chain antrea-chain { type filter hook input priority 0; } }"
58+ const nftV6Output = "table ip6 antrea { chain antrea-chain6 { type filter hook input priority 0; } }"
59+
60+ v4ErrorAction := func () ([]byte , []byte , error ) {
61+ return nil , nil , fmt .Errorf ("v4 error" )
62+ }
63+ v4SuccessAction := func () ([]byte , []byte , error ) {
64+ return []byte (nftV4Output ), nil , nil
65+ }
66+ v6SuccessAction := func () ([]byte , []byte , error ) {
67+ return []byte (nftV6Output ), nil , nil
68+ }
69+ emptySuccessAction := func () ([]byte , []byte , error ) {
70+ return []byte ("" ), nil , nil
71+ }
72+
73+ tests := []struct {
74+ name string
75+ v4Enabled bool
76+ v6Enabled bool
77+ lookPathErr error
78+ commandActions []testingexec.FakeCommandAction
79+ expectedContent string
80+ expectFile bool
81+ expectErr bool
82+ }{
83+ {
84+ name : "nft command not found" ,
85+ v4Enabled : true ,
86+ v6Enabled : true ,
87+ lookPathErr : fmt .Errorf ("command 'nft' not found in PATH" ),
88+ expectFile : false ,
89+ expectErr : false ,
90+ },
91+ {
92+ name : "v4 enabled only" ,
93+ v4Enabled : true ,
94+ v6Enabled : false ,
95+ commandActions : []testingexec.FakeCommandAction {
96+ func (cmd string , args ... string ) exec.Cmd {
97+ return & testingexec.FakeCmd {
98+ CombinedOutputScript : []testingexec.FakeAction {v4SuccessAction },
99+ }
100+ },
101+ },
102+ expectedContent : nftV4Output + "\n " ,
103+ expectFile : true ,
104+ },
105+ {
106+ name : "v6 enabled only" ,
107+ v4Enabled : false ,
108+ v6Enabled : true ,
109+ commandActions : []testingexec.FakeCommandAction {
110+ func (cmd string , args ... string ) exec.Cmd {
111+ return & testingexec.FakeCmd {
112+ CombinedOutputScript : []testingexec.FakeAction {v6SuccessAction },
113+ }
114+ },
115+ },
116+ expectedContent : nftV6Output + "\n " ,
117+ expectFile : true ,
118+ },
119+ {
120+ name : "v4 and v6 enabled" ,
121+ v4Enabled : true ,
122+ v6Enabled : true ,
123+ commandActions : []testingexec.FakeCommandAction {
124+ func (cmd string , args ... string ) exec.Cmd {
125+ return & testingexec.FakeCmd {
126+ CombinedOutputScript : []testingexec.FakeAction {v4SuccessAction },
127+ }
128+ },
129+ func (cmd string , args ... string ) exec.Cmd {
130+ return & testingexec.FakeCmd {
131+ CombinedOutputScript : []testingexec.FakeAction {v6SuccessAction },
132+ }
133+ },
134+ },
135+ expectedContent : nftV4Output + "\n " + nftV6Output + "\n " ,
136+ expectFile : true ,
137+ },
138+ {
139+ name : "v4 command error" ,
140+ v4Enabled : true ,
141+ v6Enabled : true ,
142+ commandActions : []testingexec.FakeCommandAction {
143+ func (cmd string , args ... string ) exec.Cmd {
144+ return & testingexec.FakeCmd {
145+ CombinedOutputScript : []testingexec.FakeAction {v4ErrorAction },
146+ }
147+ },
148+ },
149+ expectFile : false ,
150+ expectErr : true ,
151+ },
152+ {
153+ name : "no rules found (empty output)" ,
154+ v4Enabled : true ,
155+ v6Enabled : true ,
156+ commandActions : []testingexec.FakeCommandAction {
157+ func (cmd string , args ... string ) exec.Cmd {
158+ return & testingexec.FakeCmd {CombinedOutputScript : []testingexec.FakeAction {emptySuccessAction }}
159+ },
160+ func (cmd string , args ... string ) exec.Cmd {
161+ return & testingexec.FakeCmd {CombinedOutputScript : []testingexec.FakeAction {emptySuccessAction }}
162+ },
163+ },
164+ expectFile : false ,
165+ expectErr : false ,
166+ },
167+ }
168+
169+ for _ , tc := range tests {
170+ t .Run (tc .name , func (t * testing.T ) {
171+ fs := afero .NewMemMapFs ()
172+ fs .MkdirAll (baseDir , os .ModePerm )
173+
174+ fakeExecutor := & testingexec.FakeExec {}
175+
176+ fakeExecutor .LookPathFunc = func (cmd string ) (string , error ) {
177+ if cmd == "nft" {
178+ return "/usr/bin/nft" , tc .lookPathErr
179+ }
180+ return "" , fmt .Errorf ("command %s not expected" , cmd )
181+ }
182+ fakeExecutor .CommandScript = tc .commandActions
183+
184+ dumper := & agentDumper {
185+ fs : fs ,
186+ executor : fakeExecutor ,
187+ v4Enabled : tc .v4Enabled ,
188+ v6Enabled : tc .v6Enabled ,
189+ }
190+
191+ err := dumper .dumpNFTables (baseDir )
192+
193+ if tc .expectErr {
194+ require .Error (t , err )
195+ return
196+ }
197+
198+ require .NoError (t , err )
199+
200+ filePath := filepath .Join (baseDir , "nftables" )
201+
202+ ok , err := afero .Exists (fs , filePath )
203+ require .NoError (t , err )
204+ assert .Equal (t , tc .expectFile , ok , "Expected nftables file existence to be %t" , tc .expectFile )
205+
206+ if tc .expectFile {
207+ content , err := afero .ReadFile (fs , filePath )
208+ require .NoError (t , err )
209+ assert .Equal (t , tc .expectedContent , string (content ), "File content does not match" )
210+ }
211+ })
212+ }
213+ }
0 commit comments