diff --git a/cmd/apply.go b/cmd/apply.go index dda16ec..3af5960 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -253,7 +253,7 @@ func SetupVethDevices(netns string, devices map[string]config.VethDevice) error peerNetns := values.Peer.Netns slog.Debug("setup veth device", "netns", netns, "name", name, "addresses", values.Addresses, "routes", values.Routes, - "peer name", peerName, "peer netns", peerNetns, "peer addresses", values.Peer.Addresses, "peer routes", values.Peer.Routes) + "peer name", peerName, "peer netns", peerNetns, "peer addresses", values.Peer.Addresses, "peer routes", values.Peer.Routes) // check if device is already exists in netns _, err := n.ShowLink(name) @@ -332,7 +332,7 @@ func RunPostScript(netns string, script string) error { if err != nil { return err } - slog.Debug("post script output", "netns", netns, "script", script, "output", out) + slog.Debug("post script output", "netns", netns, "script", script, "stdout", out.Stdout, "stderr", out.Stderr) return nil } diff --git a/iproute2/base.go b/iproute2/base.go index c2e5325..5ee73ec 100644 --- a/iproute2/base.go +++ b/iproute2/base.go @@ -22,8 +22,10 @@ SOFTWARE. package iproute2 import ( + "bytes" "encoding/json" "io" + "log/slog" "os/exec" "strings" "syscall" @@ -34,6 +36,11 @@ type BaseCommand struct { prepend []string } +type CommandOut struct { + Stdout string + Stderr string +} + func (b *BaseCommand) run(args ...string) error { _, err := b.runIpCommand(args...) return err @@ -43,7 +50,11 @@ func (b *BaseCommand) runIpCommand(args ...string) (string, error) { cmd := append([]string{b.path}, args...) out, err := b.runCommand(cmd, nil) if err == nil { - return out, nil + if out.Stderr != "" { + slog.Warn("ip command warning", "msg", out.Stderr) + } + + return out.Stdout, nil } msg := err.Error() @@ -58,7 +69,7 @@ func (b *BaseCommand) runIpCommand(args ...string) (string, error) { return "", &UnknownError{Msg: err.Error()} } -func (b *BaseCommand) runCommand(cmd []string, input *string) (string, error) { +func (b *BaseCommand) runCommand(cmd []string, input *string) (*CommandOut, error) { if b.prepend != nil { cmd = append(b.prepend, cmd...) } @@ -73,7 +84,7 @@ func (b *BaseCommand) runCommand(cmd []string, input *string) (string, error) { if input != nil { stdin, err := c.StdinPipe() if err != nil { - return "", err + return nil, err } go func() { defer stdin.Close() @@ -81,16 +92,19 @@ func (b *BaseCommand) runCommand(cmd []string, input *string) (string, error) { }() } - out, err := c.CombinedOutput() - if err != nil { + var stdout, stderr bytes.Buffer + c.Stdout = &stdout + c.Stderr = &stderr + + if err := c.Run(); err != nil { exitErr, _ := err.(*exec.ExitError) status, _ := exitErr.Sys().(syscall.WaitStatus) - return "", &CommandError{ + return nil, &CommandError{ ExitStatus: status.ExitStatus(), - Msg: string(out), + Msg: stderr.String(), } } - return string(out), nil + return &CommandOut{Stdout: stdout.String(), Stderr: stderr.String()}, nil } func (b *BaseCommand) AddLink(name string, linkType string, options ...string) error { @@ -200,7 +214,7 @@ func unmarshalInterfacesData(data string) (Interfaces, error) { var addresses Interfaces err := json.Unmarshal([]byte(data), &addresses) if err != nil { - return nil, err + return nil, &UnmarshalError{Msg: err.Error(), Content: data} } return addresses, nil diff --git a/iproute2/error.go b/iproute2/error.go index 87ea93e..2e89bb3 100644 --- a/iproute2/error.go +++ b/iproute2/error.go @@ -42,6 +42,15 @@ func (e *OperationNotPermittedError) Error() string { return e.Msg } +type UnmarshalError struct { + Msg string + Content string +} + +func (e *UnmarshalError) Error() string { + return fmt.Sprint(e.Msg, ": ", e.Content) +} + type UnknownError struct { Msg string } diff --git a/iproute2/iproute2.go b/iproute2/iproute2.go index e812b75..5adc7b6 100644 --- a/iproute2/iproute2.go +++ b/iproute2/iproute2.go @@ -136,7 +136,7 @@ func (i *IpCmdWithNetns) Netns() string { return i.netns } -func (i *IpCmdWithNetns) ExecuteCommand(cmd string) (string, error) { +func (i *IpCmdWithNetns) ExecuteCommand(cmd string) (*CommandOut, error) { shell := []string{"/bin/bash"} return i.runCommand(shell, &cmd) }