feat: Implement provisioning pipelines for subscription management
- Add ReactivatePipeline to handle subscription reactivation, including scaling Docker services, health verification, status updates, audit logging, and broadcasting status changes. - Introduce RotateCredentialsPipeline for OAuth2 credential rotation, managing the deletion of old apps, creation of new ones, credential storage, access verification, and audit logging. - Create StepRunner to manage job step execution, including lifecycle management and progress broadcasting via SignalR. - Implement SuspendPipeline for subscription suspension, scaling down services, updating statuses, logging audits, and broadcasting changes. - Add UpdateScreenLimitPipeline to update Xibo CMS screen limits and record snapshots. - Introduce XiboFeatureManifests for hardcoded feature ACLs per role. - Add docker-compose.dev.yml for local development with PostgreSQL setup.
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
using OTSSignsOrchestrator.Server.Jobs;
|
||||
|
||||
namespace OTSSignsOrchestrator.Server.Tests;
|
||||
|
||||
public class ByoiCertExpiryThresholdTests
|
||||
{
|
||||
// ── ShouldAlert ─────────────────────────────────────────────────────────
|
||||
|
||||
[Theory]
|
||||
[InlineData(61, false)] // 61 days: above all thresholds → no alert
|
||||
[InlineData(60, true)] // 60 days: at first threshold → alert
|
||||
[InlineData(59, true)] // 59 days: below 60 → alert
|
||||
[InlineData(31, true)] // 31 days: between 60 and 30 → alert
|
||||
[InlineData(30, true)] // 30 days: at second threshold → alert
|
||||
[InlineData(8, true)] // 8 days: between 30 and 7 → alert
|
||||
[InlineData(7, true)] // 7 days: at critical threshold → alert
|
||||
[InlineData(1, true)] // 1 day: below critical → alert
|
||||
[InlineData(0, true)] // 0 days: expiry day → alert
|
||||
[InlineData(-1, true)] // -1 day: already expired → alert
|
||||
public void ShouldAlert_ReturnsCorrectValue(double daysRemaining, bool expected)
|
||||
{
|
||||
Assert.Equal(expected, ByoiCertExpiryJob.ShouldAlert(daysRemaining));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldAlert_LargeValue_NoAlert()
|
||||
{
|
||||
Assert.False(ByoiCertExpiryJob.ShouldAlert(365));
|
||||
}
|
||||
|
||||
// ── GetSeverity ─────────────────────────────────────────────────────────
|
||||
|
||||
[Theory]
|
||||
[InlineData(60, "Warning")]
|
||||
[InlineData(30, "Warning")]
|
||||
[InlineData(8, "Warning")]
|
||||
[InlineData(7.01, "Warning")]
|
||||
[InlineData(7, "Critical")] // Exactly at critical boundary
|
||||
[InlineData(6, "Critical")]
|
||||
[InlineData(1, "Critical")]
|
||||
[InlineData(0, "Critical")]
|
||||
[InlineData(-1, "Critical")] // Already expired
|
||||
public void GetSeverity_ReturnsCorrectLevel(double daysRemaining, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ByoiCertExpiryJob.GetSeverity(daysRemaining));
|
||||
}
|
||||
|
||||
// ── Threshold constants ─────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void AlertThresholds_AreDescending()
|
||||
{
|
||||
var thresholds = ByoiCertExpiryJob.AlertThresholdDays;
|
||||
for (int i = 1; i < thresholds.Length; i++)
|
||||
{
|
||||
Assert.True(thresholds[i - 1] > thresholds[i],
|
||||
$"Thresholds must be in descending order: {thresholds[i - 1]} should be > {thresholds[i]}");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CriticalThreshold_IsSmallestAlertThreshold()
|
||||
{
|
||||
Assert.Equal(
|
||||
ByoiCertExpiryJob.CriticalThresholdDays,
|
||||
ByoiCertExpiryJob.AlertThresholdDays[^1]);
|
||||
}
|
||||
|
||||
// ── Boundary precision ──────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void ShouldAlert_JustAboveThreshold_NoAlert()
|
||||
{
|
||||
// 60.001 days — just above 60-day threshold
|
||||
Assert.False(ByoiCertExpiryJob.ShouldAlert(60.001));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldAlert_JustBelowThreshold_Alerts()
|
||||
{
|
||||
// 59.999 days — just below 60-day threshold
|
||||
Assert.True(ByoiCertExpiryJob.ShouldAlert(59.999));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetSeverity_JustAboveCritical_IsWarning()
|
||||
{
|
||||
Assert.Equal("Warning", ByoiCertExpiryJob.GetSeverity(7.001));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetSeverity_ExactlyCritical_IsCritical()
|
||||
{
|
||||
Assert.Equal("Critical", ByoiCertExpiryJob.GetSeverity(7.0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OTSSignsOrchestrator.Server\OTSSignsOrchestrator.Server.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user