README ¶
Integration testing
Headscale relies on integration testing to ensure we remain compatible with Tailscale.
This is typically performed by starting a Headscale server and running a test "scenario" with an array of Tailscale clients and versions.
Headscale's test framework and the current set of scenarios are defined in this directory.
Tests are located in files ending with _test.go
and the framework are located in the rest.
Running integration tests locally
The easiest way to run tests locally is to use [act](INSERT LINK)
, a local GitHub Actions runner:
act pull_request -W .github/workflows/test-integration-v2-TestPingAllByIP.yaml
Alternatively, the docker run
command in each GitHub workflow file can be used.
Running integration tests on GitHub Actions
Each test currently runs as a separate workflows in GitHub actions, to add new test, run
go generate
inside ../cmd/gh-action-integration-generator/
and commit the result.
Documentation ¶
Index ¶
- Variables
- type ControlServer
- type Scenario
- func (s *Scenario) CountTailscale() int
- func (s *Scenario) CreateHeadscaleEnv(users map[string]int, tsOpts []tsic.Option, opts ...hsic.Option) error
- func (s *Scenario) CreatePreAuthKey(user string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
- func (s *Scenario) CreateTailscaleNodesInUser(userStr string, requestedVersion string, count int, opts ...tsic.Option) error
- func (s *Scenario) CreateUser(user string) 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) 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) RunTailscaleUp(userStr, loginServer, authKey string) error
- func (s *Scenario) Shutdown() error
- func (s *Scenario) Users() []string
- func (s *Scenario) WaitForTailscaleLogout()
- func (s *Scenario) WaitForTailscaleSync() error
- type TailscaleClient
- type User
Constants ¶
This section is empty.
Variables ¶
var ( // TailscaleVersions 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. TailscaleVersions = append( tailscaleVersions2021, tailscaleVersions2019..., ) )
Functions ¶
This section is empty.
Types ¶
type ControlServer ¶
type ControlServer interface { Shutdown() error SaveLog(string) error Execute(command []string) (string, error) GetHealthEndpoint() string GetEndpoint() string WaitForReady() error CreateUser(user string) error CreateAuthKey(user string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error) ListMachinesInUser(user string) ([]*v1.Machine, error) GetCert() []byte GetHostname() string GetIP() string }
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 ¶
NewScenario creates a test Scenario which can be used to bootstraps a ControlServer with a set of Users and TailscaleClients.
func (*Scenario) CountTailscale ¶
CountTailscale returns the total number of TailscaleClients in a Scenario. This is the sum of Users x TailscaleClients.
func (*Scenario) CreateHeadscaleEnv ¶
func (s *Scenario) CreateHeadscaleEnv( users map[string]int, tsOpts []tsic.Option, opts ...hsic.Option, ) error
CreateHeadscaleEnv is a conventient method returning a complete Headcale test environment with nodes of all versions, joined to the server with X users.
func (*Scenario) CreatePreAuthKey ¶
func (s *Scenario) CreatePreAuthKey( user string, 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) CreateTailscaleNodesInUser ¶
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 ¶
CreateUser creates a User to be created in the Headscale instance on behalf of the Scenario.
func (*Scenario) FindTailscaleClientByIP ¶
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)
GetIPs 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) 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 ¶
ListTailscaleClientsIPs 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) RunTailscaleUp ¶
RunTailscaleUp will log in all of the TailscaleClients associated with a User to the given ControlServer (by URL).
func (*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) WaitForTailscaleLogout ¶
func (s *Scenario) WaitForTailscaleLogout()
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.
type TailscaleClient ¶
type TailscaleClient interface { Hostname() string Shutdown() error Version() string Execute(command []string) (string, string, error) Up(loginServer, authKey string) error UpWithLoginURL(loginServer string) (*url.URL, error) Logout() error IPs() ([]netip.Addr, error) FQDN() (string, error) Status() (*ipnstate.Status, error) WaitForReady() error WaitForLogout() error WaitForPeers(expected int) error Ping(hostnameOrIP string, opts ...tsic.PingOption) error Curl(url string, opts ...tsic.CurlOption) (string, error) ID() string }
nolint
type User ¶
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.