diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e409760..86b03f2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,3 +26,5 @@ jobs: run: go get . - name: Build run: go build -v ./... + - name: Lint + run: go vet ./... diff --git a/go.mod b/go.mod index 9787118..3bac8b6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/nextmn/docker-setup go 1.25.5 require ( - github.com/nextmn/logrus-formatter v0.1.0 + github.com/nextmn/logrus-formatter v0.2.0 github.com/sirupsen/logrus v1.9.3 github.com/urfave/cli/v3 v3.6.1 ) diff --git a/go.sum b/go.sum index 1115f15..fc15490 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/nextmn/logrus-formatter v0.1.0 h1:SUVMFsckd18j/TMveaFed+mu6v4p7U9D9PuTNrI4w28= -github.com/nextmn/logrus-formatter v0.1.0/go.mod h1:+G9FGh86JyAJBDenHuMOtz2d+Dwkg5fYAUDG5rJj76M= +github.com/nextmn/logrus-formatter v0.2.0 h1:uIohVfiR8+CiLBn/gbxExSutq57uZpBq7VBi3+vThKc= +github.com/nextmn/logrus-formatter v0.2.0/go.mod h1:+G9FGh86JyAJBDenHuMOtz2d+Dwkg5fYAUDG5rJj76M= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= diff --git a/internal/app/conf.go b/internal/app/conf.go index 004be74..315cdee 100644 --- a/internal/app/conf.go +++ b/internal/app/conf.go @@ -6,6 +6,7 @@ package app import ( + "context" "fmt" "os" @@ -39,19 +40,19 @@ func (conf Conf) Oneshot() bool { } // Run exit hooks -func (conf Conf) RunExitHooks() { - conf.RunExitHook("pre") - conf.RunExitHook("nat4") - conf.RunExitHook("iproute") - conf.RunExitHook("post") +func (conf Conf) RunExitHooks(ctx context.Context) { + conf.RunExitHook(ctx, "pre") + conf.RunExitHook(ctx, "nat4") + conf.RunExitHook(ctx, "iproute") + conf.RunExitHook(ctx, "post") } // Run init hooks -func (conf Conf) RunInitHooks() { - conf.RunInitHook("pre") - conf.RunInitHook("iproute") - conf.RunInitHook("nat4") - conf.RunInitHook("post") +func (conf Conf) RunInitHooks(ctx context.Context) { + conf.RunInitHook(ctx, "pre") + conf.RunInitHook(ctx, "iproute") + conf.RunInitHook(ctx, "nat4") + conf.RunInitHook(ctx, "post") } // Add a new hook to the configuration @@ -70,9 +71,9 @@ func (conf Conf) AddHooks() { } // Run an init hook -func (conf Conf) RunInitHook(name string) { +func (conf Conf) RunInitHook(ctx context.Context, name string) { if conf.hooksList[name] != nil { - if err := conf.hooksList[name].RunInit(); err != nil { + if err := conf.hooksList[name].RunInit(ctx); err != nil { logrus.WithError(err).WithFields(logrus.Fields{ "hook-name": name, }).Error("Error while running init hook") @@ -81,9 +82,9 @@ func (conf Conf) RunInitHook(name string) { } // Run an exit hook -func (conf Conf) RunExitHook(name string) { +func (conf Conf) RunExitHook(ctx context.Context, name string) { if conf.hooksList[name] != nil { - if err := conf.hooksList[name].RunExit(); err != nil { + if err := conf.hooksList[name].RunExit(ctx); err != nil { logrus.WithError(err).WithFields(logrus.Fields{ "hook-name": name, }).Error("Error while running exit hook") diff --git a/internal/app/hook.go b/internal/app/hook.go index 2955dbc..335032d 100644 --- a/internal/app/hook.go +++ b/internal/app/hook.go @@ -5,17 +5,21 @@ package app +import ( + "context" +) + // init & exit hooks iface type Hook interface { String() []string - RunInit() error - RunExit() error + RunInit(context.Context) error + RunExit(context.Context) error } // init or exit hook iface type HookSingle interface { String() []string - Run() error + Run(context.Context) error } // init & exit hooks @@ -33,11 +37,11 @@ func (hooks HookMulti) String() []string { } // Runs init hook -func (hooks HookMulti) RunInit() error { - return hooks.init.Run() +func (hooks HookMulti) RunInit(ctx context.Context) error { + return hooks.init.Run(ctx) } // Runs exit hook -func (hooks HookMulti) RunExit() error { - return hooks.exit.Run() +func (hooks HookMulti) RunExit(ctx context.Context) error { + return hooks.exit.Run(ctx) } diff --git a/internal/app/iproutehook.go b/internal/app/iproutehook.go index 1caf304..2042cfb 100644 --- a/internal/app/iproutehook.go +++ b/internal/app/iproutehook.go @@ -6,6 +6,7 @@ package app import ( + "context" "fmt" "os" "os/exec" @@ -13,10 +14,11 @@ import ( ) // Runs iptables -func runIPRoute(args ...string) error { +func runIPRoute(ctx context.Context, args ...string) error { r := []string{"route"} r = append(r, args...) - cmd := exec.Command("ip", r...) + cmd := exec.CommandContext(ctx, "ip", r...) + cmd.Env = []string{} return cmd.Run() } @@ -57,13 +59,13 @@ func NewIPRouteHook(name string, env string) IPRouteHook { } // Run the hook if it is set -func (hook IPRouteHook) Run() error { +func (hook IPRouteHook) Run(ctx context.Context) error { if !hook.isset { return nil } for _, r := range hook.routes { r = append(r, "proto", "static") - if err := runIPRoute(r...); err != nil { + if err := runIPRoute(ctx, r...); err != nil { return err } } diff --git a/internal/app/nat4hook.go b/internal/app/nat4hook.go index 39e8b37..d3c0c97 100644 --- a/internal/app/nat4hook.go +++ b/internal/app/nat4hook.go @@ -6,6 +6,7 @@ package app import ( + "context" "fmt" "os" "os/exec" @@ -13,8 +14,9 @@ import ( ) // Runs iptables -func runIP4Tables(args ...string) error { - cmd := exec.Command("iptables", args...) +func runIP4Tables(ctx context.Context, args ...string) error { + cmd := exec.CommandContext(ctx, "iptables", args...) + cmd.Env = []string{} return cmd.Run() } @@ -47,15 +49,15 @@ func NewNat4Hooks() Nat4Hook { } // Runs IPv4 NAT init hook -func (hook Nat4Hook) RunInit() error { +func (hook Nat4Hook) RunInit(ctx context.Context) error { if !hook.isset { return nil } - if err := runIP4Tables("-I", "FORWARD", "-j", "ACCEPT"); err != nil { + if err := runIP4Tables(ctx, "-I", "FORWARD", "-j", "ACCEPT"); err != nil { return err } for _, iface := range hook.ifaces { - if err := runIP4Tables("-t", "nat", "-A", "POSTROUTING", "-o", iface, "-j", "MASQUERADE"); err != nil { + if err := runIP4Tables(ctx, "-t", "nat", "-A", "POSTROUTING", "-o", iface, "-j", "MASQUERADE"); err != nil { return err } } @@ -63,7 +65,7 @@ func (hook Nat4Hook) RunInit() error { } // Runs IPv4 NAT exit hook -func (hook Nat4Hook) RunExit() error { +func (hook Nat4Hook) RunExit(ctx context.Context) error { if !hook.isset { return nil } @@ -71,7 +73,7 @@ func (hook Nat4Hook) RunExit() error { var lasterr error for _, iface := range hook.ifaces { // if there is an error, we continue: will return at the end - if err := runIP4Tables("-t", "nat", "-D", "POSTROUTING", "-o", iface, "-j", "MASQUERADE"); err != nil { + if err := runIP4Tables(ctx, "-t", "nat", "-D", "POSTROUTING", "-o", iface, "-j", "MASQUERADE"); err != nil { errcount++ lasterr = err } @@ -79,7 +81,7 @@ func (hook Nat4Hook) RunExit() error { if errcount == 1 { return lasterr } else if errcount > 1 { - return fmt.Errorf("%i iptable errors", errcount) + return fmt.Errorf("%d iptable errors", errcount) } return nil } diff --git a/internal/app/userhook.go b/internal/app/userhook.go index 394d603..c06aef1 100644 --- a/internal/app/userhook.go +++ b/internal/app/userhook.go @@ -7,6 +7,7 @@ package app import ( "bufio" + "context" "fmt" "io" "os" @@ -61,11 +62,12 @@ func NewUserHook(name string, env string) UserHook { } // Run the hook if it is set -func (hook UserHook) Run() error { +func (hook UserHook) Run(ctx context.Context) error { if !hook.isset { return nil } - cmd := exec.Command(hook.cmd, hook.args...) + cmd := exec.CommandContext(ctx, hook.cmd, hook.args...) + cmd.Env = []string{} stdout, _ := cmd.StdoutPipe() stderr, _ := cmd.StderrPipe() if err := cmd.Start(); err != nil { diff --git a/main.go b/main.go index 97726aa..0a600d7 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "os/signal" "runtime/debug" "syscall" + "time" "github.com/nextmn/logrus-formatter/logger" @@ -37,11 +38,15 @@ func main() { Version: version, Action: func(ctx context.Context, cmd *cli.Command) error { conf := app.NewConf() - conf.RunInitHooks() + conf.RunInitHooks(ctx) if !conf.Oneshot() { + defer func() { + shCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 1*time.Second) + defer cancel() + conf.RunExitHooks(shCtx) + }() <-ctx.Done() } - conf.RunExitHooks() return nil }, }