Compare commits

...

4 commits

Author SHA1 Message Date
Vitalij Dovhanyc
11861028c4
Merge 0058a90ae9 into dc17b4d378 2024-11-22 20:43:38 +01:00
nblock
dc17b4d378
Documentation dependencies (#2252)
Some checks are pending
Build / build (push) Waiting to run
Build documentation / build (push) Waiting to run
Build documentation / deploy (push) Blocked by required conditions
Tests / test (push) Waiting to run
* Use a trailing slash
recommended by mkdocs-material

* Update doc requirements
Let mkdocs-material resolve its imaging dependencies (cairosvg and
pillow) and fix a dependabot warning along the way.

Reference compatible versions by major.minor.
2024-11-22 16:52:36 +00:00
Kristoffer Dalby
a6b19e85db
more linter fixups (#2212)
* linter fixes

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* conf

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* update nix hash

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

---------

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-11-22 15:54:58 +00:00
vdovhanych
0058a90ae9
chore: configure some actions to be skipped for forks 2024-07-11 10:14:54 +02:00
23 changed files with 546 additions and 406 deletions

View file

@ -13,6 +13,7 @@ permissions:
jobs: jobs:
build: build:
if: github.repository == 'juanfont/headscale'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
@ -36,6 +37,7 @@ jobs:
path: ./site path: ./site
deploy: deploy:
if: github.repository == 'juanfont/headscale'
environment: environment:
name: github-pages name: github-pages
url: ${{ steps.deployment.outputs.page_url }} url: ${{ steps.deployment.outputs.page_url }}

View file

@ -7,6 +7,7 @@ on:
jobs: jobs:
build: build:
if: github.repository == 'juanfont/headscale'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View file

@ -9,6 +9,7 @@ on:
jobs: jobs:
goreleaser: goreleaser:
if: github.repository == 'juanfont/headscale'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout

View file

@ -6,6 +6,7 @@ on:
jobs: jobs:
close-issues: close-issues:
if: github.repository == 'juanfont/headscale'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
issues: write issues: write

View file

@ -6,6 +6,7 @@ on:
jobs: jobs:
lockfile: lockfile:
if: github.repository == 'juanfont/headscale'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository

View file

@ -27,6 +27,7 @@ linters:
- nolintlint - nolintlint
- musttag # causes issues with imported libs - musttag # causes issues with imported libs
- depguard - depguard
- exportloopref
# We should strive to enable these: # We should strive to enable these:
- wrapcheck - wrapcheck
@ -56,9 +57,14 @@ linters-settings:
- ok - ok
- c - c
- tt - tt
- tx
- rx
gocritic: gocritic:
disabled-checks: disabled-checks:
- appendAssign - appendAssign
# TODO(kradalby): Remove this # TODO(kradalby): Remove this
- ifElseChain - ifElseChain
nlreturn:
block-size: 4

View file

@ -1,7 +1,5 @@
cairosvg~=2.7.1 mkdocs-include-markdown-plugin~=7.1
mkdocs-include-markdown-plugin~=6.2.2 mkdocs-macros-plugin~=1.3
mkdocs-macros-plugin~=1.2.0 mkdocs-material[imaging]~=9.5
mkdocs-material~=9.5.18 mkdocs-minify-plugin~=0.7
mkdocs-minify-plugin~=0.7.1 mkdocs-redirects~=1.2
mkdocs-redirects~=1.2.1
pillow~=10.1.0

View file

@ -32,7 +32,7 @@
# When updating go.mod or go.sum, a new sha will need to be calculated, # When updating go.mod or go.sum, a new sha will need to be calculated,
# update this if you have a mismatch after doing a change to thos files. # update this if you have a mismatch after doing a change to thos files.
vendorHash = "sha256-CMkYTRjmhvTTrB7JbLj0cj9VEyzpG0iUWXkaOagwYTk="; vendorHash = "sha256-Qoqu2k4vvnbRFLmT/v8lI+HCEWqJsHFs8uZRfNmwQpo=";
subPackages = ["cmd/headscale"]; subPackages = ["cmd/headscale"];

View file

@ -16,6 +16,7 @@ import (
"github.com/juanfont/headscale/hscontrol/types" "github.com/juanfont/headscale/hscontrol/types"
"github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm" "gorm.io/gorm"
"zgo.at/zcache/v2" "zgo.at/zcache/v2"
) )
@ -44,7 +45,7 @@ func TestMigrations(t *testing.T) {
routes, err := Read(h.DB, func(rx *gorm.DB) (types.Routes, error) { routes, err := Read(h.DB, func(rx *gorm.DB) (types.Routes, error) {
return GetRoutes(rx) return GetRoutes(rx)
}) })
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, routes, 10) assert.Len(t, routes, 10)
want := types.Routes{ want := types.Routes{
@ -70,7 +71,7 @@ func TestMigrations(t *testing.T) {
routes, err := Read(h.DB, func(rx *gorm.DB) (types.Routes, error) { routes, err := Read(h.DB, func(rx *gorm.DB) (types.Routes, error) {
return GetRoutes(rx) return GetRoutes(rx)
}) })
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, routes, 4) assert.Len(t, routes, 4)
want := types.Routes{ want := types.Routes{
@ -132,7 +133,7 @@ func TestMigrations(t *testing.T) {
return append(kratest, testkra...), nil return append(kratest, testkra...), nil
}) })
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, keys, 5) assert.Len(t, keys, 5)
want := []types.PreAuthKey{ want := []types.PreAuthKey{
@ -177,7 +178,7 @@ func TestMigrations(t *testing.T) {
nodes, err := Read(h.DB, func(rx *gorm.DB) (types.Nodes, error) { nodes, err := Read(h.DB, func(rx *gorm.DB) (types.Nodes, error) {
return ListNodes(rx) return ListNodes(rx)
}) })
assert.NoError(t, err) require.NoError(t, err)
for _, node := range nodes { for _, node := range nodes {
assert.Falsef(t, node.MachineKey.IsZero(), "expected non zero machinekey") assert.Falsef(t, node.MachineKey.IsZero(), "expected non zero machinekey")

View file

@ -12,6 +12,7 @@ import (
"github.com/juanfont/headscale/hscontrol/types" "github.com/juanfont/headscale/hscontrol/types"
"github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/types/ptr" "tailscale.com/types/ptr"
) )
@ -457,7 +458,12 @@ func TestBackfillIPAddresses(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
db := tt.dbFunc() db := tt.dbFunc()
alloc, err := NewIPAllocator(db, tt.prefix4, tt.prefix6, types.IPAllocationStrategySequential) alloc, err := NewIPAllocator(
db,
tt.prefix4,
tt.prefix6,
types.IPAllocationStrategySequential,
)
if err != nil { if err != nil {
t.Fatalf("failed to set up ip alloc: %s", err) t.Fatalf("failed to set up ip alloc: %s", err)
} }
@ -482,24 +488,29 @@ func TestBackfillIPAddresses(t *testing.T) {
} }
func TestIPAllocatorNextNoReservedIPs(t *testing.T) { func TestIPAllocatorNextNoReservedIPs(t *testing.T) {
alloc, err := NewIPAllocator(db, ptr.To(tsaddr.CGNATRange()), ptr.To(tsaddr.TailscaleULARange()), types.IPAllocationStrategySequential) alloc, err := NewIPAllocator(
db,
ptr.To(tsaddr.CGNATRange()),
ptr.To(tsaddr.TailscaleULARange()),
types.IPAllocationStrategySequential,
)
if err != nil { if err != nil {
t.Fatalf("failed to set up ip alloc: %s", err) t.Fatalf("failed to set up ip alloc: %s", err)
} }
// Validate that we do not give out 100.100.100.100 // Validate that we do not give out 100.100.100.100
nextQuad100, err := alloc.next(na("100.100.100.99"), ptr.To(tsaddr.CGNATRange())) nextQuad100, err := alloc.next(na("100.100.100.99"), ptr.To(tsaddr.CGNATRange()))
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, na("100.100.100.101"), *nextQuad100) assert.Equal(t, na("100.100.100.101"), *nextQuad100)
// Validate that we do not give out fd7a:115c:a1e0::53 // Validate that we do not give out fd7a:115c:a1e0::53
nextQuad100v6, err := alloc.next(na("fd7a:115c:a1e0::52"), ptr.To(tsaddr.TailscaleULARange())) nextQuad100v6, err := alloc.next(na("fd7a:115c:a1e0::52"), ptr.To(tsaddr.TailscaleULARange()))
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, na("fd7a:115c:a1e0::54"), *nextQuad100v6) assert.Equal(t, na("fd7a:115c:a1e0::54"), *nextQuad100v6)
// Validate that we do not give out fd7a:115c:a1e0::53 // Validate that we do not give out fd7a:115c:a1e0::53
nextChrome, err := alloc.next(na("100.115.91.255"), ptr.To(tsaddr.CGNATRange())) nextChrome, err := alloc.next(na("100.115.91.255"), ptr.To(tsaddr.CGNATRange()))
t.Logf("chrome: %s", nextChrome.String()) t.Logf("chrome: %s", nextChrome.String())
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, na("100.115.94.0"), *nextChrome) assert.Equal(t, na("100.115.94.0"), *nextChrome)
} }

View file

@ -17,6 +17,7 @@ import (
"github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util"
"github.com/puzpuzpuz/xsync/v3" "github.com/puzpuzpuz/xsync/v3"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/check.v1" "gopkg.in/check.v1"
"gorm.io/gorm" "gorm.io/gorm"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
@ -558,17 +559,17 @@ func TestAutoApproveRoutes(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
adb, err := newTestDB() adb, err := newTestDB()
assert.NoError(t, err) require.NoError(t, err)
pol, err := policy.LoadACLPolicyFromBytes([]byte(tt.acl)) pol, err := policy.LoadACLPolicyFromBytes([]byte(tt.acl))
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, pol) assert.NotNil(t, pol)
user, err := adb.CreateUser("test") user, err := adb.CreateUser("test")
assert.NoError(t, err) require.NoError(t, err)
pak, err := adb.CreatePreAuthKey(user.Name, false, false, nil, nil) pak, err := adb.CreatePreAuthKey(user.Name, false, false, nil, nil)
assert.NoError(t, err) require.NoError(t, err)
nodeKey := key.NewNode() nodeKey := key.NewNode()
machineKey := key.NewMachine() machineKey := key.NewMachine()
@ -590,21 +591,21 @@ func TestAutoApproveRoutes(t *testing.T) {
} }
trx := adb.DB.Save(&node) trx := adb.DB.Save(&node)
assert.NoError(t, trx.Error) require.NoError(t, trx.Error)
sendUpdate, err := adb.SaveNodeRoutes(&node) sendUpdate, err := adb.SaveNodeRoutes(&node)
assert.NoError(t, err) require.NoError(t, err)
assert.False(t, sendUpdate) assert.False(t, sendUpdate)
node0ByID, err := adb.GetNodeByID(0) node0ByID, err := adb.GetNodeByID(0)
assert.NoError(t, err) require.NoError(t, err)
// TODO(kradalby): Check state update // TODO(kradalby): Check state update
err = adb.EnableAutoApprovedRoutes(pol, node0ByID) err = adb.EnableAutoApprovedRoutes(pol, node0ByID)
assert.NoError(t, err) require.NoError(t, err)
enabledRoutes, err := adb.GetEnabledRoutes(node0ByID) enabledRoutes, err := adb.GetEnabledRoutes(node0ByID)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, enabledRoutes, len(tt.want)) assert.Len(t, enabledRoutes, len(tt.want))
tsaddr.SortPrefixes(enabledRoutes) tsaddr.SortPrefixes(enabledRoutes)
@ -697,13 +698,13 @@ func TestListEphemeralNodes(t *testing.T) {
} }
user, err := db.CreateUser("test") user, err := db.CreateUser("test")
assert.NoError(t, err) require.NoError(t, err)
pak, err := db.CreatePreAuthKey(user.Name, false, false, nil, nil) pak, err := db.CreatePreAuthKey(user.Name, false, false, nil, nil)
assert.NoError(t, err) require.NoError(t, err)
pakEph, err := db.CreatePreAuthKey(user.Name, false, true, nil, nil) pakEph, err := db.CreatePreAuthKey(user.Name, false, true, nil, nil)
assert.NoError(t, err) require.NoError(t, err)
node := types.Node{ node := types.Node{
ID: 0, ID: 0,
@ -726,16 +727,16 @@ func TestListEphemeralNodes(t *testing.T) {
} }
err = db.DB.Save(&node).Error err = db.DB.Save(&node).Error
assert.NoError(t, err) require.NoError(t, err)
err = db.DB.Save(&nodeEph).Error err = db.DB.Save(&nodeEph).Error
assert.NoError(t, err) require.NoError(t, err)
nodes, err := db.ListNodes() nodes, err := db.ListNodes()
assert.NoError(t, err) require.NoError(t, err)
ephemeralNodes, err := db.ListEphemeralNodes() ephemeralNodes, err := db.ListEphemeralNodes()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, nodes, 2) assert.Len(t, nodes, 2)
assert.Len(t, ephemeralNodes, 1) assert.Len(t, ephemeralNodes, 1)
@ -753,10 +754,10 @@ func TestRenameNode(t *testing.T) {
} }
user, err := db.CreateUser("test") user, err := db.CreateUser("test")
assert.NoError(t, err) require.NoError(t, err)
user2, err := db.CreateUser("test2") user2, err := db.CreateUser("test2")
assert.NoError(t, err) require.NoError(t, err)
node := types.Node{ node := types.Node{
ID: 0, ID: 0,
@ -777,10 +778,10 @@ func TestRenameNode(t *testing.T) {
} }
err = db.DB.Save(&node).Error err = db.DB.Save(&node).Error
assert.NoError(t, err) require.NoError(t, err)
err = db.DB.Save(&node2).Error err = db.DB.Save(&node2).Error
assert.NoError(t, err) require.NoError(t, err)
err = db.DB.Transaction(func(tx *gorm.DB) error { err = db.DB.Transaction(func(tx *gorm.DB) error {
_, err := RegisterNode(tx, node, nil, nil) _, err := RegisterNode(tx, node, nil, nil)
@ -790,10 +791,10 @@ func TestRenameNode(t *testing.T) {
_, err = RegisterNode(tx, node2, nil, nil) _, err = RegisterNode(tx, node2, nil, nil)
return err return err
}) })
assert.NoError(t, err) require.NoError(t, err)
nodes, err := db.ListNodes() nodes, err := db.ListNodes()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, nodes, 2) assert.Len(t, nodes, 2)
@ -815,26 +816,26 @@ func TestRenameNode(t *testing.T) {
err = db.Write(func(tx *gorm.DB) error { err = db.Write(func(tx *gorm.DB) error {
return RenameNode(tx, nodes[0].ID, "newname") return RenameNode(tx, nodes[0].ID, "newname")
}) })
assert.NoError(t, err) require.NoError(t, err)
nodes, err = db.ListNodes() nodes, err = db.ListNodes()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, nodes, 2) assert.Len(t, nodes, 2)
assert.Equal(t, nodes[0].Hostname, "test") assert.Equal(t, "test", nodes[0].Hostname)
assert.Equal(t, nodes[0].GivenName, "newname") assert.Equal(t, "newname", nodes[0].GivenName)
// Nodes can reuse name that is no longer used // Nodes can reuse name that is no longer used
err = db.Write(func(tx *gorm.DB) error { err = db.Write(func(tx *gorm.DB) error {
return RenameNode(tx, nodes[1].ID, "test") return RenameNode(tx, nodes[1].ID, "test")
}) })
assert.NoError(t, err) require.NoError(t, err)
nodes, err = db.ListNodes() nodes, err = db.ListNodes()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, nodes, 2) assert.Len(t, nodes, 2)
assert.Equal(t, nodes[0].Hostname, "test") assert.Equal(t, "test", nodes[0].Hostname)
assert.Equal(t, nodes[0].GivenName, "newname") assert.Equal(t, "newname", nodes[0].GivenName)
assert.Equal(t, nodes[1].GivenName, "test") assert.Equal(t, "test", nodes[1].GivenName)
// Nodes cannot be renamed to used names // Nodes cannot be renamed to used names
err = db.Write(func(tx *gorm.DB) error { err = db.Write(func(tx *gorm.DB) error {

View file

@ -488,7 +488,7 @@ func (a *AuthProviderOIDC) registerNode(
} }
// TODO(kradalby): // TODO(kradalby):
// Rewrite in elem-go // Rewrite in elem-go.
func renderOIDCCallbackTemplate( func renderOIDCCallbackTemplate(
user *types.User, user *types.User,
) (*bytes.Buffer, error) { ) (*bytes.Buffer, error) {

View file

@ -599,7 +599,7 @@ func (pol *ACLPolicy) ExpandAlias(
// TODO(kradalby): It is quite hard to understand what this function is doing, // TODO(kradalby): It is quite hard to understand what this function is doing,
// it seems like it trying to ensure that we dont include nodes that are tagged // it seems like it trying to ensure that we dont include nodes that are tagged
// when we look up the nodes owned by a user. // when we look up the nodes owned by a user.
// This should be refactored to be more clear as part of the Tags work in #1369 // This should be refactored to be more clear as part of the Tags work in #1369.
func excludeCorrectlyTaggedNodes( func excludeCorrectlyTaggedNodes(
aclPolicy *ACLPolicy, aclPolicy *ACLPolicy,
nodes types.Nodes, nodes types.Nodes,

View file

@ -11,7 +11,7 @@ import (
"github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/require"
"go4.org/netipx" "go4.org/netipx"
"gopkg.in/check.v1" "gopkg.in/check.v1"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
@ -1824,12 +1824,20 @@ func TestTheInternet(t *testing.T) {
for i := range internetPrefs { for i := range internetPrefs {
if internetPrefs[i].String() != hsExitNodeDest[i].IP { if internetPrefs[i].String() != hsExitNodeDest[i].IP {
t.Errorf("prefix from internet set %q != hsExit list %q", internetPrefs[i].String(), hsExitNodeDest[i].IP) t.Errorf(
"prefix from internet set %q != hsExit list %q",
internetPrefs[i].String(),
hsExitNodeDest[i].IP,
)
} }
} }
if len(internetPrefs) != len(hsExitNodeDest) { if len(internetPrefs) != len(hsExitNodeDest) {
t.Fatalf("expected same length of prefixes, internet: %d, hsExit: %d", len(internetPrefs), len(hsExitNodeDest)) t.Fatalf(
"expected same length of prefixes, internet: %d, hsExit: %d",
len(internetPrefs),
len(hsExitNodeDest),
)
} }
} }
@ -2036,7 +2044,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{ {
IP: "100.64.0.100/32", IP: "100.64.0.100/32",
@ -2049,7 +2062,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
}, },
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: hsExitNodeDest, DstPorts: hsExitNodeDest,
}, },
}, },
@ -2132,7 +2150,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{ {
IP: "100.64.0.100/32", IP: "100.64.0.100/32",
@ -2145,7 +2168,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
}, },
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{IP: "0.0.0.0/5", Ports: tailcfg.PortRangeAny}, {IP: "0.0.0.0/5", Ports: tailcfg.PortRangeAny},
{IP: "8.0.0.0/7", Ports: tailcfg.PortRangeAny}, {IP: "8.0.0.0/7", Ports: tailcfg.PortRangeAny},
@ -2217,7 +2245,10 @@ func TestReduceFilterRules(t *testing.T) {
IPv6: iap("fd7a:115c:a1e0::100"), IPv6: iap("fd7a:115c:a1e0::100"),
User: types.User{Name: "user100"}, User: types.User{Name: "user100"},
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/16"), netip.MustParsePrefix("16.0.0.0/16")}, RoutableIPs: []netip.Prefix{
netip.MustParsePrefix("8.0.0.0/16"),
netip.MustParsePrefix("16.0.0.0/16"),
},
}, },
}, },
peers: types.Nodes{ peers: types.Nodes{
@ -2234,7 +2265,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{ {
IP: "100.64.0.100/32", IP: "100.64.0.100/32",
@ -2247,7 +2283,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
}, },
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{ {
IP: "8.0.0.0/8", IP: "8.0.0.0/8",
@ -2294,7 +2335,10 @@ func TestReduceFilterRules(t *testing.T) {
IPv6: iap("fd7a:115c:a1e0::100"), IPv6: iap("fd7a:115c:a1e0::100"),
User: types.User{Name: "user100"}, User: types.User{Name: "user100"},
Hostinfo: &tailcfg.Hostinfo{ Hostinfo: &tailcfg.Hostinfo{
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/8"), netip.MustParsePrefix("16.0.0.0/8")}, RoutableIPs: []netip.Prefix{
netip.MustParsePrefix("8.0.0.0/8"),
netip.MustParsePrefix("16.0.0.0/8"),
},
}, },
}, },
peers: types.Nodes{ peers: types.Nodes{
@ -2311,7 +2355,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
want: []tailcfg.FilterRule{ want: []tailcfg.FilterRule{
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{ {
IP: "100.64.0.100/32", IP: "100.64.0.100/32",
@ -2324,7 +2373,12 @@ func TestReduceFilterRules(t *testing.T) {
}, },
}, },
{ {
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32", "fd7a:115c:a1e0::1/128", "fd7a:115c:a1e0::2/128"}, SrcIPs: []string{
"100.64.0.1/32",
"100.64.0.2/32",
"fd7a:115c:a1e0::1/128",
"fd7a:115c:a1e0::2/128",
},
DstPorts: []tailcfg.NetPortRange{ DstPorts: []tailcfg.NetPortRange{
{ {
IP: "8.0.0.0/16", IP: "8.0.0.0/16",
@ -3299,7 +3353,11 @@ func TestSSHRules(t *testing.T) {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
"autogroup:nonroot": "=", "autogroup:nonroot": "=",
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowAgentForwarding: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
}, },
{ {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
@ -3310,7 +3368,11 @@ func TestSSHRules(t *testing.T) {
Any: true, Any: true,
}, },
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowAgentForwarding: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
}, },
{ {
Principals: []*tailcfg.SSHPrincipal{ Principals: []*tailcfg.SSHPrincipal{
@ -3321,7 +3383,11 @@ func TestSSHRules(t *testing.T) {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
"autogroup:nonroot": "=", "autogroup:nonroot": "=",
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowAgentForwarding: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
}, },
{ {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
@ -3332,7 +3398,11 @@ func TestSSHRules(t *testing.T) {
Any: true, Any: true,
}, },
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowAgentForwarding: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowAgentForwarding: true,
AllowLocalPortForwarding: true,
},
}, },
}}, }},
}, },
@ -3392,7 +3462,7 @@ func TestSSHRules(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := tt.pol.CompileSSHPolicy(&tt.node, tt.peers) got, err := tt.pol.CompileSSHPolicy(&tt.node, tt.peers)
assert.NoError(t, err) require.NoError(t, err)
if diff := cmp.Diff(tt.want, got); diff != "" { if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("TestSSHRules() unexpected result (-want +got):\n%s", diff) t.Errorf("TestSSHRules() unexpected result (-want +got):\n%s", diff)
@ -3499,7 +3569,7 @@ func TestValidExpandTagOwnersInSources(t *testing.T) {
} }
got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{}) got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{})
assert.NoError(t, err) require.NoError(t, err)
want := []tailcfg.FilterRule{ want := []tailcfg.FilterRule{
{ {
@ -3550,7 +3620,7 @@ func TestInvalidTagValidUser(t *testing.T) {
} }
got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{}) got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{})
assert.NoError(t, err) require.NoError(t, err)
want := []tailcfg.FilterRule{ want := []tailcfg.FilterRule{
{ {
@ -3609,7 +3679,7 @@ func TestValidExpandTagOwnersInDestinations(t *testing.T) {
// c.Assert(rules[0].DstPorts[0].IP, check.Equals, "100.64.0.1/32") // c.Assert(rules[0].DstPorts[0].IP, check.Equals, "100.64.0.1/32")
got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{}) got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{})
assert.NoError(t, err) require.NoError(t, err)
want := []tailcfg.FilterRule{ want := []tailcfg.FilterRule{
{ {
@ -3679,7 +3749,7 @@ func TestValidTagInvalidUser(t *testing.T) {
} }
got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{nodes2}) got, _, err := GenerateFilterAndSSHRulesForTests(pol, node, types.Nodes{nodes2})
assert.NoError(t, err) require.NoError(t, err)
want := []tailcfg.FilterRule{ want := []tailcfg.FilterRule{
{ {

View file

@ -21,7 +21,8 @@ func Windows(url string) *elem.Element {
elem.A(attrs.Props{ elem.A(attrs.Props{
attrs.Href: "https://tailscale.com/download/windows", attrs.Href: "https://tailscale.com/download/windows",
attrs.Rel: "noreferrer noopener", attrs.Rel: "noreferrer noopener",
attrs.Target: "_blank"}, attrs.Target: "_blank",
},
elem.Text("Tailscale for Windows ")), elem.Text("Tailscale for Windows ")),
elem.Text("and install it."), elem.Text("and install it."),
), ),

View file

@ -9,6 +9,7 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/dnstype" "tailscale.com/types/dnstype"
) )
@ -36,8 +37,17 @@ func TestReadConfig(t *testing.T) {
MagicDNS: true, MagicDNS: true,
BaseDomain: "example.com", BaseDomain: "example.com",
Nameservers: Nameservers{ Nameservers: Nameservers{
Global: []string{"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001", "https://dns.nextdns.io/abc123"}, Global: []string{
Split: map[string][]string{"darp.headscale.net": {"1.1.1.1", "8.8.8.8"}, "foo.bar.com": {"1.1.1.1"}}, "1.1.1.1",
"1.0.0.1",
"2606:4700:4700::1111",
"2606:4700:4700::1001",
"https://dns.nextdns.io/abc123",
},
Split: map[string][]string{
"darp.headscale.net": {"1.1.1.1", "8.8.8.8"},
"foo.bar.com": {"1.1.1.1"},
},
}, },
ExtraRecords: []tailcfg.DNSRecord{ ExtraRecords: []tailcfg.DNSRecord{
{Name: "grafana.myvpn.example.com", Type: "A", Value: "100.64.0.3"}, {Name: "grafana.myvpn.example.com", Type: "A", Value: "100.64.0.3"},
@ -92,8 +102,17 @@ func TestReadConfig(t *testing.T) {
MagicDNS: false, MagicDNS: false,
BaseDomain: "example.com", BaseDomain: "example.com",
Nameservers: Nameservers{ Nameservers: Nameservers{
Global: []string{"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001", "https://dns.nextdns.io/abc123"}, Global: []string{
Split: map[string][]string{"darp.headscale.net": {"1.1.1.1", "8.8.8.8"}, "foo.bar.com": {"1.1.1.1"}}, "1.1.1.1",
"1.0.0.1",
"2606:4700:4700::1111",
"2606:4700:4700::1001",
"https://dns.nextdns.io/abc123",
},
Split: map[string][]string{
"darp.headscale.net": {"1.1.1.1", "8.8.8.8"},
"foo.bar.com": {"1.1.1.1"},
},
}, },
ExtraRecords: []tailcfg.DNSRecord{ ExtraRecords: []tailcfg.DNSRecord{
{Name: "grafana.myvpn.example.com", Type: "A", Value: "100.64.0.3"}, {Name: "grafana.myvpn.example.com", Type: "A", Value: "100.64.0.3"},
@ -187,7 +206,7 @@ func TestReadConfig(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
viper.Reset() viper.Reset()
err := LoadConfig(tt.configPath, true) err := LoadConfig(tt.configPath, true)
assert.NoError(t, err) require.NoError(t, err)
conf, err := tt.setup(t) conf, err := tt.setup(t)
@ -197,7 +216,7 @@ func TestReadConfig(t *testing.T) {
return return
} }
assert.NoError(t, err) require.NoError(t, err)
if diff := cmp.Diff(tt.want, conf); diff != "" { if diff := cmp.Diff(tt.want, conf); diff != "" {
t.Errorf("ReadConfig() mismatch (-want +got):\n%s", diff) t.Errorf("ReadConfig() mismatch (-want +got):\n%s", diff)
@ -277,10 +296,10 @@ func TestReadConfigFromEnv(t *testing.T) {
viper.Reset() viper.Reset()
err := LoadConfig("testdata/minimal.yaml", true) err := LoadConfig("testdata/minimal.yaml", true)
assert.NoError(t, err) require.NoError(t, err)
conf, err := tt.setup(t) conf, err := tt.setup(t)
assert.NoError(t, err) require.NoError(t, err)
if diff := cmp.Diff(tt.want, conf); diff != "" { if diff := cmp.Diff(tt.want, conf); diff != "" {
t.Errorf("ReadConfig() mismatch (-want +got):\n%s", diff) t.Errorf("ReadConfig() mismatch (-want +got):\n%s", diff)
@ -311,13 +330,25 @@ noise:
// Check configuration validation errors (1) // Check configuration validation errors (1)
err = LoadConfig(tmpDir, false) err = LoadConfig(tmpDir, false)
assert.NoError(t, err) require.NoError(t, err)
err = validateServerConfig() err = validateServerConfig()
assert.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), "Fatal config error: set either tls_letsencrypt_hostname or tls_cert_path/tls_key_path, not both") assert.Contains(
assert.Contains(t, err.Error(), "Fatal config error: the only supported values for tls_letsencrypt_challenge_type are") t,
assert.Contains(t, err.Error(), "Fatal config error: server_url must start with https:// or http://") err.Error(),
"Fatal config error: set either tls_letsencrypt_hostname or tls_cert_path/tls_key_path, not both",
)
assert.Contains(
t,
err.Error(),
"Fatal config error: the only supported values for tls_letsencrypt_challenge_type are",
)
assert.Contains(
t,
err.Error(),
"Fatal config error: server_url must start with https:// or http://",
)
// Check configuration validation errors (2) // Check configuration validation errors (2)
configYaml = []byte(`--- configYaml = []byte(`---
@ -332,7 +363,7 @@ tls_letsencrypt_challenge_type: TLS-ALPN-01
t.Fatalf("Couldn't write file %s", configFilePath) t.Fatalf("Couldn't write file %s", configFilePath)
} }
err = LoadConfig(tmpDir, false) err = LoadConfig(tmpDir, false)
assert.NoError(t, err) require.NoError(t, err)
} }
// OK // OK

View file

@ -4,12 +4,13 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestGenerateRandomStringDNSSafe(t *testing.T) { func TestGenerateRandomStringDNSSafe(t *testing.T) {
for i := 0; i < 100000; i++ { for i := 0; i < 100000; i++ {
str, err := GenerateRandomStringDNSSafe(8) str, err := GenerateRandomStringDNSSafe(8)
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, str, 8) assert.Len(t, str, 8)
} }
} }

View file

@ -12,6 +12,7 @@ import (
"github.com/juanfont/headscale/integration/hsic" "github.com/juanfont/headscale/integration/hsic"
"github.com/juanfont/headscale/integration/tsic" "github.com/juanfont/headscale/integration/tsic"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
var veryLargeDestination = []string{ var veryLargeDestination = []string{
@ -54,7 +55,7 @@ func aclScenario(
) *Scenario { ) *Scenario {
t.Helper() t.Helper()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
spec := map[string]int{ spec := map[string]int{
"user1": clientsPerUser, "user1": clientsPerUser,
@ -77,10 +78,10 @@ func aclScenario(
hsic.WithACLPolicy(policy), hsic.WithACLPolicy(policy),
hsic.WithTestName("acl"), hsic.WithTestName("acl"),
) )
assertNoErr(t, err) require.NoError(t, err)
_, err = scenario.ListTailscaleClientsFQDNs() _, err = scenario.ListTailscaleClientsFQDNs()
assertNoErrListFQDN(t, err) require.NoError(t, err)
return scenario return scenario
} }
@ -267,7 +268,7 @@ func TestACLHostsInNetMapTable(t *testing.T) {
for name, testCase := range tests { for name, testCase := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
spec := testCase.users spec := testCase.users
@ -275,22 +276,22 @@ func TestACLHostsInNetMapTable(t *testing.T) {
[]tsic.Option{}, []tsic.Option{},
hsic.WithACLPolicy(&testCase.policy), hsic.WithACLPolicy(&testCase.policy),
) )
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
allClients, err := scenario.ListTailscaleClients() allClients, err := scenario.ListTailscaleClients()
assertNoErr(t, err) require.NoError(t, err)
err = scenario.WaitForTailscaleSyncWithPeerCount(testCase.want["user1"]) err = scenario.WaitForTailscaleSyncWithPeerCount(testCase.want["user1"])
assertNoErrSync(t, err) require.NoError(t, err)
for _, client := range allClients { for _, client := range allClients {
status, err := client.Status() status, err := client.Status()
assertNoErr(t, err) require.NoError(t, err)
user := status.User[status.Self.UserID].LoginName user := status.User[status.Self.UserID].LoginName
assert.Equal(t, (testCase.want[user]), len(status.Peer)) assert.Len(t, status.Peer, (testCase.want[user]))
} }
}) })
} }
@ -319,23 +320,23 @@ func TestACLAllowUser80Dst(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
user1Clients, err := scenario.ListTailscaleClients("user1") user1Clients, err := scenario.ListTailscaleClients("user1")
assertNoErr(t, err) require.NoError(t, err)
user2Clients, err := scenario.ListTailscaleClients("user2") user2Clients, err := scenario.ListTailscaleClients("user2")
assertNoErr(t, err) require.NoError(t, err)
// Test that user1 can visit all user2 // Test that user1 can visit all user2
for _, client := range user1Clients { for _, client := range user1Clients {
for _, peer := range user2Clients { for _, peer := range user2Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
@ -343,14 +344,14 @@ func TestACLAllowUser80Dst(t *testing.T) {
for _, client := range user2Clients { for _, client := range user2Clients {
for _, peer := range user1Clients { for _, peer := range user1Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
} }
} }
} }
@ -376,10 +377,10 @@ func TestACLDenyAllPort80(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
allClients, err := scenario.ListTailscaleClients() allClients, err := scenario.ListTailscaleClients()
assertNoErr(t, err) require.NoError(t, err)
allHostnames, err := scenario.ListTailscaleClientsFQDNs() allHostnames, err := scenario.ListTailscaleClientsFQDNs()
assertNoErr(t, err) require.NoError(t, err)
for _, client := range allClients { for _, client := range allClients {
for _, hostname := range allHostnames { for _, hostname := range allHostnames {
@ -394,7 +395,7 @@ func TestACLDenyAllPort80(t *testing.T) {
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
} }
} }
} }
@ -420,23 +421,23 @@ func TestACLAllowUserDst(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
user1Clients, err := scenario.ListTailscaleClients("user1") user1Clients, err := scenario.ListTailscaleClients("user1")
assertNoErr(t, err) require.NoError(t, err)
user2Clients, err := scenario.ListTailscaleClients("user2") user2Clients, err := scenario.ListTailscaleClients("user2")
assertNoErr(t, err) require.NoError(t, err)
// Test that user1 can visit all user2 // Test that user1 can visit all user2
for _, client := range user1Clients { for _, client := range user1Clients {
for _, peer := range user2Clients { for _, peer := range user2Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
@ -444,14 +445,14 @@ func TestACLAllowUserDst(t *testing.T) {
for _, client := range user2Clients { for _, client := range user2Clients {
for _, peer := range user1Clients { for _, peer := range user1Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
} }
} }
} }
@ -476,23 +477,23 @@ func TestACLAllowStarDst(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
user1Clients, err := scenario.ListTailscaleClients("user1") user1Clients, err := scenario.ListTailscaleClients("user1")
assertNoErr(t, err) require.NoError(t, err)
user2Clients, err := scenario.ListTailscaleClients("user2") user2Clients, err := scenario.ListTailscaleClients("user2")
assertNoErr(t, err) require.NoError(t, err)
// Test that user1 can visit all user2 // Test that user1 can visit all user2
for _, client := range user1Clients { for _, client := range user1Clients {
for _, peer := range user2Clients { for _, peer := range user2Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
@ -500,14 +501,14 @@ func TestACLAllowStarDst(t *testing.T) {
for _, client := range user2Clients { for _, client := range user2Clients {
for _, peer := range user1Clients { for _, peer := range user1Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
} }
} }
} }
@ -537,23 +538,23 @@ func TestACLNamedHostsCanReachBySubnet(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
user1Clients, err := scenario.ListTailscaleClients("user1") user1Clients, err := scenario.ListTailscaleClients("user1")
assertNoErr(t, err) require.NoError(t, err)
user2Clients, err := scenario.ListTailscaleClients("user2") user2Clients, err := scenario.ListTailscaleClients("user2")
assertNoErr(t, err) require.NoError(t, err)
// Test that user1 can visit all user2 // Test that user1 can visit all user2
for _, client := range user1Clients { for _, client := range user1Clients {
for _, peer := range user2Clients { for _, peer := range user2Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
@ -561,14 +562,14 @@ func TestACLNamedHostsCanReachBySubnet(t *testing.T) {
for _, client := range user2Clients { for _, client := range user2Clients {
for _, peer := range user1Clients { for _, peer := range user1Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
} }
@ -679,10 +680,10 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test1ip4 := netip.MustParseAddr("100.64.0.1") test1ip4 := netip.MustParseAddr("100.64.0.1")
test1ip6 := netip.MustParseAddr("fd7a:115c:a1e0::1") test1ip6 := netip.MustParseAddr("fd7a:115c:a1e0::1")
test1, err := scenario.FindTailscaleClientByIP(test1ip6) test1, err := scenario.FindTailscaleClientByIP(test1ip6)
assertNoErr(t, err) require.NoError(t, err)
test1fqdn, err := test1.FQDN() test1fqdn, err := test1.FQDN()
assertNoErr(t, err) require.NoError(t, err)
test1ip4URL := fmt.Sprintf("http://%s/etc/hostname", test1ip4.String()) test1ip4URL := fmt.Sprintf("http://%s/etc/hostname", test1ip4.String())
test1ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test1ip6.String()) test1ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test1ip6.String())
test1fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test1fqdn) test1fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test1fqdn)
@ -690,10 +691,10 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test2ip4 := netip.MustParseAddr("100.64.0.2") test2ip4 := netip.MustParseAddr("100.64.0.2")
test2ip6 := netip.MustParseAddr("fd7a:115c:a1e0::2") test2ip6 := netip.MustParseAddr("fd7a:115c:a1e0::2")
test2, err := scenario.FindTailscaleClientByIP(test2ip6) test2, err := scenario.FindTailscaleClientByIP(test2ip6)
assertNoErr(t, err) require.NoError(t, err)
test2fqdn, err := test2.FQDN() test2fqdn, err := test2.FQDN()
assertNoErr(t, err) require.NoError(t, err)
test2ip4URL := fmt.Sprintf("http://%s/etc/hostname", test2ip4.String()) test2ip4URL := fmt.Sprintf("http://%s/etc/hostname", test2ip4.String())
test2ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test2ip6.String()) test2ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test2ip6.String())
test2fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test2fqdn) test2fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test2fqdn)
@ -701,10 +702,10 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3ip4 := netip.MustParseAddr("100.64.0.3") test3ip4 := netip.MustParseAddr("100.64.0.3")
test3ip6 := netip.MustParseAddr("fd7a:115c:a1e0::3") test3ip6 := netip.MustParseAddr("fd7a:115c:a1e0::3")
test3, err := scenario.FindTailscaleClientByIP(test3ip6) test3, err := scenario.FindTailscaleClientByIP(test3ip6)
assertNoErr(t, err) require.NoError(t, err)
test3fqdn, err := test3.FQDN() test3fqdn, err := test3.FQDN()
assertNoErr(t, err) require.NoError(t, err)
test3ip4URL := fmt.Sprintf("http://%s/etc/hostname", test3ip4.String()) test3ip4URL := fmt.Sprintf("http://%s/etc/hostname", test3ip4.String())
test3ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test3ip6.String()) test3ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test3ip6.String())
test3fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test3fqdn) test3fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test3fqdn)
@ -719,7 +720,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3ip4URL, test3ip4URL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test1.Curl(test3ip6URL) result, err = test1.Curl(test3ip6URL)
assert.Lenf( assert.Lenf(
@ -730,7 +731,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3ip6URL, test3ip6URL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test1.Curl(test3fqdnURL) result, err = test1.Curl(test3fqdnURL)
assert.Lenf( assert.Lenf(
@ -741,7 +742,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3fqdnURL, test3fqdnURL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
// test2 can query test3 // test2 can query test3
result, err = test2.Curl(test3ip4URL) result, err = test2.Curl(test3ip4URL)
@ -753,7 +754,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3ip4URL, test3ip4URL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test2.Curl(test3ip6URL) result, err = test2.Curl(test3ip6URL)
assert.Lenf( assert.Lenf(
@ -764,7 +765,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3ip6URL, test3ip6URL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test2.Curl(test3fqdnURL) result, err = test2.Curl(test3fqdnURL)
assert.Lenf( assert.Lenf(
@ -775,33 +776,33 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test3fqdnURL, test3fqdnURL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
// test3 cannot query test1 // test3 cannot query test1
result, err = test3.Curl(test1ip4URL) result, err = test3.Curl(test1ip4URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test3.Curl(test1ip6URL) result, err = test3.Curl(test1ip6URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test3.Curl(test1fqdnURL) result, err = test3.Curl(test1fqdnURL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
// test3 cannot query test2 // test3 cannot query test2
result, err = test3.Curl(test2ip4URL) result, err = test3.Curl(test2ip4URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test3.Curl(test2ip6URL) result, err = test3.Curl(test2ip6URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test3.Curl(test2fqdnURL) result, err = test3.Curl(test2fqdnURL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
// test1 can query test2 // test1 can query test2
result, err = test1.Curl(test2ip4URL) result, err = test1.Curl(test2ip4URL)
@ -814,7 +815,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test1.Curl(test2ip6URL) result, err = test1.Curl(test2ip6URL)
assert.Lenf( assert.Lenf(
t, t,
@ -824,7 +825,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test2ip6URL, test2ip6URL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test1.Curl(test2fqdnURL) result, err = test1.Curl(test2fqdnURL)
assert.Lenf( assert.Lenf(
@ -835,20 +836,20 @@ func TestACLNamedHostsCanReach(t *testing.T) {
test2fqdnURL, test2fqdnURL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
// test2 cannot query test1 // test2 cannot query test1
result, err = test2.Curl(test1ip4URL) result, err = test2.Curl(test1ip4URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test2.Curl(test1ip6URL) result, err = test2.Curl(test1ip6URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test2.Curl(test1fqdnURL) result, err = test2.Curl(test1fqdnURL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
}) })
} }
} }
@ -946,10 +947,10 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
test1ip6 := netip.MustParseAddr("fd7a:115c:a1e0::1") test1ip6 := netip.MustParseAddr("fd7a:115c:a1e0::1")
test1, err := scenario.FindTailscaleClientByIP(test1ip) test1, err := scenario.FindTailscaleClientByIP(test1ip)
assert.NotNil(t, test1) assert.NotNil(t, test1)
assertNoErr(t, err) require.NoError(t, err)
test1fqdn, err := test1.FQDN() test1fqdn, err := test1.FQDN()
assertNoErr(t, err) require.NoError(t, err)
test1ipURL := fmt.Sprintf("http://%s/etc/hostname", test1ip.String()) test1ipURL := fmt.Sprintf("http://%s/etc/hostname", test1ip.String())
test1ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test1ip6.String()) test1ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test1ip6.String())
test1fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test1fqdn) test1fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test1fqdn)
@ -958,10 +959,10 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
test2ip6 := netip.MustParseAddr("fd7a:115c:a1e0::2") test2ip6 := netip.MustParseAddr("fd7a:115c:a1e0::2")
test2, err := scenario.FindTailscaleClientByIP(test2ip) test2, err := scenario.FindTailscaleClientByIP(test2ip)
assert.NotNil(t, test2) assert.NotNil(t, test2)
assertNoErr(t, err) require.NoError(t, err)
test2fqdn, err := test2.FQDN() test2fqdn, err := test2.FQDN()
assertNoErr(t, err) require.NoError(t, err)
test2ipURL := fmt.Sprintf("http://%s/etc/hostname", test2ip.String()) test2ipURL := fmt.Sprintf("http://%s/etc/hostname", test2ip.String())
test2ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test2ip6.String()) test2ip6URL := fmt.Sprintf("http://[%s]/etc/hostname", test2ip6.String())
test2fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test2fqdn) test2fqdnURL := fmt.Sprintf("http://%s/etc/hostname", test2fqdn)
@ -976,7 +977,7 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
test2ipURL, test2ipURL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test1.Curl(test2ip6URL) result, err = test1.Curl(test2ip6URL)
assert.Lenf( assert.Lenf(
@ -987,7 +988,7 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
test2ip6URL, test2ip6URL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test1.Curl(test2fqdnURL) result, err = test1.Curl(test2fqdnURL)
assert.Lenf( assert.Lenf(
@ -998,19 +999,19 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
test2fqdnURL, test2fqdnURL,
result, result,
) )
assertNoErr(t, err) require.NoError(t, err)
result, err = test2.Curl(test1ipURL) result, err = test2.Curl(test1ipURL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test2.Curl(test1ip6URL) result, err = test2.Curl(test1ip6URL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
result, err = test2.Curl(test1fqdnURL) result, err = test2.Curl(test1fqdnURL)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
}) })
} }
} }
@ -1020,7 +1021,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -1046,19 +1047,19 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
"HEADSCALE_POLICY_MODE": "database", "HEADSCALE_POLICY_MODE": "database",
}), }),
) )
assertNoErr(t, err) require.NoError(t, err)
_, err = scenario.ListTailscaleClientsFQDNs() _, err = scenario.ListTailscaleClientsFQDNs()
assertNoErrListFQDN(t, err) require.NoError(t, err)
err = scenario.WaitForTailscaleSync() err = scenario.WaitForTailscaleSync()
assertNoErrSync(t, err) require.NoError(t, err)
user1Clients, err := scenario.ListTailscaleClients("user1") user1Clients, err := scenario.ListTailscaleClients("user1")
assertNoErr(t, err) require.NoError(t, err)
user2Clients, err := scenario.ListTailscaleClients("user2") user2Clients, err := scenario.ListTailscaleClients("user2")
assertNoErr(t, err) require.NoError(t, err)
all := append(user1Clients, user2Clients...) all := append(user1Clients, user2Clients...)
@ -1070,19 +1071,19 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
} }
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
p := policy.ACLPolicy{ p := policy.ACLPolicy{
ACLs: []policy.ACL{ ACLs: []policy.ACL{
@ -1100,7 +1101,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
policyFilePath := "/etc/headscale/policy.json" policyFilePath := "/etc/headscale/policy.json"
err = headscale.WriteFile(policyFilePath, pBytes) err = headscale.WriteFile(policyFilePath, pBytes)
assertNoErr(t, err) require.NoError(t, err)
// No policy is present at this time. // No policy is present at this time.
// Add a new policy from a file. // Add a new policy from a file.
@ -1113,7 +1114,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
policyFilePath, policyFilePath,
}, },
) )
assertNoErr(t, err) require.NoError(t, err)
// Get the current policy and check // Get the current policy and check
// if it is the same as the one we set. // if it is the same as the one we set.
@ -1129,7 +1130,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
}, },
&output, &output,
) )
assertNoErr(t, err) require.NoError(t, err)
assert.Len(t, output.ACLs, 1) assert.Len(t, output.ACLs, 1)
@ -1141,14 +1142,14 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
for _, client := range user1Clients { for _, client := range user1Clients {
for _, peer := range user2Clients { for _, peer := range user2Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Len(t, result, 13) assert.Len(t, result, 13)
assertNoErr(t, err) require.NoError(t, err)
} }
} }
@ -1156,14 +1157,14 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
for _, client := range user2Clients { for _, client := range user2Clients {
for _, peer := range user1Clients { for _, peer := range user1Clients {
fqdn, err := peer.FQDN() fqdn, err := peer.FQDN()
assertNoErr(t, err) require.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn) url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url) t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url) result, err := client.Curl(url)
assert.Empty(t, result) assert.Empty(t, result)
assert.Error(t, err) require.Error(t, err)
} }
} }
} }

