mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-24 18:45:24 +00:00
Get rid of dynamic errors
This commit is contained in:
parent
25b790d025
commit
d6739386a0
@ -30,7 +30,6 @@ linters:
|
||||
|
||||
# We should strive to enable these:
|
||||
- wrapcheck
|
||||
- goerr113
|
||||
- dupl
|
||||
- makezero
|
||||
|
||||
|
9
app.go
9
app.go
@ -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://") {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
7
db.go
@ -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
|
||||
|
16
machine.go
16
machine.go
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
16
utils.go
16
utils.go
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user