137 lines
2.8 KiB
Go
137 lines
2.8 KiB
Go
package testutil
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"testing/fstest"
|
|
|
|
"forge-mesh/internal/api"
|
|
"forge-mesh/internal/config"
|
|
"forge-mesh/internal/db"
|
|
"forge-mesh/internal/forge"
|
|
)
|
|
|
|
const (
|
|
DefaultBasicUser = "admin"
|
|
DefaultBasicPass = "changeme"
|
|
DefaultFleetSecret = "test-fleet-secret"
|
|
)
|
|
|
|
// TestServer wraps an httptest server with auth helpers.
|
|
type TestServer struct {
|
|
URL string
|
|
BasicUser string
|
|
BasicPass string
|
|
FleetSecret string
|
|
SQL *sql.DB
|
|
close func()
|
|
}
|
|
|
|
// Close shuts down the test server and database.
|
|
func (ts *TestServer) Close() {
|
|
if ts.close != nil {
|
|
ts.close()
|
|
}
|
|
}
|
|
|
|
// NewTestServer spins up a full forge-mesh HTTP server on a random port.
|
|
func NewTestServer(t *testing.T) *TestServer {
|
|
t.Helper()
|
|
|
|
dir := t.TempDir()
|
|
cfgPath := filepath.Join(dir, "config.json")
|
|
writeConfig(t, cfgPath, dir)
|
|
|
|
cfg, err := config.Load(cfgPath)
|
|
if err != nil {
|
|
t.Fatalf("load config: %v", err)
|
|
}
|
|
if err := cfg.EnsureDataDirs(); err != nil {
|
|
t.Fatalf("ensure dirs: %v", err)
|
|
}
|
|
|
|
conn, err := db.Open(cfg.DatabasePath)
|
|
if err != nil {
|
|
t.Fatalf("open db: %v", err)
|
|
}
|
|
|
|
kp, err := forge.LoadOrCreateKey(cfg.Forge.SigningKeyPath)
|
|
if err != nil {
|
|
conn.Close()
|
|
t.Fatalf("signing key: %v", err)
|
|
}
|
|
|
|
repoRoot, err := findRepoRoot()
|
|
if err != nil {
|
|
conn.Close()
|
|
t.Fatalf("repo root: %v", err)
|
|
}
|
|
tmplPath := filepath.Join(repoRoot, "scripts", "install.sh.tpl")
|
|
|
|
static := fstest.MapFS{
|
|
"index.html": &fstest.MapFile{Data: []byte("<html><body>test</body></html>")},
|
|
}
|
|
|
|
srv, err := api.NewServer(cfg, conn, static, "integration-test", tmplPath, kp.PublicKeyHex())
|
|
if err != nil {
|
|
conn.Close()
|
|
t.Fatalf("new server: %v", err)
|
|
}
|
|
|
|
hts := httptest.NewServer(srv.Handler())
|
|
return &TestServer{
|
|
URL: hts.URL,
|
|
BasicUser: DefaultBasicUser,
|
|
BasicPass: DefaultBasicPass,
|
|
FleetSecret: DefaultFleetSecret,
|
|
SQL: conn,
|
|
close: func() {
|
|
hts.Close()
|
|
conn.Close()
|
|
},
|
|
}
|
|
}
|
|
|
|
func writeConfig(t *testing.T, path, dir string) {
|
|
t.Helper()
|
|
content := `{
|
|
"listen_addr": ":0",
|
|
"data_dir": "` + dir + `",
|
|
"database_path": "` + filepath.Join(dir, "test.db") + `",
|
|
"operator_clearance": 4,
|
|
"auth": {
|
|
"basic_username": "admin",
|
|
"basic_password": "changeme",
|
|
"fleet_secret": "test-fleet-secret"
|
|
},
|
|
"forge": {
|
|
"signing_key_path": "` + filepath.Join(dir, "signing.key") + `",
|
|
"artifacts_dir": "` + filepath.Join(dir, "artifacts") + `"
|
|
}
|
|
}`
|
|
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
|
t.Fatalf("write config: %v", err)
|
|
}
|
|
}
|
|
|
|
func findRepoRoot() (string, error) {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dir := wd
|
|
for {
|
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
|
return dir, nil
|
|
}
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
return wd, nil
|
|
}
|
|
dir = parent
|
|
}
|
|
}
|