View file

@ -13,6 +13,7 @@ import (
"github.com/juanfont/headscale/integration/hsic" "github.com/juanfont/headscale/integration/hsic"
"github.com/juanfont/headscale/integration/tsic" "github.com/juanfont/headscale/integration/tsic"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func executeAndUnmarshal[T any](headscale ControlServer, command []string, result T) error { func executeAndUnmarshal[T any](headscale ControlServer, command []string, result T) error {
@ -34,7 +35,7 @@ func TestUserCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -43,10 +44,10 @@ func TestUserCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
var listUsers []v1.User var listUsers []v1.User
err = executeAndUnmarshal(headscale, err = executeAndUnmarshal(headscale,
@ -59,7 +60,7 @@ func TestUserCommand(t *testing.T) {
}, },
&listUsers, &listUsers,
) )
assertNoErr(t, err) require.NoError(t, err)
result := []string{listUsers[0].GetName(), listUsers[1].GetName()} result := []string{listUsers[0].GetName(), listUsers[1].GetName()}
sort.Strings(result) sort.Strings(result)
@ -81,7 +82,7 @@ func TestUserCommand(t *testing.T) {
"newname", "newname",
}, },
) )
assertNoErr(t, err) require.NoError(t, err)
var listAfterRenameUsers []v1.User var listAfterRenameUsers []v1.User
err = executeAndUnmarshal(headscale, err = executeAndUnmarshal(headscale,
@ -94,7 +95,7 @@ func TestUserCommand(t *testing.T) {
}, },
&listAfterRenameUsers, &listAfterRenameUsers,
) )
assertNoErr(t, err) require.NoError(t, err)
result = []string{listAfterRenameUsers[0].GetName(), listAfterRenameUsers[1].GetName()} result = []string{listAfterRenameUsers[0].GetName(), listAfterRenameUsers[1].GetName()}
sort.Strings(result) sort.Strings(result)
@ -114,7 +115,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
count := 3 count := 3
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -122,13 +123,13 @@ func TestPreAuthKeyCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipak")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipak"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
keys := make([]*v1.PreAuthKey, count) keys := make([]*v1.PreAuthKey, count)
assertNoErr(t, err) require.NoError(t, err)
for index := 0; index < count; index++ { for index := 0; index < count; index++ {
var preAuthKey v1.PreAuthKey var preAuthKey v1.PreAuthKey
@ -150,7 +151,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
}, },
&preAuthKey, &preAuthKey,
) )
assertNoErr(t, err) require.NoError(t, err)
keys[index] = &preAuthKey keys[index] = &preAuthKey
} }
@ -171,7 +172,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
}, },
&listedPreAuthKeys, &listedPreAuthKeys,
) )
assertNoErr(t, err) require.NoError(t, err)
// There is one key created by "scenario.CreateHeadscaleEnv" // There is one key created by "scenario.CreateHeadscaleEnv"
assert.Len(t, listedPreAuthKeys, 4) assert.Len(t, listedPreAuthKeys, 4)
@ -212,7 +213,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
continue continue
} }
assert.Equal(t, listedPreAuthKeys[index].GetAclTags(), []string{"tag:test1", "tag:test2"}) assert.Equal(t, []string{"tag:test1", "tag:test2"}, listedPreAuthKeys[index].GetAclTags())
} }
// Test key expiry // Test key expiry
@ -226,7 +227,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
listedPreAuthKeys[1].GetKey(), listedPreAuthKeys[1].GetKey(),
}, },
) )
assertNoErr(t, err) require.NoError(t, err)
var listedPreAuthKeysAfterExpire []v1.PreAuthKey var listedPreAuthKeysAfterExpire []v1.PreAuthKey
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -242,7 +243,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
}, },
&listedPreAuthKeysAfterExpire, &listedPreAuthKeysAfterExpire,
) )
assertNoErr(t, err) require.NoError(t, err)
assert.True(t, listedPreAuthKeysAfterExpire[1].GetExpiration().AsTime().Before(time.Now())) assert.True(t, listedPreAuthKeysAfterExpire[1].GetExpiration().AsTime().Before(time.Now()))
assert.True(t, listedPreAuthKeysAfterExpire[2].GetExpiration().AsTime().After(time.Now())) assert.True(t, listedPreAuthKeysAfterExpire[2].GetExpiration().AsTime().After(time.Now()))
@ -256,7 +257,7 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
user := "pre-auth-key-without-exp-user" user := "pre-auth-key-without-exp-user"
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -264,10 +265,10 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipaknaexp")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipaknaexp"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
var preAuthKey v1.PreAuthKey var preAuthKey v1.PreAuthKey
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -284,7 +285,7 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
}, },
&preAuthKey, &preAuthKey,
) )
assertNoErr(t, err) require.NoError(t, err)
var listedPreAuthKeys []v1.PreAuthKey var listedPreAuthKeys []v1.PreAuthKey
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -300,7 +301,7 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
}, },
&listedPreAuthKeys, &listedPreAuthKeys,
) )
assertNoErr(t, err) require.NoError(t, err)
// There is one key created by "scenario.CreateHeadscaleEnv" // There is one key created by "scenario.CreateHeadscaleEnv"
assert.Len(t, listedPreAuthKeys, 2) assert.Len(t, listedPreAuthKeys, 2)
@ -319,7 +320,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
user := "pre-auth-key-reus-ephm-user" user := "pre-auth-key-reus-ephm-user"
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -327,10 +328,10 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipakresueeph")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipakresueeph"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
var preAuthReusableKey v1.PreAuthKey var preAuthReusableKey v1.PreAuthKey
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -347,7 +348,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
}, },
&preAuthReusableKey, &preAuthReusableKey,
) )
assertNoErr(t, err) require.NoError(t, err)
var preAuthEphemeralKey v1.PreAuthKey var preAuthEphemeralKey v1.PreAuthKey
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -364,7 +365,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
}, },
&preAuthEphemeralKey, &preAuthEphemeralKey,
) )
assertNoErr(t, err) require.NoError(t, err)
assert.True(t, preAuthEphemeralKey.GetEphemeral()) assert.True(t, preAuthEphemeralKey.GetEphemeral())
assert.False(t, preAuthEphemeralKey.GetReusable()) assert.False(t, preAuthEphemeralKey.GetReusable())
@ -383,7 +384,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
}, },
&listedPreAuthKeys, &listedPreAuthKeys,
) )
assertNoErr(t, err) require.NoError(t, err)
// There is one key created by "scenario.CreateHeadscaleEnv" // There is one key created by "scenario.CreateHeadscaleEnv"
assert.Len(t, listedPreAuthKeys, 3) assert.Len(t, listedPreAuthKeys, 3)
@ -397,7 +398,7 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
user2 := "user2" user2 := "user2"
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -413,10 +414,10 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
hsic.WithTLS(), hsic.WithTLS(),
hsic.WithHostnameAsServerURL(), hsic.WithHostnameAsServerURL(),
) )
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
var user2Key v1.PreAuthKey var user2Key v1.PreAuthKey
@ -438,10 +439,10 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
}, },
&user2Key, &user2Key,
) )
assertNoErr(t, err) require.NoError(t, err)
allClients, err := scenario.ListTailscaleClients() allClients, err := scenario.ListTailscaleClients()
assertNoErrListClients(t, err) require.NoError(t, err)
assert.Len(t, allClients, 1) assert.Len(t, allClients, 1)
@ -449,22 +450,22 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
// Log out from user1 // Log out from user1
err = client.Logout() err = client.Logout()
assertNoErr(t, err) require.NoError(t, err)
err = scenario.WaitForTailscaleLogout() err = scenario.WaitForTailscaleLogout()
assertNoErr(t, err) require.NoError(t, err)
status, err := client.Status() status, err := client.Status()
assertNoErr(t, err) require.NoError(t, err)
if status.BackendState == "Starting" || status.BackendState == "Running" { if status.BackendState == "Starting" || status.BackendState == "Running" {
t.Fatalf("expected node to be logged out, backend state: %s", status.BackendState) t.Fatalf("expected node to be logged out, backend state: %s", status.BackendState)
} }
err = client.Login(headscale.GetEndpoint(), user2Key.GetKey()) err = client.Login(headscale.GetEndpoint(), user2Key.GetKey())
assertNoErr(t, err) require.NoError(t, err)
status, err = client.Status() status, err = client.Status()
assertNoErr(t, err) require.NoError(t, err)
if status.BackendState != "Running" { if status.BackendState != "Running" {
t.Fatalf("expected node to be logged in, backend state: %s", status.BackendState) t.Fatalf("expected node to be logged in, backend state: %s", status.BackendState)
} }
@ -485,7 +486,7 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
}, },
&listNodes, &listNodes,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listNodes, 1) assert.Len(t, listNodes, 1)
assert.Equal(t, "user2", listNodes[0].GetUser().GetName()) assert.Equal(t, "user2", listNodes[0].GetUser().GetName())
@ -498,7 +499,7 @@ func TestApiKeyCommand(t *testing.T) {
count := 5 count := 5
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -507,10 +508,10 @@ func TestApiKeyCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
keys := make([]string, count) keys := make([]string, count)
@ -526,7 +527,7 @@ func TestApiKeyCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
assert.NotEmpty(t, apiResult) assert.NotEmpty(t, apiResult)
keys[idx] = apiResult keys[idx] = apiResult
@ -545,7 +546,7 @@ func TestApiKeyCommand(t *testing.T) {
}, },
&listedAPIKeys, &listedAPIKeys,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listedAPIKeys, 5) assert.Len(t, listedAPIKeys, 5)
@ -601,7 +602,7 @@ func TestApiKeyCommand(t *testing.T) {
listedAPIKeys[idx].GetPrefix(), listedAPIKeys[idx].GetPrefix(),
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
expiredPrefixes[listedAPIKeys[idx].GetPrefix()] = true expiredPrefixes[listedAPIKeys[idx].GetPrefix()] = true
} }
@ -617,7 +618,7 @@ func TestApiKeyCommand(t *testing.T) {
}, },
&listedAfterExpireAPIKeys, &listedAfterExpireAPIKeys,
) )
assert.Nil(t, err) require.NoError(t, err)
for index := range listedAfterExpireAPIKeys { for index := range listedAfterExpireAPIKeys {
if _, ok := expiredPrefixes[listedAfterExpireAPIKeys[index].GetPrefix()]; ok { if _, ok := expiredPrefixes[listedAfterExpireAPIKeys[index].GetPrefix()]; ok {
@ -643,7 +644,7 @@ func TestApiKeyCommand(t *testing.T) {
"--prefix", "--prefix",
listedAPIKeys[0].GetPrefix(), listedAPIKeys[0].GetPrefix(),
}) })
assert.Nil(t, err) require.NoError(t, err)
var listedAPIKeysAfterDelete []v1.ApiKey var listedAPIKeysAfterDelete []v1.ApiKey
err = executeAndUnmarshal(headscale, err = executeAndUnmarshal(headscale,
@ -656,7 +657,7 @@ func TestApiKeyCommand(t *testing.T) {
}, },
&listedAPIKeysAfterDelete, &listedAPIKeysAfterDelete,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listedAPIKeysAfterDelete, 4) assert.Len(t, listedAPIKeysAfterDelete, 4)
} }
@ -666,7 +667,7 @@ func TestNodeTagCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -674,17 +675,17 @@ func TestNodeTagCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
machineKeys := []string{ machineKeys := []string{
"mkey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", "mkey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
"mkey:6abd00bb5fdda622db51387088c68e97e71ce58e7056aa54f592b6a8219d524c", "mkey:6abd00bb5fdda622db51387088c68e97e71ce58e7056aa54f592b6a8219d524c",
} }
nodes := make([]*v1.Node, len(machineKeys)) nodes := make([]*v1.Node, len(machineKeys))
assert.Nil(t, err) require.NoError(t, err)
for index, machineKey := range machineKeys { for index, machineKey := range machineKeys {
_, err := headscale.Execute( _, err := headscale.Execute(
@ -702,7 +703,7 @@ func TestNodeTagCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
var node v1.Node var node v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -720,7 +721,7 @@ func TestNodeTagCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
nodes[index] = &node nodes[index] = &node
} }
@ -739,7 +740,7 @@ func TestNodeTagCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, []string{"tag:test"}, node.GetForcedTags()) assert.Equal(t, []string{"tag:test"}, node.GetForcedTags())
@ -753,7 +754,7 @@ func TestNodeTagCommand(t *testing.T) {
"--output", "json", "--output", "json",
}, },
) )
assert.ErrorContains(t, err, "tag must start with the string 'tag:'") require.ErrorContains(t, err, "tag must start with the string 'tag:'")
// Test list all nodes after added seconds // Test list all nodes after added seconds
resultMachines := make([]*v1.Node, len(machineKeys)) resultMachines := make([]*v1.Node, len(machineKeys))
@ -767,7 +768,7 @@ func TestNodeTagCommand(t *testing.T) {
}, },
&resultMachines, &resultMachines,
) )
assert.Nil(t, err) require.NoError(t, err)
found := false found := false
for _, node := range resultMachines { for _, node := range resultMachines {
if node.GetForcedTags() != nil { if node.GetForcedTags() != nil {
@ -778,9 +779,8 @@ func TestNodeTagCommand(t *testing.T) {
} }
} }
} }
assert.Equal( assert.True(
t, t,
true,
found, found,
"should find a node with the tag 'tag:test' in the list of nodes", "should find a node with the tag 'tag:test' in the list of nodes",
) )
@ -791,18 +791,22 @@ func TestNodeAdvertiseTagNoACLCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
"user1": 1, "user1": 1,
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{tsic.WithTags([]string{"tag:test"})}, hsic.WithTestName("cliadvtags")) err = scenario.CreateHeadscaleEnv(
assertNoErr(t, err) spec,
[]tsic.Option{tsic.WithTags([]string{"tag:test"})},
hsic.WithTestName("cliadvtags"),
)
require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
// Test list all nodes after added seconds // Test list all nodes after added seconds
resultMachines := make([]*v1.Node, spec["user1"]) resultMachines := make([]*v1.Node, spec["user1"])
@ -817,7 +821,7 @@ func TestNodeAdvertiseTagNoACLCommand(t *testing.T) {
}, },
&resultMachines, &resultMachines,
) )
assert.Nil(t, err) require.NoError(t, err)
found := false found := false
for _, node := range resultMachines { for _, node := range resultMachines {
if node.GetInvalidTags() != nil { if node.GetInvalidTags() != nil {
@ -828,9 +832,8 @@ func TestNodeAdvertiseTagNoACLCommand(t *testing.T) {
} }
} }
} }
assert.Equal( assert.True(
t, t,
true,
found, found,
"should not find a node with the tag 'tag:test' in the list of nodes", "should not find a node with the tag 'tag:test' in the list of nodes",
) )
@ -841,14 +844,18 @@ func TestNodeAdvertiseTagWithACLCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
"user1": 1, "user1": 1,
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{tsic.WithTags([]string{"tag:exists"})}, hsic.WithTestName("cliadvtags"), hsic.WithACLPolicy( err = scenario.CreateHeadscaleEnv(
spec,
[]tsic.Option{tsic.WithTags([]string{"tag:exists"})},
hsic.WithTestName("cliadvtags"),
hsic.WithACLPolicy(
&policy.ACLPolicy{ &policy.ACLPolicy{
ACLs: []policy.ACL{ ACLs: []policy.ACL{
{ {
@ -861,11 +868,12 @@ func TestNodeAdvertiseTagWithACLCommand(t *testing.T) {
"tag:exists": {"user1"}, "tag:exists": {"user1"},
}, },
}, },
)) ),
assertNoErr(t, err) )
require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
// Test list all nodes after added seconds // Test list all nodes after added seconds
resultMachines := make([]*v1.Node, spec["user1"]) resultMachines := make([]*v1.Node, spec["user1"])
@ -880,7 +888,7 @@ func TestNodeAdvertiseTagWithACLCommand(t *testing.T) {
}, },
&resultMachines, &resultMachines,
) )
assert.Nil(t, err) require.NoError(t, err)
found := false found := false
for _, node := range resultMachines { for _, node := range resultMachines {
if node.GetValidTags() != nil { if node.GetValidTags() != nil {
@ -891,9 +899,8 @@ func TestNodeAdvertiseTagWithACLCommand(t *testing.T) {
} }
} }
} }
assert.Equal( assert.True(
t, t,
true,
found, found,
"should not find a node with the tag 'tag:exists' in the list of nodes", "should not find a node with the tag 'tag:exists' in the list of nodes",
) )
@ -904,7 +911,7 @@ func TestNodeCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -913,10 +920,10 @@ func TestNodeCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
// Pregenerated machine keys // Pregenerated machine keys
machineKeys := []string{ machineKeys := []string{
@ -927,7 +934,7 @@ func TestNodeCommand(t *testing.T) {
"mkey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084", "mkey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084",
} }
nodes := make([]*v1.Node, len(machineKeys)) nodes := make([]*v1.Node, len(machineKeys))
assert.Nil(t, err) require.NoError(t, err)
for index, machineKey := range machineKeys { for index, machineKey := range machineKeys {
_, err := headscale.Execute( _, err := headscale.Execute(
@ -945,7 +952,7 @@ func TestNodeCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
var node v1.Node var node v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -963,7 +970,7 @@ func TestNodeCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
nodes[index] = &node nodes[index] = &node
} }
@ -983,7 +990,7 @@ func TestNodeCommand(t *testing.T) {
}, },
&listAll, &listAll,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listAll, 5) assert.Len(t, listAll, 5)
@ -1004,7 +1011,7 @@ func TestNodeCommand(t *testing.T) {
"mkey:dc721977ac7415aafa87f7d4574cbe07c6b171834a6d37375782bdc1fb6b3584", "mkey:dc721977ac7415aafa87f7d4574cbe07c6b171834a6d37375782bdc1fb6b3584",
} }
otherUserMachines := make([]*v1.Node, len(otherUserMachineKeys)) otherUserMachines := make([]*v1.Node, len(otherUserMachineKeys))
assert.Nil(t, err) require.NoError(t, err)
for index, machineKey := range otherUserMachineKeys { for index, machineKey := range otherUserMachineKeys {
_, err := headscale.Execute( _, err := headscale.Execute(
@ -1022,7 +1029,7 @@ func TestNodeCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
var node v1.Node var node v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -1040,7 +1047,7 @@ func TestNodeCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
otherUserMachines[index] = &node otherUserMachines[index] = &node
} }
@ -1060,7 +1067,7 @@ func TestNodeCommand(t *testing.T) {
}, },
&listAllWithotherUser, &listAllWithotherUser,
) )
assert.Nil(t, err) require.NoError(t, err)
// All nodes, nodes + otherUser // All nodes, nodes + otherUser
assert.Len(t, listAllWithotherUser, 7) assert.Len(t, listAllWithotherUser, 7)
@ -1086,7 +1093,7 @@ func TestNodeCommand(t *testing.T) {
}, },
&listOnlyotherUserMachineUser, &listOnlyotherUserMachineUser,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listOnlyotherUserMachineUser, 2) assert.Len(t, listOnlyotherUserMachineUser, 2)
@ -1118,7 +1125,7 @@ func TestNodeCommand(t *testing.T) {
"--force", "--force",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
// Test: list main user after node is deleted // Test: list main user after node is deleted
var listOnlyMachineUserAfterDelete []v1.Node var listOnlyMachineUserAfterDelete []v1.Node
@ -1135,7 +1142,7 @@ func TestNodeCommand(t *testing.T) {
}, },
&listOnlyMachineUserAfterDelete, &listOnlyMachineUserAfterDelete,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listOnlyMachineUserAfterDelete, 4) assert.Len(t, listOnlyMachineUserAfterDelete, 4)
} }
@ -1145,7 +1152,7 @@ func TestNodeExpireCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -1153,10 +1160,10 @@ func TestNodeExpireCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
// Pregenerated machine keys // Pregenerated machine keys
machineKeys := []string{ machineKeys := []string{
@ -1184,7 +1191,7 @@ func TestNodeExpireCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
var node v1.Node var node v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -1202,7 +1209,7 @@ func TestNodeExpireCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
nodes[index] = &node nodes[index] = &node
} }
@ -1221,7 +1228,7 @@ func TestNodeExpireCommand(t *testing.T) {
}, },
&listAll, &listAll,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listAll, 5) assert.Len(t, listAll, 5)
@ -1241,7 +1248,7 @@ func TestNodeExpireCommand(t *testing.T) {
fmt.Sprintf("%d", listAll[idx].GetId()), fmt.Sprintf("%d", listAll[idx].GetId()),
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
} }
var listAllAfterExpiry []v1.Node var listAllAfterExpiry []v1.Node
@ -1256,7 +1263,7 @@ func TestNodeExpireCommand(t *testing.T) {
}, },
&listAllAfterExpiry, &listAllAfterExpiry,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listAllAfterExpiry, 5) assert.Len(t, listAllAfterExpiry, 5)
@ -1272,7 +1279,7 @@ func TestNodeRenameCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -1280,10 +1287,10 @@ func TestNodeRenameCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
// Pregenerated machine keys // Pregenerated machine keys
machineKeys := []string{ machineKeys := []string{
@ -1294,7 +1301,7 @@ func TestNodeRenameCommand(t *testing.T) {
"mkey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", "mkey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
} }
nodes := make([]*v1.Node, len(machineKeys)) nodes := make([]*v1.Node, len(machineKeys))
assert.Nil(t, err) require.NoError(t, err)
for index, machineKey := range machineKeys { for index, machineKey := range machineKeys {
_, err := headscale.Execute( _, err := headscale.Execute(
@ -1312,7 +1319,7 @@ func TestNodeRenameCommand(t *testing.T) {
"json", "json",
}, },
) )
assertNoErr(t, err) require.NoError(t, err)
var node v1.Node var node v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -1330,7 +1337,7 @@ func TestNodeRenameCommand(t *testing.T) {
}, },
&node, &node,
) )
assertNoErr(t, err) require.NoError(t, err)
nodes[index] = &node nodes[index] = &node
} }
@ -1349,7 +1356,7 @@ func TestNodeRenameCommand(t *testing.T) {
}, },
&listAll, &listAll,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listAll, 5) assert.Len(t, listAll, 5)
@ -1370,7 +1377,7 @@ func TestNodeRenameCommand(t *testing.T) {
fmt.Sprintf("newnode-%d", idx+1), fmt.Sprintf("newnode-%d", idx+1),
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Contains(t, res, "Node renamed") assert.Contains(t, res, "Node renamed")
} }
@ -1387,7 +1394,7 @@ func TestNodeRenameCommand(t *testing.T) {
}, },
&listAllAfterRename, &listAllAfterRename,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listAllAfterRename, 5) assert.Len(t, listAllAfterRename, 5)
@ -1408,7 +1415,7 @@ func TestNodeRenameCommand(t *testing.T) {
strings.Repeat("t", 64), strings.Repeat("t", 64),
}, },
) )
assert.ErrorContains(t, err, "not be over 63 chars") require.ErrorContains(t, err, "not be over 63 chars")
var listAllAfterRenameAttempt []v1.Node var listAllAfterRenameAttempt []v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -1422,7 +1429,7 @@ func TestNodeRenameCommand(t *testing.T) {
}, },
&listAllAfterRenameAttempt, &listAllAfterRenameAttempt,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, listAllAfterRenameAttempt, 5) assert.Len(t, listAllAfterRenameAttempt, 5)
@ -1438,7 +1445,7 @@ func TestNodeMoveCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -1447,10 +1454,10 @@ func TestNodeMoveCommand(t *testing.T) {
} }
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins")) err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
// Randomly generated node key // Randomly generated node key
machineKey := "mkey:688411b767663479632d44140f08a9fde87383adc7cdeb518f62ce28a17ef0aa" machineKey := "mkey:688411b767663479632d44140f08a9fde87383adc7cdeb518f62ce28a17ef0aa"
@ -1470,7 +1477,7 @@ func TestNodeMoveCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
var node v1.Node var node v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -1488,11 +1495,11 @@ func TestNodeMoveCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, uint64(1), node.GetId()) assert.Equal(t, uint64(1), node.GetId())
assert.Equal(t, "nomad-node", node.GetName()) assert.Equal(t, "nomad-node", node.GetName())
assert.Equal(t, node.GetUser().GetName(), "old-user") assert.Equal(t, "old-user", node.GetUser().GetName())
nodeID := fmt.Sprintf("%d", node.GetId()) nodeID := fmt.Sprintf("%d", node.GetId())
@ -1511,9 +1518,9 @@ func TestNodeMoveCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, node.GetUser().GetName(), "new-user") assert.Equal(t, "new-user", node.GetUser().GetName())
var allNodes []v1.Node var allNodes []v1.Node
err = executeAndUnmarshal( err = executeAndUnmarshal(
@ -1527,13 +1534,13 @@ func TestNodeMoveCommand(t *testing.T) {
}, },
&allNodes, &allNodes,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, allNodes, 1) assert.Len(t, allNodes, 1)
assert.Equal(t, allNodes[0].GetId(), node.GetId()) assert.Equal(t, allNodes[0].GetId(), node.GetId())
assert.Equal(t, allNodes[0].GetUser(), node.GetUser()) assert.Equal(t, allNodes[0].GetUser(), node.GetUser())
assert.Equal(t, allNodes[0].GetUser().GetName(), "new-user") assert.Equal(t, "new-user", allNodes[0].GetUser().GetName())
_, err = headscale.Execute( _, err = headscale.Execute(
[]string{ []string{
@ -1548,12 +1555,12 @@ func TestNodeMoveCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.ErrorContains( require.ErrorContains(
t, t,
err, err,
"user not found", "user not found",
) )
assert.Equal(t, node.GetUser().GetName(), "new-user") assert.Equal(t, "new-user", node.GetUser().GetName())
err = executeAndUnmarshal( err = executeAndUnmarshal(
headscale, headscale,
@ -1570,9 +1577,9 @@ func TestNodeMoveCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, node.GetUser().GetName(), "old-user") assert.Equal(t, "old-user", node.GetUser().GetName())
err = executeAndUnmarshal( err = executeAndUnmarshal(
headscale, headscale,
@ -1589,9 +1596,9 @@ func TestNodeMoveCommand(t *testing.T) {
}, },
&node, &node,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, node.GetUser().GetName(), "old-user") assert.Equal(t, "old-user", node.GetUser().GetName())
} }
func TestPolicyCommand(t *testing.T) { func TestPolicyCommand(t *testing.T) {
@ -1599,7 +1606,7 @@ func TestPolicyCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -1614,10 +1621,10 @@ func TestPolicyCommand(t *testing.T) {
"HEADSCALE_POLICY_MODE": "database", "HEADSCALE_POLICY_MODE": "database",
}), }),
) )
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
p := policy.ACLPolicy{ p := policy.ACLPolicy{
ACLs: []policy.ACL{ ACLs: []policy.ACL{
@ -1637,7 +1644,7 @@ func TestPolicyCommand(t *testing.T) {
policyFilePath := "/etc/headscale/policy.json" policyFilePath := "/etc/headscale/policy.json"
err = headscale.WriteFile(policyFilePath, pBytes) err = headscale.WriteFile(policyFilePath, pBytes)
assertNoErr(t, err) require.NoError(t, err)
// No policy is present at this time. // No policy is present at this time.
// Add a new policy from a file. // Add a new policy from a file.
@ -1651,7 +1658,7 @@ func TestPolicyCommand(t *testing.T) {
}, },
) )
assertNoErr(t, err) require.NoError(t, err)
// Get the current policy and check // Get the current policy and check
// if it is the same as the one we set. // if it is the same as the one we set.
@ -1667,11 +1674,11 @@ func TestPolicyCommand(t *testing.T) {
}, },
&output, &output,
) )
assertNoErr(t, err) require.NoError(t, err)
assert.Len(t, output.TagOwners, 1) assert.Len(t, output.TagOwners, 1)
assert.Len(t, output.ACLs, 1) assert.Len(t, output.ACLs, 1)
assert.Equal(t, output.TagOwners["tag:exists"], []string{"policy-user"}) assert.Equal(t, []string{"policy-user"}, output.TagOwners["tag:exists"])
} }
func TestPolicyBrokenConfigCommand(t *testing.T) { func TestPolicyBrokenConfigCommand(t *testing.T) {
@ -1679,7 +1686,7 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
t.Parallel() t.Parallel()
scenario, err := NewScenario(dockertestMaxWait()) scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err) require.NoError(t, err)
defer scenario.ShutdownAssertNoPanics(t) defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{ spec := map[string]int{
@ -1694,10 +1701,10 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
"HEADSCALE_POLICY_MODE": "database", "HEADSCALE_POLICY_MODE": "database",
}), }),
) )
assertNoErr(t, err) require.NoError(t, err)
headscale, err := scenario.Headscale() headscale, err := scenario.Headscale()
assertNoErr(t, err) require.NoError(t, err)
p := policy.ACLPolicy{ p := policy.ACLPolicy{
ACLs: []policy.ACL{ ACLs: []policy.ACL{
@ -1719,7 +1726,7 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
policyFilePath := "/etc/headscale/policy.json" policyFilePath := "/etc/headscale/policy.json"
err = headscale.WriteFile(policyFilePath, pBytes) err = headscale.WriteFile(policyFilePath, pBytes)
assertNoErr(t, err) require.NoError(t, err)
// No policy is present at this time. // No policy is present at this time.
// Add a new policy from a file. // Add a new policy from a file.
@ -1732,7 +1739,7 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
policyFilePath, policyFilePath,
}, },
) )
assert.ErrorContains(t, err, "verifying policy rules: invalid action") require.ErrorContains(t, err, "verifying policy rules: invalid action")
// The new policy was invalid, the old one should still be in place, which // The new policy was invalid, the old one should still be in place, which
// is none. // is none.
@ -1745,5 +1752,5 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
"json", "json",
}, },
) )
assert.ErrorContains(t, err, "acl policy not found") require.ErrorContains(t, err, "acl policy not found")
} }

