mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-03 20:24:08 +09:00
api/v2: return a device name as its FQDN
This commit is contained in:
1 parent
17cbea0f6a
commit
6474ac6dd3
3 files changed
+27
-29
No files matched your search
@@ -143,7 +143,7 @@ func registerDevices(api huma.API, b Backend) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &deviceOutput{Body: deviceFromView(node, in.Fields == "all")}, nil
|
||||
return &deviceOutput{Body: deviceFromView(node, in.Fields == "all", b.Cfg.BaseDomain)}, nil
|
||||
})
|
||||
|
||||
huma.Register(api, requireScope(huma.Operation{
|
||||
@@ -167,7 +167,7 @@ func registerDevices(api huma.API, b Backend) {
|
||||
out.Body.Devices = make([]Device, 0, nodes.Len())
|
||||
|
||||
for _, node := range nodes.All() {
|
||||
out.Body.Devices = append(out.Body.Devices, deviceFromView(node, allFields))
|
||||
out.Body.Devices = append(out.Body.Devices, deviceFromView(node, allFields, b.Cfg.BaseDomain))
|
||||
}
|
||||
|
||||
return out, nil
|
||||
@@ -429,12 +429,18 @@ func parseRoutes(routes []string) ([]netip.Prefix, error) {
|
||||
// deviceFromView maps a Headscale node onto the Tailscale Device, reading
|
||||
// through the [types.NodeView] accessors. allFields gates the route slices,
|
||||
// which Tailscale only returns for fields=all.
|
||||
func deviceFromView(view types.NodeView, allFields bool) Device {
|
||||
func deviceFromView(view types.NodeView, allFields bool, baseDomain string) Device {
|
||||
id := view.StringID()
|
||||
|
||||
// Tailscale names a device by its MagicDNS FQDN, without the root dot.
|
||||
name := view.GivenName()
|
||||
if baseDomain != "" {
|
||||
name += "." + baseDomain
|
||||
}
|
||||
|
||||
d := Device{
|
||||
Addresses: emptyIfNil(view.IPsAsString()),
|
||||
Name: view.GivenName(),
|
||||
Name: name,
|
||||
ID: id,
|
||||
NodeID: id,
|
||||
Authorized: true, // Headscale has no post-registration de-auth state.
|
||||
|
||||
@@ -146,6 +146,23 @@ func TestAPIv2Device_Get(t *testing.T) {
|
||||
assert.Equal(t, n.IPsAsString(), dev.Addresses)
|
||||
}
|
||||
|
||||
// TestAPIv2Device_NameIsFQDN: with a base domain, a device's name is its
|
||||
// MagicDNS FQDN, in a read and in the list.
|
||||
func TestAPIv2Device_NameIsFQDN(t *testing.T) {
|
||||
e := newDeviceTestEnv(t)
|
||||
e.app.cfg.BaseDomain = "tailnet.example.com"
|
||||
|
||||
assert.Equal(t, "contract-dut.tailnet.example.com", getDevice(t, e.api, e.deviceID).Name)
|
||||
|
||||
resp := e.api.Get("/api/v2/tailnet/-/devices")
|
||||
require.Equalf(t, http.StatusOK, resp.Code, "body: %s", resp.Body)
|
||||
|
||||
var list struct{ Devices []apiv2.Device }
|
||||
require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &list))
|
||||
require.Len(t, list.Devices, 1)
|
||||
assert.Equal(t, "contract-dut.tailnet.example.com", list.Devices[0].Name)
|
||||
}
|
||||
|
||||
func TestAPIv2Device_Get_UnknownID_404(t *testing.T) {
|
||||
e := newDeviceTestEnv(t)
|
||||
|
||||
|
||||
@@ -31,30 +31,6 @@ import (
|
||||
// <test_id>/<step>/<node or action index>/<check>. A listed check that
|
||||
// matches fails, so a fix must delete its entry.
|
||||
var nameSkipReasons = map[string]string{
|
||||
"names/N1/domain": v2NameBare,
|
||||
"names/N2/domain": v2NameBare,
|
||||
"names/N3/domain": v2NameBare,
|
||||
"names/N4/domain": v2NameBare,
|
||||
"names/N5/domain": v2NameBare,
|
||||
"names/N6/domain": v2NameBare,
|
||||
"names/N7/domain": v2NameBare,
|
||||
"names/N8/domain": v2NameBare,
|
||||
"names/N9a/domain": v2NameBare,
|
||||
"names/N9b/domain": v2NameBare,
|
||||
"names/N10/domain": v2NameBare,
|
||||
"names/N11/domain": v2NameBare,
|
||||
"names/N11b/domain": v2NameBare,
|
||||
"names/N12a/domain": v2NameBare,
|
||||
"names/N12b/domain": v2NameBare,
|
||||
"names/N13/domain": v2NameBare,
|
||||
"names-svc/S1/domain": v2NameBare,
|
||||
"names-svc/S2/domain": v2NameBare,
|
||||
"names-svc/S3/domain": v2NameBare,
|
||||
"names-svc/S4/domain": v2NameBare,
|
||||
"names-svc/S5/domain": v2NameBare,
|
||||
"names-svc/S6/domain": v2NameBare,
|
||||
"names-svc/S7/domain": v2NameBare,
|
||||
|
||||
"names/N11/pdb/label": adminNameFollowsHostname,
|
||||
"names/N11b/pdb/label": adminNameFollowsHostname,
|
||||
"names/N12a/pdb/label": adminNameFollowsHostname,
|
||||
@@ -64,7 +40,6 @@ var nameSkipReasons = map[string]string{
|
||||
|
||||
const (
|
||||
adminNameFollowsHostname = "ADMIN_NAME_FOLLOWS_HOSTNAME: an admin name equal to the hostname's label counts as derived from it, so a hostname change replaces it; SaaS keeps an admin name across hostname changes"
|
||||
v2NameBare = "V2_NAME_BARE: headscale's v2 device name is the bare label; SaaS's is the FQDN under the tailnet domain"
|
||||
)
|
||||
|
||||
// nameViewer is the node whose netmap every step captured.
|
||||
|
||||
Reference in new issue
Block a user