cli: remove node move command (#2922)

This commit is contained in:
Kristoffer Dalby
2025-12-01 21:43:31 +01:00
committed by GitHub
parent eec196d200
commit 16d811b306
14 changed files with 104 additions and 823 deletions

View File

@@ -34,6 +34,10 @@ release.
- If you are running a version older than 0.25.0, you must upgrade to 0.25.1 first, then upgrade to this release - If you are running a version older than 0.25.0, you must upgrade to 0.25.1 first, then upgrade to this release
- See the [upgrade path documentation](https://headscale.net/stable/about/faq/#what-is-the-recommended-update-path-can-i-skip-multiple-versions-while-updating) for detailed guidance - See the [upgrade path documentation](https://headscale.net/stable/about/faq/#what-is-the-recommended-update-path-can-i-skip-multiple-versions-while-updating) for detailed guidance
- In version 0.29, all migrations before 0.28.0 will also be removed - In version 0.29, all migrations before 0.28.0 will also be removed
- Remove ability to move nodes between users [#2922](https://github.com/juanfont/headscale/pull/2922)
- The `headscale nodes move` CLI command has been removed
- The `MoveNode` API endpoint has been removed
- Nodes are permanently associated with their user at registration time
### Changes ### Changes

View File

@@ -73,26 +73,6 @@ func init() {
} }
nodeCmd.AddCommand(deleteNodeCmd) nodeCmd.AddCommand(deleteNodeCmd)
moveNodeCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)")
err = moveNodeCmd.MarkFlagRequired("identifier")
if err != nil {
log.Fatal(err.Error())
}
moveNodeCmd.Flags().Uint64P("user", "u", 0, "New user")
moveNodeCmd.Flags().StringP("namespace", "n", "", "User")
moveNodeNamespaceFlag := moveNodeCmd.Flags().Lookup("namespace")
moveNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
moveNodeNamespaceFlag.Hidden = true
err = moveNodeCmd.MarkFlagRequired("user")
if err != nil {
log.Fatal(err.Error())
}
nodeCmd.AddCommand(moveNodeCmd)
tagCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") tagCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)")
tagCmd.MarkFlagRequired("identifier") tagCmd.MarkFlagRequired("identifier")
tagCmd.Flags().StringSliceP("tags", "t", []string{}, "List of tags to add to the node") tagCmd.Flags().StringSliceP("tags", "t", []string{}, "List of tags to add to the node")
@@ -455,66 +435,6 @@ var deleteNodeCmd = &cobra.Command{
}, },
} }
var moveNodeCmd = &cobra.Command{
Use: "move",
Short: "Move node to another user",
Aliases: []string{"mv"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
identifier, err := cmd.Flags().GetUint64("identifier")
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Error converting ID to integer: %s", err),
output,
)
}
user, err := cmd.Flags().GetUint64("user")
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Error getting user: %s", err),
output,
)
}
ctx, client, conn, cancel := newHeadscaleCLIWithConfig()
defer cancel()
defer conn.Close()
getRequest := &v1.GetNodeRequest{
NodeId: identifier,
}
_, err = client.GetNode(ctx, getRequest)
if err != nil {
ErrorOutput(
err,
"Error getting node: "+status.Convert(err).Message(),
output,
)
}
moveRequest := &v1.MoveNodeRequest{
NodeId: identifier,
User: user,
}
moveResponse, err := client.MoveNode(ctx, moveRequest)
if err != nil {
ErrorOutput(
err,
"Error moving node: "+status.Convert(err).Message(),
output,
)
}
SuccessOutput(moveResponse.GetNode(), "Node moved to another user", output)
},
}
var backfillNodeIPsCmd = &cobra.Command{ var backfillNodeIPsCmd = &cobra.Command{
Use: "backfillips", Use: "backfillips",
Short: "Backfill IPs missing from nodes", Short: "Backfill IPs missing from nodes",

View File

@@ -109,7 +109,7 @@ const file_headscale_v1_headscale_proto_rawDesc = "" +
"\x1cheadscale/v1/headscale.proto\x12\fheadscale.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17headscale/v1/user.proto\x1a\x1dheadscale/v1/preauthkey.proto\x1a\x17headscale/v1/node.proto\x1a\x19headscale/v1/apikey.proto\x1a\x19headscale/v1/policy.proto\"\x0f\n" + "\x1cheadscale/v1/headscale.proto\x12\fheadscale.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17headscale/v1/user.proto\x1a\x1dheadscale/v1/preauthkey.proto\x1a\x17headscale/v1/node.proto\x1a\x19headscale/v1/apikey.proto\x1a\x19headscale/v1/policy.proto\"\x0f\n" +
"\rHealthRequest\"E\n" + "\rHealthRequest\"E\n" +
"\x0eHealthResponse\x123\n" + "\x0eHealthResponse\x123\n" +
"\x15database_connectivity\x18\x01 \x01(\bR\x14databaseConnectivity2\x80\x17\n" + "\x15database_connectivity\x18\x01 \x01(\bR\x14databaseConnectivity2\x8d\x16\n" +
"\x10HeadscaleService\x12h\n" + "\x10HeadscaleService\x12h\n" +
"\n" + "\n" +
"CreateUser\x12\x1f.headscale.v1.CreateUserRequest\x1a .headscale.v1.CreateUserResponse\"\x17\x82\xd3\xe4\x93\x02\x11:\x01*\"\f/api/v1/user\x12\x80\x01\n" + "CreateUser\x12\x1f.headscale.v1.CreateUserRequest\x1a .headscale.v1.CreateUserResponse\"\x17\x82\xd3\xe4\x93\x02\x11:\x01*\"\f/api/v1/user\x12\x80\x01\n" +
@@ -132,8 +132,7 @@ const file_headscale_v1_headscale_proto_rawDesc = "" +
"ExpireNode\x12\x1f.headscale.v1.ExpireNodeRequest\x1a .headscale.v1.ExpireNodeResponse\"%\x82\xd3\xe4\x93\x02\x1f\"\x1d/api/v1/node/{node_id}/expire\x12\x81\x01\n" + "ExpireNode\x12\x1f.headscale.v1.ExpireNodeRequest\x1a .headscale.v1.ExpireNodeResponse\"%\x82\xd3\xe4\x93\x02\x1f\"\x1d/api/v1/node/{node_id}/expire\x12\x81\x01\n" +
"\n" + "\n" +
"RenameNode\x12\x1f.headscale.v1.RenameNodeRequest\x1a .headscale.v1.RenameNodeResponse\"0\x82\xd3\xe4\x93\x02*\"(/api/v1/node/{node_id}/rename/{new_name}\x12b\n" + "RenameNode\x12\x1f.headscale.v1.RenameNodeRequest\x1a .headscale.v1.RenameNodeResponse\"0\x82\xd3\xe4\x93\x02*\"(/api/v1/node/{node_id}/rename/{new_name}\x12b\n" +
"\tListNodes\x12\x1e.headscale.v1.ListNodesRequest\x1a\x1f.headscale.v1.ListNodesResponse\"\x14\x82\xd3\xe4\x93\x02\x0e\x12\f/api/v1/node\x12q\n" + "\tListNodes\x12\x1e.headscale.v1.ListNodesRequest\x1a\x1f.headscale.v1.ListNodesResponse\"\x14\x82\xd3\xe4\x93\x02\x0e\x12\f/api/v1/node\x12\x80\x01\n" +
"\bMoveNode\x12\x1d.headscale.v1.MoveNodeRequest\x1a\x1e.headscale.v1.MoveNodeResponse\"&\x82\xd3\xe4\x93\x02 :\x01*\"\x1b/api/v1/node/{node_id}/user\x12\x80\x01\n" +
"\x0fBackfillNodeIPs\x12$.headscale.v1.BackfillNodeIPsRequest\x1a%.headscale.v1.BackfillNodeIPsResponse\" \x82\xd3\xe4\x93\x02\x1a\"\x18/api/v1/node/backfillips\x12p\n" + "\x0fBackfillNodeIPs\x12$.headscale.v1.BackfillNodeIPsRequest\x1a%.headscale.v1.BackfillNodeIPsResponse\" \x82\xd3\xe4\x93\x02\x1a\"\x18/api/v1/node/backfillips\x12p\n" +
"\fCreateApiKey\x12!.headscale.v1.CreateApiKeyRequest\x1a\".headscale.v1.CreateApiKeyResponse\"\x19\x82\xd3\xe4\x93\x02\x13:\x01*\"\x0e/api/v1/apikey\x12w\n" + "\fCreateApiKey\x12!.headscale.v1.CreateApiKeyRequest\x1a\".headscale.v1.CreateApiKeyResponse\"\x19\x82\xd3\xe4\x93\x02\x13:\x01*\"\x0e/api/v1/apikey\x12w\n" +
"\fExpireApiKey\x12!.headscale.v1.ExpireApiKeyRequest\x1a\".headscale.v1.ExpireApiKeyResponse\" \x82\xd3\xe4\x93\x02\x1a:\x01*\"\x15/api/v1/apikey/expire\x12j\n" + "\fExpireApiKey\x12!.headscale.v1.ExpireApiKeyRequest\x1a\".headscale.v1.ExpireApiKeyResponse\" \x82\xd3\xe4\x93\x02\x1a:\x01*\"\x15/api/v1/apikey/expire\x12j\n" +
@@ -175,38 +174,36 @@ var file_headscale_v1_headscale_proto_goTypes = []any{
(*ExpireNodeRequest)(nil), // 15: headscale.v1.ExpireNodeRequest (*ExpireNodeRequest)(nil), // 15: headscale.v1.ExpireNodeRequest
(*RenameNodeRequest)(nil), // 16: headscale.v1.RenameNodeRequest (*RenameNodeRequest)(nil), // 16: headscale.v1.RenameNodeRequest
(*ListNodesRequest)(nil), // 17: headscale.v1.ListNodesRequest (*ListNodesRequest)(nil), // 17: headscale.v1.ListNodesRequest
(*MoveNodeRequest)(nil), // 18: headscale.v1.MoveNodeRequest (*BackfillNodeIPsRequest)(nil), // 18: headscale.v1.BackfillNodeIPsRequest
(*BackfillNodeIPsRequest)(nil), // 19: headscale.v1.BackfillNodeIPsRequest (*CreateApiKeyRequest)(nil), // 19: headscale.v1.CreateApiKeyRequest
(*CreateApiKeyRequest)(nil), // 20: headscale.v1.CreateApiKeyRequest (*ExpireApiKeyRequest)(nil), // 20: headscale.v1.ExpireApiKeyRequest
(*ExpireApiKeyRequest)(nil), // 21: headscale.v1.ExpireApiKeyRequest (*ListApiKeysRequest)(nil), // 21: headscale.v1.ListApiKeysRequest
(*ListApiKeysRequest)(nil), // 22: headscale.v1.ListApiKeysRequest (*DeleteApiKeyRequest)(nil), // 22: headscale.v1.DeleteApiKeyRequest
(*DeleteApiKeyRequest)(nil), // 23: headscale.v1.DeleteApiKeyRequest (*GetPolicyRequest)(nil), // 23: headscale.v1.GetPolicyRequest
(*GetPolicyRequest)(nil), // 24: headscale.v1.GetPolicyRequest (*SetPolicyRequest)(nil), // 24: headscale.v1.SetPolicyRequest
(*SetPolicyRequest)(nil), // 25: headscale.v1.SetPolicyRequest (*CreateUserResponse)(nil), // 25: headscale.v1.CreateUserResponse
(*CreateUserResponse)(nil), // 26: headscale.v1.CreateUserResponse (*RenameUserResponse)(nil), // 26: headscale.v1.RenameUserResponse
(*RenameUserResponse)(nil), // 27: headscale.v1.RenameUserResponse (*DeleteUserResponse)(nil), // 27: headscale.v1.DeleteUserResponse
(*DeleteUserResponse)(nil), // 28: headscale.v1.DeleteUserResponse (*ListUsersResponse)(nil), // 28: headscale.v1.ListUsersResponse
(*ListUsersResponse)(nil), // 29: headscale.v1.ListUsersResponse (*CreatePreAuthKeyResponse)(nil), // 29: headscale.v1.CreatePreAuthKeyResponse
(*CreatePreAuthKeyResponse)(nil), // 30: headscale.v1.CreatePreAuthKeyResponse (*ExpirePreAuthKeyResponse)(nil), // 30: headscale.v1.ExpirePreAuthKeyResponse
(*ExpirePreAuthKeyResponse)(nil), // 31: headscale.v1.ExpirePreAuthKeyResponse (*ListPreAuthKeysResponse)(nil), // 31: headscale.v1.ListPreAuthKeysResponse
(*ListPreAuthKeysResponse)(nil), // 32: headscale.v1.ListPreAuthKeysResponse (*DebugCreateNodeResponse)(nil), // 32: headscale.v1.DebugCreateNodeResponse
(*DebugCreateNodeResponse)(nil), // 33: headscale.v1.DebugCreateNodeResponse (*GetNodeResponse)(nil), // 33: headscale.v1.GetNodeResponse
(*GetNodeResponse)(nil), // 34: headscale.v1.GetNodeResponse (*SetTagsResponse)(nil), // 34: headscale.v1.SetTagsResponse
(*SetTagsResponse)(nil), // 35: headscale.v1.SetTagsResponse (*SetApprovedRoutesResponse)(nil), // 35: headscale.v1.SetApprovedRoutesResponse
(*SetApprovedRoutesResponse)(nil), // 36: headscale.v1.SetApprovedRoutesResponse (*RegisterNodeResponse)(nil), // 36: headscale.v1.RegisterNodeResponse
(*RegisterNodeResponse)(nil), // 37: headscale.v1.RegisterNodeResponse (*DeleteNodeResponse)(nil), // 37: headscale.v1.DeleteNodeResponse
(*DeleteNodeResponse)(nil), // 38: headscale.v1.DeleteNodeResponse (*ExpireNodeResponse)(nil), // 38: headscale.v1.ExpireNodeResponse
(*ExpireNodeResponse)(nil), // 39: headscale.v1.ExpireNodeResponse (*RenameNodeResponse)(nil), // 39: headscale.v1.RenameNodeResponse
(*RenameNodeResponse)(nil), // 40: headscale.v1.RenameNodeResponse (*ListNodesResponse)(nil), // 40: headscale.v1.ListNodesResponse
(*ListNodesResponse)(nil), // 41: headscale.v1.ListNodesResponse (*BackfillNodeIPsResponse)(nil), // 41: headscale.v1.BackfillNodeIPsResponse
(*MoveNodeResponse)(nil), // 42: headscale.v1.MoveNodeResponse (*CreateApiKeyResponse)(nil), // 42: headscale.v1.CreateApiKeyResponse
(*BackfillNodeIPsResponse)(nil), // 43: headscale.v1.BackfillNodeIPsResponse (*ExpireApiKeyResponse)(nil), // 43: headscale.v1.ExpireApiKeyResponse
(*CreateApiKeyResponse)(nil), // 44: headscale.v1.CreateApiKeyResponse (*ListApiKeysResponse)(nil), // 44: headscale.v1.ListApiKeysResponse
(*ExpireApiKeyResponse)(nil), // 45: headscale.v1.ExpireApiKeyResponse (*DeleteApiKeyResponse)(nil), // 45: headscale.v1.DeleteApiKeyResponse
(*ListApiKeysResponse)(nil), // 46: headscale.v1.ListApiKeysResponse (*GetPolicyResponse)(nil), // 46: headscale.v1.GetPolicyResponse
(*DeleteApiKeyResponse)(nil), // 47: headscale.v1.DeleteApiKeyResponse (*SetPolicyResponse)(nil), // 47: headscale.v1.SetPolicyResponse
(*GetPolicyResponse)(nil), // 48: headscale.v1.GetPolicyResponse
(*SetPolicyResponse)(nil), // 49: headscale.v1.SetPolicyResponse
} }
var file_headscale_v1_headscale_proto_depIdxs = []int32{ var file_headscale_v1_headscale_proto_depIdxs = []int32{
2, // 0: headscale.v1.HeadscaleService.CreateUser:input_type -> headscale.v1.CreateUserRequest 2, // 0: headscale.v1.HeadscaleService.CreateUser:input_type -> headscale.v1.CreateUserRequest
@@ -225,42 +222,40 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{
15, // 13: headscale.v1.HeadscaleService.ExpireNode:input_type -> headscale.v1.ExpireNodeRequest 15, // 13: headscale.v1.HeadscaleService.ExpireNode:input_type -> headscale.v1.ExpireNodeRequest
16, // 14: headscale.v1.HeadscaleService.RenameNode:input_type -> headscale.v1.RenameNodeRequest 16, // 14: headscale.v1.HeadscaleService.RenameNode:input_type -> headscale.v1.RenameNodeRequest
17, // 15: headscale.v1.HeadscaleService.ListNodes:input_type -> headscale.v1.ListNodesRequest 17, // 15: headscale.v1.HeadscaleService.ListNodes:input_type -> headscale.v1.ListNodesRequest
18, // 16: headscale.v1.HeadscaleService.MoveNode:input_type -> headscale.v1.MoveNodeRequest 18, // 16: headscale.v1.HeadscaleService.BackfillNodeIPs:input_type -> headscale.v1.BackfillNodeIPsRequest
19, // 17: headscale.v1.HeadscaleService.BackfillNodeIPs:input_type -> headscale.v1.BackfillNodeIPsRequest 19, // 17: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest
20, // 18: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest 20, // 18: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest
21, // 19: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest 21, // 19: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest
22, // 20: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest 22, // 20: headscale.v1.HeadscaleService.DeleteApiKey:input_type -> headscale.v1.DeleteApiKeyRequest
23, // 21: headscale.v1.HeadscaleService.DeleteApiKey:input_type -> headscale.v1.DeleteApiKeyRequest 23, // 21: headscale.v1.HeadscaleService.GetPolicy:input_type -> headscale.v1.GetPolicyRequest
24, // 22: headscale.v1.HeadscaleService.GetPolicy:input_type -> headscale.v1.GetPolicyRequest 24, // 22: headscale.v1.HeadscaleService.SetPolicy:input_type -> headscale.v1.SetPolicyRequest
25, // 23: headscale.v1.HeadscaleService.SetPolicy:input_type -> headscale.v1.SetPolicyRequest 0, // 23: headscale.v1.HeadscaleService.Health:input_type -> headscale.v1.HealthRequest
0, // 24: headscale.v1.HeadscaleService.Health:input_type -> headscale.v1.HealthRequest 25, // 24: headscale.v1.HeadscaleService.CreateUser:output_type -> headscale.v1.CreateUserResponse
26, // 25: headscale.v1.HeadscaleService.CreateUser:output_type -> headscale.v1.CreateUserResponse 26, // 25: headscale.v1.HeadscaleService.RenameUser:output_type -> headscale.v1.RenameUserResponse
27, // 26: headscale.v1.HeadscaleService.RenameUser:output_type -> headscale.v1.RenameUserResponse 27, // 26: headscale.v1.HeadscaleService.DeleteUser:output_type -> headscale.v1.DeleteUserResponse
28, // 27: headscale.v1.HeadscaleService.DeleteUser:output_type -> headscale.v1.DeleteUserResponse 28, // 27: headscale.v1.HeadscaleService.ListUsers:output_type -> headscale.v1.ListUsersResponse
29, // 28: headscale.v1.HeadscaleService.ListUsers:output_type -> headscale.v1.ListUsersResponse 29, // 28: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse
30, // 29: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse 30, // 29: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse
31, // 30: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse 31, // 30: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse
32, // 31: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse 32, // 31: headscale.v1.HeadscaleService.DebugCreateNode:output_type -> headscale.v1.DebugCreateNodeResponse
33, // 32: headscale.v1.HeadscaleService.DebugCreateNode:output_type -> headscale.v1.DebugCreateNodeResponse 33, // 32: headscale.v1.HeadscaleService.GetNode:output_type -> headscale.v1.GetNodeResponse
34, // 33: headscale.v1.HeadscaleService.GetNode:output_type -> headscale.v1.GetNodeResponse 34, // 33: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse
35, // 34: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse 35, // 34: headscale.v1.HeadscaleService.SetApprovedRoutes:output_type -> headscale.v1.SetApprovedRoutesResponse
36, // 35: headscale.v1.HeadscaleService.SetApprovedRoutes:output_type -> headscale.v1.SetApprovedRoutesResponse 36, // 35: headscale.v1.HeadscaleService.RegisterNode:output_type -> headscale.v1.RegisterNodeResponse
37, // 36: headscale.v1.HeadscaleService.RegisterNode:output_type -> headscale.v1.RegisterNodeResponse 37, // 36: headscale.v1.HeadscaleService.DeleteNode:output_type -> headscale.v1.DeleteNodeResponse
38, // 37: headscale.v1.HeadscaleService.DeleteNode:output_type -> headscale.v1.DeleteNodeResponse 38, // 37: headscale.v1.HeadscaleService.ExpireNode:output_type -> headscale.v1.ExpireNodeResponse
39, // 38: headscale.v1.HeadscaleService.ExpireNode:output_type -> headscale.v1.ExpireNodeResponse 39, // 38: headscale.v1.HeadscaleService.RenameNode:output_type -> headscale.v1.RenameNodeResponse
40, // 39: headscale.v1.HeadscaleService.RenameNode:output_type -> headscale.v1.RenameNodeResponse 40, // 39: headscale.v1.HeadscaleService.ListNodes:output_type -> headscale.v1.ListNodesResponse
41, // 40: headscale.v1.HeadscaleService.ListNodes:output_type -> headscale.v1.ListNodesResponse 41, // 40: headscale.v1.HeadscaleService.BackfillNodeIPs:output_type -> headscale.v1.BackfillNodeIPsResponse
42, // 41: headscale.v1.HeadscaleService.MoveNode:output_type -> headscale.v1.MoveNodeResponse 42, // 41: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse
43, // 42: headscale.v1.HeadscaleService.BackfillNodeIPs:output_type -> headscale.v1.BackfillNodeIPsResponse 43, // 42: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse
44, // 43: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse 44, // 43: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse
45, // 44: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse 45, // 44: headscale.v1.HeadscaleService.DeleteApiKey:output_type -> headscale.v1.DeleteApiKeyResponse
46, // 45: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse 46, // 45: headscale.v1.HeadscaleService.GetPolicy:output_type -> headscale.v1.GetPolicyResponse
47, // 46: headscale.v1.HeadscaleService.DeleteApiKey:output_type -> headscale.v1.DeleteApiKeyResponse 47, // 46: headscale.v1.HeadscaleService.SetPolicy:output_type -> headscale.v1.SetPolicyResponse
48, // 47: headscale.v1.HeadscaleService.GetPolicy:output_type -> headscale.v1.GetPolicyResponse 1, // 47: headscale.v1.HeadscaleService.Health:output_type -> headscale.v1.HealthResponse
49, // 48: headscale.v1.HeadscaleService.SetPolicy:output_type -> headscale.v1.SetPolicyResponse 24, // [24:48] is the sub-list for method output_type
1, // 49: headscale.v1.HeadscaleService.Health:output_type -> headscale.v1.HealthResponse 0, // [0:24] is the sub-list for method input_type
25, // [25:50] is the sub-list for method output_type
0, // [0:25] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name 0, // [0:0] is the sub-list for field type_name

View File

@@ -605,48 +605,6 @@ func local_request_HeadscaleService_ListNodes_0(ctx context.Context, marshaler r
return msg, metadata, err return msg, metadata, err
} }
func request_HeadscaleService_MoveNode_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq MoveNodeRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["node_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "node_id")
}
protoReq.NodeId, err = runtime.Uint64(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "node_id", err)
}
msg, err := client.MoveNode(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_MoveNode_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq MoveNodeRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["node_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "node_id")
}
protoReq.NodeId, err = runtime.Uint64(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "node_id", err)
}
msg, err := server.MoveNode(ctx, &protoReq)
return msg, metadata, err
}
var filter_HeadscaleService_BackfillNodeIPs_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} var filter_HeadscaleService_BackfillNodeIPs_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
func request_HeadscaleService_BackfillNodeIPs_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_HeadscaleService_BackfillNodeIPs_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -1167,26 +1125,6 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
} }
forward_HeadscaleService_ListNodes_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_HeadscaleService_ListNodes_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodPost, pattern_HeadscaleService_MoveNode_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveNode", runtime.WithHTTPPathPattern("/api/v1/node/{node_id}/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_MoveNode_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_MoveNode_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_HeadscaleService_BackfillNodeIPs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle(http.MethodPost, pattern_HeadscaleService_BackfillNodeIPs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
@@ -1659,23 +1597,6 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser
} }
forward_HeadscaleService_ListNodes_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_HeadscaleService_ListNodes_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodPost, pattern_HeadscaleService_MoveNode_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveNode", runtime.WithHTTPPathPattern("/api/v1/node/{node_id}/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_MoveNode_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_MoveNode_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_HeadscaleService_BackfillNodeIPs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle(http.MethodPost, pattern_HeadscaleService_BackfillNodeIPs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
@@ -1832,7 +1753,6 @@ var (
pattern_HeadscaleService_ExpireNode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "node", "node_id", "expire"}, "")) pattern_HeadscaleService_ExpireNode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "node", "node_id", "expire"}, ""))
pattern_HeadscaleService_RenameNode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "node", "node_id", "rename", "new_name"}, "")) pattern_HeadscaleService_RenameNode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "node", "node_id", "rename", "new_name"}, ""))
pattern_HeadscaleService_ListNodes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "node"}, "")) pattern_HeadscaleService_ListNodes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "node"}, ""))
pattern_HeadscaleService_MoveNode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "node", "node_id", "user"}, ""))
pattern_HeadscaleService_BackfillNodeIPs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "node", "backfillips"}, "")) pattern_HeadscaleService_BackfillNodeIPs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "node", "backfillips"}, ""))
pattern_HeadscaleService_CreateApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "apikey"}, "")) pattern_HeadscaleService_CreateApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "apikey"}, ""))
pattern_HeadscaleService_ExpireApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "apikey", "expire"}, "")) pattern_HeadscaleService_ExpireApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "apikey", "expire"}, ""))
@@ -1860,7 +1780,6 @@ var (
forward_HeadscaleService_ExpireNode_0 = runtime.ForwardResponseMessage forward_HeadscaleService_ExpireNode_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_RenameNode_0 = runtime.ForwardResponseMessage forward_HeadscaleService_RenameNode_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ListNodes_0 = runtime.ForwardResponseMessage forward_HeadscaleService_ListNodes_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_MoveNode_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_BackfillNodeIPs_0 = runtime.ForwardResponseMessage forward_HeadscaleService_BackfillNodeIPs_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_CreateApiKey_0 = runtime.ForwardResponseMessage forward_HeadscaleService_CreateApiKey_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ExpireApiKey_0 = runtime.ForwardResponseMessage forward_HeadscaleService_ExpireApiKey_0 = runtime.ForwardResponseMessage

View File

@@ -35,7 +35,6 @@ const (
HeadscaleService_ExpireNode_FullMethodName = "/headscale.v1.HeadscaleService/ExpireNode" HeadscaleService_ExpireNode_FullMethodName = "/headscale.v1.HeadscaleService/ExpireNode"
HeadscaleService_RenameNode_FullMethodName = "/headscale.v1.HeadscaleService/RenameNode" HeadscaleService_RenameNode_FullMethodName = "/headscale.v1.HeadscaleService/RenameNode"
HeadscaleService_ListNodes_FullMethodName = "/headscale.v1.HeadscaleService/ListNodes" HeadscaleService_ListNodes_FullMethodName = "/headscale.v1.HeadscaleService/ListNodes"
HeadscaleService_MoveNode_FullMethodName = "/headscale.v1.HeadscaleService/MoveNode"
HeadscaleService_BackfillNodeIPs_FullMethodName = "/headscale.v1.HeadscaleService/BackfillNodeIPs" HeadscaleService_BackfillNodeIPs_FullMethodName = "/headscale.v1.HeadscaleService/BackfillNodeIPs"
HeadscaleService_CreateApiKey_FullMethodName = "/headscale.v1.HeadscaleService/CreateApiKey" HeadscaleService_CreateApiKey_FullMethodName = "/headscale.v1.HeadscaleService/CreateApiKey"
HeadscaleService_ExpireApiKey_FullMethodName = "/headscale.v1.HeadscaleService/ExpireApiKey" HeadscaleService_ExpireApiKey_FullMethodName = "/headscale.v1.HeadscaleService/ExpireApiKey"
@@ -69,7 +68,6 @@ type HeadscaleServiceClient interface {
ExpireNode(ctx context.Context, in *ExpireNodeRequest, opts ...grpc.CallOption) (*ExpireNodeResponse, error) ExpireNode(ctx context.Context, in *ExpireNodeRequest, opts ...grpc.CallOption) (*ExpireNodeResponse, error)
RenameNode(ctx context.Context, in *RenameNodeRequest, opts ...grpc.CallOption) (*RenameNodeResponse, error) RenameNode(ctx context.Context, in *RenameNodeRequest, opts ...grpc.CallOption) (*RenameNodeResponse, error)
ListNodes(ctx context.Context, in *ListNodesRequest, opts ...grpc.CallOption) (*ListNodesResponse, error) ListNodes(ctx context.Context, in *ListNodesRequest, opts ...grpc.CallOption) (*ListNodesResponse, error)
MoveNode(ctx context.Context, in *MoveNodeRequest, opts ...grpc.CallOption) (*MoveNodeResponse, error)
BackfillNodeIPs(ctx context.Context, in *BackfillNodeIPsRequest, opts ...grpc.CallOption) (*BackfillNodeIPsResponse, error) BackfillNodeIPs(ctx context.Context, in *BackfillNodeIPsRequest, opts ...grpc.CallOption) (*BackfillNodeIPsResponse, error)
// --- ApiKeys start --- // --- ApiKeys start ---
CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error) CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error)
@@ -251,16 +249,6 @@ func (c *headscaleServiceClient) ListNodes(ctx context.Context, in *ListNodesReq
return out, nil return out, nil
} }
func (c *headscaleServiceClient) MoveNode(ctx context.Context, in *MoveNodeRequest, opts ...grpc.CallOption) (*MoveNodeResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MoveNodeResponse)
err := c.cc.Invoke(ctx, HeadscaleService_MoveNode_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *headscaleServiceClient) BackfillNodeIPs(ctx context.Context, in *BackfillNodeIPsRequest, opts ...grpc.CallOption) (*BackfillNodeIPsResponse, error) { func (c *headscaleServiceClient) BackfillNodeIPs(ctx context.Context, in *BackfillNodeIPsRequest, opts ...grpc.CallOption) (*BackfillNodeIPsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BackfillNodeIPsResponse) out := new(BackfillNodeIPsResponse)
@@ -364,7 +352,6 @@ type HeadscaleServiceServer interface {
ExpireNode(context.Context, *ExpireNodeRequest) (*ExpireNodeResponse, error) ExpireNode(context.Context, *ExpireNodeRequest) (*ExpireNodeResponse, error)
RenameNode(context.Context, *RenameNodeRequest) (*RenameNodeResponse, error) RenameNode(context.Context, *RenameNodeRequest) (*RenameNodeResponse, error)
ListNodes(context.Context, *ListNodesRequest) (*ListNodesResponse, error) ListNodes(context.Context, *ListNodesRequest) (*ListNodesResponse, error)
MoveNode(context.Context, *MoveNodeRequest) (*MoveNodeResponse, error)
BackfillNodeIPs(context.Context, *BackfillNodeIPsRequest) (*BackfillNodeIPsResponse, error) BackfillNodeIPs(context.Context, *BackfillNodeIPsRequest) (*BackfillNodeIPsResponse, error)
// --- ApiKeys start --- // --- ApiKeys start ---
CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error) CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error)
@@ -434,9 +421,6 @@ func (UnimplementedHeadscaleServiceServer) RenameNode(context.Context, *RenameNo
func (UnimplementedHeadscaleServiceServer) ListNodes(context.Context, *ListNodesRequest) (*ListNodesResponse, error) { func (UnimplementedHeadscaleServiceServer) ListNodes(context.Context, *ListNodesRequest) (*ListNodesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListNodes not implemented") return nil, status.Errorf(codes.Unimplemented, "method ListNodes not implemented")
} }
func (UnimplementedHeadscaleServiceServer) MoveNode(context.Context, *MoveNodeRequest) (*MoveNodeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method MoveNode not implemented")
}
func (UnimplementedHeadscaleServiceServer) BackfillNodeIPs(context.Context, *BackfillNodeIPsRequest) (*BackfillNodeIPsResponse, error) { func (UnimplementedHeadscaleServiceServer) BackfillNodeIPs(context.Context, *BackfillNodeIPsRequest) (*BackfillNodeIPsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method BackfillNodeIPs not implemented") return nil, status.Errorf(codes.Unimplemented, "method BackfillNodeIPs not implemented")
} }
@@ -770,24 +754,6 @@ func _HeadscaleService_ListNodes_Handler(srv interface{}, ctx context.Context, d
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _HeadscaleService_MoveNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MoveNodeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).MoveNode(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: HeadscaleService_MoveNode_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).MoveNode(ctx, req.(*MoveNodeRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_BackfillNodeIPs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _HeadscaleService_BackfillNodeIPs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BackfillNodeIPsRequest) in := new(BackfillNodeIPsRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@@ -1003,10 +969,6 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{
MethodName: "ListNodes", MethodName: "ListNodes",
Handler: _HeadscaleService_ListNodes_Handler, Handler: _HeadscaleService_ListNodes_Handler,
}, },
{
MethodName: "MoveNode",
Handler: _HeadscaleService_MoveNode_Handler,
},
{ {
MethodName: "BackfillNodeIPs", MethodName: "BackfillNodeIPs",
Handler: _HeadscaleService_BackfillNodeIPs_Handler, Handler: _HeadscaleService_BackfillNodeIPs_Handler,

View File

@@ -1006,102 +1006,6 @@ func (x *ListNodesResponse) GetNodes() []*Node {
return nil return nil
} }
type MoveNodeRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
User uint64 `protobuf:"varint,2,opt,name=user,proto3" json:"user,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MoveNodeRequest) Reset() {
*x = MoveNodeRequest{}
mi := &file_headscale_v1_node_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MoveNodeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MoveNodeRequest) ProtoMessage() {}
func (x *MoveNodeRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_node_proto_msgTypes[17]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MoveNodeRequest.ProtoReflect.Descriptor instead.
func (*MoveNodeRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_node_proto_rawDescGZIP(), []int{17}
}
func (x *MoveNodeRequest) GetNodeId() uint64 {
if x != nil {
return x.NodeId
}
return 0
}
func (x *MoveNodeRequest) GetUser() uint64 {
if x != nil {
return x.User
}
return 0
}
type MoveNodeResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MoveNodeResponse) Reset() {
*x = MoveNodeResponse{}
mi := &file_headscale_v1_node_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MoveNodeResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MoveNodeResponse) ProtoMessage() {}
func (x *MoveNodeResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_node_proto_msgTypes[18]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MoveNodeResponse.ProtoReflect.Descriptor instead.
func (*MoveNodeResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_node_proto_rawDescGZIP(), []int{18}
}
func (x *MoveNodeResponse) GetNode() *Node {
if x != nil {
return x.Node
}
return nil
}
type DebugCreateNodeRequest struct { type DebugCreateNodeRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
@@ -1114,7 +1018,7 @@ type DebugCreateNodeRequest struct {
func (x *DebugCreateNodeRequest) Reset() { func (x *DebugCreateNodeRequest) Reset() {
*x = DebugCreateNodeRequest{} *x = DebugCreateNodeRequest{}
mi := &file_headscale_v1_node_proto_msgTypes[19] mi := &file_headscale_v1_node_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1126,7 +1030,7 @@ func (x *DebugCreateNodeRequest) String() string {
func (*DebugCreateNodeRequest) ProtoMessage() {} func (*DebugCreateNodeRequest) ProtoMessage() {}
func (x *DebugCreateNodeRequest) ProtoReflect() protoreflect.Message { func (x *DebugCreateNodeRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_node_proto_msgTypes[19] mi := &file_headscale_v1_node_proto_msgTypes[17]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1139,7 +1043,7 @@ func (x *DebugCreateNodeRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DebugCreateNodeRequest.ProtoReflect.Descriptor instead. // Deprecated: Use DebugCreateNodeRequest.ProtoReflect.Descriptor instead.
func (*DebugCreateNodeRequest) Descriptor() ([]byte, []int) { func (*DebugCreateNodeRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_node_proto_rawDescGZIP(), []int{19} return file_headscale_v1_node_proto_rawDescGZIP(), []int{17}
} }
func (x *DebugCreateNodeRequest) GetUser() string { func (x *DebugCreateNodeRequest) GetUser() string {
@@ -1179,7 +1083,7 @@ type DebugCreateNodeResponse struct {
func (x *DebugCreateNodeResponse) Reset() { func (x *DebugCreateNodeResponse) Reset() {
*x = DebugCreateNodeResponse{} *x = DebugCreateNodeResponse{}
mi := &file_headscale_v1_node_proto_msgTypes[20] mi := &file_headscale_v1_node_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1191,7 +1095,7 @@ func (x *DebugCreateNodeResponse) String() string {
func (*DebugCreateNodeResponse) ProtoMessage() {} func (*DebugCreateNodeResponse) ProtoMessage() {}
func (x *DebugCreateNodeResponse) ProtoReflect() protoreflect.Message { func (x *DebugCreateNodeResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_node_proto_msgTypes[20] mi := &file_headscale_v1_node_proto_msgTypes[18]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1204,7 +1108,7 @@ func (x *DebugCreateNodeResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DebugCreateNodeResponse.ProtoReflect.Descriptor instead. // Deprecated: Use DebugCreateNodeResponse.ProtoReflect.Descriptor instead.
func (*DebugCreateNodeResponse) Descriptor() ([]byte, []int) { func (*DebugCreateNodeResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_node_proto_rawDescGZIP(), []int{20} return file_headscale_v1_node_proto_rawDescGZIP(), []int{18}
} }
func (x *DebugCreateNodeResponse) GetNode() *Node { func (x *DebugCreateNodeResponse) GetNode() *Node {
@@ -1223,7 +1127,7 @@ type BackfillNodeIPsRequest struct {
func (x *BackfillNodeIPsRequest) Reset() { func (x *BackfillNodeIPsRequest) Reset() {
*x = BackfillNodeIPsRequest{} *x = BackfillNodeIPsRequest{}
mi := &file_headscale_v1_node_proto_msgTypes[21] mi := &file_headscale_v1_node_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1235,7 +1139,7 @@ func (x *BackfillNodeIPsRequest) String() string {
func (*BackfillNodeIPsRequest) ProtoMessage() {} func (*BackfillNodeIPsRequest) ProtoMessage() {}
func (x *BackfillNodeIPsRequest) ProtoReflect() protoreflect.Message { func (x *BackfillNodeIPsRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_node_proto_msgTypes[21] mi := &file_headscale_v1_node_proto_msgTypes[19]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1248,7 +1152,7 @@ func (x *BackfillNodeIPsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use BackfillNodeIPsRequest.ProtoReflect.Descriptor instead. // Deprecated: Use BackfillNodeIPsRequest.ProtoReflect.Descriptor instead.
func (*BackfillNodeIPsRequest) Descriptor() ([]byte, []int) { func (*BackfillNodeIPsRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_node_proto_rawDescGZIP(), []int{21} return file_headscale_v1_node_proto_rawDescGZIP(), []int{19}
} }
func (x *BackfillNodeIPsRequest) GetConfirmed() bool { func (x *BackfillNodeIPsRequest) GetConfirmed() bool {
@@ -1267,7 +1171,7 @@ type BackfillNodeIPsResponse struct {
func (x *BackfillNodeIPsResponse) Reset() { func (x *BackfillNodeIPsResponse) Reset() {
*x = BackfillNodeIPsResponse{} *x = BackfillNodeIPsResponse{}
mi := &file_headscale_v1_node_proto_msgTypes[22] mi := &file_headscale_v1_node_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1279,7 +1183,7 @@ func (x *BackfillNodeIPsResponse) String() string {
func (*BackfillNodeIPsResponse) ProtoMessage() {} func (*BackfillNodeIPsResponse) ProtoMessage() {}
func (x *BackfillNodeIPsResponse) ProtoReflect() protoreflect.Message { func (x *BackfillNodeIPsResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_node_proto_msgTypes[22] mi := &file_headscale_v1_node_proto_msgTypes[20]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1292,7 +1196,7 @@ func (x *BackfillNodeIPsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use BackfillNodeIPsResponse.ProtoReflect.Descriptor instead. // Deprecated: Use BackfillNodeIPsResponse.ProtoReflect.Descriptor instead.
func (*BackfillNodeIPsResponse) Descriptor() ([]byte, []int) { func (*BackfillNodeIPsResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_node_proto_rawDescGZIP(), []int{22} return file_headscale_v1_node_proto_rawDescGZIP(), []int{20}
} }
func (x *BackfillNodeIPsResponse) GetChanges() []string { func (x *BackfillNodeIPsResponse) GetChanges() []string {
@@ -1371,12 +1275,7 @@ const file_headscale_v1_node_proto_rawDesc = "" +
"\x10ListNodesRequest\x12\x12\n" + "\x10ListNodesRequest\x12\x12\n" +
"\x04user\x18\x01 \x01(\tR\x04user\"=\n" + "\x04user\x18\x01 \x01(\tR\x04user\"=\n" +
"\x11ListNodesResponse\x12(\n" + "\x11ListNodesResponse\x12(\n" +
"\x05nodes\x18\x01 \x03(\v2\x12.headscale.v1.NodeR\x05nodes\">\n" + "\x05nodes\x18\x01 \x03(\v2\x12.headscale.v1.NodeR\x05nodes\"j\n" +
"\x0fMoveNodeRequest\x12\x17\n" +
"\anode_id\x18\x01 \x01(\x04R\x06nodeId\x12\x12\n" +
"\x04user\x18\x02 \x01(\x04R\x04user\":\n" +
"\x10MoveNodeResponse\x12&\n" +
"\x04node\x18\x01 \x01(\v2\x12.headscale.v1.NodeR\x04node\"j\n" +
"\x16DebugCreateNodeRequest\x12\x12\n" + "\x16DebugCreateNodeRequest\x12\x12\n" +
"\x04user\x18\x01 \x01(\tR\x04user\x12\x10\n" + "\x04user\x18\x01 \x01(\tR\x04user\x12\x10\n" +
"\x03key\x18\x02 \x01(\tR\x03key\x12\x12\n" + "\x03key\x18\x02 \x01(\tR\x03key\x12\x12\n" +
@@ -1407,7 +1306,7 @@ func file_headscale_v1_node_proto_rawDescGZIP() []byte {
} }
var file_headscale_v1_node_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_headscale_v1_node_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_headscale_v1_node_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_headscale_v1_node_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
var file_headscale_v1_node_proto_goTypes = []any{ var file_headscale_v1_node_proto_goTypes = []any{
(RegisterMethod)(0), // 0: headscale.v1.RegisterMethod (RegisterMethod)(0), // 0: headscale.v1.RegisterMethod
(*Node)(nil), // 1: headscale.v1.Node (*Node)(nil), // 1: headscale.v1.Node
@@ -1427,38 +1326,35 @@ var file_headscale_v1_node_proto_goTypes = []any{
(*RenameNodeResponse)(nil), // 15: headscale.v1.RenameNodeResponse (*RenameNodeResponse)(nil), // 15: headscale.v1.RenameNodeResponse
(*ListNodesRequest)(nil), // 16: headscale.v1.ListNodesRequest (*ListNodesRequest)(nil), // 16: headscale.v1.ListNodesRequest
(*ListNodesResponse)(nil), // 17: headscale.v1.ListNodesResponse (*ListNodesResponse)(nil), // 17: headscale.v1.ListNodesResponse
(*MoveNodeRequest)(nil), // 18: headscale.v1.MoveNodeRequest (*DebugCreateNodeRequest)(nil), // 18: headscale.v1.DebugCreateNodeRequest
(*MoveNodeResponse)(nil), // 19: headscale.v1.MoveNodeResponse (*DebugCreateNodeResponse)(nil), // 19: headscale.v1.DebugCreateNodeResponse
(*DebugCreateNodeRequest)(nil), // 20: headscale.v1.DebugCreateNodeRequest (*BackfillNodeIPsRequest)(nil), // 20: headscale.v1.BackfillNodeIPsRequest
(*DebugCreateNodeResponse)(nil), // 21: headscale.v1.DebugCreateNodeResponse (*BackfillNodeIPsResponse)(nil), // 21: headscale.v1.BackfillNodeIPsResponse
(*BackfillNodeIPsRequest)(nil), // 22: headscale.v1.BackfillNodeIPsRequest (*User)(nil), // 22: headscale.v1.User
(*BackfillNodeIPsResponse)(nil), // 23: headscale.v1.BackfillNodeIPsResponse (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp
(*User)(nil), // 24: headscale.v1.User (*PreAuthKey)(nil), // 24: headscale.v1.PreAuthKey
(*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp
(*PreAuthKey)(nil), // 26: headscale.v1.PreAuthKey
} }
var file_headscale_v1_node_proto_depIdxs = []int32{ var file_headscale_v1_node_proto_depIdxs = []int32{
24, // 0: headscale.v1.Node.user:type_name -> headscale.v1.User 22, // 0: headscale.v1.Node.user:type_name -> headscale.v1.User
25, // 1: headscale.v1.Node.last_seen:type_name -> google.protobuf.Timestamp 23, // 1: headscale.v1.Node.last_seen:type_name -> google.protobuf.Timestamp
25, // 2: headscale.v1.Node.expiry:type_name -> google.protobuf.Timestamp 23, // 2: headscale.v1.Node.expiry:type_name -> google.protobuf.Timestamp
26, // 3: headscale.v1.Node.pre_auth_key:type_name -> headscale.v1.PreAuthKey 24, // 3: headscale.v1.Node.pre_auth_key:type_name -> headscale.v1.PreAuthKey
25, // 4: headscale.v1.Node.created_at:type_name -> google.protobuf.Timestamp 23, // 4: headscale.v1.Node.created_at:type_name -> google.protobuf.Timestamp
0, // 5: headscale.v1.Node.register_method:type_name -> headscale.v1.RegisterMethod 0, // 5: headscale.v1.Node.register_method:type_name -> headscale.v1.RegisterMethod
1, // 6: headscale.v1.RegisterNodeResponse.node:type_name -> headscale.v1.Node 1, // 6: headscale.v1.RegisterNodeResponse.node:type_name -> headscale.v1.Node
1, // 7: headscale.v1.GetNodeResponse.node:type_name -> headscale.v1.Node 1, // 7: headscale.v1.GetNodeResponse.node:type_name -> headscale.v1.Node
1, // 8: headscale.v1.SetTagsResponse.node:type_name -> headscale.v1.Node 1, // 8: headscale.v1.SetTagsResponse.node:type_name -> headscale.v1.Node
1, // 9: headscale.v1.SetApprovedRoutesResponse.node:type_name -> headscale.v1.Node 1, // 9: headscale.v1.SetApprovedRoutesResponse.node:type_name -> headscale.v1.Node
25, // 10: headscale.v1.ExpireNodeRequest.expiry:type_name -> google.protobuf.Timestamp 23, // 10: headscale.v1.ExpireNodeRequest.expiry:type_name -> google.protobuf.Timestamp
1, // 11: headscale.v1.ExpireNodeResponse.node:type_name -> headscale.v1.Node 1, // 11: headscale.v1.ExpireNodeResponse.node:type_name -> headscale.v1.Node
1, // 12: headscale.v1.RenameNodeResponse.node:type_name -> headscale.v1.Node 1, // 12: headscale.v1.RenameNodeResponse.node:type_name -> headscale.v1.Node
1, // 13: headscale.v1.ListNodesResponse.nodes:type_name -> headscale.v1.Node 1, // 13: headscale.v1.ListNodesResponse.nodes:type_name -> headscale.v1.Node
1, // 14: headscale.v1.MoveNodeResponse.node:type_name -> headscale.v1.Node 1, // 14: headscale.v1.DebugCreateNodeResponse.node:type_name -> headscale.v1.Node
1, // 15: headscale.v1.DebugCreateNodeResponse.node:type_name -> headscale.v1.Node 15, // [15:15] is the sub-list for method output_type
16, // [16:16] is the sub-list for method output_type 15, // [15:15] is the sub-list for method input_type
16, // [16:16] is the sub-list for method input_type 15, // [15:15] is the sub-list for extension type_name
16, // [16:16] is the sub-list for extension type_name 15, // [15:15] is the sub-list for extension extendee
16, // [16:16] is the sub-list for extension extendee 0, // [0:15] is the sub-list for field type_name
0, // [0:16] is the sub-list for field type_name
} }
func init() { file_headscale_v1_node_proto_init() } func init() { file_headscale_v1_node_proto_init() }
@@ -1474,7 +1370,7 @@ func file_headscale_v1_node_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_headscale_v1_node_proto_rawDesc), len(file_headscale_v1_node_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_headscale_v1_node_proto_rawDesc), len(file_headscale_v1_node_proto_rawDesc)),
NumEnums: 1, NumEnums: 1,
NumMessages: 23, NumMessages: 21,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@@ -496,45 +496,6 @@
] ]
} }
}, },
"/api/v1/node/{nodeId}/user": {
"post": {
"operationId": "HeadscaleService_MoveNode",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1MoveNodeResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "nodeId",
"in": "path",
"required": true,
"type": "string",
"format": "uint64"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/HeadscaleServiceMoveNodeBody"
}
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/policy": { "/api/v1/policy": {
"get": { "get": {
"summary": "--- Policy start ---", "summary": "--- Policy start ---",
@@ -826,15 +787,6 @@
} }
}, },
"definitions": { "definitions": {
"HeadscaleServiceMoveNodeBody": {
"type": "object",
"properties": {
"user": {
"type": "string",
"format": "uint64"
}
}
},
"HeadscaleServiceSetApprovedRoutesBody": { "HeadscaleServiceSetApprovedRoutesBody": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1142,14 +1094,6 @@
} }
} }
}, },
"v1MoveNodeResponse": {
"type": "object",
"properties": {
"node": {
"$ref": "#/definitions/v1Node"
}
}
},
"v1Node": { "v1Node": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -196,26 +196,6 @@ func ListNodesByUser(tx *gorm.DB, uid types.UserID) (types.Nodes, error) {
return nodes, nil return nodes, nil
} }
// AssignNodeToUser assigns a Node to a user.
// Note: Validation should be done in the state layer before calling this function.
func AssignNodeToUser(tx *gorm.DB, nodeID types.NodeID, uid types.UserID) error {
// Check if the user exists
var userExists bool
if err := tx.Model(&types.User{}).Select("count(*) > 0").Where("id = ?", uid).Find(&userExists).Error; err != nil {
return fmt.Errorf("failed to check if user exists: %w", err)
}
if !userExists {
return ErrUserNotFound
}
if err := tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("user_id", uid).Error; err != nil {
return fmt.Errorf("failed to assign node to user: %w", err)
}
return nil
}
func (hsdb *HSDatabase) CreateUserForTest(name ...string) *types.User { func (hsdb *HSDatabase) CreateUserForTest(name ...string) *types.User {
if !testing.Testing() { if !testing.Testing() {
panic("CreateUserForTest can only be called during tests") panic("CreateUserForTest can only be called during tests")

View File

@@ -165,112 +165,3 @@ func TestRenameUser(t *testing.T) {
}) })
} }
} }
func TestAssignNodeToUser(t *testing.T) {
tests := []struct {
name string
test func(*testing.T, *HSDatabase)
}{
{
name: "success_reassign_node",
test: func(t *testing.T, db *HSDatabase) {
t.Helper()
oldUser := db.CreateUserForTest("old")
newUser := db.CreateUserForTest("new")
pak, err := db.CreatePreAuthKey(types.UserID(oldUser.ID), false, false, nil, nil)
require.NoError(t, err)
node := types.Node{
ID: 12,
Hostname: "testnode",
UserID: oldUser.ID,
RegisterMethod: util.RegisterMethodAuthKey,
AuthKeyID: ptr.To(pak.ID),
}
trx := db.DB.Save(&node)
require.NoError(t, trx.Error)
assert.Equal(t, oldUser.ID, node.UserID)
err = db.Write(func(tx *gorm.DB) error {
return AssignNodeToUser(tx, 12, types.UserID(newUser.ID))
})
require.NoError(t, err)
// Reload node from database to see updated values
updatedNode, err := db.GetNodeByID(12)
require.NoError(t, err)
assert.Equal(t, newUser.ID, updatedNode.UserID)
assert.Equal(t, newUser.Name, updatedNode.User.Name)
},
},
{
name: "error_user_not_found",
test: func(t *testing.T, db *HSDatabase) {
t.Helper()
oldUser := db.CreateUserForTest("old")
pak, err := db.CreatePreAuthKey(types.UserID(oldUser.ID), false, false, nil, nil)
require.NoError(t, err)
node := types.Node{
ID: 12,
Hostname: "testnode",
UserID: oldUser.ID,
RegisterMethod: util.RegisterMethodAuthKey,
AuthKeyID: ptr.To(pak.ID),
}
trx := db.DB.Save(&node)
require.NoError(t, trx.Error)
err = db.Write(func(tx *gorm.DB) error {
return AssignNodeToUser(tx, 12, 9584849)
})
assert.ErrorIs(t, err, ErrUserNotFound)
},
},
{
name: "success_reassign_to_same_user",
test: func(t *testing.T, db *HSDatabase) {
t.Helper()
user := db.CreateUserForTest("user")
pak, err := db.CreatePreAuthKey(types.UserID(user.ID), false, false, nil, nil)
require.NoError(t, err)
node := types.Node{
ID: 12,
Hostname: "testnode",
UserID: user.ID,
RegisterMethod: util.RegisterMethodAuthKey,
AuthKeyID: ptr.To(pak.ID),
}
trx := db.DB.Save(&node)
require.NoError(t, trx.Error)
err = db.Write(func(tx *gorm.DB) error {
return AssignNodeToUser(tx, 12, types.UserID(user.ID))
})
require.NoError(t, err)
// Reload node from database again to see updated values
finalNode, err := db.GetNodeByID(12)
require.NoError(t, err)
assert.Equal(t, user.ID, finalNode.UserID)
assert.Equal(t, user.Name, finalNode.User.Name)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
db, err := newSQLiteTestDB()
require.NoError(t, err)
tt.test(t, db)
})
}
}

View File

@@ -527,22 +527,6 @@ func nodesToProto(state *state.State, nodes views.Slice[types.NodeView]) []*v1.N
return response return response
} }
func (api headscaleV1APIServer) MoveNode(
ctx context.Context,
request *v1.MoveNodeRequest,
) (*v1.MoveNodeResponse, error) {
node, nodeChange, err := api.h.state.AssignNodeToUser(types.NodeID(request.GetNodeId()), types.UserID(request.GetUser()))
if err != nil {
return nil, err
}
// TODO(kradalby): Ensure the policy is also sent
// TODO(kradalby): ensure that both the selfupdate and peer updates are sent
api.h.Change(nodeChange)
return &v1.MoveNodeResponse{Node: node.Proto()}, nil
}
func (api headscaleV1APIServer) BackfillNodeIPs( func (api headscaleV1APIServer) BackfillNodeIPs(
ctx context.Context, ctx context.Context,
request *v1.BackfillNodeIPsRequest, request *v1.BackfillNodeIPsRequest,

View File

@@ -729,34 +729,6 @@ func (s *State) RenameNode(nodeID types.NodeID, newName string) (types.NodeView,
return s.persistNodeToDB(n) return s.persistNodeToDB(n)
} }
// AssignNodeToUser transfers a node to a different user.
func (s *State) AssignNodeToUser(nodeID types.NodeID, userID types.UserID) (types.NodeView, change.ChangeSet, error) {
// Validate that both node and user exist
_, found := s.GetNodeByID(nodeID)
if !found {
return types.NodeView{}, change.EmptySet, fmt.Errorf("node not found: %d", nodeID)
}
user, err := s.GetUserByID(userID)
if err != nil {
return types.NodeView{}, change.EmptySet, fmt.Errorf("user not found: %w", err)
}
// Update NodeStore before database to ensure consistency. The NodeStore update is
// blocking and will be the source of truth for the batcher. The database update must
// make the exact same change.
n, ok := s.nodeStore.UpdateNode(nodeID, func(n *types.Node) {
n.User = *user
n.UserID = uint(userID)
})
if !ok {
return types.NodeView{}, change.EmptySet, fmt.Errorf("node not found in NodeStore: %d", nodeID)
}
return s.persistNodeToDB(n)
}
// BackfillNodeIPs assigns IP addresses to nodes that don't have them. // BackfillNodeIPs assigns IP addresses to nodes that don't have them.
func (s *State) BackfillNodeIPs() ([]string, error) { func (s *State) BackfillNodeIPs() ([]string, error) {
changes, err := s.db.BackfillNodeIPs(s.ipAlloc) changes, err := s.db.BackfillNodeIPs(s.ipAlloc)

View File

@@ -1644,178 +1644,6 @@ func TestNodeRenameCommand(t *testing.T) {
assert.Contains(t, listAllAfterRenameAttempt[4].GetGivenName(), "node-5") assert.Contains(t, listAllAfterRenameAttempt[4].GetGivenName(), "node-5")
} }
func TestNodeMoveCommand(t *testing.T) {
IntegrationSkip(t)
spec := ScenarioSpec{
Users: []string{"old-user", "new-user"},
}
scenario, err := NewScenario(spec)
require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
require.NoError(t, err)
headscale, err := scenario.Headscale()
require.NoError(t, err)
// Randomly generated node key
regID := types.MustRegistrationID()
userMap, err := headscale.MapUsers()
require.NoError(t, err)
_, err = headscale.Execute(
[]string{
"headscale",
"debug",
"create-node",
"--name",
"nomad-node",
"--user",
"old-user",
"--key",
regID.String(),
"--output",
"json",
},
)
assert.NoError(t, err)
var node v1.Node
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err = executeAndUnmarshal(
headscale,
[]string{
"headscale",
"nodes",
"--user",
"old-user",
"register",
"--key",
regID.String(),
"--output",
"json",
},
&node,
)
assert.NoError(c, err)
}, 10*time.Second, 200*time.Millisecond, "Waiting for old-user node registration")
assert.Equal(t, uint64(1), node.GetId())
assert.Equal(t, "nomad-node", node.GetName())
assert.Equal(t, "old-user", node.GetUser().GetName())
nodeID := strconv.FormatUint(node.GetId(), 10)
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err = executeAndUnmarshal(
headscale,
[]string{
"headscale",
"nodes",
"move",
"--identifier",
strconv.FormatUint(node.GetId(), 10),
"--user",
strconv.FormatUint(userMap["new-user"].GetId(), 10),
"--output",
"json",
},
&node,
)
assert.NoError(c, err)
}, 10*time.Second, 200*time.Millisecond, "Waiting for node move to new-user")
assert.Equal(t, "new-user", node.GetUser().GetName())
var allNodes []v1.Node
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err = executeAndUnmarshal(
headscale,
[]string{
"headscale",
"nodes",
"list",
"--output",
"json",
},
&allNodes,
)
assert.NoError(c, err)
}, 10*time.Second, 200*time.Millisecond, "Waiting for nodes list after move")
assert.Len(t, allNodes, 1)
assert.Equal(t, allNodes[0].GetId(), node.GetId())
assert.Equal(t, allNodes[0].GetUser(), node.GetUser())
assert.Equal(t, "new-user", allNodes[0].GetUser().GetName())
_, err = headscale.Execute(
[]string{
"headscale",
"nodes",
"move",
"--identifier",
nodeID,
"--user",
"999",
"--output",
"json",
},
)
assert.ErrorContains(
t,
err,
"user not found",
)
assert.Equal(t, "new-user", node.GetUser().GetName())
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err = executeAndUnmarshal(
headscale,
[]string{
"headscale",
"nodes",
"move",
"--identifier",
nodeID,
"--user",
strconv.FormatUint(userMap["old-user"].GetId(), 10),
"--output",
"json",
},
&node,
)
assert.NoError(c, err)
}, 10*time.Second, 200*time.Millisecond, "Waiting for node move back to old-user")
assert.Equal(t, "old-user", node.GetUser().GetName())
assert.EventuallyWithT(t, func(c *assert.CollectT) {
err = executeAndUnmarshal(
headscale,
[]string{
"headscale",
"nodes",
"move",
"--identifier",
nodeID,
"--user",
strconv.FormatUint(userMap["old-user"].GetId(), 10),
"--output",
"json",
},
&node,
)
assert.NoError(c, err)
}, 10*time.Second, 200*time.Millisecond, "Waiting for node move to same user")
assert.Equal(t, "old-user", node.GetUser().GetName())
}
func TestPolicyCommand(t *testing.T) { func TestPolicyCommand(t *testing.T) {
IntegrationSkip(t) IntegrationSkip(t)

View File

@@ -123,13 +123,6 @@ service HeadscaleService {
}; };
} }
rpc MoveNode(MoveNodeRequest) returns (MoveNodeResponse) {
option (google.api.http) = {
post : "/api/v1/node/{node_id}/user",
body : "*"
};
}
rpc BackfillNodeIPs(BackfillNodeIPsRequest) rpc BackfillNodeIPs(BackfillNodeIPsRequest)
returns (BackfillNodeIPsResponse) { returns (BackfillNodeIPsResponse) {
option (google.api.http) = { option (google.api.http) = {

View File

@@ -100,13 +100,6 @@ message ListNodesRequest { string user = 1; }
message ListNodesResponse { repeated Node nodes = 1; } message ListNodesResponse { repeated Node nodes = 1; }
message MoveNodeRequest {
uint64 node_id = 1;
uint64 user = 2;
}
message MoveNodeResponse { Node node = 1; }
message DebugCreateNodeRequest { message DebugCreateNodeRequest {
string user = 1; string user = 1;
string key = 2; string key = 2;