- 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
161 lines
5.9 KiB
Go
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
|
|
}
|