View file

@ -18,6 +18,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"tailscale.com/client/tailscale/apitype" "tailscale.com/client/tailscale/apitype"
"tailscale.com/types/key" "tailscale.com/types/key"
@ -244,7 +245,11 @@ func TestEphemeral(t *testing.T) {
} }
func TestEphemeralInAlternateTimezone(t *testing.T) { func TestEphemeralInAlternateTimezone(t *testing.T) {
testEphemeralWithOptions(t, hsic.WithTestName("ephemeral-tz"), hsic.WithTimezone("America/Los_Angeles")) testEphemeralWithOptions(
t,
hsic.WithTestName("ephemeral-tz"),
hsic.WithTimezone("America/Los_Angeles"),
)
} }
func testEphemeralWithOptions(t *testing.T, opts ...hsic.Option) { func testEphemeralWithOptions(t *testing.T, opts ...hsic.Option) {
@ -1164,10 +1169,10 @@ func Test2118DeletingOnlineNodePanics(t *testing.T) {
}, },
&nodeList, &nodeList,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, nodeList, 2) assert.Len(t, nodeList, 2)
assert.True(t, nodeList[0].Online) assert.True(t, nodeList[0].GetOnline())
assert.True(t, nodeList[1].Online) assert.True(t, nodeList[1].GetOnline())
// Delete the first node, which is online // Delete the first node, which is online
_, err = headscale.Execute( _, err = headscale.Execute(
@ -1177,13 +1182,13 @@ func Test2118DeletingOnlineNodePanics(t *testing.T) {
"delete", "delete",
"--identifier", "--identifier",
// Delete the last added machine // Delete the last added machine
fmt.Sprintf("%d", nodeList[0].Id), fmt.Sprintf("%d", nodeList[0].GetId()),
"--output", "--output",
"json", "json",
"--force", "--force",
}, },
) )
assert.Nil(t, err) require.NoError(t, err)
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
@ -1200,9 +1205,8 @@ func Test2118DeletingOnlineNodePanics(t *testing.T) {
}, },
&nodeListAfter, &nodeListAfter,
) )
assert.Nil(t, err) require.NoError(t, err)
assert.Len(t, nodeListAfter, 1) assert.Len(t, nodeListAfter, 1)
assert.True(t, nodeListAfter[0].Online) assert.True(t, nodeListAfter[0].GetOnline())
assert.Equal(t, nodeList[1].Id, nodeListAfter[0].Id) assert.Equal(t, nodeList[1].GetId(), nodeListAfter[0].GetId())
} }

