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 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) 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) 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) error
- func (s *Scenario) WaitForTailscaleSyncWithPeerCount(peerCount int, timeout, retryInterval time.Duration) error
- type ScenarioSpec
- 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(10, 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(string) (string, string, error)
SaveProfile(string) error
Execute(command []string) (string, error)
WriteFile(path string, content []byte) error
ConnectToNetwork(network *dockertest.Network) error
GetHealthEndpoint() string
GetEndpoint() string
WaitForRunning() error
CreateUser(user string) (*v1.User, error)
CreateAuthKey(user uint64, reusable bool, ephemeral bool) (*v1.PreAuthKey, 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)
ApproveRoutes(uint64, []netip.Prefix) (*v1.Node, error)
GetCert() []byte
GetHostname() string
GetIPInNetwork(network *dockertest.Network) string
SetPolicy(*policyv2.Policy) error
GetAllMapReponses() (map[types.NodeID][]tailcfg.MapResponse, error)
PrimaryRoutes() (*routes.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 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 TailscaleClients. A Scenario is intended to simplify setting up a new testcase for testing a ControlServer with TailscaleClients. 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 Users and TailscaleClients.
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) CountTailscale ¶
CountTailscale returns the total number of TailscaleClients 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) 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 TailscaleClients associated with a User in a Scenario.
func (*Scenario) GetIPs ¶
GetIPs returns all netip.Addr of TailscaleClients 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 (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 TailscaleClients given the Users passed as parameters.
func (*Scenario) ListTailscaleClientsFQDNs ¶
ListTailscaleClientsFQDNs returns a list of FQDN based on Users passed as parameters.
func (*Scenario) ListTailscaleClientsIPs ¶
ListTailscaleClientsIPs returns a list of netip.Addr based on Users 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 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 TailscaleClients 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 TailscaleClients have logged out of the ControlServer.
func (*Scenario) WaitForTailscaleSync ¶
WaitForTailscaleSync blocks execution until all the TailscaleClient reports to have all other TailscaleClients present in their netmap.NetworkMap.
func (*Scenario) WaitForTailscaleSyncPerUser ¶ added in v0.27.0
WaitForTailscaleSyncPerUser blocks execution until each TailscaleClient has the expected number of peers for its user. This is useful for policies like autogroup:self where nodes only see same-user peers, not all nodes in the network.
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 TailscaleClients 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][]string
// 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
// 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 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)
// 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.