mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-24 16:41:30 +02:00
e2e/harness documents itself as feature-agnostic, but three details assumed the caller lives in this repo, so the terraform provider's acceptance suite would otherwise carry a second harness for the same product. repoRoot took the first module root above the working directory as the Docker build context, which from another module is the caller's own root, with no combined/Dockerfile.multistage in it. It now requires that ancestor to be this module, and otherwise asks the go tool for the source: for a dependent, the extracted directory of the version it pins, so the server matches the client library it was compiled against. That lookup uses -mod=readonly, since automatic vendor mode otherwise reports an empty Dir. Geolocation was disabled unconditionally. Agent-network ingest does not use it, but location-based posture checks need the database, and a rule management cannot evaluate fails rather than passing. StartClient pinned one network alias and set no hostname, so a second agent could not start and a peer's name was arbitrary. Management records that hostname, making it the peer's name in the API. The client entrypoint is copied with an explicit mode: git tracks it 100755, but the module cache extracts 0444, so a dependent's build produced a container exiting with "permission denied". Adds CombinedOption, WithGeolocation, WithServerEnv, ClientOption and WithClientName.
85 lines
2.8 KiB
Go
85 lines
2.8 KiB
Go
//go:build e2e
|
|
|
|
package harness
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// modulePath is this module, used both to recognise the repo when walking up
|
|
// from the working directory and to locate it when the suite lives elsewhere.
|
|
const modulePath = "github.com/netbirdio/netbird"
|
|
|
|
// repoRoot returns the directory the component Dockerfiles are built from.
|
|
//
|
|
// Walking up from the working directory finds it for any test inside this repo,
|
|
// no matter which package it runs from. A suite in another module gets a
|
|
// different answer that way — its own module root, where combined/Dockerfile
|
|
// does not exist — so the ancestor has to be this module and not merely some
|
|
// module. When it is not, the build context is the extracted module directory of
|
|
// whichever version that suite depends on, which is the right one: the server it
|
|
// tests against is then built from the same revision as the client library it
|
|
// was compiled with.
|
|
func repoRoot(ctx context.Context) (string, error) {
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for {
|
|
if isModule(filepath.Join(dir, "go.mod"), modulePath) {
|
|
return dir, nil
|
|
}
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
break
|
|
}
|
|
dir = parent
|
|
}
|
|
return moduleDir(ctx, modulePath)
|
|
}
|
|
|
|
// isModule reports whether the go.mod at path declares the given module.
|
|
func isModule(path, want string) bool {
|
|
b, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
for _, line := range strings.Split(string(b), "\n") {
|
|
if rest, ok := strings.CutPrefix(strings.TrimSpace(line), "module "); ok {
|
|
return strings.TrimSpace(rest) == want
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// moduleDir asks the go tool where a module's source is, which for a dependent
|
|
// module is its extracted copy in the module cache. The cache is read-only, and
|
|
// a Docker build context is only ever read.
|
|
//
|
|
// -mod=readonly is required rather than cosmetic. A caller that vendors its
|
|
// dependencies puts the go command in automatic vendor mode, where this lookup
|
|
// succeeds with an EMPTY directory — vendor/ holds packages, not module source,
|
|
// so there is nothing to report. Asking in readonly mode resolves against the
|
|
// module graph instead, which answers for both a cached module and a local
|
|
// replacement, and neither writes to go.mod.
|
|
func moduleDir(ctx context.Context, module string) (string, error) {
|
|
cmd := exec.CommandContext(ctx, "go", "list", "-mod=readonly", "-m", "-f", "{{.Dir}}", module)
|
|
out, err := cmd.Output()
|
|
if err != nil {
|
|
return "", fmt.Errorf("locate %s: %w", module, err)
|
|
}
|
|
dir := strings.TrimSpace(string(out))
|
|
if dir == "" {
|
|
return "", fmt.Errorf("locate %s: the go tool reported no directory; run `go mod download %s`", module, module)
|
|
}
|
|
if _, err := os.Stat(dir); err != nil {
|
|
return "", fmt.Errorf("locate %s: %w", module, err)
|
|
}
|
|
return dir, nil
|
|
}
|