Documentation
¶
Index ¶
- Constants
- Variables
- func GetUserByName(headscale ControlServer, username string) (*v1.User, error)
- func Webservice(s *Scenario, networkName string) (*dockertest.Resource, error)
- type ControlServer
- type LoggingRoundTripper
- type NetworkSpec
- type NodeSystemStatus
- type Scenario
- func (s *Scenario) AddAndLoginClient(t *testing.T, username string, version string, headscale ControlServer, ...) (TailscaleClient, error)
- func (s *Scenario) AddNetwork(name string) (*dockertest.Network, error)
- func (s *Scenario) AddNetworkWithSubnet(name, subnet string) (*dockertest.Network, error)
- func (s *Scenario) CountTailscale() int
- func (s *Scenario) CreateDERPServer(version string, opts ...dsic.Option) (*dsic.DERPServerInContainer, error)
- func (s *Scenario) CreateHeadscaleEnv(tsOpts []tsic.Option, opts ...hsic.Option) error
- func (s *Scenario) CreateHeadscaleEnvWithLoginURL(tsOpts []tsic.Option, opts ...hsic.Option) error
- func (s *Scenario) CreatePreAuthKey(user uint64, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
- func (s *Scenario) CreatePreAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.PreAuthKey, error)
- func (s *Scenario) CreatePreAuthKeyWithTags(user uint64, reusable bool, ephemeral bool, tags []string) (*v1.PreAuthKey, error)
- func (s *Scenario) CreateTailscaleNode(version string, opts ...tsic.Option) (TailscaleClient, error)
- func (s *Scenario) CreateTailscaleNodesInUser(userStr string, requestedVersion string, count int, opts ...tsic.Option) error
- func (s *Scenario) CreateUser(user string) (*v1.User, error)
- func (s *Scenario) FindTailscaleClientByIP(ip netip.Addr) (TailscaleClient, error)
- func (s *Scenario) GetClients(user string) ([]TailscaleClient, error)
- func (s *Scenario) GetIPs(user string) ([]netip.Addr, error)
- func (s *Scenario) GetOrCreateUser(userStr string) *User
- func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error)
- func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, error)
- func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error)
- func (s *Scenario) ListTailscaleClientsIPs(users ...string) ([]netip.Addr, error)
- func (s *Scenario) MustAddAndLoginClient(t *testing.T, username string, version string, headscale ControlServer, ...) TailscaleClient
- func (s *Scenario) Network(name string) (*dockertest.Network, error)
- func (s *Scenario) Networks() []*dockertest.Network
- func (s *Scenario) Pool() *dockertest.Pool
- func (s *Scenario) RunTailscaleUp(userStr, loginServer, authKey string) error
- func (s *Scenario) RunTailscaleUpWithURL(userStr, loginServer string) error
- func (s *Scenario) Services(name string) ([]*dockertest.Resource, error)
- func (s *Scenario) Shutdown()
- func (s *Scenario) ShutdownAssertNoPanics(t *testing.T)
- func (s *Scenario) SubnetOfNetwork(name string) (*netip.Prefix, error)
- func (s *Scenario) Users() []string
- func (s *Scenario) WaitForTailscaleLogout() error
- func (s *Scenario) WaitForTailscaleSync() error
- func (s *Scenario) WaitForTailscaleSyncPerUser(timeout, retryInterval time.Duration, opts ...SyncOption) error
- func (s *Scenario) WaitForTailscaleSyncWithPeerCount(peerCount int, timeout, retryInterval time.Duration) error
- type ScenarioSpec
- type SyncOption
- type TailscaleClient
- type User
Constants ¶
const ( // TimestampFormat is the standard timestamp format used across all integration tests // Format: "2006-01-02T15-04-05.999999999" provides high precision timestamps // suitable for debugging and log correlation in integration tests. TimestampFormat = "2006-01-02T15-04-05.999999999" // TimestampFormatRunID is used for generating unique run identifiers // Format: "20060102-150405" provides compact date-time for file/directory names. TimestampFormatRunID = "20060102-150405" )
Variables ¶
var ( // AllVersions represents a list of Tailscale versions the suite // uses to test compatibility with the [ControlServer]. // // The list contains two special cases, "head" and "unstable" which // points to the current tip of Tailscale's main branch and the latest // released unstable version. // // The rest of the version represents Tailscale versions that can be // found in Tailscale's apt repository. AllVersions = append([]string{"head", "unstable"}, capver.TailscaleLatestMajorMinor(capver.SupportedMajorMinorVersions, true)...) // MustTestVersions is the minimum set of versions we should test. // At the moment, this is arbitrarily chosen as: // // - Two unstable (HEAD and unstable) // - Two latest versions // - Two oldest supported version. MustTestVersions = append( AllVersions[0:4], AllVersions[len(AllVersions)-2:]..., ) )
Functions ¶
func GetUserByName ¶ added in v0.27.0
func GetUserByName(headscale ControlServer, username string) (*v1.User, error)
GetUserByName retrieves a user by name from the headscale server. This is a common pattern used when creating preauth keys or managing users.
func Webservice ¶ added in v0.26.0
func Webservice(s *Scenario, networkName string) (*dockertest.Resource, error)
Types ¶
type ControlServer ¶
type ControlServer interface {
Shutdown() (string, string, error)
SaveLog(path string) (string, string, error)
ReadLog() (string, string, error)
SaveProfile(path string) error
Execute(command []string) (string, error)
WriteFile(path string, content []byte) error
ConnectToNetwork(network *dockertest.Network) error
GetHealthEndpoint() string
GetEndpoint() string
WaitForRunning() error
Restart() error
CreateUser(user string) (*v1.User, error)
CreateAuthKey(user uint64, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
CreateAuthKeyWithTags(user uint64, reusable bool, ephemeral bool, tags []string) (*v1.PreAuthKey, error)
CreateAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.PreAuthKey, error)
DeleteAuthKey(id uint64) error
ListNodes(users ...string) ([]*v1.Node, error)
DeleteNode(nodeID uint64) error
NodesByUser() (map[string][]*v1.Node, error)
NodesByName() (map[string]*v1.Node, error)
ListUsers() ([]*v1.User, error)
MapUsers() (map[string]*v1.User, error)
DeleteUser(userID uint64) error
ApproveRoutes(nodeID uint64, routes []netip.Prefix) (*v1.Node, error)
SetNodeTags(nodeID uint64, tags []string) error
GetCert() []byte
GetHostname() string
GetIPInNetwork(network *dockertest.Network) string
SetPolicy(pol *policyv2.Policy) error
GetAllMapReponses() (map[types.NodeID][]tailcfg.MapResponse, error)
PrimaryRoutes() (*types.DebugRoutes, error)
DebugBatcher() (*hscontrol.DebugBatcherInfo, error)
DebugNodeStore() (map[types.NodeID]types.Node, error)
DebugFilter() ([]tailcfg.FilterRule, error)
}
type LoggingRoundTripper ¶ added in v0.26.0
type LoggingRoundTripper struct {
Hostname string
}
type NetworkSpec ¶ added in v0.29.0
type NetworkSpec struct {
// Users is the list of usernames whose nodes will be placed on this network.
Users []string
// Subnet, if set, is the CIDR for the Docker network (e.g. "198.51.100.0/24").
// When empty, Docker auto-assigns a subnet from its default pool (RFC1918).
// Use RFC 5737 TEST-NET ranges for networks that must be reachable through
// Tailscale exit nodes, since Tailscale's shrinkDefaultRoute strips RFC1918
// ranges from exit node forwarding filters.
Subnet string
}
NetworkSpec describes a Docker network for the test scenario.
type NodeSystemStatus ¶ added in v0.27.0
NodeSystemStatus represents the status of a node across different systems.
type Scenario ¶
type Scenario struct {
// contains filtered or unexported fields
}
Scenario is a representation of an environment with one ControlServer and one or more User's and its associated [TailscaleClient]s. A Scenario is intended to simplify setting up a new testcase for testing a ControlServer with [TailscaleClient]s. TODO(kradalby): make control server configurable, test correctness with Tailscale SaaS.
func NewScenario ¶
func NewScenario(spec ScenarioSpec) (*Scenario, error)
NewScenario creates a test Scenario which can be used to bootstraps a ControlServer with a set of [User]s and [TailscaleClient]s.
func (*Scenario) AddAndLoginClient ¶ added in v0.27.0
func (s *Scenario) AddAndLoginClient( t *testing.T, username string, version string, headscale ControlServer, tsOpts ...tsic.Option, ) (TailscaleClient, error)
AddAndLoginClient adds a new tailscale client to a user and logs it in. This combines the common pattern of: 1. Creating a new node 2. Finding the new node in the client list 3. Getting the user to create a preauth key 4. Logging in the new node.
func (*Scenario) AddNetwork ¶ added in v0.26.0
func (s *Scenario) AddNetwork(name string) (*dockertest.Network, error)
func (*Scenario) AddNetworkWithSubnet ¶ added in v0.29.0
func (s *Scenario) AddNetworkWithSubnet(name, subnet string) (*dockertest.Network, error)
func (*Scenario) CountTailscale ¶
CountTailscale returns the total number of [TailscaleClient]s in a Scenario. This is the sum of Users x TailscaleClients.
func (*Scenario) CreateDERPServer ¶ added in v0.24.0
func (s *Scenario) CreateDERPServer(version string, opts ...dsic.Option) (*dsic.DERPServerInContainer, error)
CreateDERPServer creates a new DERP server in a container.
func (*Scenario) CreateHeadscaleEnv ¶
func (*Scenario) CreateHeadscaleEnvWithLoginURL ¶ added in v0.26.0
func (*Scenario) CreatePreAuthKey ¶
func (s *Scenario) CreatePreAuthKey( user uint64, reusable bool, ephemeral bool, ) (*v1.PreAuthKey, error)
CreatePreAuthKey creates a "pre authentorised key" to be created in the Headscale instance on behalf of the Scenario.
func (*Scenario) CreatePreAuthKeyWithOptions ¶ added in v0.28.0
func (s *Scenario) CreatePreAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.PreAuthKey, error)
CreatePreAuthKeyWithOptions creates a "pre authorised key" with the specified options to be created in the Headscale instance on behalf of the Scenario.
func (*Scenario) CreatePreAuthKeyWithTags ¶ added in v0.28.0
func (s *Scenario) CreatePreAuthKeyWithTags( user uint64, reusable bool, ephemeral bool, tags []string, ) (*v1.PreAuthKey, error)
CreatePreAuthKeyWithTags creates a "pre authorised key" with the specified tags to be created in the Headscale instance on behalf of the Scenario.
func (*Scenario) CreateTailscaleNode ¶ added in v0.25.0
func (*Scenario) CreateTailscaleNodesInUser ¶ added in v0.19.0
func (s *Scenario) CreateTailscaleNodesInUser( userStr string, requestedVersion string, count int, opts ...tsic.Option, ) error
CreateTailscaleNodesInUser creates and adds a new TailscaleClient to a User in the Scenario.
func (*Scenario) CreateUser ¶ added in v0.19.0
CreateUser creates a User to be created in the Headscale instance on behalf of the Scenario.
func (*Scenario) FindTailscaleClientByIP ¶ added in v0.21.0
func (s *Scenario) FindTailscaleClientByIP(ip netip.Addr) (TailscaleClient, error)
FindTailscaleClientByIP returns a TailscaleClient associated with an IP address if it exists.
func (*Scenario) GetClients ¶
func (s *Scenario) GetClients(user string) ([]TailscaleClient, error)
GetClients returns all [TailscaleClient]s associated with a User in a Scenario.
func (*Scenario) GetIPs ¶
GetIPs returns all netip.Addr of [TailscaleClient]s associated with a User in a Scenario.
func (*Scenario) GetOrCreateUser ¶ added in v0.27.0
GetOrCreateUser gets or creates a user in the Scenario.
func (*Scenario) Headscale ¶
func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error)
Headscale returns a ControlServer instance based on hsic (hsic.HeadscaleInContainer). If the Scenario already has an instance, the pointer to the running container will be return, otherwise a new instance will be created. TODO(kradalby): make port and headscale configurable, multiple instances support?
func (*Scenario) ListTailscaleClients ¶
func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, error)
ListTailscaleClients returns a list of [TailscaleClient]s given the [User]s passed as parameters.
func (*Scenario) ListTailscaleClientsFQDNs ¶
ListTailscaleClientsFQDNs returns a list of FQDN based on [User]s passed as parameters.
func (*Scenario) ListTailscaleClientsIPs ¶
ListTailscaleClientsIPs returns a list of netip.Addr based on [User]s passed as parameters.
func (*Scenario) MustAddAndLoginClient ¶ added in v0.27.0
func (s *Scenario) MustAddAndLoginClient( t *testing.T, username string, version string, headscale ControlServer, tsOpts ...tsic.Option, ) TailscaleClient
MustAddAndLoginClient is like Scenario.AddAndLoginClient but fails the test on error.
func (*Scenario) Network ¶ added in v0.26.0
func (s *Scenario) Network(name string) (*dockertest.Network, error)
func (*Scenario) Networks ¶ added in v0.26.0
func (s *Scenario) Networks() []*dockertest.Network
func (*Scenario) Pool ¶ added in v0.27.0
func (s *Scenario) Pool() *dockertest.Pool
Pool returns the dockertest.Pool for the scenario.
func (*Scenario) RunTailscaleUp ¶
RunTailscaleUp will log in all of the [TailscaleClient]s associated with a User to the given ControlServer (by URL).
func (*Scenario) RunTailscaleUpWithURL ¶ added in v0.26.0
func (*Scenario) Services ¶ added in v0.26.0
func (s *Scenario) Services(name string) ([]*dockertest.Resource, error)
func (*Scenario) Shutdown ¶
func (s *Scenario) Shutdown()
Shutdown shuts down and cleans up all the containers (ControlServer, TailscaleClient) and networks associated with it. In addition, it will save the logs of the ControlServer to `/tmp/control` in the environment running the tests.
func (*Scenario) ShutdownAssertNoPanics ¶ added in v0.23.0
func (*Scenario) SubnetOfNetwork ¶ added in v0.26.0
func (*Scenario) Users ¶ added in v0.19.0
Users returns the name of all users associated with the Scenario.
func (*Scenario) WaitForTailscaleLogout ¶ added in v0.18.0
WaitForTailscaleLogout blocks execution until all [TailscaleClient]s have logged out of the ControlServer.
func (*Scenario) WaitForTailscaleSync ¶
WaitForTailscaleSync blocks execution until all the TailscaleClient reports to have all other [TailscaleClient]s present in their netmap.NetworkMap.
func (*Scenario) WaitForTailscaleSyncPerUser ¶ added in v0.27.0
func (s *Scenario) WaitForTailscaleSyncPerUser(timeout, retryInterval time.Duration, opts ...SyncOption) error
WaitForTailscaleSyncPerUser blocks until each TailscaleClient has the expected per-user peer count (necessary for policies like autogroup:self where cross-user peers are invisible).
func (*Scenario) WaitForTailscaleSyncWithPeerCount ¶ added in v0.23.0
func (s *Scenario) WaitForTailscaleSyncWithPeerCount(peerCount int, timeout, retryInterval time.Duration) error
WaitForTailscaleSyncWithPeerCount blocks execution until all the TailscaleClient reports to have all other [TailscaleClient]s present in their netmap.NetworkMap.
type ScenarioSpec ¶ added in v0.26.0
type ScenarioSpec struct {
// Users is a list of usernames that will be created.
// Each created user will get nodes equivalent to NodesPerUser
Users []string
// NodesPerUser is how many nodes should be attached to each user.
NodesPerUser int
// Networks, if set, is the separate Docker networks that should be
// created and a list of the users that should be placed in those networks.
// If not set, a single network will be created and all users+nodes will be
// added there.
// Please note that Docker networks are not necessarily routable and
// connections between them might fall back to DERP.
Networks map[string]NetworkSpec
// ExtraService, if set, is additional a map of network to additional
// container services that should be set up. These container services
// typically dont run Tailscale, e.g. web service to test subnet router.
ExtraService map[string][]extraServiceFunc
// Versions is specific list of versions to use for the test.
Versions []string
// OIDCSkipUserCreation, if true, skips creating users via headscale CLI
// during environment setup. Useful for OIDC tests where the SSH policy
// references users by name, since OIDC login creates users automatically
// and pre-creating them via CLI causes duplicate user records.
OIDCSkipUserCreation bool
// OIDCUsers, if populated, will start a Mock OIDC server and populate
// the user login stack with the given users.
// If the NodesPerUser is set, it should align with this list to ensure
// the correct users are logged in.
// This is because the MockOIDC server can only serve login
// requests based on a queue it has been given on startup.
// We currently only populates it with one login request per user.
OIDCUsers []mockoidc.MockUser
OIDCAccessTTL time.Duration
MaxWait time.Duration
}
ScenarioSpec describes the users, nodes, and network topology to set up for a given scenario.
type SyncOption ¶ added in v0.29.0
type SyncOption func(*syncOptions)
SyncOption configures Scenario.WaitForTailscaleSyncPerUser.
func WithPreBarrier ¶ added in v0.29.0
func WithPreBarrier(barrier func(context.Context) error) SyncOption
WithPreBarrier runs a precondition check before per-user peer-count waits begin, sharing the outer timeout via context. Use to gate on a server-side signal (e.g. policy compile) that the peer-count alone cannot observe.
type TailscaleClient ¶
type TailscaleClient interface {
Hostname() string
Shutdown() (string, string, error)
Version() string
Execute(
command []string,
options ...dockertestutil.ExecuteCommandOption,
) (string, string, error)
Login(loginServer, authKey string) error
LoginWithURL(loginServer string) (*url.URL, error)
Logout() error
Restart() error
Up() error
Down() error
IPs() ([]netip.Addr, error)
MustIPs() []netip.Addr
IPv4() (netip.Addr, error)
MustIPv4() netip.Addr
MustIPv6() netip.Addr
FQDN() (string, error)
MustFQDN() string
Status(...bool) (*ipnstate.Status, error)
MustStatus() *ipnstate.Status
Netmap() (*netmap.NetworkMap, error)
DebugDERPRegion(region string) (*ipnstate.DebugDERPRegionReport, error)
GetNodePrivateKey() (*key.NodePrivate, error)
Netcheck() (*netcheck.Report, error)
WaitForNeedsLogin(timeout time.Duration) error
WaitForRunning(timeout time.Duration) error
WaitForPeers(expected int, timeout, retryInterval time.Duration) error
Ping(hostnameOrIP string, opts ...tsic.PingOption) error
Curl(url string, opts ...tsic.CurlOption) (string, error)
CurlFailFast(url string) (string, error)
Traceroute(netip.Addr) (util.Traceroute, error)
ContainerID() string
MustID() types.NodeID
ReadFile(path string) ([]byte, error)
PacketFilter() ([]filter.Match, error)
ConnectToNetwork(network *dockertest.Network) error
DisconnectFromNetwork(network *dockertest.Network) error
ReconnectToNetwork(network *dockertest.Network) error
// FailingPeersAsString returns a formatted-ish multi-line-string of peers in the client
// and a bool indicating if the clients online count and peer count is equal.
FailingPeersAsString() (string, bool, error)
WriteLogs(stdout, stderr io.Writer) error
}
nolint
func FindNewClient ¶ added in v0.27.0
func FindNewClient(original, updated []TailscaleClient) (TailscaleClient, error)
FindNewClient finds a client that is in the new list but not in the original list. This is useful when dynamically adding nodes during tests and needing to identify which client was just added.
type User ¶ added in v0.19.0
type User struct {
Clients map[string]TailscaleClient
// contains filtered or unexported fields
}
User represents a User in the ControlServer and a map of TailscaleClient's associated with the User.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package tsric provides a TailscaleRustInContainer (tsric) implementation that runs the tailscale-rs axum example inside a Docker container for integration testing with headscale.
|
Package tsric provides a TailscaleRustInContainer (tsric) implementation that runs the tailscale-rs axum example inside a Docker container for integration testing with headscale. |
|
wasmic
|
|
|
wasmclient
command
This package only does something when built for GOOS=js (see main.go).
|
This package only does something when built for GOOS=js (see main.go). |