mirror of
https://github.com/qdm12/gluetun.git
synced 2026-05-09 20:29:23 +02:00
chore: do not use sentinel errors when unneeded
- main reason being it's a burden to always define sentinel errors at global scope, wrap them with `%w` instead of using a string directly - only use sentinel errors when it has to be checked using `errors.Is` - replace all usage of these sentinel errors in `fmt.Errorf` with direct strings that were in the sentinel error - exclude the sentinel error definition requirement from .golangci.yml - update unit tests to use ContainersError instead of ErrorIs so it stays as a "not a change detector test" without requiring a sentinel error
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package wireguard
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
@@ -27,19 +28,19 @@ func ConfigureDevice(client *wgctrl.Client, settings Settings) (err error) {
|
||||
func makeDeviceConfig(settings Settings) (config wgtypes.Config, err error) {
|
||||
privateKey, err := wgtypes.ParseKey(settings.PrivateKey)
|
||||
if err != nil {
|
||||
return config, ErrPrivateKeyInvalid
|
||||
return config, errors.New("cannot parse private key")
|
||||
}
|
||||
|
||||
publicKey, err := wgtypes.ParseKey(settings.PublicKey)
|
||||
if err != nil {
|
||||
return config, fmt.Errorf("%w: %s", ErrPublicKeyInvalid, settings.PublicKey)
|
||||
return config, fmt.Errorf("cannot parse public key: %s", settings.PublicKey)
|
||||
}
|
||||
|
||||
var preSharedKey *wgtypes.Key
|
||||
if settings.PreSharedKey != "" {
|
||||
preSharedKeyValue, err := wgtypes.ParseKey(settings.PreSharedKey)
|
||||
if err != nil {
|
||||
return config, ErrPreSharedKeyInvalid
|
||||
return config, errors.New("cannot parse pre-shared key")
|
||||
}
|
||||
preSharedKey = &preSharedKeyValue
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func Test_makeDeviceConfig(t *testing.T) {
|
||||
settings: Settings{
|
||||
PrivateKey: "bad key",
|
||||
},
|
||||
err: ErrPrivateKeyInvalid,
|
||||
err: errors.New("cannot parse private key"),
|
||||
},
|
||||
"bad public key": {
|
||||
settings: Settings{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package wireguard
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
@@ -25,7 +26,7 @@ func Test_New(t *testing.T) {
|
||||
settings: Settings{
|
||||
PrivateKey: "",
|
||||
},
|
||||
err: ErrPrivateKeyMissing,
|
||||
err: errors.New("private key is missing"),
|
||||
},
|
||||
"minimal valid settings": {
|
||||
settings: Settings{
|
||||
|
||||
@@ -14,12 +14,6 @@ import (
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
)
|
||||
|
||||
var (
|
||||
errKernelSupport = errors.New("kernel does not support Wireguard")
|
||||
errTunNameMismatch = errors.New("TUN device name is mismatching")
|
||||
errDeviceWaited = errors.New("device waited for")
|
||||
)
|
||||
|
||||
// Run runs the wireguard interface and waits until the context is done, then it cleans up the
|
||||
// interface and returns any error that occurred during setup or waiting. It sends an error to
|
||||
// waitError if any error occurs during setup or waiting, otherwise it sends nil when the context
|
||||
@@ -44,7 +38,7 @@ func (w *Wireguard) Run(ctx context.Context, waitError chan<- error, ready chan<
|
||||
case "userspace":
|
||||
case "kernelspace":
|
||||
if !kernelSupported {
|
||||
waitError <- fmt.Errorf("%w", errKernelSupport)
|
||||
waitError <- errors.New("kernel does not support Wireguard")
|
||||
return
|
||||
}
|
||||
setupFunction = setupKernelSpace
|
||||
@@ -199,8 +193,7 @@ func setupUserSpace(ctx context.Context,
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("getting created TUN device name: %w", err)
|
||||
} else if tunName != interfaceName {
|
||||
return 0, nil, fmt.Errorf("%w: expected %q and got %q",
|
||||
errTunNameMismatch, interfaceName, tunName)
|
||||
return 0, nil, fmt.Errorf("TUN device name is mismatching: expected %q and got %q", interfaceName, tunName)
|
||||
}
|
||||
|
||||
link, err := netLinker.LinkByName(interfaceName)
|
||||
@@ -247,7 +240,7 @@ func setupUserSpace(ctx context.Context,
|
||||
case err = <-uapiAcceptErrorCh:
|
||||
close(uapiAcceptErrorCh)
|
||||
case <-device.Wait():
|
||||
err = errDeviceWaited
|
||||
err = errors.New("device waited for")
|
||||
}
|
||||
|
||||
cleanups.Cleanup(logger)
|
||||
|
||||
@@ -88,99 +88,77 @@ func (s *Settings) SetDefaults() {
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInterfaceNameInvalid = errors.New("invalid interface name")
|
||||
ErrPrivateKeyMissing = errors.New("private key is missing")
|
||||
ErrPrivateKeyInvalid = errors.New("cannot parse private key")
|
||||
ErrPublicKeyMissing = errors.New("public key is missing")
|
||||
ErrPublicKeyInvalid = errors.New("cannot parse public key")
|
||||
ErrPreSharedKeyInvalid = errors.New("cannot parse pre-shared key")
|
||||
ErrEndpointAddrMissing = errors.New("endpoint address is missing")
|
||||
ErrEndpointPortMissing = errors.New("endpoint port is missing")
|
||||
ErrAddressMissing = errors.New("interface address is missing")
|
||||
ErrAddressNotValid = errors.New("interface address is not valid")
|
||||
ErrAllowedIPsMissing = errors.New("allowed IPs are missing")
|
||||
ErrAllowedIPNotValid = errors.New("allowed IP is not valid")
|
||||
ErrAllowedIPv6NotSupported = errors.New("allowed IPv6 address not supported")
|
||||
ErrKeepaliveIsNegative = errors.New("keep alive interval is negative")
|
||||
ErrFirewallMarkMissing = errors.New("firewall mark is missing")
|
||||
ErrMTUMissing = errors.New("MTU is missing")
|
||||
ErrImplementationInvalid = errors.New("invalid implementation")
|
||||
)
|
||||
|
||||
var interfaceNameRegexp = regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
|
||||
|
||||
func (s *Settings) Check() (err error) {
|
||||
if !interfaceNameRegexp.MatchString(s.InterfaceName) {
|
||||
return fmt.Errorf("%w: %s", ErrInterfaceNameInvalid, s.InterfaceName)
|
||||
return fmt.Errorf("invalid interface name: %s", s.InterfaceName)
|
||||
}
|
||||
|
||||
if s.PrivateKey == "" {
|
||||
return fmt.Errorf("%w", ErrPrivateKeyMissing)
|
||||
return errors.New("private key is missing")
|
||||
} else if _, err := wgtypes.ParseKey(s.PrivateKey); err != nil {
|
||||
return fmt.Errorf("%w", ErrPrivateKeyInvalid)
|
||||
return errors.New("cannot parse private key")
|
||||
}
|
||||
|
||||
if s.PublicKey == "" {
|
||||
return fmt.Errorf("%w", ErrPublicKeyMissing)
|
||||
return errors.New("public key is missing")
|
||||
} else if _, err := wgtypes.ParseKey(s.PublicKey); err != nil {
|
||||
return fmt.Errorf("%w: %s", ErrPublicKeyInvalid, s.PublicKey)
|
||||
return fmt.Errorf("cannot parse public key: %s", s.PublicKey)
|
||||
}
|
||||
|
||||
if s.PreSharedKey != "" {
|
||||
if _, err := wgtypes.ParseKey(s.PreSharedKey); err != nil {
|
||||
return fmt.Errorf("%w", ErrPreSharedKeyInvalid)
|
||||
return errors.New("cannot parse pre-shared key")
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case !s.Endpoint.Addr().IsValid():
|
||||
return fmt.Errorf("%w", ErrEndpointAddrMissing)
|
||||
return errors.New("endpoint address is missing")
|
||||
case s.Endpoint.Port() == 0:
|
||||
return fmt.Errorf("%w", ErrEndpointPortMissing)
|
||||
return errors.New("endpoint port is missing")
|
||||
}
|
||||
|
||||
if len(s.Addresses) == 0 {
|
||||
return fmt.Errorf("%w", ErrAddressMissing)
|
||||
return errors.New("interface address is missing")
|
||||
}
|
||||
for i, addr := range s.Addresses {
|
||||
if !addr.IsValid() {
|
||||
return fmt.Errorf("%w: for address %d of %d",
|
||||
ErrAddressNotValid, i+1, len(s.Addresses))
|
||||
return fmt.Errorf("interface address is not valid: for address %d of %d",
|
||||
i+1, len(s.Addresses))
|
||||
}
|
||||
}
|
||||
|
||||
if len(s.AllowedIPs) == 0 {
|
||||
return fmt.Errorf("%w", ErrAllowedIPsMissing)
|
||||
return errors.New("allowed IPs are missing")
|
||||
}
|
||||
for i, allowedIP := range s.AllowedIPs {
|
||||
switch {
|
||||
case !allowedIP.IsValid():
|
||||
return fmt.Errorf("%w: for allowed IP %d of %d",
|
||||
ErrAllowedIPNotValid, i+1, len(s.AllowedIPs))
|
||||
return fmt.Errorf("allowed IP is not valid: for allowed IP %d of %d",
|
||||
i+1, len(s.AllowedIPs))
|
||||
case allowedIP.Addr().Is6() && !*s.IPv6:
|
||||
return fmt.Errorf("%w: for allowed IP %s",
|
||||
ErrAllowedIPv6NotSupported, allowedIP)
|
||||
return fmt.Errorf("allowed IPv6 address not supported: for allowed IP %s", allowedIP)
|
||||
}
|
||||
}
|
||||
|
||||
if s.PersistentKeepaliveInterval < 0 {
|
||||
return fmt.Errorf("%w: %s", ErrKeepaliveIsNegative,
|
||||
s.PersistentKeepaliveInterval)
|
||||
return fmt.Errorf("keep alive interval is negative: %s", s.PersistentKeepaliveInterval)
|
||||
}
|
||||
|
||||
if s.FirewallMark == 0 {
|
||||
return fmt.Errorf("%w", ErrFirewallMarkMissing)
|
||||
return errors.New("firewall mark is missing")
|
||||
}
|
||||
|
||||
if s.MTU == 0 {
|
||||
return fmt.Errorf("%w", ErrMTUMissing)
|
||||
return errors.New("MTU is missing")
|
||||
}
|
||||
|
||||
switch s.Implementation {
|
||||
case "auto", "kernelspace", "userspace":
|
||||
default:
|
||||
return fmt.Errorf("%w: %s", ErrImplementationInvalid, s.Implementation)
|
||||
return fmt.Errorf("invalid implementation: %s", s.Implementation)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -84,25 +84,21 @@ func Test_Settings_Check(t *testing.T) {
|
||||
|
||||
testCases := map[string]struct {
|
||||
settings Settings
|
||||
errWrapped error
|
||||
errMessage string
|
||||
}{
|
||||
"empty settings": {
|
||||
errWrapped: ErrInterfaceNameInvalid,
|
||||
errMessage: "invalid interface name: ",
|
||||
},
|
||||
"bad interface name": {
|
||||
settings: Settings{
|
||||
InterfaceName: "$H1T",
|
||||
},
|
||||
errWrapped: ErrInterfaceNameInvalid,
|
||||
errMessage: "invalid interface name: $H1T",
|
||||
},
|
||||
"empty private key": {
|
||||
settings: Settings{
|
||||
InterfaceName: "wg0",
|
||||
},
|
||||
errWrapped: ErrPrivateKeyMissing,
|
||||
errMessage: "private key is missing",
|
||||
},
|
||||
"bad private key": {
|
||||
@@ -110,7 +106,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
InterfaceName: "wg0",
|
||||
PrivateKey: "bad key",
|
||||
},
|
||||
errWrapped: ErrPrivateKeyInvalid,
|
||||
errMessage: "cannot parse private key",
|
||||
},
|
||||
"empty public key": {
|
||||
@@ -118,7 +113,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
InterfaceName: "wg0",
|
||||
PrivateKey: validKey1,
|
||||
},
|
||||
errWrapped: ErrPublicKeyMissing,
|
||||
errMessage: "public key is missing",
|
||||
},
|
||||
"bad public key": {
|
||||
@@ -127,7 +121,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
PrivateKey: validKey1,
|
||||
PublicKey: "bad key",
|
||||
},
|
||||
errWrapped: ErrPublicKeyInvalid,
|
||||
errMessage: "cannot parse public key: bad key",
|
||||
},
|
||||
"bad preshared key": {
|
||||
@@ -137,7 +130,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
PublicKey: validKey2,
|
||||
PreSharedKey: "bad key",
|
||||
},
|
||||
errWrapped: ErrPreSharedKeyInvalid,
|
||||
errMessage: "cannot parse pre-shared key",
|
||||
},
|
||||
"invalid endpoint address": {
|
||||
@@ -146,7 +138,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
PrivateKey: validKey1,
|
||||
PublicKey: validKey2,
|
||||
},
|
||||
errWrapped: ErrEndpointAddrMissing,
|
||||
errMessage: "endpoint address is missing",
|
||||
},
|
||||
"zero endpoint port": {
|
||||
@@ -156,7 +147,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
PublicKey: validKey2,
|
||||
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 0),
|
||||
},
|
||||
errWrapped: ErrEndpointPortMissing,
|
||||
errMessage: "endpoint port is missing",
|
||||
},
|
||||
"no address": {
|
||||
@@ -166,7 +156,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
PublicKey: validKey2,
|
||||
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
||||
},
|
||||
errWrapped: ErrAddressMissing,
|
||||
errMessage: "interface address is missing",
|
||||
},
|
||||
"invalid address": {
|
||||
@@ -177,7 +166,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
||||
Addresses: []netip.Prefix{{}},
|
||||
},
|
||||
errWrapped: ErrAddressNotValid,
|
||||
errMessage: "interface address is not valid: for address 1 of 1",
|
||||
},
|
||||
|
||||
@@ -191,7 +179,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
netip.PrefixFrom(netip.AddrFrom4([4]byte{5, 6, 7, 8}), 24),
|
||||
},
|
||||
},
|
||||
errWrapped: ErrAllowedIPsMissing,
|
||||
errMessage: "allowed IPs are missing",
|
||||
},
|
||||
"invalid allowed IP": {
|
||||
@@ -205,7 +192,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
},
|
||||
AllowedIPs: []netip.Prefix{{}},
|
||||
},
|
||||
errWrapped: ErrAllowedIPNotValid,
|
||||
errMessage: "allowed IP is not valid: for allowed IP 1 of 1",
|
||||
},
|
||||
"ipv6 allowed IP": {
|
||||
@@ -222,7 +208,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
},
|
||||
IPv6: ptrTo(false),
|
||||
},
|
||||
errWrapped: ErrAllowedIPv6NotSupported,
|
||||
errMessage: "allowed IPv6 address not supported: for allowed IP ::/0",
|
||||
},
|
||||
"zero firewall mark": {
|
||||
@@ -236,7 +221,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
||||
},
|
||||
},
|
||||
errWrapped: ErrFirewallMarkMissing,
|
||||
errMessage: "firewall mark is missing",
|
||||
},
|
||||
"missing_MTU": {
|
||||
@@ -251,7 +235,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
},
|
||||
FirewallMark: 999,
|
||||
},
|
||||
errWrapped: ErrMTUMissing,
|
||||
errMessage: "MTU is missing",
|
||||
},
|
||||
"invalid implementation": {
|
||||
@@ -268,7 +251,6 @@ func Test_Settings_Check(t *testing.T) {
|
||||
MTU: 1420,
|
||||
Implementation: "x",
|
||||
},
|
||||
errWrapped: ErrImplementationInvalid,
|
||||
errMessage: "invalid implementation: x",
|
||||
},
|
||||
"all valid": {
|
||||
@@ -297,9 +279,10 @@ func Test_Settings_Check(t *testing.T) {
|
||||
|
||||
err := testCase.settings.Check()
|
||||
|
||||
assert.ErrorIs(t, err, testCase.errWrapped)
|
||||
if testCase.errWrapped != nil {
|
||||
if testCase.errMessage != "" {
|
||||
assert.EqualError(t, err, testCase.errMessage)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user