mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 18:32:29 +00:00
0622169be8
Revalidate and harden the Pulse multi-tenant GA surface across org ownership transfer, MSP invite lifecycle, tenant state fallback, registry workspace limits, and the embedded Pulse Account portal bundle.
134 lines
4.5 KiB
Go
134 lines
4.5 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/monitoring"
|
|
)
|
|
|
|
func TestConfigHandlersSetMultiTenantMonitor(t *testing.T) {
|
|
handler := &ConfigHandlers{}
|
|
handler.SetMultiTenantMonitor(nil)
|
|
if handler.mtMonitor != nil {
|
|
t.Fatalf("mtMonitor should be nil after SetMultiTenantMonitor(nil)")
|
|
}
|
|
}
|
|
|
|
func TestRouterSetMultiTenantMonitor(t *testing.T) {
|
|
router := &Router{
|
|
alertHandlers: &AlertHandlers{},
|
|
notificationHandlers: &NotificationHandlers{},
|
|
configHandlers: &ConfigHandlers{},
|
|
dockerAgentHandlers: &DockerAgentHandlers{},
|
|
unifiedAgentHandlers: &UnifiedAgentHandlers{},
|
|
kubernetesAgentHandlers: &KubernetesAgentHandlers{},
|
|
systemSettingsHandler: &SystemSettingsHandler{},
|
|
resourceHandlers: NewResourceHandlers(nil),
|
|
}
|
|
|
|
router.SetMultiTenantMonitor(nil)
|
|
|
|
if router.mtMonitor != nil {
|
|
t.Fatalf("mtMonitor should be nil after SetMultiTenantMonitor(nil)")
|
|
}
|
|
if router.resourceHandlers.tenantStateProvider == nil {
|
|
t.Fatalf("tenantStateProvider should be set on resource handlers")
|
|
}
|
|
}
|
|
|
|
func TestRouterSetMultiTenantMonitorRefreshesConfigHandlerMonitorSource(t *testing.T) {
|
|
oldMonitor, _, _ := newTestMonitor(t)
|
|
newMonitor, _, _ := newTestMonitor(t)
|
|
|
|
oldConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
|
|
newConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
|
|
setUnexportedField(t, oldMonitor, "config", oldConfig)
|
|
setUnexportedField(t, newMonitor, "config", newConfig)
|
|
|
|
oldMTM := &monitoring.MultiTenantMonitor{}
|
|
setUnexportedField(t, oldMTM, "monitors", map[string]*monitoring.Monitor{
|
|
"default": oldMonitor,
|
|
})
|
|
newMTM := &monitoring.MultiTenantMonitor{}
|
|
setUnexportedField(t, newMTM, "monitors", map[string]*monitoring.Monitor{
|
|
"default": newMonitor,
|
|
})
|
|
|
|
router := &Router{
|
|
configHandlers: &ConfigHandlers{},
|
|
}
|
|
router.configHandlers.SetMultiTenantMonitor(oldMTM)
|
|
|
|
if got := router.configHandlers.getMonitor(context.Background()); got != oldMonitor {
|
|
t.Fatalf("precondition monitor = %#v, want old monitor %#v", got, oldMonitor)
|
|
}
|
|
|
|
router.SetMultiTenantMonitor(newMTM)
|
|
|
|
if got := router.configHandlers.getMonitor(context.Background()); got != newMonitor {
|
|
t.Fatalf("config handler monitor = %#v, want reloaded monitor %#v", got, newMonitor)
|
|
}
|
|
if got := router.configHandlers.getConfig(context.Background()); got != newConfig {
|
|
t.Fatalf("config handler config = %#v, want reloaded config %#v", got, newConfig)
|
|
}
|
|
}
|
|
|
|
func TestConfigHandlersNonDefaultMissingTenantMonitorFailsClosed(t *testing.T) {
|
|
defaultConfig := &config.Config{DataPath: t.TempDir(), ConfigPath: t.TempDir()}
|
|
defaultMonitor, _, _ := newTestMonitor(t)
|
|
mtp := config.NewMultiTenantPersistence(t.TempDir())
|
|
mtm := monitoring.NewMultiTenantMonitor(defaultConfig, mtp, nil)
|
|
defer mtm.Stop()
|
|
|
|
handler := &ConfigHandlers{
|
|
defaultConfig: defaultConfig,
|
|
defaultPersistence: config.NewConfigPersistence(defaultConfig.ConfigPath),
|
|
defaultMonitor: defaultMonitor,
|
|
}
|
|
handler.SetMultiTenantMonitor(mtm)
|
|
|
|
ctx := context.WithValue(context.Background(), OrgIDContextKey, "tenant-missing")
|
|
cfg, persistence, monitor := handler.getContextState(ctx)
|
|
if cfg != nil || persistence != nil || monitor != nil {
|
|
t.Fatalf("expected missing non-default tenant state to fail closed, got cfg=%#v persistence=%#v monitor=%#v", cfg, persistence, monitor)
|
|
}
|
|
}
|
|
|
|
func TestNewRouterWiresTenantResourceStateProvider(t *testing.T) {
|
|
cfg := &config.Config{
|
|
DataPath: t.TempDir(),
|
|
ConfigPath: t.TempDir(),
|
|
}
|
|
mtm := &monitoring.MultiTenantMonitor{}
|
|
|
|
router := NewRouter(cfg, nil, mtm, nil, nil, "1.0.0")
|
|
if router.resourceHandlers == nil {
|
|
t.Fatal("expected resource handlers to be initialized")
|
|
}
|
|
if router.resourceHandlers.tenantStateProvider == nil {
|
|
t.Fatal("expected NewRouter to wire the tenant resource state provider when a multi-tenant monitor is provided")
|
|
}
|
|
}
|
|
|
|
func TestNewRouterServesTenantResourceListWithMultiTenantMonitor(t *testing.T) {
|
|
cfg := &config.Config{
|
|
DataPath: t.TempDir(),
|
|
ConfigPath: t.TempDir(),
|
|
}
|
|
mtm := &monitoring.MultiTenantMonitor{}
|
|
router := NewRouter(cfg, nil, mtm, nil, nil, "1.0.0")
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/api/resources?page=1&limit=100", nil)
|
|
req = req.WithContext(context.WithValue(req.Context(), OrgIDContextKey, "tenant-a"))
|
|
|
|
router.resourceHandlers.HandleListResources(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|