Test two namespaces

This expands the tests to verify two namespaces instead of only one.

It verifies some of the isolation, and is prework for shared nodes
testing
This commit is contained in:
Kristoffer Dalby 2021-09-20 20:18:28 +01:00
parent d68d201722
commit f905812afa
No known key found for this signature in database
GPG key ID: 09F62DC067465735

View file

@ -33,29 +33,48 @@ var (
pool dockertest.Pool
network dockertest.Network
headscale dockertest.Resource
tailscaleCount int = 25
tailscales map[string]dockertest.Resource
)
var tailscaleVersions = []string{"1.14.3", "1.12.3"}
type TestNamespace struct {
count int
tailscales map[string]dockertest.Resource
}
type IntegrationTestSuite struct {
suite.Suite
stats *suite.SuiteInformation
namespaces map[string]TestNamespace
}
func TestIntegrationTestSuite(t *testing.T) {
s := new(IntegrationTestSuite)
s.namespaces = map[string]TestNamespace{
"main": {
count: 20,
tailscales: make(map[string]dockertest.Resource),
},
"shared": {
count: 5,
tailscales: make(map[string]dockertest.Resource),
},
}
suite.Run(t, s)
// HandleStats, which allows us to check if we passed and save logs
// is called after TearDown, so we cannot tear down containers before
// we have potentially saved the logs.
for _, tailscale := range tailscales {
for _, scales := range s.namespaces {
for _, tailscale := range scales.tailscales {
if err := pool.Purge(&tailscale); err != nil {
log.Printf("Could not purge resource: %s\n", err)
}
}
}
if !s.stats.Passed() {
err := saveLog(&headscale, "test_output")
@ -147,7 +166,7 @@ func dockerRestartPolicy(config *docker.HostConfig) {
}
}
func tailscaleContainer(identifier string, version string) (string, *dockertest.Resource) {
func tailscaleContainer(namespace, identifier, version string) (string, *dockertest.Resource) {
tailscaleBuildOptions := &dockertest.BuildOptions{
Dockerfile: "Dockerfile.tailscale",
ContextDir: ".",
@ -158,7 +177,7 @@ func tailscaleContainer(identifier string, version string) (string, *dockertest.
},
},
}
hostname := fmt.Sprintf("tailscale-%s-%s", strings.Replace(version, ".", "-", -1), identifier)
hostname := fmt.Sprintf("%s-tailscale-%s-%s", namespace, strings.Replace(version, ".", "-", -1), identifier)
tailscaleOptions := &dockertest.RunOptions{
Name: hostname,
Networks: []*dockertest.Network{&network},
@ -224,12 +243,13 @@ func (s *IntegrationTestSuite) SetupSuite() {
fmt.Println("Created headscale container")
fmt.Println("Creating tailscale containers")
tailscales = make(map[string]dockertest.Resource)
for i := 0; i < tailscaleCount; i++ {
for namespace, scales := range s.namespaces {
for i := 0; i < scales.count; i++ {
version := tailscaleVersions[i%len(tailscaleVersions)]
hostname, container := tailscaleContainer(fmt.Sprint(i), version)
tailscales[hostname] = *container
hostname, container := tailscaleContainer(namespace, fmt.Sprint(i), version)
scales.tailscales[hostname] = *container
}
}
fmt.Println("Waiting for headscale to be ready")
@ -250,29 +270,31 @@ func (s *IntegrationTestSuite) SetupSuite() {
}
fmt.Println("headscale container is ready")
fmt.Println("Creating headscale namespace")
for namespace, scales := range s.namespaces {
fmt.Printf("Creating headscale namespace: %s\n", namespace)
result, err := executeCommand(
&headscale,
[]string{"headscale", "namespaces", "create", "test"},
[]string{"headscale", "namespaces", "create", namespace},
)
assert.Nil(s.T(), err)
fmt.Println("headscale create namespace result: ", result)
fmt.Println("Creating pre auth key")
fmt.Printf("Creating pre auth key for %s\n", namespace)
authKey, err := executeCommand(
&headscale,
[]string{"headscale", "-n", "test", "preauthkeys", "create", "--reusable", "--expiration", "24h"},
[]string{"headscale", "-n", namespace, "preauthkeys", "create", "--reusable", "--expiration", "24h"},
)
assert.Nil(s.T(), err)
headscaleEndpoint := fmt.Sprintf("http://headscale:%s", headscale.GetPort("8080/tcp"))
fmt.Printf("Joining tailscale containers to headscale at %s\n", headscaleEndpoint)
for hostname, tailscale := range tailscales {
for hostname, tailscale := range scales.tailscales {
command := []string{"tailscale", "up", "-login-server", headscaleEndpoint, "--authkey", strings.TrimSuffix(authKey, "\n"), "--hostname", hostname}
fmt.Println("Join command:", command)
fmt.Printf("Running join command for %s\n", hostname)
result, err = executeCommand(
result, err := executeCommand(
&tailscale,
command,
)
@ -280,6 +302,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
assert.Nil(s.T(), err)
fmt.Printf("%s joined\n", hostname)
}
}
// The nodes need a bit of time to get their updated maps from headscale
// TODO: See if we can have a more deterministic wait here.
@ -294,10 +317,11 @@ func (s *IntegrationTestSuite) HandleStats(suiteName string, stats *suite.SuiteI
}
func (s *IntegrationTestSuite) TestListNodes() {
for namespace, scales := range s.namespaces {
fmt.Println("Listing nodes")
result, err := executeCommand(
&headscale,
[]string{"headscale", "-n", "test", "nodes", "list"},
[]string{"headscale", "-n", namespace, "nodes", "list"},
)
assert.Nil(s.T(), err)
@ -305,19 +329,21 @@ func (s *IntegrationTestSuite) TestListNodes() {
// Chck that the correct count of host is present in node list
lines := strings.Split(result, "\n")
assert.Equal(s.T(), len(tailscales), len(lines)-2)
assert.Equal(s.T(), len(scales.tailscales), len(lines)-2)
for hostname := range tailscales {
for hostname := range scales.tailscales {
assert.Contains(s.T(), result, hostname)
}
}
}
func (s *IntegrationTestSuite) TestGetIpAddresses() {
for _, scales := range s.namespaces {
ipPrefix := netaddr.MustParseIPPrefix("100.64.0.0/10")
ips, err := getIPs()
ips, err := getIPs(scales.tailscales)
assert.Nil(s.T(), err)
for hostname := range tailscales {
for hostname := range scales.tailscales {
s.T().Run(hostname, func(t *testing.T) {
ip := ips[hostname]
@ -330,13 +356,15 @@ func (s *IntegrationTestSuite) TestGetIpAddresses() {
ips[hostname] = ip
})
}
}
}
func (s *IntegrationTestSuite) TestStatus() {
ips, err := getIPs()
for _, scales := range s.namespaces {
ips, err := getIPs(scales.tailscales)
assert.Nil(s.T(), err)
for hostname, tailscale := range tailscales {
for hostname, tailscale := range scales.tailscales {
s.T().Run(hostname, func(t *testing.T) {
command := []string{"tailscale", "status"}
@ -352,7 +380,7 @@ func (s *IntegrationTestSuite) TestStatus() {
// as we have IPs/tailscales
lines := strings.Split(result, "\n")
assert.Equal(t, len(ips), len(lines)-1)
assert.Equal(t, len(tailscales), len(lines)-1)
assert.Equal(t, len(scales.tailscales), len(lines)-1)
// Check that all hosts is present in all hosts status
for ipHostname, ip := range ips {
@ -361,13 +389,15 @@ func (s *IntegrationTestSuite) TestStatus() {
}
})
}
}
}
func (s *IntegrationTestSuite) TestPingAllPeers() {
ips, err := getIPs()
for _, scales := range s.namespaces {
ips, err := getIPs(scales.tailscales)
assert.Nil(s.T(), err)
for hostname, tailscale := range tailscales {
for hostname, tailscale := range scales.tailscales {
for peername, ip := range ips {
s.T().Run(fmt.Sprintf("%s-%s", hostname, peername), func(t *testing.T) {
// We currently cant ping ourselves, so skip that.
@ -394,9 +424,10 @@ func (s *IntegrationTestSuite) TestPingAllPeers() {
})
}
}
}
}
func getIPs() (map[string]netaddr.IP, error) {
func getIPs(tailscales map[string]dockertest.Resource) (map[string]netaddr.IP, error) {
ips := make(map[string]netaddr.IP)
for hostname, tailscale := range tailscales {
command := []string{"tailscale", "ip"}