up
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<!-- Keep Concelier test harness active while trimming Mongo dependencies. Allow opt-out per project. -->
|
||||
<!-- Keep Concelier test harness active while trimming legacy dependencies. Allow opt-out per project. -->
|
||||
<UseConcelierTestInfra Condition="'$(UseConcelierTestInfra)'==''">true</UseConcelierTestInfra>
|
||||
<!-- Suppress noisy warnings from duplicate usings and analyzer fixture hints during Concelier test harness runs. -->
|
||||
<NoWarn>$(NoWarn);CS0105;CS1591;CS8601;CS8602;CS8604;CS0618;RS1032;RS2007;xUnit1041;xUnit1031;xUnit2013;NU1510;NETSDK1023;SYSLIB0057</NoWarn>
|
||||
|
||||
@@ -6,7 +6,7 @@ using StellaOps.Concelier.Storage.Postgres.Advisories;
|
||||
namespace StellaOps.Concelier.WebService.DualWrite;
|
||||
|
||||
/// <summary>
|
||||
/// Postgres-backed advisory store that implements the legacy Mongo contracts.
|
||||
/// Postgres-backed advisory store that implements the legacy storage contracts.
|
||||
/// </summary>
|
||||
public sealed class DualWriteAdvisoryStore : IAdvisoryStore
|
||||
{
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace StellaOps.Concelier.WebService.Options;
|
||||
|
||||
public sealed class ConcelierOptions
|
||||
{
|
||||
[Obsolete("Mongo storage has been removed; use PostgresStorage.")]
|
||||
public StorageOptions Storage { get; set; } = new();
|
||||
[Obsolete("Legacy storage has been removed; use PostgresStorage.")]
|
||||
public LegacyStorageOptions LegacyStorage { get; set; } = new();
|
||||
|
||||
public PostgresStorageOptions? PostgresStorage { get; set; } = new PostgresStorageOptions
|
||||
{
|
||||
@@ -37,10 +37,10 @@ public sealed class ConcelierOptions
|
||||
/// </summary>
|
||||
public AirGapOptions AirGap { get; set; } = new();
|
||||
|
||||
[Obsolete("Mongo storage has been removed; use PostgresStorage.")]
|
||||
public sealed class StorageOptions
|
||||
[Obsolete("Legacy storage has been removed; use PostgresStorage.")]
|
||||
public sealed class LegacyStorageOptions
|
||||
{
|
||||
public string Driver { get; set; } = "mongo";
|
||||
public string Driver { get; set; } = "postgres";
|
||||
|
||||
public string Dsn { get; set; } = string.Empty;
|
||||
|
||||
@@ -56,7 +56,6 @@ public sealed class ConcelierOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable PostgreSQL storage for LNM linkset cache.
|
||||
/// When true, the linkset cache is stored in PostgreSQL instead of MongoDB.
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ builder.Services.AddOptions<AdvisoryObservationEventPublisherOptions>()
|
||||
{
|
||||
options.Subject ??= "concelier.advisory.observation.updated.v1";
|
||||
options.Stream ??= "CONCELIER_OBS";
|
||||
options.Transport = string.IsNullOrWhiteSpace(options.Transport) ? "mongo" : options.Transport;
|
||||
options.Transport = string.IsNullOrWhiteSpace(options.Transport) ? "inmemory" : options.Transport;
|
||||
})
|
||||
.ValidateOnStart();
|
||||
builder.Services.AddConcelierAocGuards();
|
||||
|
||||
@@ -673,7 +673,7 @@ public sealed class AcscConnector : IFeedConnector
|
||||
private async Task<AcscCursor> GetCursorCoreAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? AcscCursor.Empty : AcscCursor.FromBson(state.Cursor);
|
||||
return state is null ? AcscCursor.Empty : AcscCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(AcscCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -70,7 +70,7 @@ internal sealed record AcscCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static AcscCursor FromBson(DocumentObject? document)
|
||||
public static AcscCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -332,8 +332,8 @@ public sealed class CccsConnector : IFeedConnector
|
||||
}
|
||||
|
||||
var dtoJson = JsonSerializer.Serialize(dto, DtoSerializerOptions);
|
||||
var dtoBson = DocumentObject.Parse(dtoJson);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoBson, now);
|
||||
var dtoDoc = DocumentObject.Parse(dtoJson);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoDoc, now);
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -459,7 +459,7 @@ public sealed class CccsConnector : IFeedConnector
|
||||
private async Task<CccsCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? CccsCursor.Empty : CccsCursor.FromBson(state.Cursor);
|
||||
return state is null ? CccsCursor.Empty : CccsCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(CccsCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -70,7 +70,7 @@ internal sealed record CccsCursor(
|
||||
return doc;
|
||||
}
|
||||
|
||||
public static CccsCursor FromBson(DocumentObject? document)
|
||||
public static CccsCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -286,8 +286,8 @@ public sealed class CertBundConnector : IFeedConnector
|
||||
_diagnostics.ParseSuccess(dto.Products.Count, dto.CveIds.Count);
|
||||
parsedCount++;
|
||||
|
||||
var bson = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "cert-bund.detail.v1", bson, now);
|
||||
var doc = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "cert-bund.detail.v1", doc, now);
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -423,7 +423,7 @@ public sealed class CertBundConnector : IFeedConnector
|
||||
private async Task<CertBundCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? CertBundCursor.Empty : CertBundCursor.FromBson(state.Cursor);
|
||||
return state is null ? CertBundCursor.Empty : CertBundCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(CertBundCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -53,7 +53,7 @@ internal sealed record CertBundCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static CertBundCursor FromBson(DocumentObject? document)
|
||||
public static CertBundCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -672,7 +672,7 @@ public sealed class CertCcConnector : IFeedConnector
|
||||
private async Task<CertCcCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var record = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return CertCcCursor.FromBson(record?.Cursor);
|
||||
return CertCcCursor.FromDocument(record?.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(CertCcCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -43,7 +43,7 @@ internal sealed record CertCcCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static CertCcCursor FromBson(DocumentObject? document)
|
||||
public static CertCcCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -124,10 +124,10 @@ internal sealed record CertCcCursor(
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case DocumentString bsonString when !string.IsNullOrWhiteSpace(bsonString.AsString):
|
||||
results.Add(bsonString.AsString.Trim());
|
||||
case DocumentString docString when !string.IsNullOrWhiteSpace(docString.AsString):
|
||||
results.Add(docString.AsString.Trim());
|
||||
break;
|
||||
case DocumentObject bsonDocument when bsonDocument.TryGetValue("value", out var inner) && inner.IsString:
|
||||
case DocumentObject docObject when docObject.TryGetValue("value", out var inner) && inner.IsString:
|
||||
results.Add(inner.AsString.Trim());
|
||||
break;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ internal sealed record CertCcCursor(
|
||||
|
||||
private static bool TryReadGuid(DocumentValue value, out Guid guid)
|
||||
{
|
||||
if (value is DocumentString bsonString && Guid.TryParse(bsonString.AsString, out guid))
|
||||
if (value is DocumentString docString && Guid.TryParse(docString.AsString, out guid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ public sealed class CertFrConnector : IFeedConnector
|
||||
private async Task<CertFrCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var record = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return CertFrCursor.FromBson(record?.Cursor);
|
||||
return CertFrCursor.FromDocument(record?.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(CertFrCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -28,7 +28,7 @@ internal sealed record CertFrCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static CertFrCursor FromBson(DocumentObject? document)
|
||||
public static CertFrCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -418,7 +418,7 @@ public sealed class CertInConnector : IFeedConnector
|
||||
private async Task<CertInCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? CertInCursor.Empty : CertInCursor.FromBson(state.Cursor);
|
||||
return state is null ? CertInCursor.Empty : CertInCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(CertInCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -28,7 +28,7 @@ internal sealed record CertInCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static CertInCursor FromBson(DocumentObject? document)
|
||||
public static CertInCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Text;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Concelier.Documents;
|
||||
using MongoContracts = StellaOps.Concelier.Storage;
|
||||
using LegacyContracts = StellaOps.Concelier.Storage;
|
||||
using StorageContracts = StellaOps.Concelier.Storage.Contracts;
|
||||
using StellaOps.Concelier.Connector.Common.Http;
|
||||
using StellaOps.Concelier.Connector.Common.Telemetry;
|
||||
@@ -32,12 +32,12 @@ public sealed class SourceFetchService
|
||||
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly RawDocumentStorage _rawDocumentStorage;
|
||||
private readonly MongoContracts.IDocumentStore _documentStore;
|
||||
private readonly LegacyContracts.IDocumentStore _documentStore;
|
||||
private readonly StorageContracts.IStorageDocumentStore _storageDocumentStore;
|
||||
private readonly ILogger<SourceFetchService> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IOptionsMonitor<SourceHttpClientOptions> _httpClientOptions;
|
||||
private readonly IOptions<MongoContracts.StorageOptions> _storageOptions;
|
||||
private readonly IOptions<LegacyContracts.StorageOptions> _storageOptions;
|
||||
private readonly IJitterSource _jitterSource;
|
||||
private readonly IAdvisoryRawWriteGuard _guard;
|
||||
private readonly IAdvisoryLinksetMapper _linksetMapper;
|
||||
@@ -47,7 +47,7 @@ public sealed class SourceFetchService
|
||||
public SourceFetchService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
RawDocumentStorage rawDocumentStorage,
|
||||
MongoContracts.IDocumentStore documentStore,
|
||||
LegacyContracts.IDocumentStore documentStore,
|
||||
StorageContracts.IStorageDocumentStore storageDocumentStore,
|
||||
ILogger<SourceFetchService> logger,
|
||||
IJitterSource jitterSource,
|
||||
@@ -56,7 +56,7 @@ public sealed class SourceFetchService
|
||||
ICryptoHash hash,
|
||||
TimeProvider? timeProvider = null,
|
||||
IOptionsMonitor<SourceHttpClientOptions>? httpClientOptions = null,
|
||||
IOptions<MongoContracts.StorageOptions>? storageOptions = null)
|
||||
IOptions<LegacyContracts.StorageOptions>? storageOptions = null)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
|
||||
_rawDocumentStorage = rawDocumentStorage ?? throw new ArgumentNullException(nameof(rawDocumentStorage));
|
||||
@@ -77,7 +77,7 @@ public sealed class SourceFetchService
|
||||
public SourceFetchService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
RawDocumentStorage rawDocumentStorage,
|
||||
MongoContracts.IDocumentStore documentStore,
|
||||
LegacyContracts.IDocumentStore documentStore,
|
||||
ILogger<SourceFetchService> logger,
|
||||
IJitterSource jitterSource,
|
||||
IAdvisoryRawWriteGuard guard,
|
||||
@@ -85,7 +85,7 @@ public sealed class SourceFetchService
|
||||
ICryptoHash hash,
|
||||
TimeProvider? timeProvider = null,
|
||||
IOptionsMonitor<SourceHttpClientOptions>? httpClientOptions = null,
|
||||
IOptions<MongoContracts.StorageOptions>? storageOptions = null)
|
||||
IOptions<LegacyContracts.StorageOptions>? storageOptions = null)
|
||||
: this(
|
||||
httpClientFactory,
|
||||
rawDocumentStorage,
|
||||
|
||||
@@ -2,7 +2,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Concelier.Documents;
|
||||
using StellaOps.Concelier.Connector.Common.Fetch;
|
||||
using MongoContracts = StellaOps.Concelier.Storage;
|
||||
using LegacyContracts = StellaOps.Concelier.Storage;
|
||||
using StellaOps.Cryptography;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Common.State;
|
||||
@@ -12,17 +12,17 @@ namespace StellaOps.Concelier.Connector.Common.State;
|
||||
/// </summary>
|
||||
public sealed class SourceStateSeedProcessor
|
||||
{
|
||||
private readonly MongoContracts.IDocumentStore _documentStore;
|
||||
private readonly LegacyContracts.IDocumentStore _documentStore;
|
||||
private readonly RawDocumentStorage _rawDocumentStorage;
|
||||
private readonly MongoContracts.ISourceStateRepository _stateRepository;
|
||||
private readonly LegacyContracts.ISourceStateRepository _stateRepository;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly ILogger<SourceStateSeedProcessor> _logger;
|
||||
private readonly ICryptoHash _hash;
|
||||
|
||||
public SourceStateSeedProcessor(
|
||||
MongoContracts.IDocumentStore documentStore,
|
||||
LegacyContracts.IDocumentStore documentStore,
|
||||
RawDocumentStorage rawDocumentStorage,
|
||||
MongoContracts.ISourceStateRepository stateRepository,
|
||||
LegacyContracts.ISourceStateRepository stateRepository,
|
||||
ICryptoHash hash,
|
||||
TimeProvider? timeProvider = null,
|
||||
ILogger<SourceStateSeedProcessor>? logger = null)
|
||||
@@ -173,7 +173,7 @@ public sealed class SourceStateSeedProcessor
|
||||
|
||||
var metadata = CloneDictionary(document.Metadata);
|
||||
|
||||
var record = new MongoContracts.DocumentRecord(
|
||||
var record = new LegacyContracts.DocumentRecord(
|
||||
recordId,
|
||||
source,
|
||||
document.Uri,
|
||||
|
||||
@@ -571,7 +571,7 @@ public sealed class CveConnector : IFeedConnector
|
||||
private async Task<CveCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? CveCursor.Empty : CveCursor.FromBson(state.Cursor);
|
||||
return state is null ? CveCursor.Empty : CveCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(CveCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -49,7 +49,7 @@ internal sealed record CveCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static CveCursor FromBson(DocumentObject? document)
|
||||
public static CveCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -368,7 +368,7 @@ public sealed class DebianConnector : IFeedConnector
|
||||
continue;
|
||||
}
|
||||
|
||||
var payload = ToBson(dto);
|
||||
var payload = ToDocument(dto);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, SchemaVersion, payload, _timeProvider.GetUtcNow());
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
@@ -414,7 +414,7 @@ public sealed class DebianConnector : IFeedConnector
|
||||
DebianAdvisoryDto dto;
|
||||
try
|
||||
{
|
||||
dto = FromBson(dtoRecord.Payload);
|
||||
dto = FromDocument(dtoRecord.Payload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -438,7 +438,7 @@ public sealed class DebianConnector : IFeedConnector
|
||||
private async Task<DebianCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? DebianCursor.Empty : DebianCursor.FromBson(state.Cursor);
|
||||
return state is null ? DebianCursor.Empty : DebianCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(DebianCursor cursor, CancellationToken cancellationToken)
|
||||
@@ -508,7 +508,7 @@ public sealed class DebianConnector : IFeedConnector
|
||||
cveList);
|
||||
}
|
||||
|
||||
private static DocumentObject ToBson(DebianAdvisoryDto dto)
|
||||
private static DocumentObject ToDocument(DebianAdvisoryDto dto)
|
||||
{
|
||||
var packages = new DocumentArray();
|
||||
foreach (var package in dto.Packages)
|
||||
@@ -575,15 +575,15 @@ public sealed class DebianConnector : IFeedConnector
|
||||
};
|
||||
}
|
||||
|
||||
private static DebianAdvisoryDto FromBson(DocumentObject document)
|
||||
private static DebianAdvisoryDto FromDocument(DocumentObject document)
|
||||
{
|
||||
var advisoryId = document.GetValue("advisoryId", "").AsString;
|
||||
var sourcePackage = document.GetValue("sourcePackage", advisoryId).AsString;
|
||||
var title = document.GetValue("title", advisoryId).AsString;
|
||||
var description = document.TryGetValue("description", out var desc) ? desc.AsString : null;
|
||||
|
||||
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cvesBson
|
||||
? cvesBson.OfType<DocumentValue>()
|
||||
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cvesArr
|
||||
? cvesArr.OfType<DocumentValue>()
|
||||
.Select(static value => value.ToString())
|
||||
.Where(static s => !string.IsNullOrWhiteSpace(s))
|
||||
.Select(static s => s!)
|
||||
@@ -591,9 +591,9 @@ public sealed class DebianConnector : IFeedConnector
|
||||
: Array.Empty<string>();
|
||||
|
||||
var packages = new List<DebianPackageStateDto>();
|
||||
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packagesBson)
|
||||
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packagesArr)
|
||||
{
|
||||
foreach (var element in packagesBson.OfType<DocumentObject>())
|
||||
foreach (var element in packagesArr.OfType<DocumentObject>())
|
||||
{
|
||||
packages.Add(new DebianPackageStateDto(
|
||||
element.GetValue("package", sourcePackage).AsString,
|
||||
@@ -614,9 +614,9 @@ public sealed class DebianConnector : IFeedConnector
|
||||
}
|
||||
|
||||
var references = new List<DebianReferenceDto>();
|
||||
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray refBson)
|
||||
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray refArr)
|
||||
{
|
||||
foreach (var element in refBson.OfType<DocumentObject>())
|
||||
foreach (var element in refArr.OfType<DocumentObject>())
|
||||
{
|
||||
references.Add(new DebianReferenceDto(
|
||||
element.GetValue("url", "").AsString,
|
||||
|
||||
@@ -19,7 +19,7 @@ internal sealed record DebianCursor(
|
||||
|
||||
public static DebianCursor Empty { get; } = new(null, EmptyIds, EmptyGuidList, EmptyGuidList, EmptyCache);
|
||||
|
||||
public static DebianCursor FromBson(DocumentObject? document)
|
||||
public static DebianCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ internal sealed record DebianCursor(
|
||||
{
|
||||
if (element.Value is DocumentObject entry)
|
||||
{
|
||||
cache[element.Name] = DebianFetchCacheEntry.FromBson(entry);
|
||||
cache[element.Name] = DebianFetchCacheEntry.FromDocument(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ internal sealed record DebianFetchCacheEntry(string? ETag, DateTimeOffset? LastM
|
||||
public static DebianFetchCacheEntry FromDocument(StellaOps.Concelier.Storage.DocumentRecord document)
|
||||
=> new(document.Etag, document.LastModified);
|
||||
|
||||
public static DebianFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static DebianFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ internal sealed record SuseCursor(
|
||||
|
||||
public static SuseCursor Empty { get; } = new(null, EmptyStringList, EmptyGuidList, EmptyGuidList, EmptyCache);
|
||||
|
||||
public static SuseCursor FromBson(DocumentObject? document)
|
||||
public static SuseCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ internal sealed record SuseCursor(
|
||||
{
|
||||
if (element.Value is DocumentObject entry)
|
||||
{
|
||||
cache[element.Name] = SuseFetchCacheEntry.FromBson(entry);
|
||||
cache[element.Name] = SuseFetchCacheEntry.FromDocument(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using StellaOps.Concelier.Documents;
|
||||
using MongoContracts = StellaOps.Concelier.Storage;
|
||||
using LegacyContracts = StellaOps.Concelier.Storage;
|
||||
using StorageContracts = StellaOps.Concelier.Storage.Contracts;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Distro.Suse.Internal;
|
||||
@@ -12,10 +12,10 @@ internal sealed record SuseFetchCacheEntry(string? ETag, DateTimeOffset? LastMod
|
||||
public static SuseFetchCacheEntry FromDocument(StorageContracts.StorageDocument document)
|
||||
=> new(document.Etag, document.LastModified);
|
||||
|
||||
public static SuseFetchCacheEntry FromDocument(MongoContracts.DocumentRecord document)
|
||||
public static SuseFetchCacheEntry FromDocument(LegacyContracts.DocumentRecord document)
|
||||
=> new(document.Etag, document.LastModified);
|
||||
|
||||
public static SuseFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static SuseFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -79,7 +79,7 @@ internal sealed record SuseFetchCacheEntry(string? ETag, DateTimeOffset? LastMod
|
||||
return !LastModified.HasValue && !document.LastModified.HasValue;
|
||||
}
|
||||
|
||||
public bool Matches(MongoContracts.DocumentRecord document)
|
||||
public bool Matches(LegacyContracts.DocumentRecord document)
|
||||
{
|
||||
if (document is null)
|
||||
{
|
||||
|
||||
@@ -343,7 +343,7 @@ public sealed class SuseConnector : IFeedConnector
|
||||
var updatedDocument = document with { Metadata = metadata };
|
||||
await _documentStore.UpsertAsync(updatedDocument, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var payload = ToBson(dto);
|
||||
var payload = ToDocument(dto);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "suse.csaf.v1", payload, _timeProvider.GetUtcNow());
|
||||
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
@@ -390,7 +390,7 @@ public sealed class SuseConnector : IFeedConnector
|
||||
SuseAdvisoryDto dto;
|
||||
try
|
||||
{
|
||||
dto = FromBson(dtoRecord.Payload);
|
||||
dto = FromDocument(dtoRecord.Payload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -415,7 +415,7 @@ public sealed class SuseConnector : IFeedConnector
|
||||
private async Task<SuseCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? SuseCursor.Empty : SuseCursor.FromBson(state.Cursor);
|
||||
return state is null ? SuseCursor.Empty : SuseCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(SuseCursor cursor, CancellationToken cancellationToken)
|
||||
@@ -424,7 +424,7 @@ public sealed class SuseConnector : IFeedConnector
|
||||
await _stateRepository.UpdateCursorAsync(SourceName, document, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static DocumentObject ToBson(SuseAdvisoryDto dto)
|
||||
private static DocumentObject ToDocument(SuseAdvisoryDto dto)
|
||||
{
|
||||
var packages = new DocumentArray();
|
||||
foreach (var package in dto.Packages)
|
||||
@@ -493,7 +493,7 @@ public sealed class SuseConnector : IFeedConnector
|
||||
};
|
||||
}
|
||||
|
||||
private static SuseAdvisoryDto FromBson(DocumentObject document)
|
||||
private static SuseAdvisoryDto FromDocument(DocumentObject document)
|
||||
{
|
||||
var advisoryId = document.GetValue("advisoryId", string.Empty).AsString;
|
||||
var title = document.GetValue("title", advisoryId).AsString;
|
||||
@@ -507,8 +507,8 @@ public sealed class SuseConnector : IFeedConnector
|
||||
}
|
||||
: DateTimeOffset.UtcNow;
|
||||
|
||||
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray bsonCves
|
||||
? bsonCves.OfType<DocumentValue>()
|
||||
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cveArr
|
||||
? cveArr.OfType<DocumentValue>()
|
||||
.Select(static value => value?.ToString())
|
||||
.Where(static value => !string.IsNullOrWhiteSpace(value))
|
||||
.Select(static value => value!)
|
||||
@@ -517,9 +517,9 @@ public sealed class SuseConnector : IFeedConnector
|
||||
: Array.Empty<string>();
|
||||
|
||||
var packageList = new List<SusePackageStateDto>();
|
||||
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray bsonPackages)
|
||||
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packageArr)
|
||||
{
|
||||
foreach (var element in bsonPackages.OfType<DocumentObject>())
|
||||
foreach (var element in packageArr.OfType<DocumentObject>())
|
||||
{
|
||||
var package = element.GetValue("package", string.Empty).AsString;
|
||||
var platform = element.GetValue("platform", string.Empty).AsString;
|
||||
@@ -544,9 +544,9 @@ public sealed class SuseConnector : IFeedConnector
|
||||
}
|
||||
|
||||
var referenceList = new List<SuseReferenceDto>();
|
||||
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray bsonReferences)
|
||||
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray referenceArr)
|
||||
{
|
||||
foreach (var element in bsonReferences.OfType<DocumentObject>())
|
||||
foreach (var element in referenceArr.OfType<DocumentObject>())
|
||||
{
|
||||
var url = element.GetValue("url", string.Empty).AsString;
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
|
||||
@@ -19,7 +19,7 @@ internal sealed record UbuntuCursor(
|
||||
|
||||
public static UbuntuCursor Empty { get; } = new(null, EmptyIds, EmptyGuidList, EmptyGuidList, EmptyCache);
|
||||
|
||||
public static UbuntuCursor FromBson(DocumentObject? document)
|
||||
public static UbuntuCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ internal sealed record UbuntuCursor(
|
||||
{
|
||||
if (element.Value is DocumentObject entryDoc)
|
||||
{
|
||||
cache[element.Name] = UbuntuFetchCacheEntry.FromBson(entryDoc);
|
||||
cache[element.Name] = UbuntuFetchCacheEntry.FromDocument(entryDoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ internal sealed record UbuntuFetchCacheEntry(string? ETag, DateTimeOffset? LastM
|
||||
public static UbuntuFetchCacheEntry FromDocument(StorageContracts.StorageDocument document)
|
||||
=> new(document.Etag, document.LastModified);
|
||||
|
||||
public static UbuntuFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static UbuntuFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -144,7 +144,7 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
["ubuntu.published"] = notice.Published.ToString("O")
|
||||
};
|
||||
|
||||
var dtoDocument = ToBson(notice);
|
||||
var dtoDocument = ToDocument(notice);
|
||||
var sha256 = ComputeNoticeHash(dtoDocument);
|
||||
|
||||
var documentId = existing?.Id ?? Guid.NewGuid();
|
||||
@@ -217,7 +217,7 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
UbuntuNoticeDto notice;
|
||||
try
|
||||
{
|
||||
notice = FromBson(dto.Payload);
|
||||
notice = FromDocument(dto.Payload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -409,7 +409,7 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
private async Task<UbuntuCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? UbuntuCursor.Empty : UbuntuCursor.FromBson(state.Cursor);
|
||||
return state is null ? UbuntuCursor.Empty : UbuntuCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(UbuntuCursor cursor, CancellationToken cancellationToken)
|
||||
@@ -420,12 +420,12 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
|
||||
private string ComputeNoticeHash(DocumentObject document)
|
||||
{
|
||||
var bytes = document.ToBson();
|
||||
var bytes = document.ToDocument();
|
||||
var hash = _hash.ComputeHash(bytes, HashAlgorithms.Sha256);
|
||||
return Convert.ToHexString(hash).ToLowerInvariant();
|
||||
}
|
||||
|
||||
private static DocumentObject ToBson(UbuntuNoticeDto notice)
|
||||
private static DocumentObject ToDocument(UbuntuNoticeDto notice)
|
||||
{
|
||||
var packages = new DocumentArray();
|
||||
foreach (var package in notice.Packages)
|
||||
@@ -473,7 +473,7 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
};
|
||||
}
|
||||
|
||||
private static UbuntuNoticeDto FromBson(DocumentObject document)
|
||||
private static UbuntuNoticeDto FromDocument(DocumentObject document)
|
||||
{
|
||||
var noticeId = document.GetValue("noticeId", string.Empty).AsString;
|
||||
var published = document.TryGetValue("published", out var publishedValue)
|
||||
@@ -488,8 +488,8 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
var title = document.GetValue("title", noticeId).AsString;
|
||||
var summary = document.GetValue("summary", string.Empty).AsString;
|
||||
|
||||
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cveBson
|
||||
? cveBson.OfType<DocumentValue>()
|
||||
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cveArr
|
||||
? cveArr.OfType<DocumentValue>()
|
||||
.Select(static value => value?.ToString())
|
||||
.Where(static value => !string.IsNullOrWhiteSpace(value))
|
||||
.Select(static value => value!)
|
||||
@@ -497,9 +497,9 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
: Array.Empty<string>();
|
||||
|
||||
var packages = new List<UbuntuReleasePackageDto>();
|
||||
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packageBson)
|
||||
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packageArr)
|
||||
{
|
||||
foreach (var element in packageBson.OfType<DocumentObject>())
|
||||
foreach (var element in packageArr.OfType<DocumentObject>())
|
||||
{
|
||||
packages.Add(new UbuntuReleasePackageDto(
|
||||
Release: element.GetValue("release", string.Empty).AsString,
|
||||
@@ -511,9 +511,9 @@ public sealed class UbuntuConnector : IFeedConnector
|
||||
}
|
||||
|
||||
var references = new List<UbuntuReferenceDto>();
|
||||
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray referenceBson)
|
||||
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray referenceArr)
|
||||
{
|
||||
foreach (var element in referenceBson.OfType<DocumentObject>())
|
||||
foreach (var element in referenceArr.OfType<DocumentObject>())
|
||||
{
|
||||
var url = element.GetValue("url", string.Empty).AsString;
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
|
||||
@@ -422,7 +422,7 @@ public sealed class GhsaConnector : IFeedConnector
|
||||
private async Task<GhsaCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? GhsaCursor.Empty : GhsaCursor.FromBson(state.Cursor);
|
||||
return state is null ? GhsaCursor.Empty : GhsaCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(GhsaCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -49,7 +49,7 @@ internal sealed record GhsaCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static GhsaCursor FromBson(DocumentObject? document)
|
||||
public static GhsaCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -322,13 +322,13 @@ public sealed class IcsCisaConnector : IFeedConnector
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
WriteIndented = false,
|
||||
});
|
||||
var bson = DocumentObject.Parse(json);
|
||||
var doc = DocumentObject.Parse(json);
|
||||
var dtoRecord = new DtoRecord(
|
||||
Guid.NewGuid(),
|
||||
document.Id,
|
||||
SourceName,
|
||||
SchemaVersion,
|
||||
bson,
|
||||
doc,
|
||||
_timeProvider.GetUtcNow());
|
||||
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
@@ -1411,7 +1411,7 @@ public sealed class IcsCisaConnector : IFeedConnector
|
||||
private async Task<IcsCisaCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? IcsCisaCursor.Empty : IcsCisaCursor.FromBson(state.Cursor);
|
||||
return state is null ? IcsCisaCursor.Empty : IcsCisaCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(IcsCisaCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -28,7 +28,7 @@ internal sealed record IcsCisaCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static IcsCisaCursor FromBson(DocumentObject? document)
|
||||
public static IcsCisaCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ internal sealed record KasperskyCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static KasperskyCursor FromBson(DocumentObject? document)
|
||||
public static KasperskyCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -442,7 +442,7 @@ public sealed class KasperskyConnector : IFeedConnector
|
||||
private async Task<KasperskyCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? KasperskyCursor.Empty : KasperskyCursor.FromBson(state.Cursor);
|
||||
return state is null ? KasperskyCursor.Empty : KasperskyCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(KasperskyCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -36,7 +36,7 @@ internal sealed record JvnCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static JvnCursor FromBson(DocumentObject? document)
|
||||
public static JvnCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -314,7 +314,7 @@ public sealed class JvnConnector : IFeedConnector
|
||||
private async Task<JvnCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? JvnCursor.Empty : JvnCursor.FromBson(state.Cursor);
|
||||
return state is null ? JvnCursor.Empty : JvnCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(JvnCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -34,7 +34,7 @@ internal sealed record KevCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static KevCursor FromBson(DocumentObject? document)
|
||||
public static KevCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -386,7 +386,7 @@ public sealed class KevConnector : IFeedConnector
|
||||
private async Task<KevCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? KevCursor.Empty : KevCursor.FromBson(state.Cursor);
|
||||
return state is null ? KevCursor.Empty : KevCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(KevCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -54,7 +54,7 @@ internal sealed record KisaCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static KisaCursor FromBson(DocumentObject? document)
|
||||
public static KisaCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -287,8 +287,8 @@ public sealed class KisaConnector : IFeedConnector
|
||||
_diagnostics.ParseSuccess(category);
|
||||
_logger.LogDebug("KISA parsed detail for {DocumentId} ({Category})", document.Id, category ?? "unknown");
|
||||
|
||||
var dtoBson = DocumentObject.Parse(JsonSerializer.Serialize(parsed, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "kisa.detail.v1", dtoBson, now);
|
||||
var dtoDoc = DocumentObject.Parse(JsonSerializer.Serialize(parsed, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "kisa.detail.v1", dtoDoc, now);
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -412,7 +412,7 @@ public sealed class KisaConnector : IFeedConnector
|
||||
private async Task<KisaCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? KisaCursor.Empty : KisaCursor.FromBson(state.Cursor);
|
||||
return state is null ? KisaCursor.Empty : KisaCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(KisaCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -78,7 +78,7 @@ internal sealed record OsvCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static OsvCursor FromBson(DocumentObject? document)
|
||||
public static OsvCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -297,7 +297,7 @@ public sealed class OsvConnector : IFeedConnector
|
||||
private async Task<OsvCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? OsvCursor.Empty : OsvCursor.FromBson(state.Cursor);
|
||||
return state is null ? OsvCursor.Empty : OsvCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(OsvCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -36,7 +36,7 @@ internal sealed record RuBduCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static RuBduCursor FromBson(DocumentObject? document)
|
||||
public static RuBduCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -268,8 +268,8 @@ public sealed class RuBduConnector : IFeedConnector
|
||||
continue;
|
||||
}
|
||||
|
||||
var bson = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-bdu.v1", bson, _timeProvider.GetUtcNow());
|
||||
var doc = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-bdu.v1", doc, _timeProvider.GetUtcNow());
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
_diagnostics.ParseSuccess(
|
||||
@@ -520,7 +520,7 @@ public sealed class RuBduConnector : IFeedConnector
|
||||
private async Task<RuBduCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? RuBduCursor.Empty : RuBduCursor.FromBson(state.Cursor);
|
||||
return state is null ? RuBduCursor.Empty : RuBduCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(RuBduCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -42,7 +42,7 @@ internal sealed record RuNkckiCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static RuNkckiCursor FromBson(DocumentObject? document)
|
||||
public static RuNkckiCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -338,8 +338,8 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
continue;
|
||||
}
|
||||
|
||||
var bson = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-nkcki.v1", bson, _timeProvider.GetUtcNow());
|
||||
var doc = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-nkcki.v1", doc, _timeProvider.GetUtcNow());
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -871,7 +871,7 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
private async Task<RuNkckiCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? RuNkckiCursor.Empty : RuNkckiCursor.FromBson(state.Cursor);
|
||||
return state is null ? RuNkckiCursor.Empty : RuNkckiCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private Task UpdateCursorAsync(RuNkckiCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -52,7 +52,7 @@ internal sealed record StellaOpsMirrorCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static StellaOpsMirrorCursor FromBson(DocumentObject? document)
|
||||
public static StellaOpsMirrorCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -275,7 +275,7 @@ public sealed class StellaOpsMirrorConnector : IFeedConnector
|
||||
private async Task<StellaOpsMirrorCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(Source, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? StellaOpsMirrorCursor.Empty : StellaOpsMirrorCursor.FromBson(state.Cursor);
|
||||
return state is null ? StellaOpsMirrorCursor.Empty : StellaOpsMirrorCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(StellaOpsMirrorCursor cursor, CancellationToken cancellationToken)
|
||||
@@ -422,8 +422,8 @@ public sealed class StellaOpsMirrorConnector : IFeedConnector
|
||||
continue;
|
||||
}
|
||||
|
||||
var dtoBson = DocumentObject.Parse(json);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, Source, BundleDtoSchemaVersion, dtoBson, now);
|
||||
var dtoDoc = DocumentObject.Parse(json);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, Source, BundleDtoSchemaVersion, dtoDoc, now);
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ internal sealed record AdobeCursor(
|
||||
var cacheDocument = new DocumentObject();
|
||||
foreach (var (key, entry) in FetchCache)
|
||||
{
|
||||
cacheDocument[key] = entry.ToBson();
|
||||
cacheDocument[key] = entry.ToDocument();
|
||||
}
|
||||
|
||||
document["fetchCache"] = cacheDocument;
|
||||
@@ -138,7 +138,7 @@ internal sealed record AdobeCursor(
|
||||
{
|
||||
if (element.Value is DocumentObject entryDocument)
|
||||
{
|
||||
dictionary[element.Name] = AdobeFetchCacheEntry.FromBson(entryDocument);
|
||||
dictionary[element.Name] = AdobeFetchCacheEntry.FromDocument(entryDocument);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ internal sealed record AdobeFetchCacheEntry(string Sha256)
|
||||
{
|
||||
public static AdobeFetchCacheEntry Empty { get; } = new(string.Empty);
|
||||
|
||||
public DocumentObject ToBson()
|
||||
public DocumentObject ToDocument()
|
||||
{
|
||||
var document = new DocumentObject
|
||||
{
|
||||
@@ -160,7 +160,7 @@ internal sealed record AdobeFetchCacheEntry(string Sha256)
|
||||
return document;
|
||||
}
|
||||
|
||||
public static AdobeFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static AdobeFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
var sha = document.TryGetValue("sha256", out var shaValue) ? shaValue.AsString : string.Empty;
|
||||
return new AdobeFetchCacheEntry(sha);
|
||||
|
||||
@@ -428,12 +428,12 @@ public sealed class AppleConnector : IFeedConnector
|
||||
private async Task<AppleCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? AppleCursor.Empty : AppleCursor.FromBson(state.Cursor);
|
||||
return state is null ? AppleCursor.Empty : AppleCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(AppleCursor cursor, CancellationToken cancellationToken)
|
||||
{
|
||||
var document = cursor.ToBson();
|
||||
var document = cursor.ToDocument();
|
||||
await _stateRepository.UpdateCursorAsync(SourceName, document, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ internal sealed record AppleCursor(
|
||||
|
||||
public static AppleCursor Empty { get; } = new(null, EmptyStringCollection, EmptyGuidCollection, EmptyGuidCollection);
|
||||
|
||||
public DocumentObject ToBson()
|
||||
public DocumentObject ToDocument()
|
||||
{
|
||||
var document = new DocumentObject
|
||||
{
|
||||
@@ -37,7 +37,7 @@ internal sealed record AppleCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static AppleCursor FromBson(DocumentObject? document)
|
||||
public static AppleCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ internal sealed record ChromiumCursor(
|
||||
var cacheDocument = new DocumentObject();
|
||||
foreach (var (key, entry) in FetchCache)
|
||||
{
|
||||
cacheDocument[key] = entry.ToBson();
|
||||
cacheDocument[key] = entry.ToDocument();
|
||||
}
|
||||
|
||||
document["fetchCache"] = cacheDocument;
|
||||
@@ -113,7 +113,7 @@ internal sealed record ChromiumCursor(
|
||||
{
|
||||
if (element.Value is DocumentObject entryDocument)
|
||||
{
|
||||
dictionary[element.Name] = ChromiumFetchCacheEntry.FromBson(entryDocument);
|
||||
dictionary[element.Name] = ChromiumFetchCacheEntry.FromDocument(entryDocument);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ internal sealed record ChromiumFetchCacheEntry(string Sha256)
|
||||
{
|
||||
public static ChromiumFetchCacheEntry Empty { get; } = new(string.Empty);
|
||||
|
||||
public DocumentObject ToBson()
|
||||
public DocumentObject ToDocument()
|
||||
{
|
||||
var document = new DocumentObject
|
||||
{
|
||||
@@ -135,7 +135,7 @@ internal sealed record ChromiumFetchCacheEntry(string Sha256)
|
||||
return document;
|
||||
}
|
||||
|
||||
public static ChromiumFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static ChromiumFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
var sha = document.TryGetValue("sha256", out var shaValue) ? shaValue.AsString : string.Empty;
|
||||
return new ChromiumFetchCacheEntry(sha);
|
||||
|
||||
@@ -325,8 +325,8 @@ public sealed class CiscoConnector : IFeedConnector
|
||||
try
|
||||
{
|
||||
var dtoJson = JsonSerializer.Serialize(dto, DtoSerializerOptions);
|
||||
var dtoBson = DocumentObject.Parse(dtoJson);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoBson, _timeProvider.GetUtcNow());
|
||||
var dtoDoc = DocumentObject.Parse(dtoJson);
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoDoc, _timeProvider.GetUtcNow());
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
pendingDocuments.Remove(documentId);
|
||||
@@ -577,12 +577,12 @@ public sealed class CiscoConnector : IFeedConnector
|
||||
private async Task<CiscoCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? CiscoCursor.Empty : CiscoCursor.FromBson(state.Cursor);
|
||||
return state is null ? CiscoCursor.Empty : CiscoCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(CiscoCursor cursor, CancellationToken cancellationToken)
|
||||
{
|
||||
var document = cursor.ToBson();
|
||||
var document = cursor.ToDocument();
|
||||
await _stateRepository.UpdateCursorAsync(SourceName, document, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ internal sealed record CiscoCursor(
|
||||
|
||||
public static CiscoCursor Empty { get; } = new(null, null, EmptyGuidCollection, EmptyGuidCollection);
|
||||
|
||||
public DocumentObject ToBson()
|
||||
public DocumentObject ToDocument()
|
||||
{
|
||||
var document = new DocumentObject
|
||||
{
|
||||
@@ -33,7 +33,7 @@ internal sealed record CiscoCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static CiscoCursor FromBson(DocumentObject? document)
|
||||
public static CiscoCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ internal sealed record MsrcCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static MsrcCursor FromBson(DocumentObject? document)
|
||||
public static MsrcCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
|
||||
@@ -293,8 +293,8 @@ public sealed class MsrcConnector : IFeedConnector
|
||||
}
|
||||
|
||||
var dto = _detailParser.Parse(detail);
|
||||
var bson = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "msrc.detail.v1", bson, now);
|
||||
var doc = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "msrc.detail.v1", doc, now);
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
remainingDocuments.Remove(documentId);
|
||||
@@ -407,7 +407,7 @@ public sealed class MsrcConnector : IFeedConnector
|
||||
private async Task<MsrcCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? MsrcCursor.Empty : MsrcCursor.FromBson(state.Cursor);
|
||||
return state is null ? MsrcCursor.Empty : MsrcCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task FetchCvrfAsync(MsrcVulnerabilitySummary summary, DateTimeOffset fetchedAt, CancellationToken cancellationToken)
|
||||
|
||||
@@ -45,7 +45,7 @@ internal sealed record OracleCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static OracleCursor FromBson(DocumentObject? document)
|
||||
public static OracleCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -140,7 +140,7 @@ internal sealed record OracleCursor(
|
||||
continue;
|
||||
}
|
||||
|
||||
cache[element.Name] = OracleFetchCacheEntry.FromBson(entryDocument);
|
||||
cache[element.Name] = OracleFetchCacheEntry.FromDocument(entryDocument);
|
||||
}
|
||||
|
||||
return cache;
|
||||
@@ -171,7 +171,7 @@ internal sealed record OracleFetchCacheEntry(string? Sha256, string? ETag, DateT
|
||||
return document;
|
||||
}
|
||||
|
||||
public static OracleFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static OracleFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
var sha = document.TryGetValue("sha256", out var shaValue) ? shaValue.ToString() : string.Empty;
|
||||
string? etag = null;
|
||||
|
||||
@@ -314,7 +314,7 @@ public sealed class OracleConnector : IFeedConnector
|
||||
private async Task<OracleCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var record = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return OracleCursor.FromBson(record?.Cursor);
|
||||
return OracleCursor.FromDocument(record?.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(OracleCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -51,7 +51,7 @@ internal sealed record VmwareCursor(
|
||||
return document;
|
||||
}
|
||||
|
||||
public static VmwareCursor FromBson(DocumentObject? document)
|
||||
public static VmwareCursor FromDocument(DocumentObject? document)
|
||||
{
|
||||
if (document is null || document.ElementCount == 0)
|
||||
{
|
||||
@@ -155,7 +155,7 @@ internal sealed record VmwareCursor(
|
||||
{
|
||||
if (element.Value is DocumentObject entryDocument)
|
||||
{
|
||||
cache[element.Name] = VmwareFetchCacheEntry.FromBson(entryDocument);
|
||||
cache[element.Name] = VmwareFetchCacheEntry.FromDocument(entryDocument);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ internal sealed record VmwareFetchCacheEntry(string? Sha256, string? ETag, DateT
|
||||
return document;
|
||||
}
|
||||
|
||||
public static VmwareFetchCacheEntry FromBson(DocumentObject document)
|
||||
public static VmwareFetchCacheEntry FromDocument(DocumentObject document)
|
||||
{
|
||||
var sha256 = document.TryGetValue("sha256", out var shaValue) ? shaValue.ToString() : string.Empty;
|
||||
string? etag = null;
|
||||
|
||||
@@ -443,7 +443,7 @@ public sealed class VmwareConnector : IFeedConnector
|
||||
private async Task<VmwareCursor> GetCursorAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
|
||||
return state is null ? VmwareCursor.Empty : VmwareCursor.FromBson(state.Cursor);
|
||||
return state is null ? VmwareCursor.Empty : VmwareCursor.FromDocument(state.Cursor);
|
||||
}
|
||||
|
||||
private async Task UpdateCursorAsync(VmwareCursor cursor, CancellationToken cancellationToken)
|
||||
|
||||
@@ -28,11 +28,11 @@ public sealed record AdvisoryLinksetNormalized(
|
||||
public List<string>? CpesToList()
|
||||
=> Cpes is null ? null : Cpes.ToList();
|
||||
|
||||
public List<DocumentObject>? RangesToBson()
|
||||
=> Ranges is null ? null : Ranges.Select(BsonDocumentHelper.FromDictionary).ToList();
|
||||
public List<DocumentObject>? RangesToDocuments()
|
||||
=> Ranges is null ? null : Ranges.Select(DocumentHelper.FromDictionary).ToList();
|
||||
|
||||
public List<DocumentObject>? SeveritiesToBson()
|
||||
=> Severities is null ? null : Severities.Select(BsonDocumentHelper.FromDictionary).ToList();
|
||||
public List<DocumentObject>? SeveritiesToDocuments()
|
||||
=> Severities is null ? null : Severities.Select(DocumentHelper.FromDictionary).ToList();
|
||||
}
|
||||
|
||||
public sealed record AdvisoryLinksetProvenance(
|
||||
@@ -46,7 +46,7 @@ public sealed record AdvisoryLinksetConflict(
|
||||
IReadOnlyList<string>? Values,
|
||||
IReadOnlyList<string>? SourceIds = null);
|
||||
|
||||
internal static class BsonDocumentHelper
|
||||
internal static class DocumentHelper
|
||||
{
|
||||
public static DocumentObject FromDictionary(Dictionary<string, object?> dictionary)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ public sealed record PolicyDeltaCheckpoint(
|
||||
/// <summary>Last processed advisory ID (tie-breaker when CreatedAt matches).</summary>
|
||||
string? LastAdvisoryId,
|
||||
|
||||
/// <summary>MongoDB change-stream resume token for real-time delta subscriptions.</summary>
|
||||
/// <summary>Change-stream resume token for real-time delta subscriptions.</summary>
|
||||
string? ResumeToken,
|
||||
|
||||
/// <summary>Sequence number for ordering events within the same timestamp.</summary>
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace StellaOps.Concelier.Core.Linksets;
|
||||
///
|
||||
/// Read-through behavior:
|
||||
/// 1. First queries the configured cache (Postgres via IAdvisoryLinksetLookup)
|
||||
/// 2. On cache miss, rebuilds from MongoDB observations
|
||||
/// 2. On cache miss, rebuilds from observations
|
||||
/// 3. Stores rebuilt linksets in cache
|
||||
/// 4. Returns results
|
||||
/// </summary>
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace StellaOps.Concelier.Core.Observations;
|
||||
public sealed class AdvisoryObservationEventPublisherOptions
|
||||
{
|
||||
public bool Enabled { get; set; } = false;
|
||||
public string Transport { get; set; } = "mongo"; // mongo|nats
|
||||
public string Transport { get; set; } = "inmemory"; // inmemory|nats
|
||||
public string? NatsUrl { get; set; }
|
||||
public string Subject { get; set; } = "concelier.advisory.observation.updated.v1";
|
||||
public string DeadLetterSubject { get; set; } = "concelier.advisory.observation.updated.dead.v1";
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace StellaOps.Concelier.Core.Orchestration;
|
||||
|
||||
/// <summary>
|
||||
/// In-memory implementation of orchestrator registry store for testing and development.
|
||||
/// Production deployments should use a persistent store (MongoDB, etc.).
|
||||
/// Production deployments should use a persistent store (PostgreSQL, etc.).
|
||||
/// </summary>
|
||||
public sealed class InMemoryOrchestratorRegistryStore : IOrchestratorRegistryStore
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ public static class SignalsServiceCollectionExtensions
|
||||
/// <returns>The service collection for chaining.</returns>
|
||||
public static IServiceCollection AddConcelierSignalsServices(this IServiceCollection services)
|
||||
{
|
||||
// Register affected symbol store (in-memory by default; replace with MongoDB in production)
|
||||
// Register affected symbol store (in-memory by default; replace with persistent store in production)
|
||||
services.TryAddSingleton<IAffectedSymbolStore, InMemoryAffectedSymbolStore>();
|
||||
|
||||
// Register affected symbol provider
|
||||
|
||||
@@ -1,454 +0,0 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0": {
|
||||
"StellaOps.Concelier.Core/1.0.0": {
|
||||
"dependencies": {
|
||||
"Cronos": "0.10.0",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107",
|
||||
"MongoDB.Driver": "3.5.0",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.Aoc": "1.0.0",
|
||||
"StellaOps.Concelier.Models": "1.0.0",
|
||||
"StellaOps.Concelier.Normalization": "1.0.0",
|
||||
"StellaOps.Concelier.RawModels": "1.0.0",
|
||||
"StellaOps.Ingestion.Telemetry": "1.0.0",
|
||||
"StellaOps.Plugin": "1.0.0",
|
||||
"StellaOps.Provenance.Mongo": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.Core.dll": {}
|
||||
}
|
||||
},
|
||||
"Cronos/0.10.0": {
|
||||
"runtime": {
|
||||
"lib/net6.0/Cronos.dll": {
|
||||
"assemblyVersion": "0.10.0.0",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DnsClient/1.6.1": {
|
||||
"runtime": {
|
||||
"lib/net5.0/DnsClient.dll": {
|
||||
"assemblyVersion": "1.6.1.0",
|
||||
"fileVersion": "1.6.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.FileProviders.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Hosting.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Options/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Options.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives/10.0.0-rc.2.25502.107": {
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Primitives.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"runtime": {
|
||||
"lib/net6.0/MongoDB.Bson.dll": {
|
||||
"assemblyVersion": "3.5.0.0",
|
||||
"fileVersion": "3.5.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MongoDB.Driver/3.5.0": {
|
||||
"dependencies": {
|
||||
"DnsClient": "1.6.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"MongoDB.Bson": "3.5.0",
|
||||
"SharpCompress": "0.41.0",
|
||||
"Snappier": "1.0.0",
|
||||
"ZstdSharp.Port": "0.8.6"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net6.0/MongoDB.Driver.dll": {
|
||||
"assemblyVersion": "3.5.0.0",
|
||||
"fileVersion": "3.5.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"NuGet.Versioning/6.9.1": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/NuGet.Versioning.dll": {
|
||||
"assemblyVersion": "6.9.1.3",
|
||||
"fileVersion": "6.9.1.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"dependencies": {
|
||||
"ZstdSharp.Port": "0.8.6"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net8.0/SharpCompress.dll": {
|
||||
"assemblyVersion": "0.41.0.0",
|
||||
"fileVersion": "0.41.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Snappier/1.0.0": {
|
||||
"runtime": {
|
||||
"lib/net5.0/Snappier.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"runtime": {
|
||||
"lib/net9.0/ZstdSharp.dll": {
|
||||
"assemblyVersion": "0.8.6.0",
|
||||
"fileVersion": "0.8.6.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Aoc/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Aoc.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Concelier.Models/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.Concelier.RawModels": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.Models.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Concelier.Normalization/1.0.0": {
|
||||
"dependencies": {
|
||||
"NuGet.Versioning": "6.9.1",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.Concelier.Models": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.Normalization.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"dependencies": {
|
||||
"MongoDB.Bson": "3.5.0",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.RawModels.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.DependencyInjection/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.DependencyInjection.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Ingestion.Telemetry/1.0.0": {
|
||||
"dependencies": {
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Ingestion.Telemetry.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Plugin/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.DependencyInjection": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Plugin.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Provenance.Mongo/1.0.0": {
|
||||
"dependencies": {
|
||||
"MongoDB.Driver": "3.5.0",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Provenance.Mongo.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"StellaOps.Concelier.Core/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Cronos/0.10.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-wHL4tr8mWTvrJt/4sI3raympCNVT4F3VJI4SJHA9A/wB+8Lsq84RFGQH9bHEtvNsN1lCBTKNk+uVoDotGcYJZA==",
|
||||
"path": "cronos/0.10.0",
|
||||
"hashPath": "cronos.0.10.0.nupkg.sha512"
|
||||
},
|
||||
"DnsClient/1.6.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4H/f2uYJOZ+YObZjpY9ABrKZI+JNw3uizp6oMzTXwDw6F+2qIPhpRl/1t68O/6e98+vqNiYGu+lswmwdYUy3gg==",
|
||||
"path": "dnsclient/1.6.1",
|
||||
"hashPath": "dnsclient.1.6.1.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-H+i/Qy30Rg/K9BcW2Z6DCHPCzwMH3bCwNOjEz31shWTUDK8GeeeMnrKVusprTcRA2Y6yPST+hg2zc3whPEs14Q==",
|
||||
"path": "microsoft.extensions.configuration.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.configuration.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==",
|
||||
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-x6XVv3RiwOlN2unjyX/Zat0gI0HiRoDDdjkwBCwsMftYWpbJu4SiyRwDbrv2zAF8v8nbEEvcWi3/pUxZfaqLQw==",
|
||||
"path": "microsoft.extensions.diagnostics.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.diagnostics.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-dOpmW14MkOZIwV6269iXhoMp6alCHBoxqCR4pJ37GLjFaBIyzsIy+Ra8tsGmjHtFvEHKq0JRDIsb1PUkrK+yxw==",
|
||||
"path": "microsoft.extensions.fileproviders.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.fileproviders.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-M6zqZFbqjdCx8g5Y2XZKTfYfS0gAh4uJkmdAq/ZRDrpIr3Nd+u74allmw15jX1kM61IXM49EnTbhMzlWw5pGVQ==",
|
||||
"path": "microsoft.extensions.hosting.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.hosting.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==",
|
||||
"path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Options/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Ib6BCCjisp7ZUdhtNpSulFO0ODhz/IE4ZZd8OCqQWoRs363BQ0QOZi9KwpqpiEWo51S0kIXWqNicDPGXwpt9pQ==",
|
||||
"path": "microsoft.extensions.options/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.options.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Primitives/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-9pm2zqqn5u/OsKs2zgkhJEQQeMx9KkVOWPdHrs7Kt5sfpk+eIh/gmpi/mMH/ljS2T/PFsFdCEtm+GS/6l7zoZA==",
|
||||
"path": "microsoft.extensions.primitives/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.primitives.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
|
||||
"path": "mongodb.bson/3.5.0",
|
||||
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
|
||||
},
|
||||
"MongoDB.Driver/3.5.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ST90u7psyMkNNOWFgSkexsrB3kPn7Ynl2DlMFj2rJyYuc6SIxjmzu4ufy51yzM+cPVE1SvVcdb5UFobrRw6cMg==",
|
||||
"path": "mongodb.driver/3.5.0",
|
||||
"hashPath": "mongodb.driver.3.5.0.nupkg.sha512"
|
||||
},
|
||||
"NuGet.Versioning/6.9.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ypnSvEtpNGo48bAWn95J1oHChycCXcevFSbn53fqzLxlXFSZP7dawu8p/7mHAfGufZQSV2sBpW80XQGIfXO8kQ==",
|
||||
"path": "nuget.versioning/6.9.1",
|
||||
"hashPath": "nuget.versioning.6.9.1.nupkg.sha512"
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
|
||||
"path": "sharpcompress/0.41.0",
|
||||
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
|
||||
},
|
||||
"Snappier/1.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-rFtK2KEI9hIe8gtx3a0YDXdHOpedIf9wYCEYtBEmtlyiWVX3XlCNV03JrmmAi/Cdfn7dxK+k0sjjcLv4fpHnqA==",
|
||||
"path": "snappier/1.0.0",
|
||||
"hashPath": "snappier.1.0.0.nupkg.sha512"
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
|
||||
"path": "zstdsharp.port/0.8.6",
|
||||
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
|
||||
},
|
||||
"StellaOps.Aoc/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Concelier.Models/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Concelier.Normalization/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.DependencyInjection/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Ingestion.Telemetry/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Plugin/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Provenance.Mongo/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,7 +289,7 @@ namespace StellaOps.Concelier.Documents
|
||||
return JsonSerializer.Serialize(ordered, options);
|
||||
}
|
||||
|
||||
public byte[] ToBson() => Encoding.UTF8.GetBytes(ToJson());
|
||||
public byte[] ToDocument() => Encoding.UTF8.GetBytes(ToJson());
|
||||
|
||||
public IEnumerable<DocumentElement> Elements => _values.Select(static kvp => new DocumentElement(kvp.Key, kvp.Value ?? new DocumentValue()));
|
||||
|
||||
@@ -349,7 +349,7 @@ namespace StellaOps.Concelier.Documents
|
||||
return value switch
|
||||
{
|
||||
null => new DocumentValue(null),
|
||||
DocumentValue bson => bson,
|
||||
DocumentValue dv => dv,
|
||||
string s => new DocumentValue(s),
|
||||
Guid g => new DocumentValue(g),
|
||||
int i => new DocumentValue(i),
|
||||
|
||||
@@ -5,17 +5,17 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
namespace StellaOps.Concelier.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Lightweight compatibility bootstrapper to satisfy legacy Mongo wiring during Postgres migration.
|
||||
/// Registers in-memory stores only; no MongoDB driver/runtime required.
|
||||
/// Lightweight compatibility bootstrapper to satisfy legacy wiring during Postgres migration.
|
||||
/// Registers in-memory stores only; no storage driver/runtime required.
|
||||
/// </summary>
|
||||
public sealed class MongoBootstrapper
|
||||
public sealed class StorageBootstrapper
|
||||
{
|
||||
public Task InitializeAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static class MongoServiceCollectionExtensions
|
||||
public static class LegacyServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddMongoStorage(this IServiceCollection services, Action<StorageOptions>? configure = null)
|
||||
public static IServiceCollection AddInMemoryStorage(this IServiceCollection services, Action<StorageOptions>? configure = null)
|
||||
{
|
||||
var options = new StorageOptions();
|
||||
configure?.Invoke(options);
|
||||
@@ -31,7 +31,7 @@ public static class MongoServiceCollectionExtensions
|
||||
services.TryAddSingleton<MergeEvents.IMergeEventStore, MergeEvents.InMemoryMergeEventStore>();
|
||||
services.TryAddSingleton<PsirtFlags.IPsirtFlagStore, PsirtFlags.InMemoryPsirtFlagStore>();
|
||||
|
||||
services.TryAddSingleton<MongoBootstrapper>();
|
||||
services.TryAddSingleton<StorageBootstrapper>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,32 +19,32 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
|
||||
public class InMemoryClientSettings
|
||||
{
|
||||
public static InMemoryClientSettings FromUrl(MongoUrl url) => new();
|
||||
public static InMemoryClientSettings FromUrl(StorageUrl url) => new();
|
||||
public string? ApplicationName { get; set; }
|
||||
}
|
||||
|
||||
public class MongoUrl
|
||||
public class StorageUrl
|
||||
{
|
||||
public MongoUrl(string url) => Url = url;
|
||||
public StorageUrl(string url) => Url = url;
|
||||
public string Url { get; }
|
||||
public string DatabaseName => "default";
|
||||
}
|
||||
|
||||
public interface IMongoClient
|
||||
public interface IStorageClient
|
||||
{
|
||||
IMongoDatabase GetDatabase(string name, MongoDatabaseSettings? settings = null);
|
||||
IStorageDatabase GetDatabase(string name, StorageDatabaseSettings? settings = null);
|
||||
Task DropDatabaseAsync(string name, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public class InMemoryClient : IMongoClient
|
||||
public class InMemoryClient : IStorageClient
|
||||
{
|
||||
public InMemoryClient(string connectionString) { }
|
||||
public InMemoryClient(InMemoryClientSettings settings) { }
|
||||
public IMongoDatabase GetDatabase(string name, MongoDatabaseSettings? settings = null) => new MongoDatabase(name);
|
||||
public IStorageDatabase GetDatabase(string name, StorageDatabaseSettings? settings = null) => new StorageDatabase(name);
|
||||
public Task DropDatabaseAsync(string name, CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
public class MongoDatabaseSettings { }
|
||||
public class StorageDatabaseSettings { }
|
||||
|
||||
public sealed class DatabaseNamespace
|
||||
{
|
||||
@@ -52,9 +52,9 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
public string DatabaseName { get; }
|
||||
}
|
||||
|
||||
public interface IMongoDatabase
|
||||
public interface IStorageDatabase
|
||||
{
|
||||
IMongoCollection<TDocument> GetCollection<TDocument>(string name, MongoCollectionSettings? settings = null);
|
||||
IStorageCollection<TDocument> GetCollection<TDocument>(string name, StorageCollectionSettings? settings = null);
|
||||
DatabaseNamespace DatabaseNamespace { get; }
|
||||
Task DropCollectionAsync(string name, CancellationToken cancellationToken = default);
|
||||
DocumentObject RunCommand(DocumentObject command, CancellationToken cancellationToken = default);
|
||||
@@ -65,20 +65,20 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
Task<T> RunCommandAsync<T>(string command, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public class MongoDatabase : IMongoDatabase
|
||||
public class StorageDatabase : IStorageDatabase
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, object> _collections = new(StringComparer.Ordinal);
|
||||
|
||||
public MongoDatabase(string name)
|
||||
public StorageDatabase(string name)
|
||||
{
|
||||
Name = name;
|
||||
DatabaseNamespace = new DatabaseNamespace(name);
|
||||
}
|
||||
public string Name { get; }
|
||||
public DatabaseNamespace DatabaseNamespace { get; }
|
||||
public IMongoCollection<TDocument> GetCollection<TDocument>(string name, MongoCollectionSettings? settings = null)
|
||||
public IStorageCollection<TDocument> GetCollection<TDocument>(string name, StorageCollectionSettings? settings = null)
|
||||
{
|
||||
var collection = (MongoCollection<TDocument>)_collections.GetOrAdd(name, _ => new MongoCollection<TDocument>(name));
|
||||
var collection = (StorageCollection<TDocument>)_collections.GetOrAdd(name, _ => new StorageCollection<TDocument>(name));
|
||||
return collection;
|
||||
}
|
||||
|
||||
@@ -95,9 +95,9 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
public Task<T> RunCommandAsync<T>(string command, CancellationToken cancellationToken = default) => Task.FromResult(default(T)!);
|
||||
}
|
||||
|
||||
public class MongoCollectionSettings { }
|
||||
public class StorageCollectionSettings { }
|
||||
|
||||
public interface IMongoCollection<TDocument>
|
||||
public interface IStorageCollection<TDocument>
|
||||
{
|
||||
Task InsertOneAsync(TDocument document, InsertOneOptions? options = null, CancellationToken cancellationToken = default);
|
||||
Task InsertManyAsync(IEnumerable<TDocument> documents, InsertManyOptions? options = null, CancellationToken cancellationToken = default);
|
||||
@@ -109,21 +109,21 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
Task<long> CountDocumentsAsync(FilterDefinition<TDocument> filter, CountOptions? options = null, CancellationToken cancellationToken = default);
|
||||
Task<TProjection?> FindOneAndReplaceAsync<TProjection>(FilterDefinition<TDocument> filter, TDocument replacement, FindOneAndReplaceOptions<TDocument, TProjection>? options = null, CancellationToken cancellationToken = default);
|
||||
Task<TProjection?> FindOneAndUpdateAsync<TProjection>(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, FindOneAndUpdateOptions<TDocument, TProjection>? options = null, CancellationToken cancellationToken = default);
|
||||
IMongoIndexManager<TDocument> Indexes { get; }
|
||||
IStorageIndexManager<TDocument> Indexes { get; }
|
||||
}
|
||||
|
||||
public class MongoCollection<TDocument> : IMongoCollection<TDocument>
|
||||
public class StorageCollection<TDocument> : IStorageCollection<TDocument>
|
||||
{
|
||||
private readonly List<TDocument> _docs = new();
|
||||
|
||||
public MongoCollection(string name)
|
||||
public StorageCollection(string name)
|
||||
{
|
||||
Name = name;
|
||||
Indexes = new MongoIndexManager<TDocument>();
|
||||
Indexes = new StorageIndexManager<TDocument>();
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public IMongoIndexManager<TDocument> Indexes { get; }
|
||||
public IStorageIndexManager<TDocument> Indexes { get; }
|
||||
|
||||
public Task InsertOneAsync(TDocument document, InsertOneOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -177,12 +177,12 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
=> Task.FromResult(default(TProjection));
|
||||
}
|
||||
|
||||
public interface IMongoIndexManager<TDocument>
|
||||
public interface IStorageIndexManager<TDocument>
|
||||
{
|
||||
Task<string> CreateOneAsync(IndexKeysDefinition<TDocument> keys, CreateIndexOptions? options = null, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public sealed class MongoIndexManager<TDocument> : IMongoIndexManager<TDocument>
|
||||
public sealed class StorageIndexManager<TDocument> : IStorageIndexManager<TDocument>
|
||||
{
|
||||
public Task<string> CreateOneAsync(IndexKeysDefinition<TDocument> keys, CreateIndexOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult("stub-index");
|
||||
@@ -332,7 +332,7 @@ namespace StellaOps.Concelier.InMemoryDriver
|
||||
|
||||
namespace StellaOps.Concelier.InMemoryDriver.Linq
|
||||
{
|
||||
public interface IMongoQueryable<out T> : IQueryable<T> { }
|
||||
public interface IStorageQueryable<out T> : IQueryable<T> { }
|
||||
}
|
||||
|
||||
namespace StellaOps.Concelier.InMemoryRunner
|
||||
|
||||
@@ -6,7 +6,7 @@ using StellaOps.Concelier.Models;
|
||||
|
||||
namespace StellaOps.Concelier.Storage
|
||||
{
|
||||
public static class MongoStorageDefaults
|
||||
public static class StorageDefaults
|
||||
{
|
||||
public const string DefaultDatabaseName = "concelier";
|
||||
|
||||
@@ -349,35 +349,6 @@ public sealed record SourceStateRecord(
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
public class InMemorySourceStateRepository : ISourceStateRepository
|
||||
{
|
||||
private readonly InMemorySourceStateRepository _inner = new();
|
||||
|
||||
public InMemorySourceStateRepository()
|
||||
{
|
||||
}
|
||||
|
||||
public InMemorySourceStateRepository(object? database, StorageOptions? options)
|
||||
{
|
||||
}
|
||||
|
||||
public InMemorySourceStateRepository(object? database, object? logger)
|
||||
{
|
||||
}
|
||||
|
||||
public Task<SourceStateRecord?> TryGetAsync(string sourceName, CancellationToken cancellationToken)
|
||||
=> _inner.TryGetAsync(sourceName, cancellationToken);
|
||||
|
||||
public Task UpdateCursorAsync(string sourceName, StellaOps.Concelier.Documents.DocumentObject cursor, DateTimeOffset completedAt, CancellationToken cancellationToken)
|
||||
=> _inner.UpdateCursorAsync(sourceName, cursor, completedAt, cancellationToken);
|
||||
|
||||
public Task MarkFailureAsync(string sourceName, DateTimeOffset now, TimeSpan backoff, string reason, CancellationToken cancellationToken)
|
||||
=> _inner.MarkFailureAsync(sourceName, now, backoff, reason, cancellationToken);
|
||||
|
||||
public Task UpsertAsync(SourceStateRecord record, CancellationToken cancellationToken)
|
||||
=> _inner.UpsertAsync(record, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Advisories
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Text.Json;
|
||||
namespace StellaOps.Concelier.Storage.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Postgres-native storage document contract (Mongo-free).
|
||||
/// Postgres-native storage document contract.
|
||||
/// </summary>
|
||||
public sealed record StorageDocument(
|
||||
Guid Id,
|
||||
@@ -53,7 +53,7 @@ public interface IStorageDtoStore
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cursor/state contract for ingestion sources without Mongo/Bson dependencies.
|
||||
/// Cursor/state contract for ingestion sources.
|
||||
/// </summary>
|
||||
public sealed record SourceCursorState(
|
||||
string SourceName,
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0": {
|
||||
"StellaOps.Concelier.Models/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.Concelier.RawModels": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.Models.dll": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"runtime": {
|
||||
"lib/net6.0/MongoDB.Bson.dll": {
|
||||
"assemblyVersion": "3.5.0.0",
|
||||
"fileVersion": "3.5.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"dependencies": {
|
||||
"ZstdSharp.Port": "0.8.6"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net8.0/SharpCompress.dll": {
|
||||
"assemblyVersion": "0.41.0.0",
|
||||
"fileVersion": "0.41.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"runtime": {
|
||||
"lib/net9.0/ZstdSharp.dll": {
|
||||
"assemblyVersion": "0.8.6.0",
|
||||
"fileVersion": "0.8.6.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"dependencies": {
|
||||
"MongoDB.Bson": "3.5.0",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.RawModels.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"StellaOps.Concelier.Models/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==",
|
||||
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==",
|
||||
"path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
|
||||
"path": "mongodb.bson/3.5.0",
|
||||
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
|
||||
"path": "sharpcompress/0.41.0",
|
||||
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
|
||||
"path": "zstdsharp.port/0.8.6",
|
||||
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
|
||||
},
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0": {
|
||||
"StellaOps.Concelier.Normalization/1.0.0": {
|
||||
"dependencies": {
|
||||
"NuGet.Versioning": "6.9.1",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.Concelier.Models": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.Normalization.dll": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
|
||||
"assemblyVersion": "10.0.0.0",
|
||||
"fileVersion": "10.0.25.50307"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"runtime": {
|
||||
"lib/net6.0/MongoDB.Bson.dll": {
|
||||
"assemblyVersion": "3.5.0.0",
|
||||
"fileVersion": "3.5.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"NuGet.Versioning/6.9.1": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/NuGet.Versioning.dll": {
|
||||
"assemblyVersion": "6.9.1.3",
|
||||
"fileVersion": "6.9.1.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"dependencies": {
|
||||
"ZstdSharp.Port": "0.8.6"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net8.0/SharpCompress.dll": {
|
||||
"assemblyVersion": "0.41.0.0",
|
||||
"fileVersion": "0.41.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"runtime": {
|
||||
"lib/net9.0/ZstdSharp.dll": {
|
||||
"assemblyVersion": "0.8.6.0",
|
||||
"fileVersion": "0.8.6.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Concelier.Models/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
|
||||
"SharpCompress": "0.41.0",
|
||||
"StellaOps.Concelier.RawModels": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.Models.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"dependencies": {
|
||||
"MongoDB.Bson": "3.5.0",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.RawModels.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"StellaOps.Concelier.Normalization/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==",
|
||||
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==",
|
||||
"path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107",
|
||||
"hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
|
||||
"path": "mongodb.bson/3.5.0",
|
||||
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
|
||||
},
|
||||
"NuGet.Versioning/6.9.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ypnSvEtpNGo48bAWn95J1oHChycCXcevFSbn53fqzLxlXFSZP7dawu8p/7mHAfGufZQSV2sBpW80XQGIfXO8kQ==",
|
||||
"path": "nuget.versioning/6.9.1",
|
||||
"hashPath": "nuget.versioning.6.9.1.nupkg.sha512"
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
|
||||
"path": "sharpcompress/0.41.0",
|
||||
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
|
||||
"path": "zstdsharp.port/0.8.6",
|
||||
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
|
||||
},
|
||||
"StellaOps.Concelier.Models/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0": {
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"dependencies": {
|
||||
"MongoDB.Bson": "3.5.0",
|
||||
"SharpCompress": "0.41.0"
|
||||
},
|
||||
"runtime": {
|
||||
"StellaOps.Concelier.RawModels.dll": {}
|
||||
}
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"runtime": {
|
||||
"lib/net6.0/MongoDB.Bson.dll": {
|
||||
"assemblyVersion": "3.5.0.0",
|
||||
"fileVersion": "3.5.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"dependencies": {
|
||||
"ZstdSharp.Port": "0.8.6"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net8.0/SharpCompress.dll": {
|
||||
"assemblyVersion": "0.41.0.0",
|
||||
"fileVersion": "0.41.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"runtime": {
|
||||
"lib/net9.0/ZstdSharp.dll": {
|
||||
"assemblyVersion": "0.8.6.0",
|
||||
"fileVersion": "0.8.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"StellaOps.Concelier.RawModels/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"MongoDB.Bson/3.5.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
|
||||
"path": "mongodb.bson/3.5.0",
|
||||
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
|
||||
},
|
||||
"SharpCompress/0.41.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
|
||||
"path": "sharpcompress/0.41.0",
|
||||
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
|
||||
},
|
||||
"ZstdSharp.Port/0.8.6": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
|
||||
"path": "zstdsharp.port/0.8.6",
|
||||
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace StellaOps.Concelier.Storage.Postgres.Advisories;
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL advisory storage interface.
|
||||
/// This interface mirrors the MongoDB IAdvisoryStore but without MongoDB-specific parameters.
|
||||
/// This interface mirrors the IAdvisoryStore contract but without legacy-specific parameters.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used by connectors when configured to write to PostgreSQL storage.
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Storage.Postgres.Conversion;
|
||||
using MongoContracts = StellaOps.Concelier.Storage.Advisories;
|
||||
using AdvisoryContracts = StellaOps.Concelier.Storage.Advisories;
|
||||
using StellaOps.Concelier.Storage.Postgres.Models;
|
||||
using StellaOps.Concelier.Storage.Postgres.Repositories;
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace StellaOps.Concelier.Storage.Postgres.Advisories;
|
||||
/// <remarks>
|
||||
/// Tasks: PG-T5b.2.1, PG-T5b.2.2, PG-T5b.2.3 - Enables importers to write to PostgreSQL.
|
||||
/// </remarks>
|
||||
public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContracts.IAdvisoryStore
|
||||
public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, AdvisoryContracts.IAdvisoryStore
|
||||
{
|
||||
private readonly IAdvisoryRepository _advisoryRepository;
|
||||
private readonly IAdvisoryAliasRepository _aliasRepository;
|
||||
@@ -87,8 +87,8 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
|
||||
result.TotalChildEntities);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="MongoContracts.IAdvisoryStore.UpsertAsync" />
|
||||
Task MongoContracts.IAdvisoryStore.UpsertAsync(Advisory advisory, CancellationToken cancellationToken)
|
||||
/// <inheritdoc cref="AdvisoryContracts.IAdvisoryStore.UpsertAsync" />
|
||||
Task AdvisoryContracts.IAdvisoryStore.UpsertAsync(Advisory advisory, CancellationToken cancellationToken)
|
||||
=> UpsertAsync(advisory, sourceId: null, cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -106,7 +106,7 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
Task<Advisory?> MongoContracts.IAdvisoryStore.FindAsync(string advisoryKey, CancellationToken cancellationToken)
|
||||
Task<Advisory?> AdvisoryContracts.IAdvisoryStore.FindAsync(string advisoryKey, CancellationToken cancellationToken)
|
||||
=> FindAsync(advisoryKey, cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -128,7 +128,7 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
Task<IReadOnlyList<Advisory>> MongoContracts.IAdvisoryStore.GetRecentAsync(int limit, CancellationToken cancellationToken)
|
||||
Task<IReadOnlyList<Advisory>> AdvisoryContracts.IAdvisoryStore.GetRecentAsync(int limit, CancellationToken cancellationToken)
|
||||
=> GetRecentAsync(limit, cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -167,7 +167,7 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IAsyncEnumerable<Advisory> MongoContracts.IAdvisoryStore.StreamAsync(CancellationToken cancellationToken)
|
||||
IAsyncEnumerable<Advisory> AdvisoryContracts.IAdvisoryStore.StreamAsync(CancellationToken cancellationToken)
|
||||
=> StreamAsync(cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Text.Json;
|
||||
using StellaOps.Concelier.Documents;
|
||||
using StellaOps.Concelier.Documents.IO;
|
||||
using Contracts = StellaOps.Concelier.Storage.Contracts;
|
||||
using MongoContracts = StellaOps.Concelier.Storage;
|
||||
using LegacyContracts = StellaOps.Concelier.Storage;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres;
|
||||
|
||||
@@ -14,7 +14,7 @@ internal static class ContractsMappingExtensions
|
||||
OutputMode = JsonOutputMode.RelaxedExtendedJson
|
||||
};
|
||||
|
||||
internal static Contracts.StorageDocument ToStorageDocument(this MongoContracts.DocumentRecord record)
|
||||
internal static Contracts.StorageDocument ToStorageDocument(this LegacyContracts.DocumentRecord record)
|
||||
{
|
||||
return new Contracts.StorageDocument(
|
||||
record.Id,
|
||||
@@ -34,9 +34,9 @@ internal static class ContractsMappingExtensions
|
||||
record.FetchedAt);
|
||||
}
|
||||
|
||||
internal static MongoContracts.DocumentRecord ToMongoDocumentRecord(this Contracts.StorageDocument record)
|
||||
internal static LegacyContracts.DocumentRecord ToLegacyDocumentRecord(this Contracts.StorageDocument record)
|
||||
{
|
||||
return new MongoContracts.DocumentRecord(
|
||||
return new LegacyContracts.DocumentRecord(
|
||||
record.Id,
|
||||
record.SourceName,
|
||||
record.Uri,
|
||||
@@ -54,7 +54,7 @@ internal static class ContractsMappingExtensions
|
||||
record.FetchedAt);
|
||||
}
|
||||
|
||||
internal static Contracts.StorageDto ToStorageDto(this MongoContracts.DtoRecord record)
|
||||
internal static Contracts.StorageDto ToStorageDto(this LegacyContracts.DtoRecord record)
|
||||
{
|
||||
var json = record.Payload.ToJson(RelaxedJsonSettings);
|
||||
var payload = JsonDocument.Parse(json);
|
||||
@@ -69,22 +69,22 @@ internal static class ContractsMappingExtensions
|
||||
record.ValidatedAt);
|
||||
}
|
||||
|
||||
internal static MongoContracts.DtoRecord ToMongoDtoRecord(this Contracts.StorageDto record)
|
||||
internal static LegacyContracts.DtoRecord ToLegacyDtoRecord(this Contracts.StorageDto record)
|
||||
{
|
||||
var json = record.Payload.RootElement.GetRawText();
|
||||
var bson = DocumentObject.Parse(json);
|
||||
return new MongoContracts.DtoRecord(
|
||||
var doc = DocumentObject.Parse(json);
|
||||
return new LegacyContracts.DtoRecord(
|
||||
record.Id,
|
||||
record.DocumentId,
|
||||
record.SourceName,
|
||||
record.Format,
|
||||
bson,
|
||||
doc,
|
||||
record.CreatedAt,
|
||||
record.SchemaVersion,
|
||||
record.ValidatedAt);
|
||||
}
|
||||
|
||||
internal static Contracts.SourceCursorState ToStorageCursorState(this MongoContracts.SourceStateRecord record)
|
||||
internal static Contracts.SourceCursorState ToStorageCursorState(this LegacyContracts.SourceStateRecord record)
|
||||
{
|
||||
var cursorJson = record.Cursor is null ? null : record.Cursor.ToJson(RelaxedJsonSettings);
|
||||
var cursor = cursorJson is null ? null : JsonDocument.Parse(cursorJson);
|
||||
@@ -101,14 +101,14 @@ internal static class ContractsMappingExtensions
|
||||
record.LastFailureReason);
|
||||
}
|
||||
|
||||
internal static MongoContracts.SourceStateRecord ToMongoSourceStateRecord(this Contracts.SourceCursorState record)
|
||||
internal static LegacyContracts.SourceStateRecord ToLegacySourceStateRecord(this Contracts.SourceCursorState record)
|
||||
{
|
||||
var bsonCursor = record.Cursor is null ? null : DocumentObject.Parse(record.Cursor.RootElement.GetRawText());
|
||||
return new MongoContracts.SourceStateRecord(
|
||||
var docCursor = record.Cursor is null ? null : DocumentObject.Parse(record.Cursor.RootElement.GetRawText());
|
||||
return new LegacyContracts.SourceStateRecord(
|
||||
record.SourceName,
|
||||
record.Enabled,
|
||||
record.Paused,
|
||||
bsonCursor,
|
||||
docCursor,
|
||||
record.LastSuccess,
|
||||
record.LastFailure,
|
||||
record.FailCount,
|
||||
|
||||
@@ -3,7 +3,7 @@ using StellaOps.Concelier.Storage.Postgres.Models;
|
||||
namespace StellaOps.Concelier.Storage.Postgres.Conversion;
|
||||
|
||||
/// <summary>
|
||||
/// Result of converting a MongoDB advisory document to PostgreSQL entities.
|
||||
/// Result of converting an advisory document to PostgreSQL entities.
|
||||
/// Contains the main advisory entity and all related child entities.
|
||||
/// </summary>
|
||||
public sealed class AdvisoryConversionResult
|
||||
|
||||
@@ -70,7 +70,7 @@ public sealed class PostgresDocumentStore : IDocumentStore, Contracts.IStorageDo
|
||||
=> (await FindAsync(id, cancellationToken).ConfigureAwait(false))?.ToStorageDocument();
|
||||
|
||||
async Task<Contracts.StorageDocument> Contracts.IStorageDocumentStore.UpsertAsync(Contracts.StorageDocument record, CancellationToken cancellationToken)
|
||||
=> (await UpsertAsync(record.ToMongoDocumentRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDocument();
|
||||
=> (await UpsertAsync(record.ToLegacyDocumentRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDocument();
|
||||
|
||||
Task Contracts.IStorageDocumentStore.UpdateStatusAsync(Guid id, string status, CancellationToken cancellationToken)
|
||||
=> UpdateStatusAsync(id, status, cancellationToken);
|
||||
|
||||
@@ -96,7 +96,7 @@ internal sealed class PostgresDtoStore : IDtoStore, Contracts.IStorageDtoStore
|
||||
}
|
||||
|
||||
async Task<Contracts.StorageDto> Contracts.IStorageDtoStore.UpsertAsync(Contracts.StorageDto record, CancellationToken cancellationToken)
|
||||
=> (await UpsertAsync(record.ToMongoDtoRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDto();
|
||||
=> (await UpsertAsync(record.ToLegacyDtoRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDto();
|
||||
|
||||
async Task<Contracts.StorageDto?> Contracts.IStorageDtoStore.FindByDocumentIdAsync(Guid documentId, CancellationToken cancellationToken)
|
||||
=> (await FindByDocumentIdAsync(documentId, cancellationToken).ConfigureAwait(false))?.ToStorageDto();
|
||||
|
||||
@@ -5,12 +5,12 @@ using StellaOps.Concelier.Storage.Postgres.Advisories;
|
||||
using StellaOps.Infrastructure.Postgres;
|
||||
using StellaOps.Infrastructure.Postgres.Options;
|
||||
using StellaOps.Concelier.Core.Linksets;
|
||||
using MongoContracts = StellaOps.Concelier.Storage;
|
||||
using MongoAdvisories = StellaOps.Concelier.Storage.Advisories;
|
||||
using MongoExporting = StellaOps.Concelier.Storage.Exporting;
|
||||
using MongoJpFlags = StellaOps.Concelier.Storage.JpFlags;
|
||||
using MongoPsirt = StellaOps.Concelier.Storage.PsirtFlags;
|
||||
using MongoHistory = StellaOps.Concelier.Storage.ChangeHistory;
|
||||
using StorageContracts = StellaOps.Concelier.Storage;
|
||||
using AdvisoryContracts = StellaOps.Concelier.Storage.Advisories;
|
||||
using ExportingContracts = StellaOps.Concelier.Storage.Exporting;
|
||||
using JpFlagsContracts = StellaOps.Concelier.Storage.JpFlags;
|
||||
using PsirtContracts = StellaOps.Concelier.Storage.PsirtFlags;
|
||||
using HistoryContracts = StellaOps.Concelier.Storage.ChangeHistory;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres;
|
||||
|
||||
@@ -46,20 +46,20 @@ public static class ServiceCollectionExtensions
|
||||
services.AddScoped<IAdvisoryWeaknessRepository, AdvisoryWeaknessRepository>();
|
||||
services.AddScoped<IKevFlagRepository, KevFlagRepository>();
|
||||
services.AddScoped<StellaOps.Concelier.Storage.Postgres.Repositories.ISourceStateRepository, SourceStateRepository>();
|
||||
services.AddScoped<MongoAdvisories.IAdvisoryStore, PostgresAdvisoryStore>();
|
||||
services.AddScoped<AdvisoryContracts.IAdvisoryStore, PostgresAdvisoryStore>();
|
||||
services.AddScoped<IDocumentRepository, DocumentRepository>();
|
||||
services.AddScoped<MongoContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
|
||||
services.AddScoped<StorageContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
|
||||
services.AddScoped<IFeedSnapshotRepository, FeedSnapshotRepository>();
|
||||
services.AddScoped<IAdvisorySnapshotRepository, AdvisorySnapshotRepository>();
|
||||
services.AddScoped<IMergeEventRepository, MergeEventRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetStore, AdvisoryLinksetCacheRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetLookup>(sp => sp.GetRequiredService<IAdvisoryLinksetStore>());
|
||||
services.AddScoped<MongoContracts.IDocumentStore, PostgresDocumentStore>();
|
||||
services.AddScoped<MongoContracts.IDtoStore, PostgresDtoStore>();
|
||||
services.AddScoped<MongoExporting.IExportStateStore, PostgresExportStateStore>();
|
||||
services.AddScoped<MongoPsirt.IPsirtFlagStore, PostgresPsirtFlagStore>();
|
||||
services.AddScoped<MongoJpFlags.IJpFlagStore, PostgresJpFlagStore>();
|
||||
services.AddScoped<MongoHistory.IChangeHistoryStore, PostgresChangeHistoryStore>();
|
||||
services.AddScoped<StorageContracts.IDocumentStore, PostgresDocumentStore>();
|
||||
services.AddScoped<StorageContracts.IDtoStore, PostgresDtoStore>();
|
||||
services.AddScoped<ExportingContracts.IExportStateStore, PostgresExportStateStore>();
|
||||
services.AddScoped<PsirtContracts.IPsirtFlagStore, PostgresPsirtFlagStore>();
|
||||
services.AddScoped<JpFlagsContracts.IJpFlagStore, PostgresJpFlagStore>();
|
||||
services.AddScoped<HistoryContracts.IChangeHistoryStore, PostgresChangeHistoryStore>();
|
||||
|
||||
return services;
|
||||
}
|
||||
@@ -89,20 +89,20 @@ public static class ServiceCollectionExtensions
|
||||
services.AddScoped<IAdvisoryWeaknessRepository, AdvisoryWeaknessRepository>();
|
||||
services.AddScoped<IKevFlagRepository, KevFlagRepository>();
|
||||
services.AddScoped<StellaOps.Concelier.Storage.Postgres.Repositories.ISourceStateRepository, SourceStateRepository>();
|
||||
services.AddScoped<MongoAdvisories.IAdvisoryStore, PostgresAdvisoryStore>();
|
||||
services.AddScoped<AdvisoryContracts.IAdvisoryStore, PostgresAdvisoryStore>();
|
||||
services.AddScoped<IDocumentRepository, DocumentRepository>();
|
||||
services.AddScoped<MongoContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
|
||||
services.AddScoped<StorageContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
|
||||
services.AddScoped<IFeedSnapshotRepository, FeedSnapshotRepository>();
|
||||
services.AddScoped<IAdvisorySnapshotRepository, AdvisorySnapshotRepository>();
|
||||
services.AddScoped<IMergeEventRepository, MergeEventRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetStore, AdvisoryLinksetCacheRepository>();
|
||||
services.AddScoped<IAdvisoryLinksetLookup>(sp => sp.GetRequiredService<IAdvisoryLinksetStore>());
|
||||
services.AddScoped<MongoContracts.IDocumentStore, PostgresDocumentStore>();
|
||||
services.AddScoped<MongoContracts.IDtoStore, PostgresDtoStore>();
|
||||
services.AddScoped<MongoExporting.IExportStateStore, PostgresExportStateStore>();
|
||||
services.AddScoped<MongoPsirt.IPsirtFlagStore, PostgresPsirtFlagStore>();
|
||||
services.AddScoped<MongoJpFlags.IJpFlagStore, PostgresJpFlagStore>();
|
||||
services.AddScoped<MongoHistory.IChangeHistoryStore, PostgresChangeHistoryStore>();
|
||||
services.AddScoped<StorageContracts.IDocumentStore, PostgresDocumentStore>();
|
||||
services.AddScoped<StorageContracts.IDtoStore, PostgresDtoStore>();
|
||||
services.AddScoped<ExportingContracts.IExportStateStore, PostgresExportStateStore>();
|
||||
services.AddScoped<PsirtContracts.IPsirtFlagStore, PostgresPsirtFlagStore>();
|
||||
services.AddScoped<JpFlagsContracts.IJpFlagStore, PostgresJpFlagStore>();
|
||||
services.AddScoped<HistoryContracts.IChangeHistoryStore, PostgresChangeHistoryStore>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ using StellaOps.Concelier.Documents;
|
||||
using StellaOps.Concelier.Storage.Postgres.Models;
|
||||
using StellaOps.Concelier.Storage.Postgres.Repositories;
|
||||
using Contracts = StellaOps.Concelier.Storage.Contracts;
|
||||
using MongoContracts = StellaOps.Concelier.Storage;
|
||||
using LegacyContracts = StellaOps.Concelier.Storage;
|
||||
|
||||
namespace StellaOps.Concelier.Storage.Postgres;
|
||||
|
||||
/// <summary>
|
||||
/// Adapter that satisfies the legacy source state contract using PostgreSQL storage and provides a Postgres-native cursor contract.
|
||||
/// </summary>
|
||||
public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepository, Contracts.ISourceStateStore
|
||||
public sealed class PostgresSourceStateAdapter : LegacyContracts.ISourceStateRepository, Contracts.ISourceStateStore
|
||||
{
|
||||
private readonly ISourceRepository _sourceRepository;
|
||||
private readonly Repositories.ISourceStateRepository _stateRepository;
|
||||
@@ -28,7 +28,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
public async Task<MongoContracts.SourceStateRecord?> TryGetAsync(string sourceName, CancellationToken cancellationToken)
|
||||
public async Task<LegacyContracts.SourceStateRecord?> TryGetAsync(string sourceName, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(sourceName);
|
||||
|
||||
@@ -46,7 +46,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
|
||||
|
||||
var cursor = string.IsNullOrWhiteSpace(state.Cursor) ? null : DocumentObject.Parse(state.Cursor);
|
||||
var backoffUntil = TryParseBackoffUntil(state.Metadata);
|
||||
return new MongoContracts.SourceStateRecord(
|
||||
return new LegacyContracts.SourceStateRecord(
|
||||
sourceName,
|
||||
Enabled: true,
|
||||
Paused: false,
|
||||
@@ -115,7 +115,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
|
||||
_ = await _stateRepository.UpsertAsync(entity, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task UpsertAsync(MongoContracts.SourceStateRecord record, CancellationToken cancellationToken)
|
||||
public async Task UpsertAsync(LegacyContracts.SourceStateRecord record, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(record);
|
||||
var source = await EnsureSourceAsync(record.SourceName, cancellationToken).ConfigureAwait(false);
|
||||
@@ -146,7 +146,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
|
||||
=> MarkFailureAsync(sourceName, now, backoff, reason, cancellationToken);
|
||||
|
||||
Task Contracts.ISourceStateStore.UpsertAsync(Contracts.SourceCursorState record, CancellationToken cancellationToken)
|
||||
=> UpsertAsync(record.ToMongoSourceStateRecord(), cancellationToken);
|
||||
=> UpsertAsync(record.ToLegacySourceStateRecord(), cancellationToken);
|
||||
|
||||
private async Task<SourceEntity> EnsureSourceAsync(string sourceName, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace StellaOps.Concelier.Connector.Common.Tests;
|
||||
public sealed class SourceFetchServiceGuardTests : IAsyncLifetime
|
||||
{
|
||||
private readonly InMemoryDbRunner _runner;
|
||||
private readonly IMongoDatabase _database;
|
||||
private readonly IStorageDatabase _database;
|
||||
private readonly RawDocumentStorage _rawStorage;
|
||||
private readonly ICryptoHash _hash;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public sealed class SourceStateSeedProcessorTests : IAsyncLifetime
|
||||
{
|
||||
private readonly InMemoryDbRunner _runner;
|
||||
private readonly InMemoryClient _client;
|
||||
private readonly IMongoDatabase _database;
|
||||
private readonly IStorageDatabase _database;
|
||||
private readonly DocumentStore _documentStore;
|
||||
private readonly RawDocumentStorage _rawStorage;
|
||||
private readonly InMemorySourceStateRepository _stateRepository;
|
||||
|
||||
@@ -52,7 +52,7 @@ public sealed class TimeWindowCursorPlannerTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TimeWindowCursorState_RoundTripThroughBson()
|
||||
public void TimeWindowCursorState_RoundTripThroughDocument()
|
||||
{
|
||||
var state = new TimeWindowCursorState(
|
||||
new DateTimeOffset(2024, 9, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
|
||||
@@ -480,7 +480,7 @@ public sealed class RedHatConnectorTests : IAsyncLifetime
|
||||
var json = File.ReadAllText(jsonPath);
|
||||
|
||||
using var jsonDocument = JsonDocument.Parse(json);
|
||||
var bson = DocumentObject.Parse(json);
|
||||
var doc = DocumentObject.Parse(json);
|
||||
|
||||
var metadata = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
@@ -501,7 +501,7 @@ public sealed class RedHatConnectorTests : IAsyncLifetime
|
||||
LastModified: fixture.ValidatedAt,
|
||||
PayloadId: null);
|
||||
|
||||
var dto = new DtoRecord(Guid.NewGuid(), document.Id, RedHatConnectorPlugin.SourceName, "redhat.csaf.v2", bson, fixture.ValidatedAt);
|
||||
var dto = new DtoRecord(Guid.NewGuid(), document.Id, RedHatConnectorPlugin.SourceName, "redhat.csaf.v2", doc, fixture.ValidatedAt);
|
||||
|
||||
var advisory = RedHatMapper.Map(RedHatConnectorPlugin.SourceName, dto, document, jsonDocument);
|
||||
Assert.NotNull(advisory);
|
||||
|
||||
@@ -56,7 +56,7 @@ public sealed class RuBduConnectorSnapshotTests : IAsyncLifetime
|
||||
var stateRepository = harness.ServiceProvider.GetRequiredService<ISourceStateRepository>();
|
||||
var initialState = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(initialState);
|
||||
var cursorBeforeParse = initialState!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(initialState.Cursor);
|
||||
var cursorBeforeParse = initialState!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromDocument(initialState.Cursor);
|
||||
Assert.NotEmpty(cursorBeforeParse.PendingDocuments);
|
||||
var expectedDocumentIds = cursorBeforeParse.PendingDocuments.ToArray();
|
||||
|
||||
@@ -217,7 +217,7 @@ public sealed class RuBduConnectorSnapshotTests : IAsyncLifetime
|
||||
var state = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(state);
|
||||
|
||||
var cursor = state!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(state.Cursor);
|
||||
var cursor = state!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromDocument(state.Cursor);
|
||||
var snapshot = new
|
||||
{
|
||||
PendingDocuments = cursor.PendingDocuments.Select(static guid => guid.ToString()).OrderBy(static id => id, StringComparer.Ordinal).ToArray(),
|
||||
|
||||
@@ -89,17 +89,17 @@ public sealed class StellaOpsMirrorConnectorTests : IAsyncLifetime
|
||||
Assert.NotNull(state);
|
||||
|
||||
var cursorDocument = state!.Cursor ?? new DocumentObject();
|
||||
var digestValue = cursorDocument.TryGetValue("bundleDigest", out var digestBson) ? digestBson.AsString : string.Empty;
|
||||
var digestValue = cursorDocument.TryGetValue("bundleDigest", out var digestDoc) ? digestDoc.AsString : string.Empty;
|
||||
Assert.Equal(NormalizeDigest(bundleDigest), NormalizeDigest(digestValue));
|
||||
|
||||
var pendingDocumentsArray = cursorDocument.TryGetValue("pendingDocuments", out var pendingDocsBson) && pendingDocsBson is DocumentArray pendingArray
|
||||
var pendingDocumentsArray = cursorDocument.TryGetValue("pendingDocuments", out var pendingDocsDoc) && pendingDocsDoc is DocumentArray pendingArray
|
||||
? pendingArray
|
||||
: new DocumentArray();
|
||||
Assert.Single(pendingDocumentsArray);
|
||||
var pendingDocumentId = Guid.Parse(pendingDocumentsArray[0].AsString);
|
||||
Assert.Equal(bundleDocument.Id, pendingDocumentId);
|
||||
|
||||
var pendingMappingsArray = cursorDocument.TryGetValue("pendingMappings", out var pendingMappingsBson) && pendingMappingsBson is DocumentArray mappingsArray
|
||||
var pendingMappingsArray = cursorDocument.TryGetValue("pendingMappings", out var pendingMappingsDoc) && pendingMappingsDoc is DocumentArray mappingsArray
|
||||
? mappingsArray
|
||||
: new DocumentArray();
|
||||
Assert.Empty(pendingMappingsArray);
|
||||
|
||||
@@ -143,7 +143,7 @@ public sealed class OracleConnectorTests : IAsyncLifetime
|
||||
var stateRepository = provider.GetRequiredService<ISourceStateRepository>();
|
||||
var state = await stateRepository.TryGetAsync(VndrOracleConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(state);
|
||||
var cursor = OracleCursor.FromBson(state!.Cursor);
|
||||
var cursor = OracleCursor.FromDocument(state!.Cursor);
|
||||
Assert.Empty(cursor.PendingDocuments);
|
||||
Assert.Empty(cursor.PendingMappings);
|
||||
Assert.Equal(2, cursor.FetchCache.Count);
|
||||
@@ -250,7 +250,7 @@ public sealed class OracleConnectorTests : IAsyncLifetime
|
||||
var stateRepository = provider.GetRequiredService<ISourceStateRepository>();
|
||||
var state = await stateRepository.TryGetAsync(VndrOracleConnectorPlugin.SourceName, CancellationToken.None);
|
||||
Assert.NotNull(state);
|
||||
var cursor = OracleCursor.FromBson(state!.Cursor);
|
||||
var cursor = OracleCursor.FromDocument(state!.Cursor);
|
||||
Assert.Empty(cursor.PendingDocuments);
|
||||
Assert.Empty(cursor.PendingMappings);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public sealed class VmwareConnectorTests : IAsyncLifetime
|
||||
Assert.NotNull(state);
|
||||
Assert.Empty(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray : new DocumentArray());
|
||||
Assert.Empty(state.Cursor.TryGetValue("pendingMappings", out var pendingMaps) ? pendingMaps.AsDocumentArray : new DocumentArray());
|
||||
var cursorSnapshot = VmwareCursor.FromBson(state.Cursor);
|
||||
var cursorSnapshot = VmwareCursor.FromDocument(state.Cursor);
|
||||
_output.WriteLine($"Initial fetch cache entries: {cursorSnapshot.FetchCache.Count}");
|
||||
foreach (var entry in cursorSnapshot.FetchCache)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ public sealed class MergePrecedenceIntegrationTests : IAsyncLifetime
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
// {
|
||||
// await _fixture.Database.DropCollectionAsync(MongoStorageDefaults.Collections.MergeEvent);
|
||||
// await _fixture.Database.DropCollectionAsync(StorageDefaults.Collections.MergeEvent);
|
||||
// }
|
||||
// catch (StorageCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
|
||||
@@ -16,12 +16,12 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
|
||||
public HealthWebAppFactory()
|
||||
{
|
||||
// Ensure options binder sees required storage values before Program.Main executes.
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "mongodb://localhost:27017/test-health");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "mongo");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "Host=localhost;Port=5432;Database=test-health");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "postgres");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__COMMANDTIMEOUTSECONDS", "30");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__TELEMETRY__ENABLED", "false");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_SKIP_OPTIONS_VALIDATION", "1");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "mongodb://localhost:27017/test-health");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "Host=localhost;Port=5432;Database=test-health");
|
||||
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Testing");
|
||||
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Testing");
|
||||
}
|
||||
@@ -32,8 +32,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
var overrides = new Dictionary<string, string?>
|
||||
{
|
||||
{"Storage:Dsn", "mongodb://localhost:27017/test-health"},
|
||||
{"Storage:Driver", "mongo"},
|
||||
{"Storage:Dsn", "Host=localhost;Port=5432;Database=test-health"},
|
||||
{"Storage:Driver", "postgres"},
|
||||
{"Storage:CommandTimeoutSeconds", "30"},
|
||||
{"Telemetry:Enabled", "false"}
|
||||
};
|
||||
@@ -41,8 +41,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
|
||||
config.AddInMemoryCollection(overrides);
|
||||
});
|
||||
|
||||
builder.UseSetting("CONCELIER__STORAGE__DSN", "mongodb://localhost:27017/test-health");
|
||||
builder.UseSetting("CONCELIER__STORAGE__DRIVER", "mongo");
|
||||
builder.UseSetting("CONCELIER__STORAGE__DSN", "Host=localhost;Port=5432;Database=test-health");
|
||||
builder.UseSetting("CONCELIER__STORAGE__DRIVER", "postgres");
|
||||
builder.UseSetting("CONCELIER__STORAGE__COMMANDTIMEOUTSECONDS", "30");
|
||||
builder.UseSetting("CONCELIER__TELEMETRY__ENABLED", "false");
|
||||
|
||||
@@ -54,8 +54,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
Storage = new ConcelierOptions.StorageOptions
|
||||
{
|
||||
Dsn = "mongodb://localhost:27017/test-health",
|
||||
Driver = "mongo",
|
||||
Dsn = "Host=localhost;Port=5432;Database=test-health",
|
||||
Driver = "postgres",
|
||||
CommandTimeoutSeconds = 30
|
||||
},
|
||||
Telemetry = new ConcelierOptions.TelemetryOptions
|
||||
@@ -67,8 +67,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
|
||||
services.AddSingleton<IConfigureOptions<ConcelierOptions>>(sp => new ConfigureOptions<ConcelierOptions>(opts =>
|
||||
{
|
||||
opts.Storage ??= new ConcelierOptions.StorageOptions();
|
||||
opts.Storage.Driver = "mongo";
|
||||
opts.Storage.Dsn = "mongodb://localhost:27017/test-health";
|
||||
opts.Storage.Driver = "postgres";
|
||||
opts.Storage.Dsn = "Host=localhost;Port=5432;Database=test-health";
|
||||
opts.Storage.CommandTimeoutSeconds = 30;
|
||||
|
||||
opts.Telemetry ??= new ConcelierOptions.TelemetryOptions();
|
||||
@@ -77,8 +77,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
|
||||
services.PostConfigure<ConcelierOptions>(opts =>
|
||||
{
|
||||
opts.Storage ??= new ConcelierOptions.StorageOptions();
|
||||
opts.Storage.Driver = "mongo";
|
||||
opts.Storage.Dsn = "mongodb://localhost:27017/test-health";
|
||||
opts.Storage.Driver = "postgres";
|
||||
opts.Storage.Dsn = "Host=localhost;Port=5432;Database=test-health";
|
||||
opts.Storage.CommandTimeoutSeconds = 30;
|
||||
|
||||
opts.Telemetry ??= new ConcelierOptions.TelemetryOptions();
|
||||
|
||||
@@ -5,7 +5,7 @@ using StellaOps.Concelier.Documents.Serialization.Attributes;
|
||||
namespace StellaOps.Concelier.WebService.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Minimal linkset document used only for seeding the Mongo collection in WebService integration tests.
|
||||
/// Minimal linkset document used for seeding the storage in WebService integration tests.
|
||||
/// Matches the shape written by the linkset ingestion pipeline.
|
||||
/// </summary>
|
||||
internal sealed class AdvisoryLinksetDocument
|
||||
|
||||
@@ -22,14 +22,14 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
|
||||
{
|
||||
public OrchestratorTestWebAppFactory()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "mongodb://localhost:27017/orch-tests");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "mongo");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "Host=localhost;Port=5432;Database=orch-tests");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "postgres");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__COMMANDTIMEOUTSECONDS", "30");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__TELEMETRY__ENABLED", "false");
|
||||
Environment.SetEnvironmentVariable("CONCELIER__AUTHORITY__ENABLED", "false"); // disable auth so tests can hit endpoints without tokens
|
||||
Environment.SetEnvironmentVariable("CONCELIER_SKIP_OPTIONS_VALIDATION", "1");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "mongodb://localhost:27017/orch-tests");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_BYPASS_MONGO", "1");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "Host=localhost;Port=5432;Database=orch-tests");
|
||||
Environment.SetEnvironmentVariable("CONCELIER_BYPASS_EXTERNAL_STORAGE", "1");
|
||||
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Testing");
|
||||
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Testing");
|
||||
}
|
||||
@@ -42,8 +42,8 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
|
||||
{
|
||||
cfg.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Concelier:Storage:Dsn"] = "mongodb://localhost:27017/orch-tests",
|
||||
["Concelier:Storage:Driver"] = "mongo",
|
||||
["Concelier:Storage:Dsn"] = "Host=localhost;Port=5432;Database=orch-tests",
|
||||
["Concelier:Storage:Driver"] = "postgres",
|
||||
["Concelier:Storage:CommandTimeoutSeconds"] = "30",
|
||||
["Concelier:Telemetry:Enabled"] = "false",
|
||||
["Concelier:Authority:Enabled"] = "false"
|
||||
@@ -62,8 +62,8 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
|
||||
{
|
||||
Storage = new ConcelierOptions.StorageOptions
|
||||
{
|
||||
Dsn = "mongodb://localhost:27017/orch-tests",
|
||||
Driver = "mongo",
|
||||
Dsn = "Host=localhost;Port=5432;Database=orch-tests",
|
||||
Driver = "postgres",
|
||||
CommandTimeoutSeconds = 30
|
||||
},
|
||||
Telemetry = new ConcelierOptions.TelemetryOptions
|
||||
@@ -78,10 +78,10 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
|
||||
services.AddSingleton(forcedOptions);
|
||||
services.AddSingleton<IOptions<ConcelierOptions>>(_ => Microsoft.Extensions.Options.Options.Create(forcedOptions));
|
||||
|
||||
// Force Mongo storage options to a deterministic in-memory test DSN.
|
||||
// Force storage options to a deterministic in-memory test DSN.
|
||||
services.PostConfigure<StorageOptions>(opts =>
|
||||
{
|
||||
opts.ConnectionString = "mongodb://localhost:27017/orch-tests";
|
||||
opts.ConnectionString = "Host=localhost;Port=5432;Database=orch-tests";
|
||||
opts.DatabaseName = "orch-tests";
|
||||
opts.CommandTimeout = TimeSpan.FromSeconds(30);
|
||||
});
|
||||
|
||||
@@ -64,8 +64,6 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
|
||||
private readonly ITestOutputHelper _output;
|
||||
private InMemoryDbRunner _runner = null!;
|
||||
private Process? _externalMongo;
|
||||
private string? _externalMongoDataPath;
|
||||
private ConcelierApplicationFactory _factory = null!;
|
||||
|
||||
public WebServiceEndpointsTests(ITestOutputHelper output)
|
||||
@@ -1735,12 +1733,12 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
private async Task SeedObservationDocumentsAsync(IEnumerable<AdvisoryObservationDocument> documents)
|
||||
{
|
||||
var client = new InMemoryClient(_runner.ConnectionString);
|
||||
var database = client.GetDatabase(MongoStorageDefaults.DefaultDatabaseName);
|
||||
var collection = database.GetCollection<AdvisoryObservationDocument>(MongoStorageDefaults.Collections.AdvisoryObservations);
|
||||
var database = client.GetDatabase(StorageDefaults.DefaultDatabaseName);
|
||||
var collection = database.GetCollection<AdvisoryObservationDocument>(StorageDefaults.Collections.AdvisoryObservations);
|
||||
|
||||
try
|
||||
{
|
||||
await database.DropCollectionAsync(MongoStorageDefaults.Collections.AdvisoryObservations);
|
||||
await database.DropCollectionAsync(StorageDefaults.Collections.AdvisoryObservations);
|
||||
}
|
||||
catch (StorageCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -1771,12 +1769,12 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
private async Task SeedLinksetDocumentsAsync(IEnumerable<AdvisoryLinksetDocument> documents)
|
||||
{
|
||||
var client = new InMemoryClient(_runner.ConnectionString);
|
||||
var database = client.GetDatabase(MongoStorageDefaults.DefaultDatabaseName);
|
||||
var collection = database.GetCollection<AdvisoryLinksetDocument>(MongoStorageDefaults.Collections.AdvisoryLinksets);
|
||||
var database = client.GetDatabase(StorageDefaults.DefaultDatabaseName);
|
||||
var collection = database.GetCollection<AdvisoryLinksetDocument>(StorageDefaults.Collections.AdvisoryLinksets);
|
||||
|
||||
try
|
||||
{
|
||||
await database.DropCollectionAsync(MongoStorageDefaults.Collections.AdvisoryLinksets);
|
||||
await database.DropCollectionAsync(StorageDefaults.Collections.AdvisoryLinksets);
|
||||
}
|
||||
catch (StorageCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -2004,7 +2002,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
IDictionary<string, string?>? environmentOverrides = null)
|
||||
{
|
||||
var defaultPostgresDsn = "Host=localhost;Port=5432;Database=concelier_test;Username=postgres;Password=postgres";
|
||||
_connectionString = string.IsNullOrWhiteSpace(connectionString) || connectionString.StartsWith("mongodb://", StringComparison.OrdinalIgnoreCase)
|
||||
_connectionString = string.IsNullOrWhiteSpace(connectionString)
|
||||
? defaultPostgresDsn
|
||||
: connectionString;
|
||||
_authorityConfigure = authorityConfigure;
|
||||
@@ -2098,7 +2096,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
services.AddSingleton<IJobCoordinator>(sp => sp.GetRequiredService<StubJobCoordinator>());
|
||||
services.PostConfigure<ConcelierOptions>(options =>
|
||||
{
|
||||
options.Storage.Driver = "mongo";
|
||||
options.Storage.Driver = "postgres";
|
||||
options.Storage.Dsn = _connectionString;
|
||||
options.Storage.CommandTimeoutSeconds = 30;
|
||||
options.Plugins.Directory ??= Path.Combine(AppContext.BaseDirectory, "StellaOps.Concelier.PluginBinaries");
|
||||
@@ -2362,8 +2360,8 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
|
||||
|
||||
using var validationScope = _factory.Services.CreateScope();
|
||||
var database = validationScope.ServiceProvider.GetRequiredService<IMongoDatabase>();
|
||||
var statements = database.GetCollection<DocumentObject>(MongoStorageDefaults.Collections.AdvisoryStatements);
|
||||
var database = validationScope.ServiceProvider.GetRequiredService<IStorageDatabase>();
|
||||
var statements = database.GetCollection<DocumentObject>(StorageDefaults.Collections.AdvisoryStatements);
|
||||
|
||||
var stored = await statements
|
||||
.Find(Builders<DocumentObject>.Filter.Eq("_id", statementId.ToString()))
|
||||
@@ -2379,8 +2377,8 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
finally
|
||||
{
|
||||
using var cleanupScope = _factory.Services.CreateScope();
|
||||
var database = cleanupScope.ServiceProvider.GetRequiredService<IMongoDatabase>();
|
||||
var statements = database.GetCollection<DocumentObject>(MongoStorageDefaults.Collections.AdvisoryStatements);
|
||||
var database = cleanupScope.ServiceProvider.GetRequiredService<IStorageDatabase>();
|
||||
var statements = database.GetCollection<DocumentObject>(StorageDefaults.Collections.AdvisoryStatements);
|
||||
await statements.DeleteOneAsync(Builders<DocumentObject>.Filter.Eq("_id", statementId.ToString()));
|
||||
}
|
||||
}
|
||||
@@ -2461,10 +2459,10 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
private async Task SeedCanonicalAdvisoriesAsync(params Advisory[] advisories)
|
||||
{
|
||||
using var scope = _factory.Services.CreateScope();
|
||||
var database = scope.ServiceProvider.GetRequiredService<IMongoDatabase>();
|
||||
var database = scope.ServiceProvider.GetRequiredService<IStorageDatabase>();
|
||||
|
||||
await DropCollectionIfExistsAsync(database, MongoStorageDefaults.Collections.Advisory);
|
||||
await DropCollectionIfExistsAsync(database, MongoStorageDefaults.Collections.Alias);
|
||||
await DropCollectionIfExistsAsync(database, StorageDefaults.Collections.Advisory);
|
||||
await DropCollectionIfExistsAsync(database, StorageDefaults.Collections.Alias);
|
||||
|
||||
if (advisories.Length == 0)
|
||||
{
|
||||
@@ -2478,7 +2476,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task DropCollectionIfExistsAsync(IMongoDatabase database, string collectionName)
|
||||
private static async Task DropCollectionIfExistsAsync(IStorageDatabase database, string collectionName)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -2576,8 +2574,8 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
private async Task SeedAdvisoryRawDocumentsAsync(params DocumentObject[] documents)
|
||||
{
|
||||
var client = new InMemoryClient(_runner.ConnectionString);
|
||||
var database = client.GetDatabase(MongoStorageDefaults.DefaultDatabaseName);
|
||||
var collection = database.GetCollection<DocumentObject>(MongoStorageDefaults.Collections.AdvisoryRaw);
|
||||
var database = client.GetDatabase(StorageDefaults.DefaultDatabaseName);
|
||||
var collection = database.GetCollection<DocumentObject>(StorageDefaults.Collections.AdvisoryRaw);
|
||||
await collection.DeleteManyAsync(FilterDefinition<DocumentObject>.Empty);
|
||||
if (documents.Length > 0)
|
||||
{
|
||||
@@ -2705,252 +2703,6 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
|
||||
using var client = factory.CreateClient();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure Mongo2Go can start without external downloads by pointing it to cached binaries and OpenSSL 1.1 libs shipped in repo.
|
||||
/// </summary>
|
||||
private static void PrepareMongoEnvironment()
|
||||
{
|
||||
var repoRoot = FindRepoRoot();
|
||||
if (repoRoot is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var cacheDir = Path.Combine(repoRoot, ".cache", "mongodb-local");
|
||||
Directory.CreateDirectory(cacheDir);
|
||||
Environment.SetEnvironmentVariable("MONGO2GO_CACHE_LOCATION", cacheDir);
|
||||
Environment.SetEnvironmentVariable("MONGO2GO_DOWNLOADS", cacheDir);
|
||||
Environment.SetEnvironmentVariable("MONGO2GO_MONGODB_VERSION", "4.4.4");
|
||||
Environment.SetEnvironmentVariable("MONGO2GO_MONGODB_PLATFORM", "linux");
|
||||
|
||||
var opensslPath = Path.Combine(repoRoot, "tests", "native", "openssl-1.1", "linux-x64");
|
||||
if (Directory.Exists(opensslPath))
|
||||
{
|
||||
// Prepend OpenSSL 1.1 path so Mongo2Go binaries find libssl/libcrypto.
|
||||
var existing = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
|
||||
var combined = string.IsNullOrEmpty(existing) ? opensslPath : $"{opensslPath}:{existing}";
|
||||
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", combined);
|
||||
}
|
||||
|
||||
// Also drop the OpenSSL libs next to the mongod binary Mongo2Go will spawn, in case LD_LIBRARY_PATH is ignored.
|
||||
var repoNuget = Path.Combine(repoRoot, ".nuget", "packages", "mongo2go");
|
||||
var homeNuget = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages", "mongo2go");
|
||||
var mongoBin = Directory.Exists(repoNuget)
|
||||
? Directory.GetFiles(repoNuget, "mongod", SearchOption.AllDirectories)
|
||||
.FirstOrDefault(path => path.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase))
|
||||
: null;
|
||||
|
||||
// Prefer globally cached Mongo2Go binaries if repo-local cache is missing.
|
||||
mongoBin ??= Directory.Exists(homeNuget)
|
||||
? Directory.GetFiles(homeNuget, "mongod", SearchOption.AllDirectories)
|
||||
.FirstOrDefault(path => path.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase))
|
||||
: null;
|
||||
|
||||
if (mongoBin is not null && File.Exists(mongoBin) && Directory.Exists(opensslPath))
|
||||
{
|
||||
var binDir = Path.GetDirectoryName(mongoBin)!;
|
||||
|
||||
// Create a tiny wrapper so the loader always gets LD_LIBRARY_PATH even if vstest strips it.
|
||||
var wrapperPath = Path.Combine(cacheDir, "mongod-wrapper.sh");
|
||||
Directory.CreateDirectory(cacheDir);
|
||||
var script = $"#!/usr/bin/env bash\nset -euo pipefail\nexport LD_LIBRARY_PATH=\"{opensslPath}:${{LD_LIBRARY_PATH:-}}\"\nexec \"{mongoBin}\" \"$@\"\n";
|
||||
File.WriteAllText(wrapperPath, script);
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
try
|
||||
{
|
||||
File.SetUnixFileMode(wrapperPath,
|
||||
UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
|
||||
UnixFileMode.GroupRead | UnixFileMode.GroupExecute |
|
||||
UnixFileMode.OtherRead | UnixFileMode.OtherExecute);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Best-effort; if not supported, chmod will fall back to default permissions.
|
||||
}
|
||||
}
|
||||
|
||||
// Force Mongo2Go to use the wrapper to avoid downloads and inject OpenSSL search path.
|
||||
Environment.SetEnvironmentVariable("MONGO2GO_MONGODB_BINARY", wrapperPath);
|
||||
|
||||
// Keep direct LD_LIBRARY_PATH/PATH hints for any code paths that still honour parent env.
|
||||
var existing = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
|
||||
var combined = string.IsNullOrEmpty(existing) ? binDir : $"{binDir}:{existing}";
|
||||
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", combined);
|
||||
Environment.SetEnvironmentVariable("PATH", $"{binDir}:{Environment.GetEnvironmentVariable("PATH")}");
|
||||
|
||||
foreach (var libName in new[] { "libssl.so.1.1", "libcrypto.so.1.1" })
|
||||
{
|
||||
var target = Path.Combine(binDir, libName);
|
||||
var source = Path.Combine(opensslPath, libName);
|
||||
if (File.Exists(source) && !File.Exists(target))
|
||||
{
|
||||
File.Copy(source, target);
|
||||
}
|
||||
}
|
||||
|
||||
// If the Mongo2Go global cache is different from the first hit, add its bin dir too.
|
||||
var globalBin = Directory.Exists(homeNuget)
|
||||
? Directory.GetFiles(homeNuget, "mongod", SearchOption.AllDirectories)
|
||||
.FirstOrDefault(path => path.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase))
|
||||
: null;
|
||||
if (globalBin is not null)
|
||||
{
|
||||
var globalDir = Path.GetDirectoryName(globalBin)!;
|
||||
var withGlobal = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH") ?? string.Empty;
|
||||
if (!withGlobal.Split(':', StringSplitOptions.RemoveEmptyEntries).Contains(globalDir))
|
||||
{
|
||||
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", $"{globalDir}:{withGlobal}".TrimEnd(':'));
|
||||
}
|
||||
Environment.SetEnvironmentVariable("PATH", $"{globalDir}:{Environment.GetEnvironmentVariable("PATH")}");
|
||||
foreach (var libName in new[] { "libssl.so.1.1", "libcrypto.so.1.1" })
|
||||
{
|
||||
var target = Path.Combine(globalDir, libName);
|
||||
var source = Path.Combine(opensslPath, libName);
|
||||
if (File.Exists(source) && !File.Exists(target))
|
||||
{
|
||||
File.Copy(source, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryStartExternalMongo(out string? connectionString)
|
||||
{
|
||||
connectionString = null;
|
||||
|
||||
var repoRoot = FindRepoRoot();
|
||||
if (repoRoot is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var mongodCandidates = new List<string>();
|
||||
void AddCandidates(string root)
|
||||
{
|
||||
if (Directory.Exists(root))
|
||||
{
|
||||
mongodCandidates.AddRange(Directory.GetFiles(root, "mongod", SearchOption.AllDirectories)
|
||||
.Where(p => p.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
}
|
||||
|
||||
AddCandidates(Path.Combine(repoRoot, ".nuget", "packages", "mongo2go"));
|
||||
AddCandidates(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages", "mongo2go"));
|
||||
|
||||
var mongodPath = mongodCandidates.FirstOrDefault();
|
||||
if (mongodPath is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dataDir = Path.Combine(repoRoot, ".cache", "mongodb-local", $"manual-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(dataDir);
|
||||
|
||||
var opensslPath = Path.Combine(repoRoot, "tests", "native", "openssl-1.1", "linux-x64");
|
||||
var port = GetEphemeralPort();
|
||||
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = mongodPath,
|
||||
ArgumentList =
|
||||
{
|
||||
"--dbpath", dataDir,
|
||||
"--bind_ip", "127.0.0.1",
|
||||
"--port", port.ToString(),
|
||||
"--nojournal",
|
||||
"--quiet",
|
||||
"--replSet", "rs0"
|
||||
},
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true
|
||||
};
|
||||
|
||||
var existingLd = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
|
||||
var ldCombined = string.IsNullOrEmpty(existingLd) ? opensslPath : $"{opensslPath}:{existingLd}";
|
||||
psi.Environment["LD_LIBRARY_PATH"] = ldCombined;
|
||||
psi.Environment["PATH"] = $"{Path.GetDirectoryName(mongodPath)}:{Environment.GetEnvironmentVariable("PATH")}";
|
||||
|
||||
_externalMongo = Process.Start(psi);
|
||||
_externalMongoDataPath = dataDir;
|
||||
|
||||
if (_externalMongo is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Small ping loop to ensure mongod is ready
|
||||
var client = new InMemoryClient($"mongodb://127.0.0.1:{port}");
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
while (sw.Elapsed < TimeSpan.FromSeconds(5))
|
||||
{
|
||||
try
|
||||
{
|
||||
client.GetDatabase("admin").RunCommand<DocumentObject>("{ ping: 1 }");
|
||||
// Initiate single-node replica set so features expecting replset work.
|
||||
client.GetDatabase("admin").RunCommand<DocumentObject>(DocumentObject.Parse("{ replSetInitiate: { _id: \"rs0\", members: [ { _id: 0, host: \"127.0.0.1:" + port + "\" } ] } }"));
|
||||
// Wait for primary
|
||||
var readySw = System.Diagnostics.Stopwatch.StartNew();
|
||||
while (readySw.Elapsed < TimeSpan.FromSeconds(5))
|
||||
{
|
||||
var status = client.GetDatabase("admin").RunCommand<DocumentObject>(DocumentObject.Parse("{ replSetGetStatus: 1 }"));
|
||||
var myState = status["members"].AsDocumentArray.FirstOrDefault(x => x["self"].AsBoolean);
|
||||
if (myState != null && myState["state"].ToInt32() == 1)
|
||||
{
|
||||
connectionString = $"mongodb://127.0.0.1:{port}/?replicaSet=rs0";
|
||||
return true;
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
// fallback if primary not reached
|
||||
connectionString = $"mongodb://127.0.0.1:{port}";
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
try { _externalMongo.Kill(true); } catch { /* ignore */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int GetEphemeralPort()
|
||||
{
|
||||
var listener = new System.Net.Sockets.TcpListener(IPAddress.Loopback, 0);
|
||||
listener.Start();
|
||||
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
listener.Stop();
|
||||
return port;
|
||||
}
|
||||
|
||||
private static string? FindRepoRoot()
|
||||
{
|
||||
var current = AppContext.BaseDirectory;
|
||||
string? lastMatch = null;
|
||||
while (!string.IsNullOrEmpty(current))
|
||||
{
|
||||
if (File.Exists(Path.Combine(current, "Directory.Build.props")))
|
||||
{
|
||||
lastMatch = current;
|
||||
}
|
||||
|
||||
var parent = Directory.GetParent(current);
|
||||
if (parent is null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
current = parent.FullName;
|
||||
}
|
||||
|
||||
return lastMatch;
|
||||
}
|
||||
|
||||
private static AdvisoryIngestRequest BuildAdvisoryIngestRequest(
|
||||
string? contentHash,
|
||||
string upstreamId,
|
||||
|
||||
Reference in New Issue
Block a user