Merge pull request #597 from kradalby/db-error-handling

This commit is contained in:
Kristoffer Dalby 2022-06-03 10:23:21 +02:00 committed by GitHub
commit 19b6405332
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 18 deletions

13
api.go
View file

@ -474,7 +474,16 @@ func (h *Headscale) handleMachineRefreshKey(
Str("machine", machine.Hostname). Str("machine", machine.Hostname).
Msg("We have the OldNodeKey in the database. This is a key refresh") Msg("We have the OldNodeKey in the database. This is a key refresh")
machine.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) machine.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey)
h.db.Save(&machine)
if err := h.db.Save(&machine).Error; err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to update machine key in the database")
ctx.String(http.StatusInternalServerError, "Internal server error")
return
}
resp.AuthURL = "" resp.AuthURL = ""
resp.User = *machine.Namespace.toUser() resp.User = *machine.Namespace.toUser()
@ -484,7 +493,7 @@ func (h *Headscale) handleMachineRefreshKey(
Caller(). Caller().
Err(err). Err(err).
Msg("Cannot encode message") Msg("Cannot encode message")
ctx.String(http.StatusInternalServerError, "Extremely sad!") ctx.String(http.StatusInternalServerError, "Internal server error")
return return
} }

View file

@ -57,7 +57,10 @@ func (h *Headscale) CreateAPIKey(
Hash: hash, Hash: hash,
Expiration: expiration, Expiration: expiration,
} }
h.db.Save(&key)
if err := h.db.Save(&key).Error; err != nil {
return "", nil, fmt.Errorf("failed to save API key to database: %w", err)
}
return keyStr, &key, nil return keyStr, &key, nil
} }

4
db.go
View file

@ -214,7 +214,9 @@ func (h *Headscale) setValue(key string, value string) error {
return nil return nil
} }
h.db.Create(keyValue) if err := h.db.Create(keyValue).Error; err != nil {
return fmt.Errorf("failed to create key value pair in the database: %w", err)
}
return nil return nil
} }

View file

@ -60,7 +60,7 @@ func (s *IntegrationCLITestSuite) SetupTest() {
} }
headscaleOptions := &dockertest.RunOptions{ headscaleOptions := &dockertest.RunOptions{
Name: "headscale", Name: "headscale-cli",
Mounts: []string{ Mounts: []string{
fmt.Sprintf("%s/integration_test/etc:/etc/headscale", currentPath), fmt.Sprintf("%s/integration_test/etc:/etc/headscale", currentPath),
}, },

View file

@ -378,19 +378,26 @@ func (h *Headscale) SetTags(machine *Machine, tags []string) error {
return err return err
} }
h.setLastStateChangeToNow(machine.Namespace.Name) h.setLastStateChangeToNow(machine.Namespace.Name)
h.db.Save(machine)
if err := h.db.Save(machine).Error; err != nil {
return fmt.Errorf("failed to update tags for machine in the database: %w", err)
}
return nil return nil
} }
// ExpireMachine takes a Machine struct and sets the expire field to now. // ExpireMachine takes a Machine struct and sets the expire field to now.
func (h *Headscale) ExpireMachine(machine *Machine) { func (h *Headscale) ExpireMachine(machine *Machine) error {
now := time.Now() now := time.Now()
machine.Expiry = &now machine.Expiry = &now
h.setLastStateChangeToNow(machine.Namespace.Name) h.setLastStateChangeToNow(machine.Namespace.Name)
h.db.Save(machine) if err := h.db.Save(machine).Error; err != nil {
return fmt.Errorf("failed to expire machine in the database: %w", err)
}
return nil
} }
// RenameMachine takes a Machine struct and a new GivenName for the machines // RenameMachine takes a Machine struct and a new GivenName for the machines
@ -413,13 +420,15 @@ func (h *Headscale) RenameMachine(machine *Machine, newName string) error {
h.setLastStateChangeToNow(machine.Namespace.Name) h.setLastStateChangeToNow(machine.Namespace.Name)
h.db.Save(machine) if err := h.db.Save(machine).Error; err != nil {
return fmt.Errorf("failed to rename machine in the database: %w", err)
}
return nil return nil
} }
// RefreshMachine takes a Machine struct and sets the expire field to now. // RefreshMachine takes a Machine struct and sets the expire field to now.
func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) { func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) error {
now := time.Now() now := time.Now()
machine.LastSuccessfulUpdate = &now machine.LastSuccessfulUpdate = &now
@ -427,7 +436,14 @@ func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) {
h.setLastStateChangeToNow(machine.Namespace.Name) h.setLastStateChangeToNow(machine.Namespace.Name)
h.db.Save(machine) if err := h.db.Save(machine).Error; err != nil {
return fmt.Errorf(
"failed to refresh machine (update expiration) in the database: %w",
err,
)
}
return nil
} }
// DeleteMachine softs deletes a Machine from the database. // DeleteMachine softs deletes a Machine from the database.
@ -793,7 +809,9 @@ func (h *Headscale) RegisterMachine(machine Machine,
machine.IPAddresses = ips machine.IPAddresses = ips
h.db.Save(&machine) if err := h.db.Save(&machine).Error; err != nil {
return nil, fmt.Errorf("failed register(save) machine in the database: %w", err)
}
log.Trace(). log.Trace().
Caller(). Caller().
@ -853,7 +871,10 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error {
} }
machine.EnabledRoutes = newRoutes machine.EnabledRoutes = newRoutes
h.db.Save(&machine)
if err := h.db.Save(machine).Error; err != nil {
return fmt.Errorf("failed enable routes for machine in the database: %w", err)
}
return nil return nil
} }

