feat: initialize managed portal
This commit is contained in:
209
internal/managed/manager.go
Normal file
209
internal/managed/manager.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package managed
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
registry *Registry
|
||||
docker DockerRuntime
|
||||
remote *RemoteClient
|
||||
}
|
||||
|
||||
type ServiceState struct {
|
||||
ID string `json:"id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
ProjectType string `json:"project_type"`
|
||||
ProjectRoot string `json:"project_root"`
|
||||
ContainerName string `json:"container_name"`
|
||||
APIBaseURL string `json:"api_base_url"`
|
||||
ServiceName string `json:"service_name"`
|
||||
ConfigPath string `json:"config_path"`
|
||||
RTSPField string `json:"rtsp_field"`
|
||||
ResultType string `json:"result_type"`
|
||||
ResultPaths map[string]string `json:"result_paths"`
|
||||
Status string `json:"status"`
|
||||
RTSP string `json:"rtsp,omitempty"`
|
||||
Summary *ResultSummary `json:"summary,omitempty"`
|
||||
ResultFiles []ResultFile `json:"result_files,omitempty"`
|
||||
ConfigError string `json:"config_error,omitempty"`
|
||||
ResultError string `json:"result_error,omitempty"`
|
||||
ServiceError string `json:"service_error,omitempty"`
|
||||
}
|
||||
|
||||
func NewManager(registry *Registry, docker DockerRuntime, remote *RemoteClient) *Manager {
|
||||
if registry == nil {
|
||||
registry = EmptyRegistry()
|
||||
}
|
||||
if docker == nil {
|
||||
docker = NewDockerController()
|
||||
}
|
||||
if remote == nil {
|
||||
remote = NewRemoteClient(nil)
|
||||
}
|
||||
return &Manager{
|
||||
registry: registry,
|
||||
docker: docker,
|
||||
remote: remote,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) List() []*ServiceState {
|
||||
states := make([]*ServiceState, 0, len(m.registry.Services))
|
||||
for _, service := range m.registry.Services {
|
||||
states = append(states, m.snapshot(service, false))
|
||||
}
|
||||
return states
|
||||
}
|
||||
|
||||
func (m *Manager) Detail(id string) (*ServiceState, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.snapshot(service, true), nil
|
||||
}
|
||||
|
||||
func (m *Manager) Summary(id string) (*ResultSummary, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.remote.GetSummary(context.Background(), service)
|
||||
}
|
||||
|
||||
func (m *Manager) Files(id string) ([]ResultFile, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.remote.GetFiles(context.Background(), service)
|
||||
}
|
||||
|
||||
func (m *Manager) PreviewFile(id, path string, lines int) (*FilePreview, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.remote.PreviewFile(context.Background(), service, path, lines)
|
||||
}
|
||||
|
||||
func (m *Manager) Download(ctx context.Context, id, path string) (*http.Response, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.remote.Download(ctx, service, path)
|
||||
}
|
||||
|
||||
func (m *Manager) UpdateRTSP(id, rtsp string) (*ServiceState, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.TrimSpace(rtsp) == "" {
|
||||
return nil, fmt.Errorf("rtsp url is required")
|
||||
}
|
||||
if _, err := m.remote.UpdateRTSP(context.Background(), service, rtsp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.snapshot(service, true), nil
|
||||
}
|
||||
|
||||
func (m *Manager) Restart(id string) (*ServiceState, error) {
|
||||
service, err := m.lookup(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := m.docker.RestartContainer(service.ContainerName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.snapshot(service, true), nil
|
||||
}
|
||||
|
||||
func (m *Manager) lookup(id string) (Service, error) {
|
||||
service, ok := m.registry.Get(id)
|
||||
if !ok {
|
||||
return Service{}, fmt.Errorf("%w: %s", ErrServiceNotFound, id)
|
||||
}
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (m *Manager) snapshot(service Service, includeFiles bool) *ServiceState {
|
||||
state := &ServiceState{
|
||||
ID: service.ID,
|
||||
DisplayName: service.DisplayName,
|
||||
ProjectType: service.ProjectType,
|
||||
ProjectRoot: service.ProjectRoot,
|
||||
ContainerName: service.ContainerName,
|
||||
APIBaseURL: service.APIBaseURL,
|
||||
ServiceName: service.ServiceName,
|
||||
ConfigPath: service.ConfigPath,
|
||||
RTSPField: service.RTSPField,
|
||||
ResultType: service.ResultType,
|
||||
ResultPaths: service.ResultPaths,
|
||||
Status: "unknown",
|
||||
}
|
||||
|
||||
if payload, err := m.remote.GetConfig(context.Background(), service); err == nil {
|
||||
state.RTSP = extractRTSP(payload)
|
||||
state.ConfigPath = extractConfigPath(payload)
|
||||
} else {
|
||||
state.ConfigError = err.Error()
|
||||
}
|
||||
|
||||
if status, err := m.docker.GetContainerStatus(service.ContainerName); err == nil {
|
||||
state.Status = status
|
||||
} else {
|
||||
state.Status = status
|
||||
if !IsDockerUnavailable(err) {
|
||||
state.ServiceError = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
if summary, err := m.remote.GetSummary(context.Background(), service); err == nil {
|
||||
state.Summary = summary
|
||||
} else {
|
||||
state.ResultError = err.Error()
|
||||
}
|
||||
|
||||
if includeFiles {
|
||||
if files, err := m.remote.GetFiles(context.Background(), service); err == nil {
|
||||
state.ResultFiles = files
|
||||
} else if state.ResultError == "" {
|
||||
state.ResultError = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func extractRTSP(payload map[string]any) string {
|
||||
if payload == nil {
|
||||
return ""
|
||||
}
|
||||
if stream, ok := payload["stream"].(map[string]any); ok {
|
||||
if rtsp, ok := stream["rtsp_url"].(string); ok {
|
||||
return strings.TrimSpace(rtsp)
|
||||
}
|
||||
}
|
||||
if runtime, ok := payload["runtime"].(map[string]any); ok {
|
||||
if rtsp, ok := runtime["rtsp_url"].(string); ok {
|
||||
return strings.TrimSpace(rtsp)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func extractConfigPath(payload map[string]any) string {
|
||||
if payload == nil {
|
||||
return ""
|
||||
}
|
||||
if configPath, ok := payload["config_path"].(string); ok {
|
||||
return strings.TrimSpace(configPath)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user