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:
Quentin McGaw
2026-05-02 00:50:16 +00:00
parent 9b6f048fe8
commit 4a78989d9d
172 changed files with 666 additions and 1433 deletions
+4 -3
View File
@@ -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
}
+1 -1
View File
@@ -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{
+2 -1
View File
@@ -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{
+3 -10
View File
@@ -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)
+19 -41
View File
@@ -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
+3 -20
View File
@@ -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)
}
})
}