istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tools/istio-iptables/pkg/dependencies/stub.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package dependencies 16 17 import ( 18 "bufio" 19 "fmt" 20 "io" 21 "os" 22 "strings" 23 24 "istio.io/istio/pkg/env" 25 "istio.io/istio/tools/istio-iptables/pkg/constants" 26 ) 27 28 var DryRunFilePath = env.Register("DRY_RUN_FILE_PATH", "", "If provided, StdoutStubDependencies will write the input from stdin to the given file.") 29 30 // TODO BML replace DIY mocks/state with something better 31 type DependenciesStub struct { 32 ExecutedNormally []string 33 ExecutedQuietly []string 34 ExecutedStdin []string 35 ExecutedAll []string 36 } 37 38 func (s *DependenciesStub) Run(cmd constants.IptablesCmd, iptVer *IptablesVersion, stdin io.ReadSeeker, args ...string) error { 39 s.execute(false /*quietly*/, cmd, iptVer, stdin, args...) 40 _ = s.writeAllToDryRunPath() 41 return nil 42 } 43 44 func (s *DependenciesStub) RunQuietlyAndIgnore(cmd constants.IptablesCmd, iptVer *IptablesVersion, stdin io.ReadSeeker, args ...string) { 45 s.execute(true /*quietly*/, cmd, iptVer, stdin, args...) 46 _ = s.writeAllToDryRunPath() 47 } 48 49 func (s *DependenciesStub) DetectIptablesVersion(ipV6 bool) (IptablesVersion, error) { 50 if ipV6 { 51 return IptablesVersion{ 52 DetectedBinary: "ip6tables", 53 DetectedSaveBinary: "ip6tables-save", 54 DetectedRestoreBinary: "ip6tables-restore", 55 }, nil 56 } 57 return IptablesVersion{ 58 DetectedBinary: "iptables", 59 DetectedSaveBinary: "iptables-save", 60 DetectedRestoreBinary: "iptables-restore", 61 }, nil 62 } 63 64 func (s *DependenciesStub) execute(quietly bool, cmd constants.IptablesCmd, iptVer *IptablesVersion, stdin io.ReadSeeker, args ...string) { 65 // We are either getting iptables rules as a `stdin` blob in `iptables-save` format (if this is a restore) 66 if stdin != nil { 67 buf := bufio.NewScanner(stdin) 68 for buf.Scan() { 69 stdincmd := buf.Text() 70 s.ExecutedAll = append(s.ExecutedAll, stdincmd) 71 s.ExecutedStdin = append(s.ExecutedStdin, stdincmd) 72 } 73 } else { 74 // ...or as discrete individual commands 75 cmdline := strings.Join(append([]string{iptVer.CmdToString(cmd)}, args...), " ") 76 s.ExecutedAll = append(s.ExecutedAll, cmdline) 77 if quietly { 78 s.ExecutedQuietly = append(s.ExecutedQuietly, cmdline) 79 } else { 80 s.ExecutedNormally = append(s.ExecutedNormally, cmdline) 81 } 82 } 83 } 84 85 // TODO BML this is more than a stub actually needs to do, we should be able to drop this testing hack 86 // and skip writing to a file, but some tests are not *actually* doing unit testing and need this. 87 func (s *DependenciesStub) writeAllToDryRunPath() error { 88 path := DryRunFilePath.Get() 89 if path != "" { 90 // Print the input into the given output file. 91 f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) 92 if err != nil { 93 return fmt.Errorf("unable to open dry run output file %v: %v", path, err) 94 } 95 96 defer f.Close() 97 98 for _, line := range s.ExecutedAll { 99 _, err := f.WriteString(line + "\n") 100 if err != nil { 101 return fmt.Errorf("unable to write lines to dry run output file %v: %v", path, err) 102 } 103 } 104 } 105 return nil 106 }