all: apply lint auto-fixes and update test expectations

Apply additional golangci-lint auto-fixes (wsl_v5, formatting)
and update SSH policy test error message expectations to match
the new sentinel error formats introduced in the err113 fixes.
This commit is contained in:
Kristoffer Dalby 2026-01-20 16:28:35 +00:00
parent 8bfd508cf0
commit 58b532ae3c
31 changed files with 110 additions and 68 deletions

View file

@ -35,7 +35,8 @@ func init() {
checkPolicy.Flags().StringP("file", "f", "", "Path to a policy file in HuJSON format")
if err := checkPolicy.MarkFlagRequired("file"); err != nil {
err := checkPolicy.MarkFlagRequired("file")
if err != nil {
log.Fatal().Err(err).Msg("")
}

View file

@ -16,7 +16,7 @@ import (
// Sentinel errors for CLI commands.
var (
ErrNameOrIDRequired = errors.New("--name or --identifier flag is required")
ErrNameOrIDRequired = errors.New("--name or --identifier flag is required")
ErrMultipleUsersFoundUseID = errors.New("unable to determine user, query returned multiple users, use ID")
)

View file

@ -321,7 +321,8 @@ func checkRequiredFiles() DoctorResult {
for _, file := range requiredFiles {
cmd := exec.CommandContext(context.Background(), "test", "-e", file)
if err := cmd.Run(); err != nil {
err := cmd.Run()
if err != nil {
missingFiles = append(missingFiles, file)
}
}

View file

@ -49,7 +49,8 @@ func runIntegrationTest(env *command.Env) error {
log.Printf("Running pre-flight system checks...")
}
if err := runDoctorCheck(env.Context()); err != nil {
err := runDoctorCheck(env.Context())
if err != nil {
return fmt.Errorf("pre-flight checks failed: %w", err)
}

View file

@ -261,7 +261,8 @@ AND auth_key_id NOT IN (
if err == nil && routesExists {
log.Info().Msg("Dropping leftover routes table")
if err := tx.Exec("DROP TABLE routes").Error; err != nil {
err := tx.Exec("DROP TABLE routes").Error
if err != nil {
return fmt.Errorf("dropping routes table: %w", err)
}
}
@ -294,7 +295,8 @@ AND auth_key_id NOT IN (
_ = tx.Exec("DROP TABLE IF EXISTS " + table + "_old").Error
// Rename current table to _old
if err := tx.Exec("ALTER TABLE " + table + " RENAME TO " + table + "_old").Error; err != nil {
err := tx.Exec("ALTER TABLE " + table + " RENAME TO " + table + "_old").Error
if err != nil {
return fmt.Errorf("renaming table %s to %s_old: %w", table, table, err)
}
}
@ -368,7 +370,8 @@ AND auth_key_id NOT IN (
}
for _, createSQL := range tableCreationSQL {
if err := tx.Exec(createSQL).Error; err != nil {
err := tx.Exec(createSQL).Error
if err != nil {
return fmt.Errorf("creating new table: %w", err)
}
}
@ -397,7 +400,8 @@ AND auth_key_id NOT IN (
}
for _, copySQL := range dataCopySQL {
if err := tx.Exec(copySQL).Error; err != nil {
err := tx.Exec(copySQL).Error
if err != nil {
return fmt.Errorf("copying data: %w", err)
}
}
@ -420,14 +424,16 @@ AND auth_key_id NOT IN (
}
for _, indexSQL := range indexes {
if err := tx.Exec(indexSQL).Error; err != nil {
err := tx.Exec(indexSQL).Error
if err != nil {
return fmt.Errorf("creating index: %w", err)
}
}
// Drop old tables only after everything succeeds
for _, table := range tablesToRename {
if err := tx.Exec("DROP TABLE IF EXISTS " + table + "_old").Error; err != nil {
err := tx.Exec("DROP TABLE IF EXISTS " + table + "_old").Error
if err != nil {
log.Warn().Str("table", table+"_old").Err(err).Msg("Failed to drop old table, but migration succeeded")
}
}
@ -946,18 +952,21 @@ func runMigrations(cfg types.DatabaseConfig, dbConn *gorm.DB, migrations *gormig
if needsFKDisabled {
// Disable foreign keys for this migration
if err := dbConn.Exec("PRAGMA foreign_keys = OFF").Error; err != nil {
err := dbConn.Exec("PRAGMA foreign_keys = OFF").Error
if err != nil {
return fmt.Errorf("disabling foreign keys for migration %s: %w", migrationID, err)
}
} else {
// Ensure foreign keys are enabled for this migration
if err := dbConn.Exec("PRAGMA foreign_keys = ON").Error; err != nil {
err := dbConn.Exec("PRAGMA foreign_keys = ON").Error
if err != nil {
return fmt.Errorf("enabling foreign keys for migration %s: %w", migrationID, err)
}
}
// Run up to this specific migration (will only run the next pending migration)
if err := migrations.MigrateTo(migrationID); err != nil {
err := migrations.MigrateTo(migrationID)
if err != nil {
return fmt.Errorf("running migration %s: %w", migrationID, err)
}
}
@ -1009,7 +1018,8 @@ func runMigrations(cfg types.DatabaseConfig, dbConn *gorm.DB, migrations *gormig
}
} else {
// PostgreSQL can run all migrations in one block - no foreign key issues
if err := migrations.Migrate(); err != nil {
err := migrations.Migrate()
if err != nil {
return err
}
}

View file

@ -365,7 +365,8 @@ func (c *Config) Validate() error {
// ToURL builds a properly encoded SQLite connection string using _pragma parameters
// compatible with modernc.org/sqlite driver.
func (c *Config) ToURL() (string, error) {
if err := c.Validate(); err != nil {
err := c.Validate()
if err != nil {
return "", fmt.Errorf("invalid config: %w", err)
}

View file

@ -12,9 +12,9 @@ import (
// Sentinel errors for text serialisation.
var (
ErrTextUnmarshalFailed = errors.New("failed to unmarshal text value")
ErrUnsupportedType = errors.New("unsupported type")
ErrTextMarshalerOnly = errors.New("only encoding.TextMarshaler is supported")
ErrTextUnmarshalFailed = errors.New("failed to unmarshal text value")
ErrUnsupportedType = errors.New("unsupported type")
ErrTextMarshalerOnly = errors.New("only encoding.TextMarshaler is supported")
)
// Got from https://github.com/xdg-go/strum/blob/main/types.go

View file

@ -28,7 +28,8 @@ func (hsdb *HSDatabase) CreateUser(user types.User) (*types.User, error) {
// CreateUser creates a new User. Returns error if could not be created
// or another user already exists.
func CreateUser(tx *gorm.DB, user types.User) (*types.User, error) {
if err := util.ValidateHostname(user.Name); err != nil {
err := util.ValidateHostname(user.Name)
if err != nil {
return nil, err
}
if err := tx.Create(&user).Error; err != nil {
@ -164,7 +165,8 @@ func ListUsers(tx *gorm.DB, where ...*types.User) ([]types.User, error) {
}
users := []types.User{}
if err := tx.Where(user).Find(&users).Error; err != nil {
err := tx.Where(user).Find(&users).Error
if err != nil {
return nil, err
}

View file

@ -74,6 +74,7 @@ func (d *DERPServer) GenerateRegion() (tailcfg.DERPRegion, error) {
if err != nil {
return tailcfg.DERPRegion{}, err
}
var (
host string
port int
@ -416,7 +417,8 @@ type DERPVerifyTransport struct {
func (t *DERPVerifyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
buf := new(bytes.Buffer)
if err := t.handleVerifyRequest(req, buf); err != nil {
err := t.handleVerifyRequest(req, buf)
if err != nil {
log.Error().Caller().Err(err).Msg("Failed to handle client verify request: ")
return nil, err

View file

@ -154,7 +154,8 @@ func (h *Headscale) KeyHandler(
}
writer.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(writer).Encode(resp); err != nil {
err := json.NewEncoder(writer).Encode(resp)
if err != nil {
log.Error().Err(err).Msg("failed to encode key response")
}

View file

@ -667,7 +667,8 @@ func (mc *multiChannelNodeConn) send(data *tailcfg.MapResponse) error {
Str("conn.id", conn.id).Int("connection_index", i).
Msg("send: attempting to send to connection")
if err := conn.send(data); err != nil {
err := conn.send(data)
if err != nil {
lastErr = err
failedConnections = append(failedConnections, i)

View file

@ -123,9 +123,9 @@ const (
// Channel configuration.
NORMAL_BUFFER_SIZE = 50
SMALL_BUFFER_SIZE = 3
TINY_BUFFER_SIZE = 1 // For maximum contention
LARGE_BUFFER_SIZE = 200
SMALL_BUFFER_SIZE = 3
TINY_BUFFER_SIZE = 1 // For maximum contention
LARGE_BUFFER_SIZE = 200
)
// TestData contains all test entities created for a test scenario.
@ -1145,6 +1145,7 @@ func XTestBatcherChannelClosingRace(t *testing.T) {
wg.Go(func() {
runtime.Gosched() // Yield to introduce timing variability
_ = batcher.AddNode(testNode.n.ID, ch2, tailcfg.CapabilityVersion(100))
})
@ -1747,6 +1748,7 @@ func XTestBatcherScalability(t *testing.T) {
for i := range testNodes {
node := testNodes[i]
_ = batcher.AddNode(node.n.ID, node.ch, tailcfg.CapabilityVersion(100))
connectedNodesMutex.Lock()
connectedNodes[node.n.ID] = true

View file

@ -283,7 +283,8 @@ func (ns *noiseServer) NoiseRegistrationHandler(
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
writer.WriteHeader(http.StatusOK)
if err := json.NewEncoder(writer).Encode(registerResponse); err != nil {
err := json.NewEncoder(writer).Encode(registerResponse)
if err != nil {
log.Error().Caller().Err(err).Msg("NoiseRegistrationHandler: failed to encode RegisterResponse")
return
}

View file

@ -1214,7 +1214,7 @@ func TestSSHPolicyRules(t *testing.T) {
]
}`,
expectErr: true,
errorMessage: `invalid SSH action "invalid", must be one of: accept, check`,
errorMessage: `invalid SSH action: "invalid", must be one of: accept, check`,
},
{
name: "invalid-check-period",
@ -1249,7 +1249,7 @@ func TestSSHPolicyRules(t *testing.T) {
]
}`,
expectErr: true,
errorMessage: "autogroup \"autogroup:invalid\" is not supported",
errorMessage: `autogroup not supported for SSH: "autogroup:invalid" for SSH user`,
},
{
name: "autogroup-nonroot-should-use-wildcard-with-root-excluded",

View file

@ -106,7 +106,7 @@ func TestInvalidateAutogroupSelfCache(t *testing.T) {
require.NoError(t, err)
}
require.Equal(t, len(initialNodes), len(pm.filterRulesMap))
require.Len(t, pm.filterRulesMap, len(initialNodes))
tests := []struct {
name string

View file

@ -3131,8 +3131,8 @@ func TestACL_UnmarshalJSON_WithCommentFields(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, tt.expected.Action, acl.Action)
assert.Equal(t, tt.expected.Protocol, acl.Protocol)
assert.Equal(t, len(tt.expected.Sources), len(acl.Sources))
assert.Equal(t, len(tt.expected.Destinations), len(acl.Destinations))
assert.Len(t, acl.Sources, len(tt.expected.Sources))
assert.Len(t, acl.Destinations, len(tt.expected.Destinations))
// Compare sources
for i, expectedSrc := range tt.expected.Sources {
@ -3179,8 +3179,8 @@ func TestACL_UnmarshalJSON_Roundtrip(t *testing.T) {
// Should be equal
assert.Equal(t, original.Action, unmarshaled.Action)
assert.Equal(t, original.Protocol, unmarshaled.Protocol)
assert.Equal(t, len(original.Sources), len(unmarshaled.Sources))
assert.Equal(t, len(original.Destinations), len(unmarshaled.Destinations))
assert.Len(t, unmarshaled.Sources, len(original.Sources))
assert.Len(t, unmarshaled.Destinations, len(original.Destinations))
}
func TestACL_UnmarshalJSON_PolicyIntegration(t *testing.T) {

View file

@ -249,7 +249,8 @@ func (m *mapSession) serveLongPoll() {
return
}
if err := m.writeMap(update); err != nil {
err := m.writeMap(update)
if err != nil {
m.errf(err, "cannot write update to client")
return
}
@ -258,7 +259,8 @@ func (m *mapSession) serveLongPoll() {
m.resetKeepAlive()
case <-m.keepAliveTicker.C:
if err := m.writeMap(&keepAlive); err != nil {
err := m.writeMap(&keepAlive)
if err != nil {
m.errf(err, "cannot write keep alive")
return
}

View file

@ -133,4 +133,3 @@ func TestNetInfoPreservationInRegistrationFlow(t *testing.T) {
assert.Equal(t, 7, result.PreferredDERP, "Should preserve DERP region from existing node")
})
}

View file

@ -187,7 +187,8 @@ func NewState(cfg *types.Config) (*State, error) {
func (s *State) Close() error {
s.nodeStore.Stop()
if err := s.db.Close(); err != nil {
err := s.db.Close()
if err != nil {
return fmt.Errorf("closing database: %w", err)
}
@ -741,7 +742,8 @@ func (s *State) SetApprovedRoutes(nodeID types.NodeID, routes []netip.Prefix) (t
// RenameNode changes the display name of a node.
func (s *State) RenameNode(nodeID types.NodeID, newName string) (types.NodeView, change.Change, error) {
if err := util.ValidateHostname(newName); err != nil {
err := util.ValidateHostname(newName)
if err != nil {
return types.NodeView{}, change.Change{}, fmt.Errorf("renaming node: %w", err)
}
@ -1214,7 +1216,8 @@ func (s *State) createAndSaveNewNode(params newNodeParams) (types.NodeView, erro
// New node - database first to get ID, then NodeStore
savedNode, err := hsdb.Write(s.db.DB, func(tx *gorm.DB) (*types.Node, error) {
if err := tx.Save(&nodeToRegister).Error; err != nil {
err := tx.Save(&nodeToRegister).Error
if err != nil {
return nil, fmt.Errorf("failed to save node: %w", err)
}

View file

@ -29,16 +29,16 @@ const (
PKCEMethodPlain string = "plain"
PKCEMethodS256 string = "S256"
defaultNodeStoreBatchSize = 100
defaultWALAutocheckpoint = 1000 // SQLite default
defaultNodeStoreBatchSize = 100
defaultWALAutocheckpoint = 1000 // SQLite default
)
var (
errOidcMutuallyExclusive = errors.New("oidc_client_secret and oidc_client_secret_path are mutually exclusive")
errServerURLSuffix = errors.New("server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable")
errServerURLSame = errors.New("server_url cannot use the same domain as base_domain in a way that could make the DERP and headscale server unreachable")
errInvalidPKCEMethod = errors.New("pkce.method must be either 'plain' or 'S256'")
errNoPrefixConfigured = errors.New("no IPv4 or IPv6 prefix configured, minimum one prefix is required")
errOidcMutuallyExclusive = errors.New("oidc_client_secret and oidc_client_secret_path are mutually exclusive")
errServerURLSuffix = errors.New("server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable")
errServerURLSame = errors.New("server_url cannot use the same domain as base_domain in a way that could make the DERP and headscale server unreachable")
errInvalidPKCEMethod = errors.New("pkce.method must be either 'plain' or 'S256'")
errNoPrefixConfigured = errors.New("no IPv4 or IPv6 prefix configured, minimum one prefix is required")
errInvalidAllocationStrategy = errors.New("invalid prefixes.allocation strategy")
)
@ -406,7 +406,8 @@ func LoadConfig(path string, isFile bool) error {
viper.SetDefault("prefixes.allocation", string(IPAllocationStrategySequential))
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
log.Warn().Msg("No config file found, using defaults")
return nil
}
@ -446,7 +447,8 @@ func validateServerConfig() error {
depr.fatal("oidc.map_legacy_users")
if viper.GetBool("oidc.enabled") {
if err := validatePKCEMethod(viper.GetString("oidc.pkce.method")); err != nil {
err := validatePKCEMethod(viper.GetString("oidc.pkce.method"))
if err != nil {
return err
}
}
@ -984,7 +986,8 @@ func LoadServerConfig() (*Config, error) {
// - Control plane runs on login.tailscale.com/controlplane.tailscale.com
// - MagicDNS (BaseDomain) for users is on a *.ts.net domain per tailnet (e.g. tail-scale.ts.net)
if dnsConfig.BaseDomain != "" {
if err := isSafeServerURL(serverURL, dnsConfig.BaseDomain); err != nil {
err := isSafeServerURL(serverURL, dnsConfig.BaseDomain)
if err != nil {
return nil, err
}
}

View file

@ -573,7 +573,8 @@ func (node *Node) ApplyHostnameFromHostInfo(hostInfo *tailcfg.Hostinfo) {
}
newHostname := strings.ToLower(hostInfo.Hostname)
if err := util.ValidateHostname(newHostname); err != nil {
err := util.ValidateHostname(newHostname)
if err != nil {
log.Warn().
Str("node.id", node.ID.String()).
Str("current_hostname", node.Hostname).

View file

@ -66,7 +66,8 @@ func TestUnmarshallOIDCClaims(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var got OIDCClaims
if err := json.Unmarshal([]byte(tt.jsonstr), &got); err != nil {
err := json.Unmarshal([]byte(tt.jsonstr), &got)
if err != nil {
t.Errorf("UnmarshallOIDCClaims() error = %v", err)
return
}
@ -482,7 +483,8 @@ func TestOIDCClaimsJSONToUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var got OIDCClaims
if err := json.Unmarshal([]byte(tt.jsonstr), &got); err != nil {
err := json.Unmarshal([]byte(tt.jsonstr), &got)
if err != nil {
t.Errorf("TestOIDCClaimsJSONToUser() error = %v", err)
return
}

View file

@ -31,17 +31,17 @@ var ErrInvalidHostName = errors.New("invalid hostname")
// Sentinel errors for username validation.
var (
ErrUsernameTooShort = errors.New("username must be at least 2 characters long")
ErrUsernameTooShort = errors.New("username must be at least 2 characters long")
ErrUsernameMustStartLetter = errors.New("username must start with a letter")
ErrUsernameTooManyAt = errors.New("username cannot contain more than one '@'")
ErrUsernameInvalidChar = errors.New("username contains invalid character")
ErrUsernameTooManyAt = errors.New("username cannot contain more than one '@'")
ErrUsernameInvalidChar = errors.New("username contains invalid character")
)
// Sentinel errors for hostname validation.
var (
ErrHostnameTooShort = errors.New("hostname too short, must be at least 2 characters")
ErrHostnameHyphenEnds = errors.New("hostname cannot start or end with a hyphen")
ErrHostnameDotEnds = errors.New("hostname cannot start or end with a dot")
ErrHostnameTooShort = errors.New("hostname too short, must be at least 2 characters")
ErrHostnameHyphenEnds = errors.New("hostname cannot start or end with a hyphen")
ErrHostnameDotEnds = errors.New("hostname cannot start or end with a dot")
)
// ValidateUsername checks if a username is valid.

View file

@ -14,6 +14,7 @@ func YesNo(msg string) bool {
fmt.Fprint(os.Stderr, msg+" [y/n] ")
var resp string
_, _ = fmt.Scanln(&resp)
resp = strings.ToLower(resp)

View file

@ -106,6 +106,7 @@ func TestYesNo(t *testing.T) {
// Check that the prompt was written to stderr
var stderrBuf bytes.Buffer
_, _ = io.Copy(&stderrBuf, stderrR)
stderrR.Close()
@ -149,6 +150,7 @@ func TestYesNoPromptMessage(t *testing.T) {
// Check that the custom message was included in the prompt
var stderrBuf bytes.Buffer
_, _ = io.Copy(&stderrBuf, stderrR)
stderrR.Close()

View file

@ -323,7 +323,8 @@ func EnsureHostname(hostinfo *tailcfg.Hostinfo, machineKey, nodeKey string) stri
}
lowercased := strings.ToLower(hostinfo.Hostname)
if err := ValidateHostname(lowercased); err == nil {
err := ValidateHostname(lowercased)
if err == nil {
return lowercased
}

View file

@ -79,7 +79,7 @@ func TestAPIAuthenticationBypass(t *testing.T) {
t.Run("HTTP_NoAuthHeader", func(t *testing.T) {
// Test 1: Request without any Authorization header
// Expected: Should return 401 with ONLY "Unauthorized" text, no user data
req, err := http.NewRequestWithContext(context.Background(), "GET", apiURL, nil)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, apiURL, nil)
require.NoError(t, err)
resp, err := client.Do(req)
@ -131,7 +131,7 @@ func TestAPIAuthenticationBypass(t *testing.T) {
t.Run("HTTP_InvalidAuthHeader", func(t *testing.T) {
// Test 2: Request with invalid Authorization header (missing "Bearer " prefix)
// Expected: Should return 401 with ONLY "Unauthorized" text, no user data
req, err := http.NewRequestWithContext(context.Background(), "GET", apiURL, nil)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, apiURL, nil)
require.NoError(t, err)
req.Header.Set("Authorization", "InvalidToken")
@ -165,7 +165,7 @@ func TestAPIAuthenticationBypass(t *testing.T) {
// Test 3: Request with Bearer prefix but invalid token
// Expected: Should return 401 with ONLY "Unauthorized" text, no user data
// Note: Both malformed and properly formatted invalid tokens should return 401
req, err := http.NewRequestWithContext(context.Background(), "GET", apiURL, nil)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, apiURL, nil)
require.NoError(t, err)
req.Header.Set("Authorization", "Bearer invalid-token-12345")
@ -198,7 +198,7 @@ func TestAPIAuthenticationBypass(t *testing.T) {
t.Run("HTTP_ValidAPIKey", func(t *testing.T) {
// Test 4: Request with valid API key
// Expected: Should return 200 with user data (this is the authorized case)
req, err := http.NewRequestWithContext(context.Background(), "GET", apiURL, nil)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, apiURL, nil)
require.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAPIKey)
@ -294,6 +294,7 @@ func TestAPIAuthenticationBypassCurl(t *testing.T) {
)
var responseBodySb295 strings.Builder
for _, line := range lines {
if after, ok := strings.CutPrefix(line, "HTTP_CODE:"); ok {
httpCode = after
@ -301,6 +302,7 @@ func TestAPIAuthenticationBypassCurl(t *testing.T) {
responseBodySb295.WriteString(line)
}
}
responseBody += responseBodySb295.String()
// Should return 401
@ -345,6 +347,7 @@ func TestAPIAuthenticationBypassCurl(t *testing.T) {
)
var responseBodySb344 strings.Builder
for _, line := range lines {
if after, ok := strings.CutPrefix(line, "HTTP_CODE:"); ok {
httpCode = after
@ -352,6 +355,7 @@ func TestAPIAuthenticationBypassCurl(t *testing.T) {
responseBodySb344.WriteString(line)
}
}
responseBody += responseBodySb344.String()
assert.Equal(t, "401", httpCode)

View file

@ -355,7 +355,7 @@ func TestAuthKeyLogoutAndReloginNewUser(t *testing.T) {
status, err := client.Status()
assert.NoError(ct, err, "Failed to get status for client %s", client.Hostname())
assert.Equal(ct, "user1@test.no", status.User[status.Self.UserID].LoginName, "Client %s should be logged in as user1 after user switch, got %s", client.Hostname(), status.User[status.Self.UserID].LoginName)
}, 30*time.Second, 2*time.Second, fmt.Sprintf("validating %s is logged in as user1 after auth key user switch", client.Hostname()))
}, 30*time.Second, 2*time.Second, "validating %s is logged in as user1 after auth key user switch", client.Hostname())
}
}

View file

@ -1,7 +1,6 @@
package integration
import (
"fmt"
"net/netip"
"slices"
"testing"
@ -364,7 +363,7 @@ func TestAuthWebFlowLogoutAndReloginNewUser(t *testing.T) {
status, err := client.Status()
assert.NoError(ct, err, "Failed to get status for client %s", client.Hostname())
assert.Equal(ct, "user1@test.no", status.User[status.Self.UserID].LoginName, "Client %s should be logged in as user1 after web flow user switch, got %s", client.Hostname(), status.User[status.Self.UserID].LoginName)
}, 30*time.Second, 2*time.Second, fmt.Sprintf("validating %s is logged in as user1 after web flow user switch", client.Hostname()))
}, 30*time.Second, 2*time.Second, "validating %s is logged in as user1 after web flow user switch", client.Hostname())
}
// Test connectivity after user switch

View file

@ -109,7 +109,8 @@ func DERPVerify(
defer c.Close()
var result error
if err := c.Connect(t.Context()); err != nil {
err := c.Connect(t.Context())
if err != nil {
result = fmt.Errorf("client Connect: %w", err)
}

View file

@ -199,6 +199,7 @@ func TestResolveMagicDNSExtraRecordsPath(t *testing.T) {
},
})
require.NoError(t, err)
command := []string{"echo", fmt.Sprintf("'%s'", string(b4)), ">", erPath}
_, err = hs.Execute([]string{"bash", "-c", strings.Join(command, " ")})
require.NoError(t, err)