Maint: move OpenVPN streams processing to config package
This commit is contained in:
60
internal/openvpn/config/logs.go
Normal file
60
internal/openvpn/config/logs.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
func processLogLine(s string) (filtered string, level logging.Level) {
|
||||
for _, ignored := range []string{
|
||||
"WARNING: you are using user/group/chroot/setcon without persist-tun -- this may cause restarts to fail",
|
||||
"NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay",
|
||||
} {
|
||||
if s == ignored {
|
||||
return "", logging.LevelDebug
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case strings.HasPrefix(s, "NOTE: "):
|
||||
filtered = strings.TrimPrefix(s, "NOTE: ")
|
||||
level = logging.LevelInfo
|
||||
case strings.HasPrefix(s, "WARNING: "):
|
||||
filtered = strings.TrimPrefix(s, "WARNING: ")
|
||||
level = logging.LevelWarn
|
||||
case strings.HasPrefix(s, "Options error: "):
|
||||
filtered = strings.TrimPrefix(s, "Options error: ")
|
||||
level = logging.LevelError
|
||||
case s == "Initialization Sequence Completed":
|
||||
return color.HiGreenString(s), logging.LevelInfo
|
||||
case s == "AUTH: Received control message: AUTH_FAILED":
|
||||
filtered = s + `
|
||||
|
||||
Your credentials might be wrong 🤨
|
||||
|
||||
`
|
||||
level = logging.LevelError
|
||||
case strings.Contains(s, "TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)"): //nolint:lll
|
||||
filtered = s + `
|
||||
🚒🚒🚒🚒🚒🚨🚨🚨🚨🚨🚨🚒🚒🚒🚒🚒
|
||||
That error usually happens because either:
|
||||
|
||||
1. The VPN server IP address you are trying to connect to is no longer valid 🔌
|
||||
Update your server information using https://github.com/qdm12/gluetun/wiki/Updating-Servers
|
||||
|
||||
2. The VPN server crashed 💥, try changing your VPN servers filtering options such as REGION
|
||||
|
||||
3. Your Internet connection is not working 🤯, ensure it works
|
||||
|
||||
4. Something else ➡️ https://github.com/qdm12/gluetun/issues/new/choose
|
||||
`
|
||||
level = logging.LevelWarn
|
||||
default:
|
||||
filtered = s
|
||||
level = logging.LevelInfo
|
||||
}
|
||||
filtered = constants.ColorOpenvpn().Sprintf(filtered)
|
||||
return filtered, level
|
||||
}
|
||||
57
internal/openvpn/config/logs_test.go
Normal file
57
internal/openvpn/config/logs_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/qdm12/golibs/logging"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_processLogLine(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := map[string]struct {
|
||||
s string
|
||||
filtered string
|
||||
level logging.Level
|
||||
}{
|
||||
"empty string": {"", "", logging.LevelInfo},
|
||||
"random string": {"asdasqdb", "asdasqdb", logging.LevelInfo},
|
||||
"openvpn unknown": {
|
||||
"message",
|
||||
"message",
|
||||
logging.LevelInfo},
|
||||
"openvpn note": {
|
||||
"NOTE: message",
|
||||
"message",
|
||||
logging.LevelInfo},
|
||||
"openvpn warning": {
|
||||
"WARNING: message",
|
||||
"message",
|
||||
logging.LevelWarn},
|
||||
"openvpn options error": {
|
||||
"Options error: message",
|
||||
"message",
|
||||
logging.LevelError},
|
||||
"openvpn ignored message": {
|
||||
"NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay",
|
||||
"",
|
||||
logging.LevelDebug},
|
||||
"openvpn success": {
|
||||
"Initialization Sequence Completed",
|
||||
"Initialization Sequence Completed",
|
||||
logging.LevelInfo},
|
||||
"openvpn auth failed": {
|
||||
"AUTH: Received control message: AUTH_FAILED",
|
||||
"AUTH: Received control message: AUTH_FAILED\n\nYour credentials might be wrong 🤨\n\n",
|
||||
logging.LevelError},
|
||||
}
|
||||
for name, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
filtered, level := processLogLine(tc.s)
|
||||
assert.Equal(t, tc.filtered, filtered)
|
||||
assert.Equal(t, tc.level, level)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,12 @@ import (
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
var _ Interface = (*Configurator)(nil)
|
||||
|
||||
type Interface interface {
|
||||
VersionGetter
|
||||
AuthWriter
|
||||
Starter
|
||||
Runner
|
||||
Writer
|
||||
}
|
||||
|
||||
|
||||
41
internal/openvpn/config/run.go
Normal file
41
internal/openvpn/config/run.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
type Runner interface {
|
||||
Run(ctx context.Context, errCh chan<- error, ready chan<- struct{},
|
||||
logger logging.Logger, settings configuration.OpenVPN)
|
||||
}
|
||||
|
||||
func (c *Configurator) Run(ctx context.Context, errCh chan<- error,
|
||||
ready chan<- struct{}, logger logging.Logger, settings configuration.OpenVPN) {
|
||||
stdoutLines, stderrLines, waitError, err := c.start(ctx, settings.Version, settings.Flags)
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
streamCtx, streamCancel := context.WithCancel(context.Background())
|
||||
streamDone := make(chan struct{})
|
||||
go streamLines(streamCtx, streamDone, logger,
|
||||
stdoutLines, stderrLines, ready)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
<-waitError
|
||||
close(waitError)
|
||||
streamCancel()
|
||||
<-streamDone
|
||||
errCh <- ctx.Err()
|
||||
case err := <-waitError:
|
||||
close(waitError)
|
||||
streamCancel()
|
||||
<-streamDone
|
||||
errCh <- err
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,7 @@ const (
|
||||
binOpenvpn25 = "openvpn"
|
||||
)
|
||||
|
||||
type Starter interface {
|
||||
Start(ctx context.Context, version string, flags []string) (
|
||||
stdoutLines, stderrLines chan string, waitError chan error, err error)
|
||||
}
|
||||
|
||||
func (c *Configurator) Start(ctx context.Context, version string, flags []string) (
|
||||
func (c *Configurator) start(ctx context.Context, version string, flags []string) (
|
||||
stdoutLines, stderrLines chan string, waitError chan error, err error) {
|
||||
var bin string
|
||||
switch version {
|
||||
|
||||
53
internal/openvpn/config/stream.go
Normal file
53
internal/openvpn/config/stream.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
func streamLines(ctx context.Context, done chan<- struct{},
|
||||
logger logging.Logger, stdout, stderr chan string,
|
||||
tunnelReady chan<- struct{}) {
|
||||
defer close(done)
|
||||
|
||||
var line string
|
||||
|
||||
for {
|
||||
errLine := false
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Context should only be canceled after stdout and stderr are done
|
||||
// being written to.
|
||||
close(stdout)
|
||||
close(stderr)
|
||||
return
|
||||
case line = <-stdout:
|
||||
case line = <-stderr:
|
||||
errLine = true
|
||||
}
|
||||
line, level := processLogLine(line)
|
||||
if line == "" {
|
||||
continue // filtered out
|
||||
}
|
||||
if errLine {
|
||||
level = logging.LevelError
|
||||
}
|
||||
switch level {
|
||||
case logging.LevelDebug:
|
||||
logger.Debug(line)
|
||||
case logging.LevelInfo:
|
||||
logger.Info(line)
|
||||
case logging.LevelWarn:
|
||||
logger.Warn(line)
|
||||
case logging.LevelError:
|
||||
logger.Error(line)
|
||||
}
|
||||
if strings.Contains(line, "Initialization Sequence Completed") {
|
||||
// do not close tunnelReady in case the initialization
|
||||
// happens multiple times without Openvpn restarting
|
||||
tunnelReady <- struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user