15
poll.go
View file

@ -115,7 +115,20 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) {
machine.Endpoints = req.Endpoints machine.Endpoints = req.Endpoints
machine.LastSeen = &now machine.LastSeen = &now
} }
h.db.Updates(machine)
if err := h.db.Updates(machine).Error; err != nil {
if err != nil {
log.Error().
Str("handler", "PollNetMap").
Str("id", ctx.Param("id")).
Str("machine", machine.Hostname).
Err(err).
Msg("Failed to persist/update machine in the database")
ctx.String(http.StatusInternalServerError, ":(")
return
}
}
data, err := h.getMapResponse(machineKey, req, machine) data, err := h.getMapResponse(machineKey, req, machine)
if err != nil { if err != nil {

View file

@ -4,6 +4,7 @@ import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt"
"strconv" "strconv"
"time" "time"
@ -60,7 +61,10 @@ func (h *Headscale) CreatePreAuthKey(
CreatedAt: &now, CreatedAt: &now,
Expiration: expiration, Expiration: expiration,
} }
h.db.Save(&key)
if err := h.db.Save(&key).Error; err != nil {
return nil, fmt.Errorf("failed to create key in the database: %w", err)
}
return &key, nil return &key, nil
} }
@ -114,9 +118,13 @@ func (h *Headscale) ExpirePreAuthKey(k *PreAuthKey) error {
} }
// UsePreAuthKey marks a PreAuthKey as used. // UsePreAuthKey marks a PreAuthKey as used.
func (h *Headscale) UsePreAuthKey(k *PreAuthKey) { func (h *Headscale) UsePreAuthKey(k *PreAuthKey) error {
k.Used = true k.Used = true
h.db.Save(k) if err := h.db.Save(k).Error; err != nil {
return fmt.Errorf("failed to update key used status in the database: %w", err)
}
return nil
} }
// checkKeyValidity does the heavy lifting for validation of the PreAuthKey coming from a node // checkKeyValidity does the heavy lifting for validation of the PreAuthKey coming from a node

View file

@ -1,6 +1,8 @@
package headscale package headscale
import ( import (
"fmt"
"inet.af/netaddr" "inet.af/netaddr"
) )
@ -108,7 +110,10 @@ func (h *Headscale) EnableNodeRoute(
} }
machine.EnabledRoutes = enabledRoutes machine.EnabledRoutes = enabledRoutes
h.db.Save(&machine)
if err := h.db.Save(&machine).Error; err != nil {
return fmt.Errorf("failed to update node routes in the database: %w", err)
}
return nil return nil
} }