restructure command/api to use stable IDs (#2261)

This commit is contained in:
Kristoffer Dalby 2024-12-10 16:23:55 +01:00 committed by GitHub
parent 08bd4b9bc5
commit 64fd1f9483
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1902 additions and 3613 deletions

View file

@ -1,18 +1,21 @@
package integration
import (
"cmp"
"encoding/json"
"fmt"
"sort"
"strings"
"testing"
"time"
tcmp "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/juanfont/headscale/hscontrol/policy"
"github.com/juanfont/headscale/integration/hsic"
"github.com/juanfont/headscale/integration/tsic"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/exp/slices"
)
@ -30,6 +33,16 @@ func executeAndUnmarshal[T any](headscale ControlServer, command []string, resul
return nil
}
// Interface ensuring that we can sort structs from gRPC that
// have an ID field.
type GRPCSortable interface {
GetId() uint64
}
func sortWithID[T GRPCSortable](a, b T) int {
return cmp.Compare(a.GetId(), b.GetId())
}
func TestUserCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@ -49,7 +62,7 @@ func TestUserCommand(t *testing.T) {
headscale, err := scenario.Headscale()
assertNoErr(t, err)
var listUsers []v1.User
var listUsers []*v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
@ -62,8 +75,8 @@ func TestUserCommand(t *testing.T) {
)
assertNoErr(t, err)
slices.SortFunc(listUsers, sortWithID)
result := []string{listUsers[0].GetName(), listUsers[1].GetName()}
sort.Strings(result)
assert.Equal(
t,
@ -76,15 +89,14 @@ func TestUserCommand(t *testing.T) {
"headscale",
"users",
"rename",
"--output",
"json",
"user2",
"newname",
"--output=json",
fmt.Sprintf("--identifier=%d", listUsers[1].GetId()),
"--new-name=newname",
},
)
assertNoErr(t, err)
var listAfterRenameUsers []v1.User
var listAfterRenameUsers []*v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
@ -97,14 +109,131 @@ func TestUserCommand(t *testing.T) {
)
assertNoErr(t, err)
slices.SortFunc(listUsers, sortWithID)
result = []string{listAfterRenameUsers[0].GetName(), listAfterRenameUsers[1].GetName()}
sort.Strings(result)
assert.Equal(
t,
[]string{"newname", "user1"},
[]string{"user1", "newname"},
result,
)
var listByUsername []*v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"users",
"list",
"--output",
"json",
"--name=user1",
},
&listByUsername,
)
assertNoErr(t, err)
slices.SortFunc(listByUsername, sortWithID)
want := []*v1.User{
{
Id: 1,
Name: "user1",
},
}
if diff := tcmp.Diff(want, listByUsername, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
t.Errorf("unexpected users (-want +got):\n%s", diff)
}
var listByID []*v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"users",
"list",
"--output",
"json",
"--identifier=1",
},
&listByID,
)
assertNoErr(t, err)
slices.SortFunc(listByID, sortWithID)
want = []*v1.User{
{
Id: 1,
Name: "user1",
},
}
if diff := tcmp.Diff(want, listByID, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
t.Errorf("unexpected users (-want +got):\n%s", diff)
}
deleteResult, err := headscale.Execute(
[]string{
"headscale",
"users",
"destroy",
"--force",
// Delete "user1"
"--identifier=1",
},
)
assert.Nil(t, err)
assert.Contains(t, deleteResult, "User destroyed")
var listAfterIDDelete []*v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"users",
"list",
"--output",
"json",
},
&listAfterIDDelete,
)
assertNoErr(t, err)
slices.SortFunc(listAfterIDDelete, sortWithID)
want = []*v1.User{
{
Id: 2,
Name: "newname",
},
}
if diff := tcmp.Diff(want, listAfterIDDelete, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
t.Errorf("unexpected users (-want +got):\n%s", diff)
}
deleteResult, err = headscale.Execute(
[]string{
"headscale",
"users",
"destroy",
"--force",
"--name=newname",
},
)
assert.Nil(t, err)
assert.Contains(t, deleteResult, "User destroyed")
var listAfterNameDelete []v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"users",
"list",
"--output",
"json",
},
&listAfterNameDelete,
)
assertNoErr(t, err)
require.Len(t, listAfterNameDelete, 0)
}
func TestPreAuthKeyCommand(t *testing.T) {
@ -1716,4 +1845,3 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
)
assert.ErrorContains(t, err, "acl policy not found")
}