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 }