-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #81 from kradalby/integration-tests
Add Integration tests
- Loading branch information
Showing
14 changed files
with
408 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// integration tests are not needed in docker | ||
// ignoring it let us speed up the integration test | ||
// development | ||
integration_test.go | ||
|
||
Dockerfile* | ||
docker-compose* | ||
.dockerignore | ||
.goreleaser.yml | ||
.git | ||
.github | ||
.gitignore | ||
README.md | ||
LICENSE | ||
.vscode | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,4 @@ | |
config.json | ||
*.key | ||
/db.sqlite | ||
*.sqlite3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,19 @@ | ||
FROM golang:latest AS build | ||
ENV GOPATH /go | ||
COPY . /go/src/headscale | ||
|
||
COPY go.mod go.sum /go/src/headscale/ | ||
WORKDIR /go/src/headscale | ||
RUN go mod download | ||
|
||
COPY . /go/src/headscale | ||
|
||
RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale | ||
RUN test -e /go/bin/headscale | ||
|
||
FROM scratch | ||
COPY --from=build /go/bin/headscale /go/bin/headscale | ||
FROM ubuntu:latest | ||
|
||
COPY --from=build /go/bin/headscale /usr/local/bin/headscale | ||
ENV TZ UTC | ||
|
||
EXPOSE 8080/tcp | ||
ENTRYPOINT ["/go/bin/headscale"] | ||
CMD ["headscale"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM ubuntu:latest | ||
|
||
RUN apt-get update \ | ||
&& apt-get install -y gnupg curl \ | ||
&& curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/focal.gpg | apt-key add - \ | ||
&& curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/focal.list | tee /etc/apt/sources.list.d/tailscale.list \ | ||
&& apt-get update \ | ||
&& apt-get install -y tailscale \ | ||
&& rm -rf /var/lib/apt/lists/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
// +build integration | ||
|
||
package headscale | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"os" | ||
"strings" | ||
|
||
"github.com/ory/dockertest/v3" | ||
"github.com/ory/dockertest/v3/docker" | ||
"inet.af/netaddr" | ||
|
||
"gopkg.in/check.v1" | ||
) | ||
|
||
var _ = check.Suite(&IntegrationSuite{}) | ||
|
||
type IntegrationSuite struct{} | ||
|
||
var integrationTmpDir string | ||
var ih Headscale | ||
|
||
var pool dockertest.Pool | ||
var network dockertest.Network | ||
var headscale dockertest.Resource | ||
var tailscaleCount int = 10 | ||
var tailscales map[string]dockertest.Resource | ||
|
||
func executeCommand(resource *dockertest.Resource, cmd []string) (string, error) { | ||
var stdout bytes.Buffer | ||
var stderr bytes.Buffer | ||
|
||
exitCode, err := resource.Exec( | ||
cmd, | ||
dockertest.ExecOptions{ | ||
StdOut: &stdout, | ||
StdErr: &stderr, | ||
}, | ||
) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
if exitCode != 0 { | ||
fmt.Println("Command: ", cmd) | ||
fmt.Println("stdout: ", stdout.String()) | ||
fmt.Println("stderr: ", stderr.String()) | ||
return "", fmt.Errorf("command failed with: %s", stderr.String()) | ||
} | ||
|
||
return stdout.String(), nil | ||
} | ||
|
||
func dockerRestartPolicy(config *docker.HostConfig) { | ||
// set AutoRemove to true so that stopped container goes away by itself | ||
config.AutoRemove = true | ||
config.RestartPolicy = docker.RestartPolicy{ | ||
Name: "no", | ||
} | ||
} | ||
|
||
func (s *IntegrationSuite) SetUpSuite(c *check.C) { | ||
var err error | ||
h = Headscale{ | ||
dbType: "sqlite3", | ||
dbString: "integration_test_db.sqlite3", | ||
} | ||
|
||
if ppool, err := dockertest.NewPool(""); err == nil { | ||
pool = *ppool | ||
} else { | ||
log.Fatalf("Could not connect to docker: %s", err) | ||
} | ||
|
||
if pnetwork, err := pool.CreateNetwork("headscale-test"); err == nil { | ||
network = *pnetwork | ||
} else { | ||
log.Fatalf("Could not create network: %s", err) | ||
} | ||
|
||
headscaleBuildOptions := &dockertest.BuildOptions{ | ||
Dockerfile: "Dockerfile", | ||
ContextDir: ".", | ||
} | ||
|
||
tailscaleBuildOptions := &dockertest.BuildOptions{ | ||
Dockerfile: "Dockerfile.tailscale", | ||
ContextDir: ".", | ||
} | ||
|
||
currentPath, err := os.Getwd() | ||
if err != nil { | ||
log.Fatalf("Could not determine current path: %s", err) | ||
} | ||
|
||
headscaleOptions := &dockertest.RunOptions{ | ||
Name: "headscale", | ||
Mounts: []string{ | ||
fmt.Sprintf("%s/integration_test/etc:/etc/headscale", currentPath), | ||
fmt.Sprintf("%s/derp.yaml:/etc/headscale/derp.yaml", currentPath), | ||
}, | ||
Networks: []*dockertest.Network{&network}, | ||
// Cmd: []string{"sleep", "3600"}, | ||
Cmd: []string{"headscale", "serve"}, | ||
PortBindings: map[docker.Port][]docker.PortBinding{ | ||
"8080/tcp": []docker.PortBinding{{HostPort: "8080"}}, | ||
}, | ||
Env: []string{}, | ||
} | ||
|
||
fmt.Println("Creating headscale container") | ||
if pheadscale, err := pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, dockerRestartPolicy); err == nil { | ||
headscale = *pheadscale | ||
} else { | ||
log.Fatalf("Could not start resource: %s", err) | ||
} | ||
fmt.Println("Created headscale container") | ||
|
||
fmt.Println("Creating tailscale containers") | ||
tailscales = make(map[string]dockertest.Resource) | ||
for i := 0; i < tailscaleCount; i++ { | ||
hostname := fmt.Sprintf("tailscale%d", i) | ||
tailscaleOptions := &dockertest.RunOptions{ | ||
Name: hostname, | ||
Networks: []*dockertest.Network{&network}, | ||
// Make the container run until killed | ||
// Cmd: []string{"sleep", "3600"}, | ||
Cmd: []string{"tailscaled", "--tun=userspace-networking", "--socks5-server=localhost:1055"}, | ||
Env: []string{}, | ||
} | ||
|
||
if pts, err := pool.BuildAndRunWithBuildOptions(tailscaleBuildOptions, tailscaleOptions, dockerRestartPolicy); err == nil { | ||
tailscales[hostname] = *pts | ||
} else { | ||
log.Fatalf("Could not start resource: %s", err) | ||
} | ||
fmt.Printf("Created %s container\n", hostname) | ||
} | ||
|
||
fmt.Println("Waiting for headscale to be ready") | ||
hostEndpoint := fmt.Sprintf("localhost:%s", headscale.GetPort("8080/tcp")) | ||
|
||
if err := pool.Retry(func() error { | ||
url := fmt.Sprintf("http://%s/health", hostEndpoint) | ||
resp, err := http.Get(url) | ||
if err != nil { | ||
return err | ||
} | ||
if resp.StatusCode != http.StatusOK { | ||
return fmt.Errorf("status code not OK") | ||
} | ||
return nil | ||
}); err != nil { | ||
log.Fatalf("Could not connect to docker: %s", err) | ||
} | ||
fmt.Println("headscale container is ready") | ||
|
||
fmt.Println("Creating headscale namespace") | ||
result, err := executeCommand( | ||
&headscale, | ||
[]string{"headscale", "namespaces", "create", "test"}, | ||
) | ||
c.Assert(err, check.IsNil) | ||
|
||
fmt.Println("Creating pre auth key") | ||
authKey, err := executeCommand( | ||
&headscale, | ||
[]string{"headscale", "-n", "test", "preauthkeys", "create", "--reusable", "--expiration", "24h"}, | ||
) | ||
c.Assert(err, check.IsNil) | ||
|
||
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 { | ||
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( | ||
&tailscale, | ||
command, | ||
) | ||
fmt.Println("tailscale result: ", result) | ||
c.Assert(err, check.IsNil) | ||
fmt.Printf("%s joined\n", hostname) | ||
} | ||
} | ||
|
||
func (s *IntegrationSuite) TearDownSuite(c *check.C) { | ||
if err := pool.Purge(&headscale); err != nil { | ||
log.Printf("Could not purge resource: %s\n", err) | ||
} | ||
|
||
for _, tailscale := range tailscales { | ||
if err := pool.Purge(&tailscale); err != nil { | ||
log.Printf("Could not purge resource: %s\n", err) | ||
} | ||
} | ||
|
||
if err := network.Close(); err != nil { | ||
log.Printf("Could not close network: %s\n", err) | ||
} | ||
} | ||
|
||
func (s *IntegrationSuite) TestListNodes(c *check.C) { | ||
fmt.Println("Listing nodes") | ||
result, err := executeCommand( | ||
&headscale, | ||
[]string{"headscale", "-n", "test", "nodes", "list"}, | ||
) | ||
c.Assert(err, check.IsNil) | ||
|
||
for hostname, _ := range tailscales { | ||
c.Assert(strings.Contains(result, hostname), check.Equals, true) | ||
} | ||
} | ||
|
||
func (s *IntegrationSuite) TestGetIpAddresses(c *check.C) { | ||
ipPrefix := netaddr.MustParseIPPrefix("100.64.0.0/10") | ||
ips := make(map[string]netaddr.IP) | ||
for hostname, tailscale := range tailscales { | ||
command := []string{"tailscale", "ip"} | ||
|
||
result, err := executeCommand( | ||
&tailscale, | ||
command, | ||
) | ||
c.Assert(err, check.IsNil) | ||
|
||
ip, err := netaddr.ParseIP(strings.TrimSuffix(result, "\n")) | ||
c.Assert(err, check.IsNil) | ||
|
||
fmt.Printf("IP for %s: %s", hostname, result) | ||
|
||
// c.Assert(ip.Valid(), check.IsTrue) | ||
c.Assert(ip.Is4(), check.Equals, true) | ||
c.Assert(ipPrefix.Contains(ip), check.Equals, true) | ||
|
||
ips[hostname] = ip | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
derp.yaml | ||
*.sqlite | ||
*.sqlite3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"server_url": "http://headscale:8080", | ||
"listen_addr": "0.0.0.0:8080", | ||
"private_key_path": "private.key", | ||
"derp_map_path": "derp.yaml", | ||
"ephemeral_node_inactivity_timeout": "30m", | ||
"db_type": "sqlite3", | ||
"db_path": "/tmp/integration_test_db.sqlite3", | ||
"acl_policy_path": "", | ||
"log_level": "trace" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
SEmQwCu+tGywQWEUsf93TpTRUvlB7WhnCdHgWrSXjEA= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters