grpcv1: share list-RPC response helpers

This commit is contained in:
Kristoffer Dalby
2026-06-16 12:28:53 +00:00
parent fdc7e26c8a
commit c3cfbf1cc0
+16 -22
View File
@@ -4,6 +4,7 @@
package hscontrol package hscontrol
import ( import (
"cmp"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@@ -11,7 +12,6 @@ import (
"net/netip" "net/netip"
"os" "os"
"slices" "slices"
"sort"
"strings" "strings"
"time" "time"
@@ -44,6 +44,13 @@ func newHeadscaleV1APIServer(h *Headscale) v1.HeadscaleServiceServer {
} }
} }
// sortByID sorts a slice of proto messages by ascending Id.
func sortByID[T interface{ GetId() uint64 }](s []T) {
slices.SortFunc(s, func(a, b T) int {
return cmp.Compare(a.GetId(), b.GetId())
})
}
func (api headscaleV1APIServer) CreateUser( func (api headscaleV1APIServer) CreateUser(
ctx context.Context, ctx context.Context,
request *v1.CreateUserRequest, request *v1.CreateUserRequest,
@@ -137,9 +144,7 @@ func (api headscaleV1APIServer) ListUsers(
response[index] = user.Proto() response[index] = user.Proto()
} }
sort.Slice(response, func(i, j int) bool { sortByID(response)
return response[i].Id < response[j].Id
})
return &v1.ListUsersResponse{Users: response}, nil return &v1.ListUsersResponse{Users: response}, nil
} }
@@ -223,9 +228,7 @@ func (api headscaleV1APIServer) ListPreAuthKeys(
response[index] = key.Proto() response[index] = key.Proto()
} }
sort.Slice(response, func(i, j int) bool { sortByID(response)
return response[i].Id < response[j].Id
})
return &v1.ListPreAuthKeysResponse{PreAuthKeys: response}, nil return &v1.ListPreAuthKeysResponse{PreAuthKeys: response}, nil
} }
@@ -527,24 +530,19 @@ func (api headscaleV1APIServer) ListNodes(
ctx context.Context, ctx context.Context,
request *v1.ListNodesRequest, request *v1.ListNodesRequest,
) (*v1.ListNodesResponse, error) { ) (*v1.ListNodesResponse, error) {
// TODO(kradalby): it looks like this can be simplified a lot,
// the filtering of nodes by user, vs nodes as a whole can
// probably be done once.
// TODO(kradalby): This should be done in one tx. // TODO(kradalby): This should be done in one tx.
var nodes views.Slice[types.NodeView]
if request.GetUser() != "" { if request.GetUser() != "" {
user, err := api.h.state.GetUserByName(request.GetUser()) user, err := api.h.state.GetUserByName(request.GetUser())
if err != nil { if err != nil {
return nil, err return nil, err
} }
nodes := api.h.state.ListNodesByUser(types.UserID(user.ID)) nodes = api.h.state.ListNodesByUser(types.UserID(user.ID))
} else {
response := nodesToProto(api.h.state, nodes) nodes = api.h.state.ListNodes()
return &v1.ListNodesResponse{Nodes: response}, nil
} }
nodes := api.h.state.ListNodes()
response := nodesToProto(api.h.state, nodes) response := nodesToProto(api.h.state, nodes)
return &v1.ListNodesResponse{Nodes: response}, nil return &v1.ListNodesResponse{Nodes: response}, nil
} }
@@ -564,9 +562,7 @@ func nodesToProto(state *state.State, nodes views.Slice[types.NodeView]) []*v1.N
response[index] = resp response[index] = resp
} }
sort.Slice(response, func(i, j int) bool { sortByID(response)
return response[i].Id < response[j].Id
})
return response return response
} }
@@ -661,9 +657,7 @@ func (api headscaleV1APIServer) ListApiKeys(
response[index] = key.Proto() response[index] = key.Proto()
} }
sort.Slice(response, func(i, j int) bool { sortByID(response)
return response[i].Id < response[j].Id
})
return &v1.ListApiKeysResponse{ApiKeys: response}, nil return &v1.ListApiKeysResponse{ApiKeys: response}, nil
} }