chore(deps): implement github.com/qdm12/golibs/command locally (#2418)

This commit is contained in:
Quentin McGaw
2024-08-21 15:21:31 +02:00
committed by GitHub
parent 4d60b71583
commit a2b3d7e30c
26 changed files with 537 additions and 95 deletions

View File

@@ -33,7 +33,7 @@ func isDeleteMatchInstruction(instruction string) bool {
}
func deleteIPTablesRule(ctx context.Context, iptablesBinary, instruction string,
runner Runner, logger Logger) (err error) {
runner CmdRunner, logger Logger) (err error) {
targetRule, err := parseIptablesInstruction(instruction)
if err != nil {
return fmt.Errorf("parsing iptables command: %w", err)
@@ -68,7 +68,7 @@ func deleteIPTablesRule(ctx context.Context, iptablesBinary, instruction string,
// findLineNumber finds the line number of an iptables rule.
// It returns 0 if the rule is not found.
func findLineNumber(ctx context.Context, iptablesBinary string,
instruction iptablesInstruction, runner Runner, logger Logger) (
instruction iptablesInstruction, runner CmdRunner, logger Logger) (
lineNumber uint16, err error) {
listFlags := []string{"-t", instruction.table, "-L", instruction.chain,
"--line-numbers", "-n", "-v"}

View File

@@ -62,7 +62,7 @@ func Test_deleteIPTablesRule(t *testing.T) {
testCases := map[string]struct {
instruction string
makeRunner func(ctrl *gomock.Controller) *MockRunner
makeRunner func(ctrl *gomock.Controller) *MockCmdRunner
makeLogger func(ctrl *gomock.Controller) *MockLogger
errWrapped error
errMessage string
@@ -75,8 +75,8 @@ func Test_deleteIPTablesRule(t *testing.T) {
},
"list_error": {
instruction: "-t nat --delete PREROUTING -i tun0 -p tcp --dport 43716 -j REDIRECT --to-ports 5678",
makeRunner: func(ctrl *gomock.Controller) *MockRunner {
runner := NewMockRunner(ctrl)
makeRunner: func(ctrl *gomock.Controller) *MockCmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().
Run(newCmdMatcherListRules(iptablesBinary, "nat", "PREROUTING")).
Return("", errTest)
@@ -93,8 +93,8 @@ func Test_deleteIPTablesRule(t *testing.T) {
},
"rule_not_found": {
instruction: "-t nat --delete PREROUTING -i tun0 -p tcp --dport 43716 -j REDIRECT --to-ports 5678",
makeRunner: func(ctrl *gomock.Controller) *MockRunner {
runner := NewMockRunner(ctrl)
makeRunner: func(ctrl *gomock.Controller) *MockCmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newCmdMatcherListRules(iptablesBinary, "nat", "PREROUTING")).
Return(`Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
@@ -112,8 +112,8 @@ func Test_deleteIPTablesRule(t *testing.T) {
},
"rule_found_delete_error": {
instruction: "-t nat --delete PREROUTING -i tun0 -p tcp --dport 43716 -j REDIRECT --to-ports 5678",
makeRunner: func(ctrl *gomock.Controller) *MockRunner {
runner := NewMockRunner(ctrl)
makeRunner: func(ctrl *gomock.Controller) *MockCmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newCmdMatcherListRules(iptablesBinary, "nat", "PREROUTING")).
Return("Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)\n"+
"num pkts bytes target prot opt in out source destination \n"+
@@ -137,8 +137,8 @@ func Test_deleteIPTablesRule(t *testing.T) {
},
"rule_found_delete_success": {
instruction: "-t nat --delete PREROUTING -i tun0 -p tcp --dport 43716 -j REDIRECT --to-ports 5678",
makeRunner: func(ctrl *gomock.Controller) *MockRunner {
runner := NewMockRunner(ctrl)
makeRunner: func(ctrl *gomock.Controller) *MockCmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newCmdMatcherListRules(iptablesBinary, "nat", "PREROUTING")).
Return("Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)\n"+
"num pkts bytes target prot opt in out source destination \n"+
@@ -168,7 +168,7 @@ func Test_deleteIPTablesRule(t *testing.T) {
ctx := context.Background()
instruction := testCase.instruction
var runner *MockRunner
var runner *MockCmdRunner
if testCase.makeRunner != nil {
runner = testCase.makeRunner(ctrl)
}

View File

@@ -7,11 +7,10 @@ import (
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/routing"
"github.com/qdm12/golibs/command"
)
type Config struct { //nolint:maligned
runner command.Runner
runner CmdRunner
logger Logger
iptablesMutex sync.Mutex
ip6tablesMutex sync.Mutex
@@ -36,7 +35,7 @@ type Config struct { //nolint:maligned
// NewConfig creates a new Config instance and returns an error
// if no iptables implementation is available.
func NewConfig(ctx context.Context, logger Logger,
runner command.Runner, defaultRoutes []routing.DefaultRoute,
runner CmdRunner, defaultRoutes []routing.DefaultRoute,
localNetworks []routing.LocalNetwork) (config *Config, err error) {
iptables, err := checkIptablesSupport(ctx, runner, "iptables", "iptables-nft", "iptables-legacy")
if err != nil {

View File

@@ -1,9 +1,9 @@
package firewall
import "github.com/qdm12/golibs/command"
import "os/exec"
type Runner interface {
Run(cmd command.ExecCmd) (output string, err error)
type CmdRunner interface {
Run(cmd *exec.Cmd) (output string, err error)
}
type Logger interface {

View File

@@ -6,14 +6,12 @@ import (
"fmt"
"os/exec"
"strings"
"github.com/qdm12/golibs/command"
)
// findIP6tablesSupported checks for multiple iptables implementations
// and returns the iptables path that is supported. If none work, an
// empty string path is returned.
func findIP6tablesSupported(ctx context.Context, runner command.Runner) (
func findIP6tablesSupported(ctx context.Context, runner CmdRunner) (
ip6tablesPath string, err error) {
ip6tablesPath, err = checkIptablesSupport(ctx, runner, "ip6tables", "ip6tables-nft", "ip6tables-legacy")
if errors.Is(err, ErrIPTablesNotSupported) {

View File

@@ -1,3 +1,3 @@
package firewall
//go:generate mockgen -destination=mocks_test.go -package=$GOPACKAGE . Runner,Logger
//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . CmdRunner,Logger

View File

@@ -1,41 +1,41 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/qdm12/gluetun/internal/firewall (interfaces: Runner,Logger)
// Source: github.com/qdm12/gluetun/internal/firewall (interfaces: CmdRunner,Logger)
// Package firewall is a generated GoMock package.
package firewall
import (
exec "os/exec"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
command "github.com/qdm12/golibs/command"
)
// MockRunner is a mock of Runner interface.
type MockRunner struct {
// MockCmdRunner is a mock of CmdRunner interface.
type MockCmdRunner struct {
ctrl *gomock.Controller
recorder *MockRunnerMockRecorder
recorder *MockCmdRunnerMockRecorder
}
// MockRunnerMockRecorder is the mock recorder for MockRunner.
type MockRunnerMockRecorder struct {
mock *MockRunner
// MockCmdRunnerMockRecorder is the mock recorder for MockCmdRunner.
type MockCmdRunnerMockRecorder struct {
mock *MockCmdRunner
}
// NewMockRunner creates a new mock instance.
func NewMockRunner(ctrl *gomock.Controller) *MockRunner {
mock := &MockRunner{ctrl: ctrl}
mock.recorder = &MockRunnerMockRecorder{mock}
// NewMockCmdRunner creates a new mock instance.
func NewMockCmdRunner(ctrl *gomock.Controller) *MockCmdRunner {
mock := &MockCmdRunner{ctrl: ctrl}
mock.recorder = &MockCmdRunnerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockRunner) EXPECT() *MockRunnerMockRecorder {
func (m *MockCmdRunner) EXPECT() *MockCmdRunnerMockRecorder {
return m.recorder
}
// Run mocks base method.
func (m *MockRunner) Run(arg0 command.ExecCmd) (string, error) {
func (m *MockCmdRunner) Run(arg0 *exec.Cmd) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Run", arg0)
ret0, _ := ret[0].(string)
@@ -44,9 +44,9 @@ func (m *MockRunner) Run(arg0 command.ExecCmd) (string, error) {
}
// Run indicates an expected call of Run.
func (mr *MockRunnerMockRecorder) Run(arg0 interface{}) *gomock.Call {
func (mr *MockCmdRunnerMockRecorder) Run(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockRunner)(nil).Run), arg0)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockCmdRunner)(nil).Run), arg0)
}
// MockLogger is a mock of Logger interface.

View File

@@ -8,8 +8,6 @@ import (
"os/exec"
"sort"
"strings"
"github.com/qdm12/golibs/command"
)
var (
@@ -19,7 +17,7 @@ var (
ErrIPTablesNotSupported = errors.New("no iptables supported found")
)
func checkIptablesSupport(ctx context.Context, runner command.Runner,
func checkIptablesSupport(ctx context.Context, runner CmdRunner,
iptablesPathsToTry ...string) (iptablesPath string, err error) {
iptablesPathToUnsupportedMessage := make(map[string]string, len(iptablesPathsToTry))
for _, pathToTest := range iptablesPathsToTry {
@@ -62,7 +60,7 @@ func checkIptablesSupport(ctx context.Context, runner command.Runner,
}
func testIptablesPath(ctx context.Context, path string,
runner command.Runner) (ok bool, unsupportedMessage string,
runner CmdRunner) (ok bool, unsupportedMessage string,
criticalErr error) {
// Just listing iptables rules often work but we need
// to modify them to ensure we can support the iptables

View File

@@ -6,7 +6,6 @@ import (
"testing"
"github.com/golang/mock/gomock"
"github.com/qdm12/golibs/command"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -41,15 +40,15 @@ func Test_checkIptablesSupport(t *testing.T) {
const inputPolicy = "ACCEPT"
testCases := map[string]struct {
buildRunner func(ctrl *gomock.Controller) command.Runner
buildRunner func(ctrl *gomock.Controller) CmdRunner
iptablesPathsToTry []string
iptablesPath string
errSentinel error
errMessage string
}{
"critical error when checking": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher("path1")).
Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher("path1")).
@@ -62,8 +61,8 @@ func Test_checkIptablesSupport(t *testing.T) {
"output (exit code 4)",
},
"found valid path": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher("path1")).
Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher("path1")).
@@ -78,8 +77,8 @@ func Test_checkIptablesSupport(t *testing.T) {
iptablesPath: "path1",
},
"all permission denied": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher("path1")).
Return("Permission denied (you must be root) more context", errDummy)
runner.EXPECT().Run(newAppendTestRuleMatcher("path2")).
@@ -93,8 +92,8 @@ func Test_checkIptablesSupport(t *testing.T) {
"path2: context: Permission denied (you must be root) (exit code 4)",
},
"no valid path": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher("path1")).
Return("output 1", errDummy)
runner.EXPECT().Run(newAppendTestRuleMatcher("path2")).
@@ -139,15 +138,15 @@ func Test_testIptablesPath(t *testing.T) {
const inputPolicy = "ACCEPT"
testCases := map[string]struct {
buildRunner func(ctrl *gomock.Controller) command.Runner
buildRunner func(ctrl *gomock.Controller) CmdRunner
ok bool
unsupportedMessage string
criticalErrWrapped error
criticalErrMessage string
}{
"append test rule permission denied": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).
Return("Permission denied (you must be root)", errDummy)
return runner
@@ -155,8 +154,8 @@ func Test_testIptablesPath(t *testing.T) {
unsupportedMessage: "Permission denied (you must be root) (exit code 4)",
},
"append test rule unsupported": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).
Return("some output", errDummy)
return runner
@@ -164,8 +163,8 @@ func Test_testIptablesPath(t *testing.T) {
unsupportedMessage: "some output (exit code 4)",
},
"remove test rule error": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).
Return("some output", errDummy)
@@ -175,8 +174,8 @@ func Test_testIptablesPath(t *testing.T) {
criticalErrMessage: "failed cleaning up test rule: some output (exit code 4)",
},
"list input rules permission denied": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newListInputRulesMatcher(path)).
@@ -186,8 +185,8 @@ func Test_testIptablesPath(t *testing.T) {
unsupportedMessage: "Permission denied (you must be root) (exit code 4)",
},
"list input rules unsupported": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newListInputRulesMatcher(path)).
@@ -197,8 +196,8 @@ func Test_testIptablesPath(t *testing.T) {
unsupportedMessage: "some output (exit code 4)",
},
"list input rules no policy": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newListInputRulesMatcher(path)).
@@ -209,8 +208,8 @@ func Test_testIptablesPath(t *testing.T) {
criticalErrMessage: "input policy not found: in INPUT rules: some\noutput",
},
"set policy permission denied": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newListInputRulesMatcher(path)).
@@ -222,8 +221,8 @@ func Test_testIptablesPath(t *testing.T) {
unsupportedMessage: "Permission denied (you must be root) (exit code 4)",
},
"set policy unsupported": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newListInputRulesMatcher(path)).
@@ -235,8 +234,8 @@ func Test_testIptablesPath(t *testing.T) {
unsupportedMessage: "some output (exit code 4)",
},
"success": {
buildRunner: func(ctrl *gomock.Controller) command.Runner {
runner := NewMockRunner(ctrl)
buildRunner: func(ctrl *gomock.Controller) CmdRunner {
runner := NewMockCmdRunner(ctrl)
runner.EXPECT().Run(newAppendTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newDeleteTestRuleMatcher(path)).Return("", nil)
runner.EXPECT().Run(newListInputRulesMatcher(path)).