1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-07-27 13:48:02 +02:00

pass spec at scenario create

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2025-03-11 09:01:11 +01:00
parent 5f8b3b8072
commit 3e30f82acd
No known key found for this signature in database
12 changed files with 333 additions and 334 deletions

View File

@ -54,15 +54,16 @@ func aclScenario(
clientsPerUser int,
) *Scenario {
t.Helper()
scenario, err := NewScenario(dockertestMaxWait())
require.NoError(t, err)
spec := ScenarioSpec{
NodesPerUser: clientsPerUser,
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
require.NoError(t, err)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{
// Alpine containers dont have ip6tables set up, which causes
// tailscaled to stop configuring the wgengine, causing it
@ -256,12 +257,11 @@ func TestACLHostsInNetMapTable(t *testing.T) {
for name, testCase := range tests {
t.Run(name, func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait())
caseSpec := testCase.users
scenario, err := NewScenario(caseSpec)
require.NoError(t, err)
spec := testCase.users
err = scenario.CreateHeadscaleEnv(spec,
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{},
hsic.WithACLPolicy(&testCase.policy),
)
@ -1009,16 +1009,16 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{
// Alpine containers dont have ip6tables set up, which causes
// tailscaled to stop configuring the wgengine, causing it

View File

@ -19,15 +19,15 @@ func TestAuthKeyLogoutAndReloginSameUser(t *testing.T) {
for _, https := range []bool{true, false} {
t.Run(fmt.Sprintf("with-https-%t", https), func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
opts := []hsic.Option{hsic.WithTestName("pingallbyip")}
if https {
opts = append(opts, []hsic.Option{
@ -35,7 +35,7 @@ func TestAuthKeyLogoutAndReloginSameUser(t *testing.T) {
}...)
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, opts...)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, opts...)
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -152,16 +152,16 @@ func TestAuthKeyLogoutAndReloginNewUser(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{},
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{},
hsic.WithTestName("keyrelognewuser"),
hsic.WithTLS(),
)
@ -235,15 +235,15 @@ func TestAuthKeyLogoutAndReloginSameUserExpiredKey(t *testing.T) {
for _, https := range []bool{true, false} {
t.Run(fmt.Sprintf("with-https-%t", https), func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
opts := []hsic.Option{hsic.WithTestName("pingallbyip")}
if https {
opts = append(opts, []hsic.Option{
@ -251,7 +251,7 @@ func TestAuthKeyLogoutAndReloginSameUserExpiredKey(t *testing.T) {
}...)
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, opts...)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, opts...)
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()

View File

@ -51,7 +51,15 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
baseScenario, err := NewScenario(dockertestMaxWait())
// Logins to MockOIDC is served by a queue with a strict order,
// if we use more than one node per user, the order of the logins
// will not be deterministic and the test will fail.
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1", "user2"},
}
baseScenario, err := NewScenario(spec)
assertNoErr(t, err)
scenario := AuthOIDCScenario{
@ -59,14 +67,6 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
// Logins to MockOIDC is served by a queue with a strict order,
// if we use more than one node per user, the order of the logins
// will not be deterministic and the test will fail.
spec := map[string]int{
"user1": 1,
"user2": 1,
}
mockusers := []mockoidc.MockUser{
oidcMockUser("user1", true),
oidcMockUser("user2", false),
@ -84,7 +84,6 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcauthping"),
hsic.WithConfigEnv(oidcMap),
hsic.WithTLS(),
@ -159,7 +158,12 @@ func TestOIDCExpireNodesBasedOnTokenExpiry(t *testing.T) {
shortAccessTTL := 5 * time.Minute
baseScenario, err := NewScenario(dockertestMaxWait())
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1", "user2"},
}
baseScenario, err := NewScenario(spec)
assertNoErr(t, err)
baseScenario.pool.MaxWait = 5 * time.Minute
@ -169,11 +173,6 @@ func TestOIDCExpireNodesBasedOnTokenExpiry(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"user1": 1,
"user2": 1,
}
oidcConfig, err := scenario.runMockOIDC(shortAccessTTL, []mockoidc.MockUser{
oidcMockUser("user1", true),
oidcMockUser("user2", false),
@ -189,7 +188,6 @@ func TestOIDCExpireNodesBasedOnTokenExpiry(t *testing.T) {
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcexpirenodes"),
hsic.WithConfigEnv(oidcMap),
)
@ -335,7 +333,14 @@ func TestOIDC024UserCreation(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
baseScenario, err := NewScenario(dockertestMaxWait())
spec := ScenarioSpec{
NodesPerUser: 1,
}
for _, user := range tt.cliUsers {
spec.Users = append(spec.Users, user)
}
baseScenario, err := NewScenario(spec)
assertNoErr(t, err)
scenario := AuthOIDCScenario{
@ -343,11 +348,6 @@ func TestOIDC024UserCreation(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{}
for _, user := range tt.cliUsers {
spec[user] = 1
}
var mockusers []mockoidc.MockUser
for _, user := range tt.oidcUsers {
mockusers = append(mockusers, oidcMockUser(user, tt.emailVerified))
@ -369,7 +369,6 @@ func TestOIDC024UserCreation(t *testing.T) {
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcmigration"),
hsic.WithConfigEnv(oidcMap),
hsic.WithTLS(),
@ -405,7 +404,13 @@ func TestOIDCAuthenticationWithPKCE(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
baseScenario, err := NewScenario(dockertestMaxWait())
// Single user with one node for testing PKCE flow
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1"},
}
baseScenario, err := NewScenario(spec)
assertNoErr(t, err)
scenario := AuthOIDCScenario{
@ -413,11 +418,6 @@ func TestOIDCAuthenticationWithPKCE(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
// Single user with one node for testing PKCE flow
spec := map[string]int{
"user1": 1,
}
mockusers := []mockoidc.MockUser{
oidcMockUser("user1", true),
}
@ -435,7 +435,6 @@ func TestOIDCAuthenticationWithPKCE(t *testing.T) {
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcauthpkce"),
hsic.WithConfigEnv(oidcMap),
hsic.WithTLS(),
@ -465,7 +464,8 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
baseScenario, err := NewScenario(dockertestMaxWait())
// Create no nodes and no users
baseScenario, err := NewScenario(ScenarioSpec{})
assertNoErr(t, err)
scenario := AuthOIDCScenario{
@ -473,9 +473,6 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
// Create no nodes and no users
spec := map[string]int{}
// First login creates the first OIDC user
// Second login logs in the same node, which creates a new node
// Third login logs in the same node back into the original user
@ -497,7 +494,6 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcauthrelog"),
hsic.WithConfigEnv(oidcMap),
hsic.WithTLS(),
@ -680,7 +676,6 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
}
func (s *AuthOIDCScenario) CreateHeadscaleEnv(
users map[string]int,
opts ...hsic.Option,
) error {
headscale, err := s.Headscale(opts...)
@ -693,21 +688,21 @@ func (s *AuthOIDCScenario) CreateHeadscaleEnv(
return err
}
for userName, clientCount := range users {
if clientCount != 1 {
for _, userName := range s.spec.Users {
if s.spec.NodesPerUser != 1 {
// OIDC scenario only supports one client per user.
// This is because the MockOIDC server can only serve login
// requests based on a queue it has been given on startup.
// We currently only populates it with one login request per user.
return fmt.Errorf("client count must be 1 for OIDC scenario.")
}
log.Printf("creating user %s with %d clients", userName, clientCount)
log.Printf("creating user %s with %d clients", userName, s.spec.NodesPerUser)
err = s.CreateUser(userName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount)
err = s.CreateTailscaleNodesInUser(userName, "all", s.spec.NodesPerUser)
if err != nil {
return err
}

View File

@ -23,9 +23,13 @@ type AuthWebFlowScenario struct {
func TestAuthWebFlowAuthenticationPingAll(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
baseScenario, err := NewScenario(dockertestMaxWait())
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
baseScenario, err := NewScenario(spec)
if err != nil {
t.Fatalf("failed to create scenario: %s", err)
}
@ -35,13 +39,7 @@ func TestAuthWebFlowAuthenticationPingAll(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"user1": len(MustTestVersions),
"user2": len(MustTestVersions),
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("webauthping"),
hsic.WithEmbeddedDERPServerOnly(),
hsic.WithTLS(),
@ -71,7 +69,12 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
baseScenario, err := NewScenario(dockertestMaxWait())
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
baseScenario, err := NewScenario(spec)
assertNoErr(t, err)
scenario := AuthWebFlowScenario{
@ -79,12 +82,7 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"user1": len(MustTestVersions),
"user2": len(MustTestVersions),
}
err = scenario.CreateHeadscaleEnv(spec,
err = scenario.CreateHeadscaleEnv(
hsic.WithTestName("weblogout"),
hsic.WithTLS(),
)
@ -137,7 +135,7 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
t.Logf("all clients logged out")
for userName := range spec {
for _, userName := range spec.Users {
err = scenario.runTailscaleUp(userName, headscale.GetEndpoint())
if err != nil {
t.Fatalf("failed to run tailscale up (%q): %s", headscale.GetEndpoint(), err)
@ -196,7 +194,6 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
users map[string]int,
opts ...hsic.Option,
) error {
headscale, err := s.Headscale(opts...)
@ -209,14 +206,14 @@ func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
return err
}
for userName, clientCount := range users {
log.Printf("creating user %s with %d clients", userName, clientCount)
for _, userName := range s.spec.Users {
log.Printf("creating user %s with %d clients", userName, s.spec.NodesPerUser)
err = s.CreateUser(userName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount)
err = s.CreateTailscaleNodesInUser(userName, "all", s.spec.NodesPerUser)
if err != nil {
return err
}

View File

@ -48,15 +48,15 @@ func TestUserCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -246,15 +246,15 @@ func TestPreAuthKeyCommand(t *testing.T) {
user := "preauthkeyspace"
count := 3
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{user},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipak"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clipak"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -387,16 +387,15 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
t.Parallel()
user := "pre-auth-key-without-exp-user"
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{user},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipaknaexp"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clipaknaexp"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -450,16 +449,15 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
t.Parallel()
user := "pre-auth-key-reus-ephm-user"
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{user},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipakresueeph"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clipakresueeph"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -529,16 +527,15 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
user1 := "user1"
user2 := "user2"
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{user1, user2},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
spec,
[]tsic.Option{},
hsic.WithTestName("clipak"),
hsic.WithEmbeddedDERPServerOnly(),
@ -618,15 +615,15 @@ func TestApiKeyCommand(t *testing.T) {
count := 5
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -785,15 +782,15 @@ func TestNodeTagCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -974,16 +971,16 @@ func TestNodeAdvertiseTagCommand(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{tsic.WithTags([]string{"tag:test"})},
hsic.WithTestName("cliadvtags"),
hsic.WithACLPolicy(tt.policy),
@ -1027,15 +1024,15 @@ func TestNodeCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"node-user", "other-user"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -1266,15 +1263,15 @@ func TestNodeExpireCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"node-expire-user"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -1392,15 +1389,15 @@ func TestNodeRenameCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"node-rename-command"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -1557,15 +1554,15 @@ func TestNodeMoveCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"old-user", "new-user"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err)
headscale, err := scenario.Headscale()
@ -1717,16 +1714,15 @@ func TestPolicyCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
Users: []string{"user1"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
spec,
[]tsic.Option{},
hsic.WithTestName("clins"),
hsic.WithConfigEnv(map[string]string{
@ -1804,17 +1800,16 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
spec,
[]tsic.Option{},
hsic.WithTestName("clins"),
hsic.WithConfigEnv(map[string]string{

View File

@ -31,15 +31,15 @@ func TestDERPVerifyEndpoint(t *testing.T) {
certHeadscale, keyHeadscale, err := integrationutil.CreateCertificate(hostname)
assertNoErr(t, err)
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
derper, err := scenario.CreateDERPServer("head",
dsic.WithCACert(certHeadscale),
dsic.WithVerifyClientURL(fmt.Sprintf("https://%s/verify", net.JoinHostPort(hostname, strconv.Itoa(headscalePort)))),
@ -66,7 +66,7 @@ func TestDERPVerifyEndpoint(t *testing.T) {
},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{tsic.WithCACert(derper.GetCert())},
err = scenario.CreateHeadscaleEnv([]tsic.Option{tsic.WithCACert(derper.GetCert())},
hsic.WithHostname(hostname),
hsic.WithPort(headscalePort),
hsic.WithCustomTLS(certHeadscale, keyHeadscale),

View File

@ -17,16 +17,16 @@ func TestResolveMagicDNS(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("magicdns"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("magicdns"))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -87,15 +87,15 @@ func TestResolveMagicDNSExtraRecordsPath(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1", "user2"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
const erPath = "/tmp/extra_records.json"
extraRecords := []tailcfg.DNSRecord{
@ -107,7 +107,7 @@ func TestResolveMagicDNSExtraRecordsPath(t *testing.T) {
}
b, _ := json.Marshal(extraRecords)
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{
err = scenario.CreateHeadscaleEnv([]tsic.Option{
tsic.WithDockerEntrypoint([]string{
"/bin/sh",
"-c",
@ -364,16 +364,16 @@ func TestValidateResolvConf(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 3,
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("resolvconf"), hsic.WithConfigEnv(tt.conf))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("resolvconf"), hsic.WithConfigEnv(tt.conf))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()

View File

@ -28,16 +28,17 @@ func TestPingAllByIP(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
MaxWait: dockertestMaxWait(),
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{},
hsic.WithTestName("pingallbyip"),
hsic.WithEmbeddedDERPServerOnly(),
@ -69,16 +70,16 @@ func TestPingAllByIPPublicDERP(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{},
hsic.WithTestName("pingallbyippubderp"),
)
@ -119,25 +120,25 @@ func testEphemeralWithOptions(t *testing.T, opts ...hsic.Option) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"user1": len(MustTestVersions),
"user2": len(MustTestVersions),
}
headscale, err := scenario.Headscale(opts...)
assertNoErrHeadscaleEnv(t, err)
for userName, clientCount := range spec {
for _, userName := range spec.Users {
err = scenario.CreateUser(userName)
if err != nil {
t.Fatalf("failed to create user %s: %s", userName, err)
}
err = scenario.CreateTailscaleNodesInUser(userName, "all", clientCount, []tsic.Option{}...)
err = scenario.CreateTailscaleNodesInUser(userName, "all", spec.NodesPerUser, []tsic.Option{}...)
if err != nil {
t.Fatalf("failed to create tailscale nodes in user %s: %s", userName, err)
}
@ -192,15 +193,15 @@ func TestEphemeral2006DeletedTooQuickly(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"user1": len(MustTestVersions),
"user2": len(MustTestVersions),
}
headscale, err := scenario.Headscale(
hsic.WithTestName("ephemeral2006"),
hsic.WithConfigEnv(map[string]string{
@ -209,13 +210,13 @@ func TestEphemeral2006DeletedTooQuickly(t *testing.T) {
)
assertNoErrHeadscaleEnv(t, err)
for userName, clientCount := range spec {
for _, userName := range spec.Users {
err = scenario.CreateUser(userName)
if err != nil {
t.Fatalf("failed to create user %s: %s", userName, err)
}
err = scenario.CreateTailscaleNodesInUser(userName, "all", clientCount, []tsic.Option{}...)
err = scenario.CreateTailscaleNodesInUser(userName, "all", spec.NodesPerUser, []tsic.Option{}...)
if err != nil {
t.Fatalf("failed to create tailscale nodes in user %s: %s", userName, err)
}
@ -285,7 +286,7 @@ func TestEphemeral2006DeletedTooQuickly(t *testing.T) {
// registered.
time.Sleep(3 * time.Minute)
for userName := range spec {
for _, userName := range spec.Users {
nodes, err := headscale.ListNodes(userName)
if err != nil {
log.Error().
@ -306,16 +307,16 @@ func TestPingAllByHostname(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyname"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("pingallbyname"))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -355,16 +356,16 @@ func TestTaildrop(t *testing.T) {
return err
}
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{},
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{},
hsic.WithTestName("taildrop"),
hsic.WithEmbeddedDERPServerOnly(),
hsic.WithTLS(),
@ -527,16 +528,16 @@ func TestUpdateHostnameFromClient(t *testing.T) {
"3": "user3-host",
}
scenario, err := NewScenario(dockertestMaxWait())
assertNoErrf(t, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 3,
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("updatehostname"))
scenario, err := NewScenario(spec)
assertNoErrf(t, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("updatehostname"))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -648,16 +649,16 @@ func TestExpireNode(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("expirenode"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("expirenode"))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -775,16 +776,16 @@ func TestNodeOnlineStatus(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("online"))
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("online"))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -891,16 +892,16 @@ func TestPingAllByIPManyUpDown(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: len(MustTestVersions),
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{},
hsic.WithTestName("pingallbyipmany"),
hsic.WithEmbeddedDERPServerOnly(),
@ -971,16 +972,16 @@ func Test2118DeletingOnlineNodePanics(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1", "user2"},
}
err = scenario.CreateHeadscaleEnv(spec,
scenario, err := NewScenario(spec)
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{},
hsic.WithTestName("deletenocrash"),
hsic.WithEmbeddedDERPServerOnly(),

View File

@ -29,16 +29,16 @@ func TestEnablingRoutes(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 3,
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clienableroute"))
scenario, err := NewScenario(spec)
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clienableroute"))
assertNoErrHeadscaleEnv(t, err)
allClients, err := scenario.ListTailscaleClients()
@ -202,16 +202,16 @@ func TestHASubnetRouterFailover(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario(dockertestMaxWait())
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 4,
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{},
scenario, err := NewScenario(spec)
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{},
hsic.WithTestName("clienableroute"),
hsic.WithEmbeddedDERPServerOnly(),
hsic.WithTLS(),
@ -526,18 +526,16 @@ func TestEnableDisableAutoApprovedRoute(t *testing.T) {
expectedRoutes := "172.0.0.0/24"
user := "user2"
scenario, err := NewScenario(dockertestMaxWait())
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{"user1"},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{tsic.WithTags([]string{"tag:approve"})}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
scenario, err := NewScenario(spec)
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{tsic.WithTags([]string{"tag:approve"})}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
&policyv1.ACLPolicy{
ACLs: []policyv1.ACL{
{
@ -547,7 +545,7 @@ func TestEnableDisableAutoApprovedRoute(t *testing.T) {
},
},
TagOwners: map[string][]string{
"tag:approve": {user},
"tag:approve": {"user1"},
},
AutoApprovers: policyv1.AutoApprovers{
Routes: map[string][]string{
@ -626,16 +624,16 @@ func TestAutoApprovedSubRoute2068(t *testing.T) {
user := "user1"
scenario, err := NewScenario(dockertestMaxWait())
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 1,
Users: []string{user},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{tsic.WithTags([]string{"tag:approve"})},
scenario, err := NewScenario(spec)
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{tsic.WithTags([]string{"tag:approve"})},
hsic.WithTestName("clienableroute"),
hsic.WithEmbeddedDERPServerOnly(),
hsic.WithTLS(),
@ -698,16 +696,16 @@ func TestSubnetRouteACL(t *testing.T) {
user := "user4"
scenario, err := NewScenario(dockertestMaxWait())
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 2,
Users: []string{user},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
scenario, err := NewScenario(spec)
require.NoErrorf(t, err, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
&policyv1.ACLPolicy{
Groups: policyv1.Groups{
"group:admins": {user},
@ -921,16 +919,16 @@ func TestEnablingExitRoutes(t *testing.T) {
user := "user2"
scenario, err := NewScenario(dockertestMaxWait())
assertNoErrf(t, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
spec := ScenarioSpec{
NodesPerUser: 2,
Users: []string{user},
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{
scenario, err := NewScenario(spec)
assertNoErrf(t, "failed to create scenario: %s", err)
defer scenario.ShutdownAssertNoPanics(t)
err = scenario.CreateHeadscaleEnv([]tsic.Option{
tsic.WithExtraLoginArgs([]string{"--advertise-exit-node"}),
}, hsic.WithTestName("clienableroute"))
assertNoErrHeadscaleEnv(t, err)

View File

@ -91,6 +91,30 @@ type Scenario struct {
networks map[string]*dockertest.Network
mu sync.Mutex
spec ScenarioSpec
userToNetwork map[string]*dockertest.Network
}
// ScenarioSpec describes the users, nodes, and network topology to
// set up for a given scenario.
type ScenarioSpec struct {
// Users is a list of usernames that will be created.
// Each created user will get nodes equivalent to NodesPerUser
Users []string
// NodesPerUser is how many nodes should be attached to each user.
NodesPerUser int
// Networks, if set, is the deparate Docker networks that should be
// created and a list of the users that should be placed in those networks.
// If not set, a single network will be created and all users+nodes will be
// added there.
// Please note that Docker networks are not necessarily routable and
// connections between them might fall back to DERP.
Networks map[string][]string
MaxWait time.Duration
}
var TestHashPrefix = "hs-" + util.MustGenerateRandomStringDNSSafe(scenarioHashLength)
@ -98,20 +122,52 @@ var TestDefaultNetwork = TestHashPrefix + "-default"
// NewScenario creates a test Scenario which can be used to bootstraps a ControlServer with
// a set of Users and TailscaleClients.
func NewScenario(maxWait time.Duration) (*Scenario, error) {
func NewScenario(spec ScenarioSpec) (*Scenario, error) {
pool, err := dockertest.NewPool("")
if err != nil {
return nil, fmt.Errorf("could not connect to docker: %w", err)
}
pool.MaxWait = maxWait
if spec.MaxWait == 0 {
pool.MaxWait = dockertestMaxWait()
} else {
pool.MaxWait = spec.MaxWait
}
return &Scenario{
s := &Scenario{
controlServers: xsync.NewMapOf[string, ControlServer](),
users: make(map[string]*User),
pool: pool,
}, nil
spec: spec,
}
var userToNetwork map[string]*dockertest.Network
if spec.Networks != nil || len(spec.Networks) != 0 {
for name, users := range s.spec.Networks {
networkName := TestHashPrefix + "-" + name
network, err := s.AddNetwork(networkName)
if err != nil {
return nil, err
}
for _, user := range users {
if n2, ok := userToNetwork[user]; ok {
return nil, fmt.Errorf("users can only have nodes placed in one network: %s into %s but already in %s", user, network.Network.Name, n2.Network.Name)
}
mak.Set(&userToNetwork, user, network)
}
}
} else {
_, err := s.AddNetwork(TestDefaultNetwork)
if err != nil {
return nil, err
}
}
s.userToNetwork = userToNetwork
return s, nil
}
func (s *Scenario) AddNetwork(name string) (*dockertest.Network, error) {
@ -494,76 +550,33 @@ func (s *Scenario) WaitForTailscaleSyncWithPeerCount(peerCount int) error {
return nil
}
// ScenarioSpec describes the users, nodes, and network topology to
// set up for a given scenario.
type ScenarioSpec struct {
// Users is a list of usernames that will be created.
// Each created user will get nodes equivalent to NodesPerUser
Users []string
// NodesPerUser is how many nodes should be attached to each user.
NodesPerUser int
// Networks, if set, is the deparate Docker networks that should be
// created and a list of the users that should be placed in those networks.
// If not set, a single network will be created and all users+nodes will be
// added there.
// Please note that Docker networks are not necessarily routable and
// connections between them might fall back to DERP.
Networks map[string][]string
}
// CreateHeadscaleEnv is a convenient method returning a complete Headcale
// test environment with nodes of all versions, joined to the server with X
// users.
// CreateHeadscaleEnv starts the headscale environment and the clients
// according to the ScenarioSpec passed to the Scenario.
func (s *Scenario) CreateHeadscaleEnv(
spec ScenarioSpec,
tsOpts []tsic.Option,
opts ...hsic.Option,
) error {
var userToNetwork map[string]*dockertest.Network
if spec.Networks != nil || len(spec.Networks) != 0 {
for name, users := range spec.Networks {
networkName := TestHashPrefix + "-" + name
network, err := s.AddNetwork(networkName)
if err != nil {
return err
}
for _, user := range users {
if n2, ok := userToNetwork[user]; ok {
return fmt.Errorf("users can only have nodes placed in one network: %s into %s but already in %s", user, network.Network.Name, n2.Network.Name)
}
mak.Set(&userToNetwork, user, network)
}
}
} else {
_, err := s.AddNetwork(TestDefaultNetwork)
if err != nil {
return err
}
}
headscale, err := s.Headscale(opts...)
if err != nil {
return err
}
sort.Strings(spec.Users)
for _, user := range spec.Users {
sort.Strings(s.spec.Users)
for _, user := range s.spec.Users {
err = s.CreateUser(user)
if err != nil {
return err
}
var opts []tsic.Option
if userToNetwork != nil {
opts = append(tsOpts, tsic.WithNetwork(userToNetwork[user]))
if s.userToNetwork != nil {
opts = append(tsOpts, tsic.WithNetwork(s.userToNetwork[user]))
} else {
opts = append(tsOpts, tsic.WithNetwork(s.networks[TestDefaultNetwork]))
}
err = s.CreateTailscaleNodesInUser(user, "all", spec.NodesPerUser, opts...)
err = s.CreateTailscaleNodesInUser(user, "all", s.spec.NodesPerUser, opts...)
if err != nil {
return err
}

View File

@ -33,7 +33,7 @@ func TestHeadscale(t *testing.T) {
user := "test-space"
scenario, err := NewScenario(dockertestMaxWait())
scenario, err := NewScenario(ScenarioSpec{})
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)
@ -82,7 +82,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
count := 1
scenario, err := NewScenario(dockertestMaxWait())
scenario, err := NewScenario(ScenarioSpec{})
assertNoErr(t, err)
defer scenario.ShutdownAssertNoPanics(t)

View File

@ -50,15 +50,15 @@ var retry = func(times int, sleepInterval time.Duration,
func sshScenario(t *testing.T, policy *policyv1.ACLPolicy, clientsPerUser int) *Scenario {
t.Helper()
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
spec := ScenarioSpec{
NodesPerUser: clientsPerUser,
Users: []string{"user1", "user2"},
}
scenario, err := NewScenario(spec)
assertNoErr(t, err)
err = scenario.CreateHeadscaleEnv(spec,
err = scenario.CreateHeadscaleEnv(
[]tsic.Option{
tsic.WithSSH(),