Files
sub2api-cn-relay-manager/internal/store/sqlite/managed_resources_repo.go
phamnazage-jpg 85d495dd16 feat(control-plane): harden host-scoped reconcile and acceptance evidence
- add batch-scoped reconcile_runs persistence and queries
- route batch detail and reconcile writes through batch_id/host_id
- refresh production boards with host-scope acceptance artifacts
- include latest real-host acceptance evidence for self_service and subscription
2026-05-18 22:22:22 +08:00

161 lines
5.9 KiB
Go

package sqlite
import (
"context"
"fmt"
"strings"
)
type ManagedResource struct {
ID int64
BatchID int64
HostID int64
ResourceType string
HostResourceID string
ResourceName string
}
type ManagedResourcesRepo struct {
db execQuerier
}
func newManagedResourcesRepo(db execQuerier) *ManagedResourcesRepo {
return &ManagedResourcesRepo{db: db}
}
func (r *ManagedResourcesRepo) Create(ctx context.Context, resource ManagedResource) (int64, error) {
resourceType := strings.TrimSpace(resource.ResourceType)
hostResourceID := strings.TrimSpace(resource.HostResourceID)
resourceName := strings.TrimSpace(resource.ResourceName)
switch {
case resource.BatchID <= 0:
return 0, fmt.Errorf("batch_id is required")
case resource.HostID <= 0:
return 0, fmt.Errorf("host_id is required")
case resourceType == "":
return 0, fmt.Errorf("resource_type is required")
case hostResourceID == "":
return 0, fmt.Errorf("host_resource_id is required")
case resourceName == "":
return 0, fmt.Errorf("resource_name is required")
}
result, err := r.db.ExecContext(ctx, `INSERT INTO managed_resources (batch_id, host_id, resource_type, host_resource_id, resource_name) VALUES (?, ?, ?, ?, ?)`, resource.BatchID, resource.HostID, resourceType, hostResourceID, resourceName)
if err != nil {
return 0, fmt.Errorf("insert managed resource %q: %w", hostResourceID, err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("read inserted managed resource id for %q: %w", hostResourceID, err)
}
return id, nil
}
func (r *ManagedResourcesRepo) GetByResourceIdentity(ctx context.Context, hostID int64, resourceType, hostResourceID string) (ManagedResource, error) {
resourceType = strings.TrimSpace(resourceType)
hostResourceID = strings.TrimSpace(hostResourceID)
if hostID <= 0 {
return ManagedResource{}, fmt.Errorf("host_id is required")
}
if resourceType == "" {
return ManagedResource{}, fmt.Errorf("resource_type is required")
}
if hostResourceID == "" {
return ManagedResource{}, fmt.Errorf("host_resource_id is required")
}
var resource ManagedResource
if err := r.db.QueryRowContext(ctx, `SELECT id, batch_id, host_id, resource_type, host_resource_id, resource_name FROM managed_resources WHERE host_id = ? AND resource_type = ? AND host_resource_id = ?`, hostID, resourceType, hostResourceID).Scan(&resource.ID, &resource.BatchID, &resource.HostID, &resource.ResourceType, &resource.HostResourceID, &resource.ResourceName); err != nil {
return ManagedResource{}, err
}
return resource, nil
}
func (r *ManagedResourcesRepo) GetByBatchID(ctx context.Context, batchID int64) ([]ManagedResource, error) {
if batchID <= 0 {
return nil, fmt.Errorf("batch_id is required")
}
rows, err := r.db.QueryContext(ctx, `SELECT id, batch_id, host_id, resource_type, host_resource_id, resource_name FROM managed_resources WHERE batch_id = ? ORDER BY id`, batchID)
if err != nil {
return nil, fmt.Errorf("query managed resources: %w", err)
}
defer rows.Close()
resources := make([]ManagedResource, 0)
for rows.Next() {
var resource ManagedResource
if err := rows.Scan(&resource.ID, &resource.BatchID, &resource.HostID, &resource.ResourceType, &resource.HostResourceID, &resource.ResourceName); err != nil {
return nil, fmt.Errorf("scan managed resource: %w", err)
}
resources = append(resources, resource)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate managed resources: %w", err)
}
return resources, nil
}
func (r *ManagedResourcesRepo) ListByProviderID(ctx context.Context, providerID int64) ([]ManagedResource, error) {
if providerID <= 0 {
return nil, fmt.Errorf("provider_id is required")
}
rows, err := r.db.QueryContext(ctx, `SELECT mr.id, mr.batch_id, mr.host_id, mr.resource_type, mr.host_resource_id, mr.resource_name
FROM managed_resources mr
JOIN import_batches ib ON ib.id = mr.batch_id
WHERE ib.provider_id = ?
ORDER BY mr.id`, providerID)
if err != nil {
return nil, fmt.Errorf("query managed resources by provider_id %d: %w", providerID, err)
}
defer rows.Close()
resources := make([]ManagedResource, 0)
for rows.Next() {
var resource ManagedResource
if err := rows.Scan(&resource.ID, &resource.BatchID, &resource.HostID, &resource.ResourceType, &resource.HostResourceID, &resource.ResourceName); err != nil {
return nil, fmt.Errorf("scan managed resource by provider_id %d: %w", providerID, err)
}
resources = append(resources, resource)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate managed resources by provider_id %d: %w", providerID, err)
}
return resources, nil
}
func (r *ManagedResourcesRepo) ListByProviderIDAndHostID(ctx context.Context, providerID, hostID int64) ([]ManagedResource, error) {
if providerID <= 0 {
return nil, fmt.Errorf("provider_id is required")
}
if hostID <= 0 {
return nil, fmt.Errorf("host_id is required")
}
rows, err := r.db.QueryContext(ctx, `SELECT mr.id, mr.batch_id, mr.host_id, mr.resource_type, mr.host_resource_id, mr.resource_name
FROM managed_resources mr
JOIN import_batches ib ON ib.id = mr.batch_id
WHERE ib.provider_id = ? AND mr.host_id = ?
ORDER BY mr.id`, providerID, hostID)
if err != nil {
return nil, fmt.Errorf("query managed resources by provider_id %d and host_id %d: %w", providerID, hostID, err)
}
defer rows.Close()
resources := make([]ManagedResource, 0)
for rows.Next() {
var resource ManagedResource
if err := rows.Scan(&resource.ID, &resource.BatchID, &resource.HostID, &resource.ResourceType, &resource.HostResourceID, &resource.ResourceName); err != nil {
return nil, fmt.Errorf("scan managed resource by provider_id %d and host_id %d: %w", providerID, hostID, err)
}
resources = append(resources, resource)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate managed resources by provider_id %d and host_id %d: %w", providerID, hostID, err)
}
return resources, nil
}