mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-26 17:03:06 +00:00
Merge branch 'magic-dns-support' of https://github.com/juanfont/headscale into magic-dns-support
This commit is contained in:
commit
9a0c9768ad
9 changed files with 125 additions and 170 deletions
36
.github/workflows/build.yml
vendored
Normal file
36
.github/workflows/build.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: "1.16.3"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
go version
|
||||||
|
go install golang.org/x/lint/golint@latest
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y make
|
||||||
|
|
||||||
|
- name: Run lint
|
||||||
|
run: make build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: headscale-linux
|
||||||
|
path: headscale
|
2
api.go
2
api.go
|
@ -282,7 +282,7 @@ func (h *Headscale) getMapResponse(mKey wgkey.Key, req tailcfg.MapRequest, m *Ma
|
||||||
log.Trace().
|
log.Trace().
|
||||||
Str("func", "getMapResponse").
|
Str("func", "getMapResponse").
|
||||||
Str("machine", req.Hostinfo.Hostname).
|
Str("machine", req.Hostinfo.Hostname).
|
||||||
Interface("payload", resp).
|
// Interface("payload", resp).
|
||||||
Msgf("Generated map response: %s", tailMapResponseToString(resp))
|
Msgf("Generated map response: %s", tailMapResponseToString(resp))
|
||||||
|
|
||||||
var respBody []byte
|
var respBody []byte
|
||||||
|
|
35
app.go
35
app.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -67,9 +68,6 @@ type Headscale struct {
|
||||||
aclPolicy *ACLPolicy
|
aclPolicy *ACLPolicy
|
||||||
aclRules *[]tailcfg.FilterRule
|
aclRules *[]tailcfg.FilterRule
|
||||||
|
|
||||||
clientsUpdateChannels sync.Map
|
|
||||||
clientsUpdateChannelMutex sync.Mutex
|
|
||||||
|
|
||||||
lastStateChange sync.Map
|
lastStateChange sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,10 +156,9 @@ func (h *Headscale) expireEphemeralNodesWorker() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Str("machine", m.Name).Msg("🤮 Cannot delete ephemeral machine from the database")
|
log.Error().Err(err).Str("machine", m.Name).Msg("🤮 Cannot delete ephemeral machine from the database")
|
||||||
}
|
}
|
||||||
updateRequestsFromNode.WithLabelValues("ephemeral-node-update").Inc()
|
|
||||||
h.notifyChangesToPeers(&m)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
h.setLastStateChangeToNow(ns.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,14 +261,28 @@ func (h *Headscale) setLastStateChangeToNow(namespace string) {
|
||||||
h.lastStateChange.Store(namespace, now)
|
h.lastStateChange.Store(namespace, now)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Headscale) getLastStateChange(namespace string) time.Time {
|
func (h *Headscale) getLastStateChange(namespaces ...string) time.Time {
|
||||||
if wrapped, ok := h.lastStateChange.Load(namespace); ok {
|
times := []time.Time{}
|
||||||
lastChange, _ := wrapped.(time.Time)
|
|
||||||
return lastChange
|
for _, namespace := range namespaces {
|
||||||
|
if wrapped, ok := h.lastStateChange.Load(namespace); ok {
|
||||||
|
lastChange, _ := wrapped.(time.Time)
|
||||||
|
|
||||||
|
times = append(times, lastChange)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UTC()
|
sort.Slice(times, func(i, j int) bool {
|
||||||
h.lastStateChange.Store(namespace, now)
|
return times[i].After(times[j])
|
||||||
return now
|
})
|
||||||
|
|
||||||
|
log.Trace().Msgf("Latest times %#v", times)
|
||||||
|
|
||||||
|
if len(times) == 0 {
|
||||||
|
return time.Now().UTC()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return times[0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -10,6 +10,7 @@ require (
|
||||||
github.com/docker/cli v20.10.8+incompatible // indirect
|
github.com/docker/cli v20.10.8+incompatible // indirect
|
||||||
github.com/docker/docker v20.10.8+incompatible // indirect
|
github.com/docker/docker v20.10.8+incompatible // indirect
|
||||||
github.com/efekarakus/termcolor v1.0.1
|
github.com/efekarakus/termcolor v1.0.1
|
||||||
|
github.com/fatih/set v0.2.1 // indirect
|
||||||
github.com/gin-gonic/gin v1.7.4
|
github.com/gin-gonic/gin v1.7.4
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible
|
github.com/gofrs/uuid v4.0.0+incompatible
|
||||||
github.com/google/go-github v17.0.0+incompatible // indirect
|
github.com/google/go-github v17.0.0+incompatible // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -204,6 +204,8 @@ github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:Pjfxu
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||||
|
github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
|
||||||
|
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||||
|
|
135
machine.go
135
machine.go
|
@ -2,13 +2,13 @@ package headscale
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/set"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
|
@ -66,7 +66,7 @@ func (h *Headscale) getDirectPeers(m *Machine) (Machines, error) {
|
||||||
if err := h.db.Preload("Namespace").Where("namespace_id = ? AND machine_key <> ? AND registered",
|
if err := h.db.Preload("Namespace").Where("namespace_id = ? AND machine_key <> ? AND registered",
|
||||||
m.NamespaceID, m.MachineKey).Find(&machines).Error; err != nil {
|
m.NamespaceID, m.MachineKey).Find(&machines).Error; err != nil {
|
||||||
log.Error().Err(err).Msg("Error accessing db")
|
log.Error().Err(err).Msg("Error accessing db")
|
||||||
return nil, err
|
return Machines{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(machines, func(i, j int) bool { return machines[i].ID < machines[j].ID })
|
sort.Slice(machines, func(i, j int) bool { return machines[i].ID < machines[j].ID })
|
||||||
|
@ -88,7 +88,7 @@ func (h *Headscale) getShared(m *Machine) (Machines, error) {
|
||||||
sharedMachines := []SharedMachine{}
|
sharedMachines := []SharedMachine{}
|
||||||
if err := h.db.Preload("Namespace").Preload("Machine").Where("namespace_id = ?",
|
if err := h.db.Preload("Namespace").Preload("Machine").Where("namespace_id = ?",
|
||||||
m.NamespaceID).Find(&sharedMachines).Error; err != nil {
|
m.NamespaceID).Find(&sharedMachines).Error; err != nil {
|
||||||
return nil, err
|
return Machines{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
peers := make(Machines, 0)
|
peers := make(Machines, 0)
|
||||||
|
@ -112,7 +112,7 @@ func (h *Headscale) getPeers(m *Machine) (Machines, error) {
|
||||||
Str("func", "getPeers").
|
Str("func", "getPeers").
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("Cannot fetch peers")
|
Msg("Cannot fetch peers")
|
||||||
return nil, err
|
return Machines{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
shared, err := h.getShared(m)
|
shared, err := h.getShared(m)
|
||||||
|
@ -121,7 +121,7 @@ func (h *Headscale) getPeers(m *Machine) (Machines, error) {
|
||||||
Str("func", "getDirectPeers").
|
Str("func", "getDirectPeers").
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("Cannot fetch peers")
|
Msg("Cannot fetch peers")
|
||||||
return nil, err
|
return Machines{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
peers := append(direct, shared...)
|
peers := append(direct, shared...)
|
||||||
|
@ -214,118 +214,31 @@ func (m *Machine) GetHostInfo() (*tailcfg.Hostinfo, error) {
|
||||||
return &hostinfo, nil
|
return &hostinfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Headscale) notifyChangesToPeers(m *Machine) {
|
|
||||||
peers, err := h.getPeers(m)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().
|
|
||||||
Str("func", "notifyChangesToPeers").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msgf("Error getting peers: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, peer := range peers {
|
|
||||||
log.Info().
|
|
||||||
Str("func", "notifyChangesToPeers").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Str("peer", peer.Name).
|
|
||||||
Str("address", peer.IPAddress).
|
|
||||||
Msgf("Notifying peer %s (%s)", peer.Name, peer.IPAddress)
|
|
||||||
err := h.sendRequestOnUpdateChannel(&peer)
|
|
||||||
if err != nil {
|
|
||||||
log.Info().
|
|
||||||
Str("func", "notifyChangesToPeers").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Str("peer", peer.Name).
|
|
||||||
Msgf("Peer %s does not have an open update client, skipping.", peer.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Trace().
|
|
||||||
Str("func", "notifyChangesToPeers").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Str("peer", peer.Name).
|
|
||||||
Str("address", peer.IPAddress).
|
|
||||||
Msgf("Notified peer %s (%s)", peer.Name, peer.IPAddress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Headscale) getOrOpenUpdateChannel(m *Machine) <-chan struct{} {
|
|
||||||
var updateChan chan struct{}
|
|
||||||
if storedChan, ok := h.clientsUpdateChannels.Load(m.ID); ok {
|
|
||||||
if unwrapped, ok := storedChan.(chan struct{}); ok {
|
|
||||||
updateChan = unwrapped
|
|
||||||
} else {
|
|
||||||
log.Error().
|
|
||||||
Str("handler", "openUpdateChannel").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msg("Failed to convert update channel to struct{}")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Debug().
|
|
||||||
Str("handler", "openUpdateChannel").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msg("Update channel not found, creating")
|
|
||||||
|
|
||||||
updateChan = make(chan struct{})
|
|
||||||
h.clientsUpdateChannels.Store(m.ID, updateChan)
|
|
||||||
}
|
|
||||||
return updateChan
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Headscale) closeUpdateChannel(m *Machine) {
|
|
||||||
h.clientsUpdateChannelMutex.Lock()
|
|
||||||
defer h.clientsUpdateChannelMutex.Unlock()
|
|
||||||
|
|
||||||
if storedChan, ok := h.clientsUpdateChannels.Load(m.ID); ok {
|
|
||||||
if unwrapped, ok := storedChan.(chan struct{}); ok {
|
|
||||||
close(unwrapped)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.clientsUpdateChannels.Delete(m.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Headscale) sendRequestOnUpdateChannel(m *Machine) error {
|
|
||||||
h.clientsUpdateChannelMutex.Lock()
|
|
||||||
defer h.clientsUpdateChannelMutex.Unlock()
|
|
||||||
|
|
||||||
pUp, ok := h.clientsUpdateChannels.Load(uint64(m.ID))
|
|
||||||
if ok {
|
|
||||||
log.Info().
|
|
||||||
Str("func", "requestUpdate").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msgf("Notifying peer %s", m.Name)
|
|
||||||
|
|
||||||
if update, ok := pUp.(chan struct{}); ok {
|
|
||||||
log.Trace().
|
|
||||||
Str("func", "requestUpdate").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msgf("Update channel is %#v", update)
|
|
||||||
|
|
||||||
updateRequestsToNode.Inc()
|
|
||||||
update <- struct{}{}
|
|
||||||
|
|
||||||
log.Trace().
|
|
||||||
Str("func", "requestUpdate").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msgf("Notified machine %s", m.Name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := errors.New("machine does not have an open update channel")
|
|
||||||
log.Info().
|
|
||||||
Str("func", "requestUpdate").
|
|
||||||
Str("machine", m.Name).
|
|
||||||
Msgf("Machine %s does not have an open update channel", m.Name)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Headscale) isOutdated(m *Machine) bool {
|
func (h *Headscale) isOutdated(m *Machine) bool {
|
||||||
err := h.UpdateMachine(m)
|
err := h.UpdateMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// It does not seem meaningful to propagate this error as the end result
|
||||||
|
// will have to be that the machine has to be considered outdated.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
lastChange := h.getLastStateChange(m.Namespace.Name)
|
sharedMachines, _ := h.getShared(m)
|
||||||
|
|
||||||
|
namespaceSet := set.New(set.ThreadSafe)
|
||||||
|
namespaceSet.Add(m.Namespace.Name)
|
||||||
|
|
||||||
|
// Check if any of our shared namespaces has updates that we have
|
||||||
|
// not propagated.
|
||||||
|
for _, sharedMachine := range sharedMachines {
|
||||||
|
namespaceSet.Add(sharedMachine.Namespace.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces := make([]string, namespaceSet.Size())
|
||||||
|
for index, namespace := range namespaceSet.List() {
|
||||||
|
namespaces[index] = namespace.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
lastChange := h.getLastStateChange(namespaces...)
|
||||||
log.Trace().
|
log.Trace().
|
||||||
Str("func", "keepAlive").
|
Str("func", "keepAlive").
|
||||||
Str("machine", m.Name).
|
Str("machine", m.Name).
|
||||||
|
|
10
metrics.go
10
metrics.go
|
@ -26,16 +26,16 @@ var (
|
||||||
Namespace: prometheusNamespace,
|
Namespace: prometheusNamespace,
|
||||||
Name: "update_request_from_node_total",
|
Name: "update_request_from_node_total",
|
||||||
Help: "The number of updates requested by a node/update function",
|
Help: "The number of updates requested by a node/update function",
|
||||||
}, []string{"state"})
|
}, []string{"namespace", "machine", "state"})
|
||||||
updateRequestsToNode = promauto.NewCounter(prometheus.CounterOpts{
|
updateRequestsSentToNode = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
Namespace: prometheusNamespace,
|
Namespace: prometheusNamespace,
|
||||||
Name: "update_request_to_node_total",
|
Name: "update_request_sent_to_node_total",
|
||||||
Help: "The number of calls/messages issued on a specific nodes update channel",
|
Help: "The number of calls/messages issued on a specific nodes update channel",
|
||||||
})
|
}, []string{"namespace", "machine", "status"})
|
||||||
//TODO(kradalby): This is very debugging, we might want to remove it.
|
//TODO(kradalby): This is very debugging, we might want to remove it.
|
||||||
updateRequestsReceivedOnChannel = promauto.NewCounterVec(prometheus.CounterOpts{
|
updateRequestsReceivedOnChannel = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
Namespace: prometheusNamespace,
|
Namespace: prometheusNamespace,
|
||||||
Name: "update_request_received_on_channel_total",
|
Name: "update_request_received_on_channel_total",
|
||||||
Help: "The number of update requests received on an update channel",
|
Help: "The number of update requests received on an update channel",
|
||||||
}, []string{"machine"})
|
}, []string{"namespace", "machine"})
|
||||||
)
|
)
|
||||||
|
|
|
@ -176,24 +176,17 @@ func (h *Headscale) checkForNamespacesPendingUpdates() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
names := []string{}
|
namespaces := []string{}
|
||||||
err = json.Unmarshal([]byte(v), &names)
|
err = json.Unmarshal([]byte(v), &namespaces)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, name := range names {
|
for _, namespace := range namespaces {
|
||||||
log.Trace().
|
log.Trace().
|
||||||
Str("func", "RequestMapUpdates").
|
Str("func", "RequestMapUpdates").
|
||||||
Str("machine", name).
|
Str("machine", namespace).
|
||||||
Msg("Sending updates to nodes in namespace")
|
Msg("Sending updates to nodes in namespacespace")
|
||||||
machines, err := h.ListMachinesInNamespace(name)
|
h.setLastStateChangeToNow(namespace)
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, m := range *machines {
|
|
||||||
updateRequestsFromNode.WithLabelValues("namespace-update").Inc()
|
|
||||||
h.notifyChangesToPeers(&m)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
newV, err := h.getValue("namespaces_pending_updates")
|
newV, err := h.getValue("namespaces_pending_updates")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
55
poll.go
55
poll.go
|
@ -140,10 +140,9 @@ func (h *Headscale) PollNetMapHandler(c *gin.Context) {
|
||||||
Str("id", c.Param("id")).
|
Str("id", c.Param("id")).
|
||||||
Str("machine", m.Name).
|
Str("machine", m.Name).
|
||||||
Msg("Loading or creating update channel")
|
Msg("Loading or creating update channel")
|
||||||
updateChan := h.getOrOpenUpdateChannel(m)
|
updateChan := make(chan struct{})
|
||||||
|
|
||||||
pollDataChan := make(chan []byte)
|
pollDataChan := make(chan []byte)
|
||||||
// defer close(pollData)
|
|
||||||
|
|
||||||
keepAliveChan := make(chan []byte)
|
keepAliveChan := make(chan []byte)
|
||||||
|
|
||||||
|
@ -159,8 +158,8 @@ func (h *Headscale) PollNetMapHandler(c *gin.Context) {
|
||||||
|
|
||||||
// It sounds like we should update the nodes when we have received a endpoint update
|
// It sounds like we should update the nodes when we have received a endpoint update
|
||||||
// even tho the comments in the tailscale code dont explicitly say so.
|
// even tho the comments in the tailscale code dont explicitly say so.
|
||||||
updateRequestsFromNode.WithLabelValues("endpoint-update").Inc()
|
updateRequestsFromNode.WithLabelValues(m.Name, m.Namespace.Name, "endpoint-update").Inc()
|
||||||
go h.notifyChangesToPeers(m)
|
go func() { updateChan <- struct{}{} }()
|
||||||
return
|
return
|
||||||
} else if req.OmitPeers && req.Stream {
|
} else if req.OmitPeers && req.Stream {
|
||||||
log.Warn().
|
log.Warn().
|
||||||
|
@ -185,8 +184,8 @@ func (h *Headscale) PollNetMapHandler(c *gin.Context) {
|
||||||
Str("handler", "PollNetMap").
|
Str("handler", "PollNetMap").
|
||||||
Str("machine", m.Name).
|
Str("machine", m.Name).
|
||||||
Msg("Notifying peers")
|
Msg("Notifying peers")
|
||||||
updateRequestsFromNode.WithLabelValues("full-update").Inc()
|
updateRequestsFromNode.WithLabelValues(m.Name, m.Namespace.Name, "full-update").Inc()
|
||||||
go h.notifyChangesToPeers(m)
|
go func() { updateChan <- struct{}{} }()
|
||||||
|
|
||||||
h.PollNetMapStream(c, m, req, mKey, pollDataChan, keepAliveChan, updateChan, cancelKeepAlive)
|
h.PollNetMapStream(c, m, req, mKey, pollDataChan, keepAliveChan, updateChan, cancelKeepAlive)
|
||||||
log.Trace().
|
log.Trace().
|
||||||
|
@ -206,10 +205,10 @@ func (h *Headscale) PollNetMapStream(
|
||||||
mKey wgkey.Key,
|
mKey wgkey.Key,
|
||||||
pollDataChan chan []byte,
|
pollDataChan chan []byte,
|
||||||
keepAliveChan chan []byte,
|
keepAliveChan chan []byte,
|
||||||
updateChan <-chan struct{},
|
updateChan chan struct{},
|
||||||
cancelKeepAlive chan struct{},
|
cancelKeepAlive chan struct{},
|
||||||
) {
|
) {
|
||||||
go h.scheduledPollWorker(cancelKeepAlive, keepAliveChan, mKey, req, m)
|
go h.scheduledPollWorker(cancelKeepAlive, updateChan, keepAliveChan, mKey, req, m)
|
||||||
|
|
||||||
c.Stream(func(w io.Writer) bool {
|
c.Stream(func(w io.Writer) bool {
|
||||||
log.Trace().
|
log.Trace().
|
||||||
|
@ -325,7 +324,7 @@ func (h *Headscale) PollNetMapStream(
|
||||||
Str("machine", m.Name).
|
Str("machine", m.Name).
|
||||||
Str("channel", "update").
|
Str("channel", "update").
|
||||||
Msg("Received a request for update")
|
Msg("Received a request for update")
|
||||||
updateRequestsReceivedOnChannel.WithLabelValues(m.Name).Inc()
|
updateRequestsReceivedOnChannel.WithLabelValues(m.Name, m.Namespace.Name).Inc()
|
||||||
if h.isOutdated(m) {
|
if h.isOutdated(m) {
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("handler", "PollNetMapStream").
|
Str("handler", "PollNetMapStream").
|
||||||
|
@ -350,6 +349,7 @@ func (h *Headscale) PollNetMapStream(
|
||||||
Str("channel", "update").
|
Str("channel", "update").
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("Could not write the map response")
|
Msg("Could not write the map response")
|
||||||
|
updateRequestsSentToNode.WithLabelValues(m.Name, m.Namespace.Name, "failed").Inc()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
log.Trace().
|
log.Trace().
|
||||||
|
@ -357,14 +357,15 @@ func (h *Headscale) PollNetMapStream(
|
||||||
Str("machine", m.Name).
|
Str("machine", m.Name).
|
||||||
Str("channel", "update").
|
Str("channel", "update").
|
||||||
Msg("Updated Map has been sent")
|
Msg("Updated Map has been sent")
|
||||||
|
updateRequestsSentToNode.WithLabelValues(m.Name, m.Namespace.Name, "success").Inc()
|
||||||
|
|
||||||
// Keep track of the last successful update,
|
// Keep track of the last successful update,
|
||||||
// we sometimes end in a state were the update
|
// we sometimes end in a state were the update
|
||||||
// is not picked up by a client and we use this
|
// is not picked up by a client and we use this
|
||||||
// to determine if we should "force" an update.
|
// to determine if we should "force" an update.
|
||||||
// TODO(kradalby): Abstract away all the database calls, this can cause race conditions
|
// TODO(kradalby): Abstract away all the database calls, this can cause race conditions
|
||||||
// when an outdated machine object is kept alive, e.g. db is update from
|
// when an outdated machine object is kept alive, e.g. db is update from
|
||||||
// command line, but then overwritten.
|
// command line, but then overwritten.
|
||||||
err = h.UpdateMachine(m)
|
err = h.UpdateMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().
|
log.Error().
|
||||||
|
@ -423,7 +424,8 @@ func (h *Headscale) PollNetMapStream(
|
||||||
Str("machine", m.Name).
|
Str("machine", m.Name).
|
||||||
Str("channel", "Done").
|
Str("channel", "Done").
|
||||||
Msg("Closing update channel")
|
Msg("Closing update channel")
|
||||||
h.closeUpdateChannel(m)
|
//h.closeUpdateChannel(m)
|
||||||
|
close(updateChan)
|
||||||
|
|
||||||
log.Trace().
|
log.Trace().
|
||||||
Str("handler", "PollNetMapStream").
|
Str("handler", "PollNetMapStream").
|
||||||
|
@ -446,13 +448,14 @@ func (h *Headscale) PollNetMapStream(
|
||||||
|
|
||||||
func (h *Headscale) scheduledPollWorker(
|
func (h *Headscale) scheduledPollWorker(
|
||||||
cancelChan <-chan struct{},
|
cancelChan <-chan struct{},
|
||||||
|
updateChan chan<- struct{},
|
||||||
keepAliveChan chan<- []byte,
|
keepAliveChan chan<- []byte,
|
||||||
mKey wgkey.Key,
|
mKey wgkey.Key,
|
||||||
req tailcfg.MapRequest,
|
req tailcfg.MapRequest,
|
||||||
m *Machine,
|
m *Machine,
|
||||||
) {
|
) {
|
||||||
keepAliveTicker := time.NewTicker(60 * time.Second)
|
keepAliveTicker := time.NewTicker(60 * time.Second)
|
||||||
updateCheckerTicker := time.NewTicker(30 * time.Second)
|
updateCheckerTicker := time.NewTicker(10 * time.Second)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -476,16 +479,12 @@ func (h *Headscale) scheduledPollWorker(
|
||||||
keepAliveChan <- data
|
keepAliveChan <- data
|
||||||
|
|
||||||
case <-updateCheckerTicker.C:
|
case <-updateCheckerTicker.C:
|
||||||
// Send an update request regardless of outdated or not, if data is sent
|
log.Debug().
|
||||||
// to the node is determined in the updateChan consumer block
|
Str("func", "scheduledPollWorker").
|
||||||
err := h.sendRequestOnUpdateChannel(m)
|
Str("machine", m.Name).
|
||||||
if err != nil {
|
Msg("Sending update request")
|
||||||
log.Error().
|
updateRequestsFromNode.WithLabelValues(m.Name, m.Namespace.Name, "scheduled-update").Inc()
|
||||||
Str("func", "keepAlive").
|
updateChan <- struct{}{}
|
||||||
Str("machine", m.Name).
|
|
||||||
Err(err).
|
|
||||||
Msgf("Failed to send update request to %s", m.Name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue