Get rid of dynamic errors

This commit is contained in:
Kristoffer Dalby 2021-11-15 19:18:14 +00:00
parent 25b790d025
commit d6739386a0
No known key found for this signature in database
GPG key ID: 09F62DC067465735
10 changed files with 53 additions and 22 deletions

View file

@ -30,7 +30,6 @@ linters:
# We should strive to enable these:
- wrapcheck
- goerr113
- dupl
- makezero

9
app.go
View file

@ -52,6 +52,11 @@ const (
Sqlite = "sqlite3"
updateInterval = 5000
HTTPReadTimeout = 30 * time.Second
errUnsupportedDatabase = Error("unsupported DB")
errUnsupportedLetsEncryptChallengeType = Error(
"unknown value for Lets Encrypt challenge type",
)
)
// Config contains the initial Headscale configuration.
@ -166,7 +171,7 @@ func NewHeadscale(cfg Config) (*Headscale, error) {
case Sqlite:
dbString = cfg.DBpath
default:
return nil, errors.New("unsupported DB")
return nil, errUnsupportedDatabase
}
app := Headscale{
@ -626,7 +631,7 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
return certManager.TLSConfig(), nil
default:
return nil, errors.New("unknown value for TLSLetsEncryptChallengeType")
return nil, errUnsupportedLetsEncryptChallengeType
}
} else if h.cfg.TLSCertPath == "" {
if !strings.HasPrefix(h.cfg.ServerURL, "http://") {

View file

@ -4,6 +4,7 @@ import (
"fmt"
survey "github.com/AlecAivazis/survey/v2"
"github.com/juanfont/headscale"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/pterm/pterm"
"github.com/rs/zerolog/log"
@ -19,6 +20,10 @@ func init() {
namespaceCmd.AddCommand(renameNamespaceCmd)
}
const (
errMissingParameter = headscale.Error("missing parameters")
)
var namespaceCmd = &cobra.Command{
Use: "namespaces",
Short: "Manage the namespaces of Headscale",
@ -29,7 +34,7 @@ var createNamespaceCmd = &cobra.Command{
Short: "Creates a new namespace",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("missing parameters")
return errMissingParameter
}
return nil
@ -71,7 +76,7 @@ var destroyNamespaceCmd = &cobra.Command{
Short: "Destroys a namespace",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("missing parameters")
return errMissingParameter
}
return nil
@ -197,7 +202,7 @@ var renameNamespaceCmd = &cobra.Command{
Args: func(cmd *cobra.Command, args []string) error {
expectedArguments := 2
if len(args) < expectedArguments {
return fmt.Errorf("missing parameters")
return errMissingParameter
}
return nil

View file

@ -178,7 +178,7 @@ var expirePreAuthKeyCmd = &cobra.Command{
Short: "Expire a preauthkey",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("missing parameters")
return errMissingParameter
}
return nil

View file

@ -81,6 +81,7 @@ func LoadConfig(path string) error {
errorText += "Fatal config error: server_url must start with https:// or http://\n"
}
if errorText != "" {
//nolint
return errors.New(strings.TrimSuffix(errorText, "\n"))
} else {
return nil
@ -305,6 +306,8 @@ func getHeadscaleApp() (*headscale.Headscale, error) {
// to avoid races
minInactivityTimeout, _ := time.ParseDuration("65s")
if viper.GetDuration("ephemeral_node_inactivity_timeout") <= minInactivityTimeout {
// TODO: Find a better way to return this text
//nolint
err := fmt.Errorf(
"ephemeral_node_inactivity_timeout (%s) is set too low, must be more than %s",
viper.GetString("ephemeral_node_inactivity_timeout"),

7
db.go
View file

@ -9,7 +9,10 @@ import (
"gorm.io/gorm/logger"
)
const dbVersion = "1"
const (
dbVersion = "1"
errValueNotFound = Error("not found")
)
// KV is a key-value store in a psql table. For future use...
type KV struct {
@ -92,7 +95,7 @@ func (h *Headscale) getValue(key string) (string, error) {
result.Error,
gorm.ErrRecordNotFound,
) {
return "", errors.New("not found")
return "", errValueNotFound
}
return row.Value, nil

View file

@ -20,6 +20,12 @@ import (
"tailscale.com/types/wgkey"
)
const (
errMachineNotFound = Error("machine not found")
errMachineAlreadyRegistered = Error("machine already registered")
errMachineRouteIsNotAvailable = Error("route is not available on machine")
)
// Machine is a Headscale client.
type Machine struct {
ID uint64 `gorm:"primary_key"`
@ -248,7 +254,7 @@ func (h *Headscale) GetMachine(namespace string, name string) (*Machine, error)
}
}
return nil, fmt.Errorf("machine not found")
return nil, errMachineNotFound
}
// GetMachineByID finds a Machine by ID and returns the Machine struct.
@ -615,7 +621,7 @@ func (h *Headscale) RegisterMachine(
result.Error,
gorm.ErrRecordNotFound,
) {
return nil, errors.New("Machine not found")
return nil, errMachineNotFound
}
log.Trace().
@ -624,7 +630,7 @@ func (h *Headscale) RegisterMachine(
Msg("Attempting to register machine")
if machine.isAlreadyRegistered() {
err := errors.New("Machine already registered")
err := errMachineAlreadyRegistered
log.Error().
Caller().
Err(err).
@ -740,9 +746,9 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error {
for _, newRoute := range newRoutes {
if !containsIPPrefix(availableRoutes, newRoute) {
return fmt.Errorf(
"route (%s) is not available on node %s",
"route (%s) is not available on node %s: %w",
machine.Name,
newRoute,
newRoute, errMachineRouteIsNotAvailable,
)
}
}

View file

@ -16,6 +16,7 @@ const (
errPreAuthKeyNotFound = Error("AuthKey not found")
errPreAuthKeyExpired = Error("AuthKey expired")
errSingleUseAuthKeyHasBeenUsed = Error("AuthKey has already been used")
errNamespaceMismatch = Error("namespace mismatch")
)
// PreAuthKey describes a pre-authorization key usable in a particular namespace.
@ -87,7 +88,7 @@ func (h *Headscale) GetPreAuthKey(namespace string, key string) (*PreAuthKey, er
}
if pak.Namespace.Name != namespace {
return nil, errors.New("Namespace mismatch")
return nil, errNamespaceMismatch
}
return pak, nil

View file

@ -2,12 +2,15 @@ package headscale
import (
"encoding/json"
"fmt"
"gorm.io/datatypes"
"inet.af/netaddr"
)
const (
errRouteIsNotAvailable = Error("route is not available")
)
// Deprecated: use machine function instead
// GetAdvertisedNodeRoutes returns the subnet routes advertised by a node (identified by
// namespace and node name).
@ -129,7 +132,7 @@ func (h *Headscale) EnableNodeRoute(
}
if !available {
return fmt.Errorf("route (%s) is not available on node %s", nodeName, routeStr)
return errRouteIsNotAvailable
}
routes, err := json.Marshal(enabledRoutes)

View file

@ -20,6 +20,12 @@ import (
"tailscale.com/types/wgkey"
)
const (
errCannotDecryptReponse = Error("cannot decrypt response")
errResponseMissingNonce = Error("response missing nonce")
errCouldNotAllocateIP = Error("could not find any suitable IP")
)
// Error is used to compare errors as per https://dave.cheney.net/2016/04/07/constant-errors
type Error string
@ -46,7 +52,7 @@ func decodeMsg(
}
// fmt.Println(string(decrypted))
if err := json.Unmarshal(decrypted, output); err != nil {
return fmt.Errorf("response: %w", err)
return err
}
return nil
@ -55,7 +61,7 @@ func decodeMsg(
func decryptMsg(msg []byte, pubKey *wgkey.Key, privKey *wgkey.Private) ([]byte, error) {
var nonce [24]byte
if len(msg) < len(nonce)+1 {
return nil, fmt.Errorf("response missing nonce, len=%d", len(msg))
return nil, errResponseMissingNonce
}
copy(nonce[:], msg)
msg = msg[len(nonce):]
@ -63,7 +69,7 @@ func decryptMsg(msg []byte, pubKey *wgkey.Key, privKey *wgkey.Private) ([]byte,
pub, pri := (*[32]byte)(pubKey), (*[32]byte)(privKey)
decrypted, ok := box.Open(nil, msg, &nonce, pub, pri)
if !ok {
return nil, fmt.Errorf("cannot decrypt response")
return nil, errCannotDecryptReponse
}
return decrypted, nil
@ -106,7 +112,7 @@ func (h *Headscale) getAvailableIP() (*netaddr.IP, error) {
for {
if !ipPrefix.Contains(ip) {
return nil, fmt.Errorf("could not find any suitable IP in %s", ipPrefix)
return nil, errCouldNotAllocateIP
}
// Some OS (including Linux) does not like when IPs ends with 0 or 255, which
@ -143,7 +149,7 @@ func (h *Headscale) getUsedIPs() ([]netaddr.IP, error) {
if addr != "" {
ip, err := netaddr.ParseIP(addr)
if err != nil {
return nil, fmt.Errorf("failed to parse ip from database, %w", err)
return nil, fmt.Errorf("failed to parse ip from database: %w", err)
}
ips[index] = ip