.github, tstest/natlab/vmtest: replace old VM runner job with natlab tests
The "vm" CI job ran a single test (TestRunUbuntu2404 from tstest/integration/vms) on a privileged self-hosted runner. Its coverage is nearly all redundant with the modern natlab vmtest suite, which boots real Ubuntu VMs and already exercises connectivity, kernel TUN, SSH, Taildrop, ACME, and OS DNS integration on GitHub-hosted runners. The two things it tested that natlab didn't are added back as natlab tests so the runner can be decommissioned: TestUbuntuSystemdUnit runs tailscaled via the stock systemd unit that Linux packages ship (cmd/tailscaled/tailscaled.service with tailscaled.defaults as its EnvironmentFile) instead of launching the binary directly, verifying the unit's directives and its Type=notify readiness handshake. TestDNSExtraRecordsSearchDomains verifies that control-plane DNS ExtraRecords and search domains are resolvable through the guest's OS resolver (libc to systemd-resolved to quad-100). Updates #13038 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I8d0dfb8b8153289e7ca78f3af03dfece9497bfe8
This commit is contained in:
committed by
Brad Fitzpatrick
parent
6bf05cb63e
commit
bef2cd8088
@@ -97,6 +97,9 @@ type Env struct {
|
||||
selfSignedDERPCertPinning bool // serve test DERP map with sha256-raw cert pins
|
||||
fakeACME bool // point tailscaled at vnet's fake ACME server
|
||||
|
||||
controlDNSDomain string // MagicDNS domain for the test control server (see ControlDNS)
|
||||
controlDNS *tailcfg.DNSConfig // DNS config for the test control server (see ControlDNS)
|
||||
|
||||
// Shared resource initialization (sync.Once for things multiple nodes share).
|
||||
vnetOnce sync.Once
|
||||
gokrazyOnce sync.Once
|
||||
@@ -403,6 +406,16 @@ func FakeACME() EnvOption {
|
||||
return envOptFunc(func(e *Env) { e.fakeACME = true })
|
||||
}
|
||||
|
||||
// ControlDNS returns an [EnvOption] that makes the test control server send
|
||||
// the given DNS configuration in MapResponses, with node names placed under
|
||||
// the given MagicDNS domain (e.g. "tailnet.test").
|
||||
func ControlDNS(magicDNSDomain string, cfg *tailcfg.DNSConfig) EnvOption {
|
||||
return envOptFunc(func(e *Env) {
|
||||
e.controlDNSDomain = magicDNSDomain
|
||||
e.controlDNS = cfg
|
||||
})
|
||||
}
|
||||
|
||||
// AddNetwork creates a new virtual network. Arguments follow the same pattern as
|
||||
// vnet.Config.AddNetwork (string IPs, NAT types, NetworkService values).
|
||||
func (e *Env) AddNetwork(opts ...any) *vnet.Network {
|
||||
@@ -430,6 +443,7 @@ type Node struct {
|
||||
joinTailnet bool
|
||||
runSSH bool // true to enable the node's Tailscale SSH server
|
||||
noAgent bool // true to skip TTA agent setup (e.g. macOS VMs without TTA)
|
||||
systemdUnit bool // true to run tailscaled via the stock systemd unit (Linux cloud VMs only)
|
||||
advertiseRoutes string
|
||||
snatSubnetRoutes *bool // nil means default (true)
|
||||
webServerPort int
|
||||
@@ -463,6 +477,8 @@ func (e *Env) AddNode(name string, opts ...any) *Node {
|
||||
n.runSSH = true
|
||||
case nodeOptNoAgent:
|
||||
n.noAgent = true
|
||||
case nodeOptSystemdUnit:
|
||||
n.systemdUnit = true
|
||||
case nodeOptAdvertiseRoutes:
|
||||
n.advertiseRoutes = string(o)
|
||||
case nodeOptSNATSubnetRoutes:
|
||||
@@ -482,6 +498,10 @@ func (e *Env) AddNode(name string, opts ...any) *Node {
|
||||
})
|
||||
}
|
||||
|
||||
if n.systemdUnit && (n.os.IsGokrazy || n.os.GOOS() != "linux") {
|
||||
e.t.Fatalf("SystemdUnit is only supported on Linux cloud VMs; node %s is %s", name, n.os.Name)
|
||||
}
|
||||
|
||||
// macOS VMs require a macOS arm64 host (Apple Virtualization.framework via
|
||||
// tailmac). Skip the test now rather than letting it proceed through the
|
||||
// rest of the setup only to fail later.
|
||||
@@ -520,6 +540,7 @@ type nodeOptOS OSImage
|
||||
type nodeOptNoTailscale struct{}
|
||||
type nodeOptTailscaleSSH struct{}
|
||||
type nodeOptNoAgent struct{}
|
||||
type nodeOptSystemdUnit struct{}
|
||||
type nodeOptAdvertiseRoutes string
|
||||
type nodeOptSNATSubnetRoutes bool
|
||||
type nodeOptWebServer int
|
||||
@@ -542,6 +563,14 @@ func TailscaleSSH() nodeOptTailscaleSSH { return nodeOptTailscaleSSH{} }
|
||||
// won't work. Useful for VMs that just need to boot and respond to ICMP.
|
||||
func NoAgent() nodeOptNoAgent { return nodeOptNoAgent{} }
|
||||
|
||||
// SystemdUnit returns a NodeOption that makes the node run tailscaled via the
|
||||
// stock systemd unit that Linux packages ship (cmd/tailscaled/tailscaled.service
|
||||
// with cmd/tailscaled/tailscaled.defaults as its EnvironmentFile), instead of
|
||||
// launching tailscaled directly as a background process. This exercises the
|
||||
// unit's sandboxing directives and its Type=notify readiness handshake.
|
||||
// It is only supported on Linux cloud VMs (e.g. Ubuntu, Debian).
|
||||
func SystemdUnit() nodeOptSystemdUnit { return nodeOptSystemdUnit{} }
|
||||
|
||||
// AdvertiseRoutes returns a NodeOption that configures the node to advertise
|
||||
// the given routes (comma-separated CIDRs) when joining the tailnet.
|
||||
func AdvertiseRoutes(routes string) nodeOptAdvertiseRoutes {
|
||||
@@ -1642,6 +1671,11 @@ func (e *Env) initVnet() {
|
||||
if e.selfSignedDERPCertPinning {
|
||||
e.server.ControlServer().DERPMap = e.buildSelfSignedDERPMap()
|
||||
}
|
||||
if e.controlDNS != nil {
|
||||
cs := e.server.ControlServer()
|
||||
cs.MagicDNSDomain = e.controlDNSDomain
|
||||
cs.DNSConfig = e.controlDNS.Clone()
|
||||
}
|
||||
if e.fakeACME {
|
||||
cs := e.server.ControlServer()
|
||||
cs.MagicDNSDomain = "tailnet.test"
|
||||
|
||||
Reference in New Issue
Block a user