Pulse/internal/api/hosted_agent_install_command_test.go
2026-04-11 16:47:37 +01:00

88 lines
2.9 KiB
Go

package api
import (
"encoding/json"
"net/http"
"net/http/httptest"
"regexp"
"strings"
"testing"
"github.com/rcourtman/pulse-go-rewrite/internal/config"
"github.com/rcourtman/pulse-go-rewrite/internal/monitoring"
"github.com/stretchr/testify/require"
)
func TestHostedTenantAgentInstallCommand_GeneratesOrgBoundTokenAndCommand(t *testing.T) {
setMockModeForTest(t, true)
dataDir := t.TempDir()
cfg := &config.Config{
DataPath: dataDir,
PublicURL: "https://cloud.example.com",
}
router := &Router{
config: cfg,
persistence: config.NewConfigPersistence(dataDir),
multiTenant: config.NewMultiTenantPersistence(dataDir),
hostedMode: true,
}
orgID := "acme"
// Ensure org directory exists so OrgExists() passes.
_, err := router.multiTenant.GetPersistence(orgID)
require.NoError(t, err)
// Initialize tenant monitor to verify we update already-loaded tenant configs.
router.mtMonitor = monitoring.NewMultiTenantMonitor(cfg, router.multiTenant, nil)
t.Cleanup(router.mtMonitor.Stop)
tenantMonitor, err := router.mtMonitor.GetMonitor(orgID)
require.NoError(t, err)
require.NotNil(t, tenantMonitor)
mux := http.NewServeMux()
mux.HandleFunc("POST /api/admin/orgs/{id}/agent-install-command", router.handleHostedTenantAgentInstallCommand)
req := httptest.NewRequest(http.MethodPost, "/api/admin/orgs/"+orgID+"/agent-install-command", strings.NewReader(`{"type":"pbs"}`))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
mux.ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
var resp hostedTenantAgentInstallCommandResponse
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp))
require.Equal(t, orgID, resp.OrgID)
require.Contains(t, resp.Command, "https://cloud.example.com/install.sh")
require.Contains(t, resp.Command, "--token "+posixShellQuote(resp.Token))
require.Contains(t, resp.Command, "--proxmox-type "+posixShellQuote("pbs"))
require.Regexp(t, regexp.MustCompile(`^[a-f0-9]{64}$`), resp.Token)
// Token is persisted to global token store with org binding.
tokens, err := router.persistence.LoadAPITokens()
require.NoError(t, err)
require.NotEmpty(t, tokens)
found := false
for _, tok := range tokens {
if tok.OrgID == orgID && tok.Name != "" && tok.Hash != "" {
// Validate raw token matches this record.
if _, ok := (&config.Config{APITokens: []config.APITokenRecord{tok}}).ValidateAPIToken(resp.Token); ok {
require.Equal(t, "pbs", tok.Metadata["install_type"])
require.Equal(t, "hosted_agent_install_command", tok.Metadata["issued_via"])
found = true
break
}
}
}
require.True(t, found, "expected persisted org-bound token record matching response token")
// Existing tenant monitor config sees the token immediately.
require.NotNil(t, tenantMonitor.GetConfig())
_, ok := tenantMonitor.GetConfig().ValidateAPIToken(resp.Token)
require.True(t, ok, "expected tenant monitor config to validate newly issued token")
}