#2140 Fixed reflection of hostname change (#2199)

* #2140 Fixed updating of hostname and givenName when it is updated in HostInfo

* #2140 Added integration tests

* #2140 Fix unit tests

* Changed IsAutomaticNameMode to GivenNameHasBeenChanged. Fixed errors in files according to golangci-lint rules
This commit is contained in:
hopleus 2024-10-17 18:45:33 +03:00 committed by GitHub
parent 45c9585b52
commit b6dc6eb36c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 221 additions and 2 deletions

View file

@ -471,7 +471,7 @@ func (m *mapSession) handleEndpointUpdate() {
// Check if the Hostinfo of the node has changed.
// If it has changed, check if there has been a change to
// the routable IPs of the host and update update them in
// the routable IPs of the host and update them in
// the database. Then send a Changed update
// (containing the whole node object) to peers to inform about
// the route change.
@ -510,6 +510,12 @@ func (m *mapSession) handleEndpointUpdate() {
m.node.ID)
}
// Check if there has been a change to Hostname and update them
// in the database. Then send a Changed update
// (containing the whole node object) to peers to inform about
// the hostname change.
m.node.ApplyHostnameFromHostInfo(m.req.Hostinfo)
if err := m.h.db.DB.Save(m.node).Error; err != nil {
m.errf(err, "Failed to persist/update node in the database")
http.Error(m.w, "", http.StatusInternalServerError)
@ -526,7 +532,8 @@ func (m *mapSession) handleEndpointUpdate() {
ChangeNodes: []types.NodeID{m.node.ID},
Message: "called from handlePoll -> update",
},
m.node.ID)
m.node.ID,
)
m.w.WriteHeader(http.StatusOK)
mapResponseEndpointUpdates.WithLabelValues("ok").Inc()

View file

@ -97,6 +97,11 @@ type (
Nodes []*Node
)
// GivenNameHasBeenChanged returns whether the `givenName` can be automatically changed based on the `Hostname` of the node.
func (node *Node) GivenNameHasBeenChanged() bool {
return node.GivenName == util.ConvertWithFQDNRules(node.Hostname)
}
// IsExpired returns whether the node registration has expired.
func (node Node) IsExpired() bool {
// If Expiry is not set, the client has not indicated that
@ -347,6 +352,21 @@ func (node *Node) RegisterMethodToV1Enum() v1.RegisterMethod {
}
}
// ApplyHostnameFromHostInfo takes a Hostinfo struct and updates the node.
func (node *Node) ApplyHostnameFromHostInfo(hostInfo *tailcfg.Hostinfo) {
if hostInfo == nil {
return
}
if node.Hostname != hostInfo.Hostname {
if node.GivenNameHasBeenChanged() {
node.GivenName = util.ConvertWithFQDNRules(hostInfo.Hostname)
}
node.Hostname = hostInfo.Hostname
}
}
// ApplyPeerChange takes a PeerChange struct and updates the node.
func (node *Node) ApplyPeerChange(change *tailcfg.PeerChange) {
if change.Key != nil {

View file

@ -337,6 +337,66 @@ func TestPeerChangeFromMapRequest(t *testing.T) {
}
}
func TestApplyHostnameFromHostInfo(t *testing.T) {
tests := []struct {
name string
nodeBefore Node
change *tailcfg.Hostinfo
want Node
}{
{
name: "hostinfo-not-exists",
nodeBefore: Node{
GivenName: "manual-test.local",
Hostname: "TestHost.Local",
},
change: nil,
want: Node{
GivenName: "manual-test.local",
Hostname: "TestHost.Local",
},
},
{
name: "hostinfo-exists-no-automatic-givenName",
nodeBefore: Node{
GivenName: "manual-test.local",
Hostname: "TestHost.Local",
},
change: &tailcfg.Hostinfo{
Hostname: "NewHostName.Local",
},
want: Node{
GivenName: "manual-test.local",
Hostname: "NewHostName.Local",
},
},
{
name: "hostinfo-exists-automatic-givenName",
nodeBefore: Node{
GivenName: "automaticname.test",
Hostname: "AutomaticName.Test",
},
change: &tailcfg.Hostinfo{
Hostname: "NewHostName.Local",
},
want: Node{
GivenName: "newhostname.local",
Hostname: "NewHostName.Local",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.nodeBefore.ApplyHostnameFromHostInfo(tt.change)
if diff := cmp.Diff(tt.want, tt.nodeBefore, util.Comparers...); diff != "" {
t.Errorf("Patch unexpected result (-want +got):\n%s", diff)
}
})
}
}
func TestApplyPeerChange(t *testing.T) {
tests := []struct {
name string