View file

@ -92,9 +92,9 @@ func TestEnablingRoutes(t *testing.T) {
assert.Len(t, routes, 3) assert.Len(t, routes, 3)
for _, route := range routes { for _, route := range routes {
assert.Equal(t, true, route.GetAdvertised()) assert.True(t, route.GetAdvertised())
assert.Equal(t, false, route.GetEnabled()) assert.False(t, route.GetEnabled())
assert.Equal(t, false, route.GetIsPrimary()) assert.False(t, route.GetIsPrimary())
} }
// Verify that no routes has been sent to the client, // Verify that no routes has been sent to the client,
@ -139,9 +139,9 @@ func TestEnablingRoutes(t *testing.T) {
assert.Len(t, enablingRoutes, 3) assert.Len(t, enablingRoutes, 3)
for _, route := range enablingRoutes { for _, route := range enablingRoutes {
assert.Equal(t, true, route.GetAdvertised()) assert.True(t, route.GetAdvertised())
assert.Equal(t, true, route.GetEnabled()) assert.True(t, route.GetEnabled())
assert.Equal(t, true, route.GetIsPrimary()) assert.True(t, route.GetIsPrimary())
} }
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
@ -212,18 +212,18 @@ func TestEnablingRoutes(t *testing.T) {
assertNoErr(t, err) assertNoErr(t, err)
for _, route := range disablingRoutes { for _, route := range disablingRoutes {
assert.Equal(t, true, route.GetAdvertised()) assert.True(t, route.GetAdvertised())
if route.GetId() == routeToBeDisabled.GetId() { if route.GetId() == routeToBeDisabled.GetId() {
assert.Equal(t, false, route.GetEnabled()) assert.False(t, route.GetEnabled())
// since this is the only route of this cidr, // since this is the only route of this cidr,
// it will not failover, and remain Primary // it will not failover, and remain Primary
// until something can replace it. // until something can replace it.
assert.Equal(t, true, route.GetIsPrimary()) assert.True(t, route.GetIsPrimary())
} else { } else {
assert.Equal(t, true, route.GetEnabled()) assert.True(t, route.GetEnabled())
assert.Equal(t, true, route.GetIsPrimary()) assert.True(t, route.GetIsPrimary())
} }
} }
@ -342,9 +342,9 @@ func TestHASubnetRouterFailover(t *testing.T) {
t.Logf("initial routes %#v", routes) t.Logf("initial routes %#v", routes)
for _, route := range routes { for _, route := range routes {
assert.Equal(t, true, route.GetAdvertised()) assert.True(t, route.GetAdvertised())
assert.Equal(t, false, route.GetEnabled()) assert.False(t, route.GetEnabled())
assert.Equal(t, false, route.GetIsPrimary()) assert.False(t, route.GetIsPrimary())
} }
// Verify that no routes has been sent to the client, // Verify that no routes has been sent to the client,
@ -391,14 +391,14 @@ func TestHASubnetRouterFailover(t *testing.T) {
assert.Len(t, enablingRoutes, 2) assert.Len(t, enablingRoutes, 2)
// Node 1 is primary // Node 1 is primary
assert.Equal(t, true, enablingRoutes[0].GetAdvertised()) assert.True(t, enablingRoutes[0].GetAdvertised())
assert.Equal(t, true, enablingRoutes[0].GetEnabled()) assert.True(t, enablingRoutes[0].GetEnabled())
assert.Equal(t, true, enablingRoutes[0].GetIsPrimary(), "both subnet routers are up, expected r1 to be primary") assert.True(t, enablingRoutes[0].GetIsPrimary(), "both subnet routers are up, expected r1 to be primary")
// Node 2 is not primary // Node 2 is not primary
assert.Equal(t, true, enablingRoutes[1].GetAdvertised()) assert.True(t, enablingRoutes[1].GetAdvertised())
assert.Equal(t, true, enablingRoutes[1].GetEnabled()) assert.True(t, enablingRoutes[1].GetEnabled())
assert.Equal(t, false, enablingRoutes[1].GetIsPrimary(), "both subnet routers are up, expected r2 to be non-primary") assert.False(t, enablingRoutes[1].GetIsPrimary(), "both subnet routers are up, expected r2 to be non-primary")
// Verify that the client has routes from the primary machine // Verify that the client has routes from the primary machine
srs1, err := subRouter1.Status() srs1, err := subRouter1.Status()
@ -446,14 +446,14 @@ func TestHASubnetRouterFailover(t *testing.T) {
assert.Len(t, routesAfterMove, 2) assert.Len(t, routesAfterMove, 2)
// Node 1 is not primary // Node 1 is not primary
assert.Equal(t, true, routesAfterMove[0].GetAdvertised()) assert.True(t, routesAfterMove[0].GetAdvertised())
assert.Equal(t, true, routesAfterMove[0].GetEnabled()) assert.True(t, routesAfterMove[0].GetEnabled())
assert.Equal(t, false, routesAfterMove[0].GetIsPrimary(), "r1 is down, expected r2 to be primary") assert.False(t, routesAfterMove[0].GetIsPrimary(), "r1 is down, expected r2 to be primary")
// Node 2 is primary // Node 2 is primary
assert.Equal(t, true, routesAfterMove[1].GetAdvertised()) assert.True(t, routesAfterMove[1].GetAdvertised())
assert.Equal(t, true, routesAfterMove[1].GetEnabled()) assert.True(t, routesAfterMove[1].GetEnabled())
assert.Equal(t, true, routesAfterMove[1].GetIsPrimary(), "r1 is down, expected r2 to be primary") assert.True(t, routesAfterMove[1].GetIsPrimary(), "r1 is down, expected r2 to be primary")
srs2, err = subRouter2.Status() srs2, err = subRouter2.Status()
@ -501,16 +501,16 @@ func TestHASubnetRouterFailover(t *testing.T) {
assert.Len(t, routesAfterBothDown, 2) assert.Len(t, routesAfterBothDown, 2)
// Node 1 is not primary // Node 1 is not primary
assert.Equal(t, true, routesAfterBothDown[0].GetAdvertised()) assert.True(t, routesAfterBothDown[0].GetAdvertised())
assert.Equal(t, true, routesAfterBothDown[0].GetEnabled()) assert.True(t, routesAfterBothDown[0].GetEnabled())
assert.Equal(t, false, routesAfterBothDown[0].GetIsPrimary(), "r1 and r2 is down, expected r2 to _still_ be primary") assert.False(t, routesAfterBothDown[0].GetIsPrimary(), "r1 and r2 is down, expected r2 to _still_ be primary")
// Node 2 is primary // Node 2 is primary
// if the node goes down, but no other suitable route is // if the node goes down, but no other suitable route is
// available, keep the last known good route. // available, keep the last known good route.
assert.Equal(t, true, routesAfterBothDown[1].GetAdvertised()) assert.True(t, routesAfterBothDown[1].GetAdvertised())
assert.Equal(t, true, routesAfterBothDown[1].GetEnabled()) assert.True(t, routesAfterBothDown[1].GetEnabled())
assert.Equal(t, true, routesAfterBothDown[1].GetIsPrimary(), "r1 and r2 is down, expected r2 to _still_ be primary") assert.True(t, routesAfterBothDown[1].GetIsPrimary(), "r1 and r2 is down, expected r2 to _still_ be primary")
// TODO(kradalby): Check client status // TODO(kradalby): Check client status
// Both are expected to be down // Both are expected to be down
@ -560,14 +560,14 @@ func TestHASubnetRouterFailover(t *testing.T) {
assert.Len(t, routesAfter1Up, 2) assert.Len(t, routesAfter1Up, 2)
// Node 1 is primary // Node 1 is primary
assert.Equal(t, true, routesAfter1Up[0].GetAdvertised()) assert.True(t, routesAfter1Up[0].GetAdvertised())
assert.Equal(t, true, routesAfter1Up[0].GetEnabled()) assert.True(t, routesAfter1Up[0].GetEnabled())
assert.Equal(t, true, routesAfter1Up[0].GetIsPrimary(), "r1 is back up, expected r1 to become be primary") assert.True(t, routesAfter1Up[0].GetIsPrimary(), "r1 is back up, expected r1 to become be primary")
// Node 2 is not primary // Node 2 is not primary
assert.Equal(t, true, routesAfter1Up[1].GetAdvertised()) assert.True(t, routesAfter1Up[1].GetAdvertised())
assert.Equal(t, true, routesAfter1Up[1].GetEnabled()) assert.True(t, routesAfter1Up[1].GetEnabled())
assert.Equal(t, false, routesAfter1Up[1].GetIsPrimary(), "r1 is back up, expected r1 to become be primary") assert.False(t, routesAfter1Up[1].GetIsPrimary(), "r1 is back up, expected r1 to become be primary")
// Verify that the route is announced from subnet router 1 // Verify that the route is announced from subnet router 1
clientStatus, err = client.Status() clientStatus, err = client.Status()
@ -614,14 +614,14 @@ func TestHASubnetRouterFailover(t *testing.T) {
assert.Len(t, routesAfter2Up, 2) assert.Len(t, routesAfter2Up, 2)
// Node 1 is not primary // Node 1 is not primary
assert.Equal(t, true, routesAfter2Up[0].GetAdvertised()) assert.True(t, routesAfter2Up[0].GetAdvertised())
assert.Equal(t, true, routesAfter2Up[0].GetEnabled()) assert.True(t, routesAfter2Up[0].GetEnabled())
assert.Equal(t, true, routesAfter2Up[0].GetIsPrimary(), "r1 and r2 is back up, expected r1 to _still_ be primary") assert.True(t, routesAfter2Up[0].GetIsPrimary(), "r1 and r2 is back up, expected r1 to _still_ be primary")
// Node 2 is primary // Node 2 is primary
assert.Equal(t, true, routesAfter2Up[1].GetAdvertised()) assert.True(t, routesAfter2Up[1].GetAdvertised())
assert.Equal(t, true, routesAfter2Up[1].GetEnabled()) assert.True(t, routesAfter2Up[1].GetEnabled())
assert.Equal(t, false, routesAfter2Up[1].GetIsPrimary(), "r1 and r2 is back up, expected r1 to _still_ be primary") assert.False(t, routesAfter2Up[1].GetIsPrimary(), "r1 and r2 is back up, expected r1 to _still_ be primary")
// Verify that the route is announced from subnet router 1 // Verify that the route is announced from subnet router 1
clientStatus, err = client.Status() clientStatus, err = client.Status()
@ -677,14 +677,14 @@ func TestHASubnetRouterFailover(t *testing.T) {
t.Logf("routes after disabling r1 %#v", routesAfterDisabling1) t.Logf("routes after disabling r1 %#v", routesAfterDisabling1)
// Node 1 is not primary // Node 1 is not primary
assert.Equal(t, true, routesAfterDisabling1[0].GetAdvertised()) assert.True(t, routesAfterDisabling1[0].GetAdvertised())
assert.Equal(t, false, routesAfterDisabling1[0].GetEnabled()) assert.False(t, routesAfterDisabling1[0].GetEnabled())
assert.Equal(t, false, routesAfterDisabling1[0].GetIsPrimary()) assert.False(t, routesAfterDisabling1[0].GetIsPrimary())
// Node 2 is primary // Node 2 is primary
assert.Equal(t, true, routesAfterDisabling1[1].GetAdvertised()) assert.True(t, routesAfterDisabling1[1].GetAdvertised())
assert.Equal(t, true, routesAfterDisabling1[1].GetEnabled()) assert.True(t, routesAfterDisabling1[1].GetEnabled())
assert.Equal(t, true, routesAfterDisabling1[1].GetIsPrimary()) assert.True(t, routesAfterDisabling1[1].GetIsPrimary())
// Verify that the route is announced from subnet router 1 // Verify that the route is announced from subnet router 1
clientStatus, err = client.Status() clientStatus, err = client.Status()
@ -735,14 +735,14 @@ func TestHASubnetRouterFailover(t *testing.T) {
assert.Len(t, routesAfterEnabling1, 2) assert.Len(t, routesAfterEnabling1, 2)
// Node 1 is not primary // Node 1 is not primary
assert.Equal(t, true, routesAfterEnabling1[0].GetAdvertised()) assert.True(t, routesAfterEnabling1[0].GetAdvertised())
assert.Equal(t, true, routesAfterEnabling1[0].GetEnabled()) assert.True(t, routesAfterEnabling1[0].GetEnabled())
assert.Equal(t, false, routesAfterEnabling1[0].GetIsPrimary()) assert.False(t, routesAfterEnabling1[0].GetIsPrimary())
// Node 2 is primary // Node 2 is primary
assert.Equal(t, true, routesAfterEnabling1[1].GetAdvertised()) assert.True(t, routesAfterEnabling1[1].GetAdvertised())
assert.Equal(t, true, routesAfterEnabling1[1].GetEnabled()) assert.True(t, routesAfterEnabling1[1].GetEnabled())
assert.Equal(t, true, routesAfterEnabling1[1].GetIsPrimary()) assert.True(t, routesAfterEnabling1[1].GetIsPrimary())
// Verify that the route is announced from subnet router 1 // Verify that the route is announced from subnet router 1
clientStatus, err = client.Status() clientStatus, err = client.Status()
@ -795,9 +795,9 @@ func TestHASubnetRouterFailover(t *testing.T) {
t.Logf("routes after deleting r2 %#v", routesAfterDeleting2) t.Logf("routes after deleting r2 %#v", routesAfterDeleting2)
// Node 1 is primary // Node 1 is primary
assert.Equal(t, true, routesAfterDeleting2[0].GetAdvertised()) assert.True(t, routesAfterDeleting2[0].GetAdvertised())
assert.Equal(t, true, routesAfterDeleting2[0].GetEnabled()) assert.True(t, routesAfterDeleting2[0].GetEnabled())
assert.Equal(t, true, routesAfterDeleting2[0].GetIsPrimary()) assert.True(t, routesAfterDeleting2[0].GetIsPrimary())
// Verify that the route is announced from subnet router 1 // Verify that the route is announced from subnet router 1
clientStatus, err = client.Status() clientStatus, err = client.Status()
@ -893,9 +893,9 @@ func TestEnableDisableAutoApprovedRoute(t *testing.T) {
assert.Len(t, routes, 1) assert.Len(t, routes, 1)
// All routes should be auto approved and enabled // All routes should be auto approved and enabled
assert.Equal(t, true, routes[0].GetAdvertised()) assert.True(t, routes[0].GetAdvertised())
assert.Equal(t, true, routes[0].GetEnabled()) assert.True(t, routes[0].GetEnabled())
assert.Equal(t, true, routes[0].GetIsPrimary()) assert.True(t, routes[0].GetIsPrimary())
// Stop advertising route // Stop advertising route
command = []string{ command = []string{
@ -924,9 +924,9 @@ func TestEnableDisableAutoApprovedRoute(t *testing.T) {
assert.Len(t, notAdvertisedRoutes, 1) assert.Len(t, notAdvertisedRoutes, 1)
// Route is no longer advertised // Route is no longer advertised
assert.Equal(t, false, notAdvertisedRoutes[0].GetAdvertised()) assert.False(t, notAdvertisedRoutes[0].GetAdvertised())
assert.Equal(t, false, notAdvertisedRoutes[0].GetEnabled()) assert.False(t, notAdvertisedRoutes[0].GetEnabled())
assert.Equal(t, true, notAdvertisedRoutes[0].GetIsPrimary()) assert.True(t, notAdvertisedRoutes[0].GetIsPrimary())
// Advertise route again // Advertise route again
command = []string{ command = []string{
@ -955,9 +955,9 @@ func TestEnableDisableAutoApprovedRoute(t *testing.T) {
assert.Len(t, reAdvertisedRoutes, 1) assert.Len(t, reAdvertisedRoutes, 1)
// All routes should be auto approved and enabled // All routes should be auto approved and enabled
assert.Equal(t, true, reAdvertisedRoutes[0].GetAdvertised()) assert.True(t, reAdvertisedRoutes[0].GetAdvertised())
assert.Equal(t, true, reAdvertisedRoutes[0].GetEnabled()) assert.True(t, reAdvertisedRoutes[0].GetEnabled())
assert.Equal(t, true, reAdvertisedRoutes[0].GetIsPrimary()) assert.True(t, reAdvertisedRoutes[0].GetIsPrimary())
} }
func TestAutoApprovedSubRoute2068(t *testing.T) { func TestAutoApprovedSubRoute2068(t *testing.T) {
@ -1163,9 +1163,9 @@ func TestSubnetRouteACL(t *testing.T) {
assert.Len(t, routes, 1) assert.Len(t, routes, 1)
for _, route := range routes { for _, route := range routes {
assert.Equal(t, true, route.GetAdvertised()) assert.True(t, route.GetAdvertised())
assert.Equal(t, false, route.GetEnabled()) assert.False(t, route.GetEnabled())
assert.Equal(t, false, route.GetIsPrimary()) assert.False(t, route.GetIsPrimary())
} }
// Verify that no routes has been sent to the client, // Verify that no routes has been sent to the client,
@ -1212,9 +1212,9 @@ func TestSubnetRouteACL(t *testing.T) {
assert.Len(t, enablingRoutes, 1) assert.Len(t, enablingRoutes, 1)
// Node 1 has active route // Node 1 has active route
assert.Equal(t, true, enablingRoutes[0].GetAdvertised()) assert.True(t, enablingRoutes[0].GetAdvertised())
assert.Equal(t, true, enablingRoutes[0].GetEnabled()) assert.True(t, enablingRoutes[0].GetEnabled())
assert.Equal(t, true, enablingRoutes[0].GetIsPrimary()) assert.True(t, enablingRoutes[0].GetIsPrimary())
// Verify that the client has routes from the primary machine // Verify that the client has routes from the primary machine
srs1, _ := subRouter1.Status() srs1, _ := subRouter1.Status()

View file

@ -21,6 +21,7 @@ import (
"github.com/puzpuzpuz/xsync/v3" "github.com/puzpuzpuz/xsync/v3"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"tailscale.com/envknob" "tailscale.com/envknob"
) )
@ -205,11 +206,11 @@ func (s *Scenario) ShutdownAssertNoPanics(t *testing.T) {
if t != nil { if t != nil {
stdout, err := os.ReadFile(stdoutPath) stdout, err := os.ReadFile(stdoutPath)
assert.NoError(t, err) require.NoError(t, err)
assert.NotContains(t, string(stdout), "panic") assert.NotContains(t, string(stdout), "panic")
stderr, err := os.ReadFile(stderrPath) stderr, err := os.ReadFile(stderrPath)
assert.NoError(t, err) require.NoError(t, err)
assert.NotContains(t, string(stderr), "panic") assert.NotContains(t, string(stderr), "panic")
} }

View file

@ -1,5 +1,6 @@
---
site_name: Headscale site_name: Headscale
site_url: https://juanfont.github.io/headscale site_url: https://juanfont.github.io/headscale/
edit_uri: blob/main/docs/ # Change the master branch to main as we are using main as a main branch edit_uri: blob/main/docs/ # Change the master branch to main as we are using main as a main branch
site_author: Headscale authors site_author: Headscale authors
site_description: >- site_description: >-