mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 18:45:53 +00:00
149 lines
5.3 KiB
Go
149 lines
5.3 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/actionlifecycle"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/api/resourceapi"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
|
unified "github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
|
|
"github.com/rcourtman/pulse-go-rewrite/pkg/auth"
|
|
)
|
|
|
|
// ResourceHandlers preserves the established router and extension surface
|
|
// while composing the resource-query service with API-owned action mutations.
|
|
// QueryService owns resource registry construction, durable resource storage,
|
|
// filtering, projections, and read handlers. The fields below remain here
|
|
// because action lifecycle and operator-state mutations are separate domains.
|
|
type ResourceHandlers struct {
|
|
resourceapi.QueryService
|
|
|
|
cfg *config.Config
|
|
tenantStateProvider TenantStateProvider
|
|
actionExecutor ActionExecutor
|
|
actionCompleted func(unified.ActionAuditRecord)
|
|
actionTransition func(orgID string, record unified.ActionAuditRecord)
|
|
policyAdmission *actionlifecycle.PolicyAdmissionCoordinator
|
|
actionEmergencyStop func(orgID string) (bool, error)
|
|
actionDecisionAuthorizer actionlifecycle.DecisionAuthorizer
|
|
actionExecutionAuthorizer actionlifecycle.ExecutionAuthorizer
|
|
actionRefreshPlanner actionlifecycle.RefreshPlanner
|
|
operatorStateChanged func(orgID, resourceID string)
|
|
}
|
|
|
|
type ResourceDiscoveryReadinessProvider = resourceapi.ResourceDiscoveryReadinessProvider
|
|
type SupplementalRecordsProvider = resourceapi.SupplementalRecordsProvider
|
|
type TenantSupplementalRecordsProvider = resourceapi.TenantSupplementalRecordsProvider
|
|
type SupplementalSnapshotSourceOwner = resourceapi.SupplementalSnapshotSourceOwner
|
|
type TenantSupplementalSnapshotSourceOwner = resourceapi.TenantSupplementalSnapshotSourceOwner
|
|
type ResourcesResponse = resourceapi.ResourcesResponse
|
|
type ResourcesMeta = resourceapi.ResourcesMeta
|
|
type StorageSummaryResponse = resourceapi.StorageSummaryResponse
|
|
type StorageSummaryIncident = resourceapi.StorageSummaryIncident
|
|
type StorageIncidentsResponse = resourceapi.StorageIncidentsResponse
|
|
type StorageIncidentSection = resourceapi.StorageIncidentSection
|
|
|
|
func EmptyResourcesResponse() ResourcesResponse { return resourceapi.EmptyResourcesResponse() }
|
|
|
|
func EmptyStorageSummaryResponse() StorageSummaryResponse {
|
|
return resourceapi.EmptyStorageSummaryResponse()
|
|
}
|
|
|
|
func EmptyStorageIncidentsResponse() StorageIncidentsResponse {
|
|
return resourceapi.EmptyStorageIncidentsResponse()
|
|
}
|
|
|
|
// NewResourceHandlers builds the compatibility composition used by Router.
|
|
func NewResourceHandlers(cfg *config.Config) *ResourceHandlers {
|
|
return &ResourceHandlers{
|
|
QueryService: *resourceapi.NewQueryService(cfg),
|
|
cfg: cfg,
|
|
policyAdmission: &actionlifecycle.PolicyAdmissionCoordinator{},
|
|
}
|
|
}
|
|
|
|
func (h *ResourceHandlers) ensureQueryService() *resourceapi.QueryService {
|
|
return &h.QueryService
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetStateProvider(provider SnapshotProvider) {
|
|
h.ensureQueryService().SetStateProvider(provider)
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetTenantStateProvider(provider TenantStateProvider) {
|
|
h.tenantStateProvider = provider
|
|
h.ensureQueryService().SetTenantStateProvider(provider)
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetActionExecutor(executor ActionExecutor) {
|
|
h.actionExecutor = executor
|
|
checker, _ := executor.(actionlifecycle.AvailabilityChecker)
|
|
h.ensureQueryService().SetActionAvailabilityChecker(checker)
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetActionEmergencyStopChecker(checker func(orgID string) (bool, error)) {
|
|
h.actionEmergencyStop = checker
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetActionAuthorizers(decision actionlifecycle.DecisionAuthorizer, execution actionlifecycle.ExecutionAuthorizer) {
|
|
h.actionDecisionAuthorizer = decision
|
|
h.actionExecutionAuthorizer = execution
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetActionRefreshPlanner(planner actionlifecycle.RefreshPlanner) {
|
|
h.actionRefreshPlanner = planner
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetActionCompletedPublisher(publisher func(unified.ActionAuditRecord)) {
|
|
h.actionCompleted = publisher
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetActionTransitionPublisher(publisher func(orgID string, record unified.ActionAuditRecord)) {
|
|
h.actionTransition = publisher
|
|
}
|
|
|
|
func (h *ResourceHandlers) SetOperatorStateChanged(callback func(orgID, resourceID string)) {
|
|
h.operatorStateChanged = callback
|
|
}
|
|
|
|
func (h *ResourceHandlers) buildRegistry(orgID string) (*unified.ResourceRegistry, error) {
|
|
return h.ensureQueryService().BuildRegistry(orgID)
|
|
}
|
|
|
|
func (h *ResourceHandlers) getStore(orgID string) (unified.ResourceStore, error) {
|
|
return h.ensureQueryService().Store(orgID)
|
|
}
|
|
|
|
func (h *ResourceHandlers) invalidateCache(orgID string) {
|
|
h.ensureQueryService().InvalidateCache(orgID)
|
|
}
|
|
|
|
func (h *ResourceHandlers) CloseTenantStore(orgID string) error {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
return h.QueryService.CloseTenantStore(orgID)
|
|
}
|
|
|
|
func (h *ResourceHandlers) CloseStores() error {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
return h.QueryService.CloseStores()
|
|
}
|
|
|
|
// firstNonEmptyTrimmed is retained for non-resource connection projections.
|
|
func firstNonEmptyTrimmed(values ...string) string {
|
|
for _, value := range values {
|
|
if trimmed := strings.TrimSpace(value); trimmed != "" {
|
|
return trimmed
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getUserID(r *http.Request) string {
|
|
return auth.GetUser(r.Context())
|
|
}
|