fleet: require a minimum version of the peer at the handshake [CI]
MoShiro__MinAgentVersion makes the backend refuse agents below it at hello (fleet_version_required); fleet.min_server_version or MOSHIRO_MIN_SERVER_VERSION makes the agent drop a backend below it. Either side waits five seconds and shakes hands again, because the other one may be updating.
This commit is contained in:
1 parent
fb3a9c260f
commit
5822285a88
16 files changed
+266
-7
No files matched your search
@@ -42,7 +42,7 @@ public sealed class AgentHarness : IAsyncDisposable
|
||||
public byte[] TlsPublicKey => _identity.Certificate.PublicKey.ExportSubjectPublicKeyInfo();
|
||||
|
||||
/// <param name="pin">带信任根固定的加入码(码、创世指纹、属主):节点按固定了创世和属主的方式注册。</param>
|
||||
public static async Task<AgentHarness> StartAsync(BackendFixture backend, Action<AgentConfig>? configure = null, string? name = null, (string Code, string Genesis, string[] Controllers)? pin = null)
|
||||
public static async Task<AgentHarness> StartAsync(BackendFixture backend, Action<AgentConfig>? configure = null, string? name = null, (string Code, string Genesis, string[] Controllers)? pin = null, bool waitForConnection = true)
|
||||
{
|
||||
string directory = Path.Combine(Path.GetTempPath(), "moshiro-agent-" + Guid.NewGuid().ToString("N"));
|
||||
string token = pin?.Code ?? await backend.CreateJoinTokenAsync();
|
||||
@@ -71,7 +71,11 @@ public sealed class AgentHarness : IAsyncDisposable
|
||||
}
|
||||
|
||||
await app.Ready;
|
||||
await BackendFixture.EventuallyAsync(() => Task.FromResult(app.Link.IsConnected), because: "the agent should connect to the backend");
|
||||
if (waitForConnection)
|
||||
{
|
||||
await BackendFixture.EventuallyAsync(() => Task.FromResult(app.Link.IsConnected), because: "the agent should connect to the backend");
|
||||
}
|
||||
|
||||
return harness;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Text.Json;
|
||||
using Fleet.Core;
|
||||
using Fleet.Rpc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MoShiro.Backend.Application;
|
||||
using MoShiro.TestSupport;
|
||||
|
||||
namespace MoShiro.Backend.Tests;
|
||||
|
||||
public sealed class VersionRequirementTests : IClassFixture<BackendFixture>
|
||||
{
|
||||
private readonly BackendFixture _backend;
|
||||
|
||||
public VersionRequirementTests(BackendFixture backend)
|
||||
{
|
||||
_backend = backend;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AnAgentBelowTheRequiredVersion_IsRejectedAtHello_AndGetsInOnceTheRequirementIsMet()
|
||||
{
|
||||
BackendOptions options = _backend.App.Services.GetRequiredService<BackendOptions>();
|
||||
options.MinAgentVersion = "9.0.0"; // 模拟器的版本是 0.0.1-sim
|
||||
try
|
||||
{
|
||||
await using AgentSimulator old = await _backend.ConnectAgentAsync(hello: false);
|
||||
var hello = new HelloParams { NodeVersion = "0.0.1-sim", NowUtcMs = TimeProvider.System.GetUtcNow().ToUnixTimeMilliseconds() };
|
||||
RpcMessage reply = await old.RequestRawAsync(FleetMethods.Hello, JsonSerializer.SerializeToElement(hello, FleetRpcContext.Default.HelloParams));
|
||||
Assert.Equal(FleetErrors.VersionRequired.Value, reply.Error!.Data!.Code);
|
||||
Assert.Contains("9.0.0", reply.Error.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
options.MinAgentVersion = null; // 共用的后端:恢复,别影响别的测试
|
||||
}
|
||||
|
||||
await using AgentSimulator ok = await _backend.ConnectAgentAsync();
|
||||
Assert.True(_backend.App.Services.GetRequiredService<MoShiro.Backend.Application.IAgentGateway>().IsOnline(ok.NodeId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", "Slow")]
|
||||
public async Task AnAgentTheBackendRejectedForItsVersion_TriesAgainEveryFiveSeconds_AndComesOnlineWhenAccepted()
|
||||
{
|
||||
BackendOptions options = _backend.App.Services.GetRequiredService<BackendOptions>();
|
||||
IAgentGateway gateway = _backend.App.Services.GetRequiredService<IAgentGateway>();
|
||||
options.MinAgentVersion = "999.0.0";
|
||||
try
|
||||
{
|
||||
await using AgentHarness agent = await AgentHarness.StartAsync(_backend, waitForConnection: false);
|
||||
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||
Assert.False(gateway.IsOnline(agent.NodeId));
|
||||
|
||||
options.MinAgentVersion = null; // 通过了:下一次握手(最迟 5 秒)就上线
|
||||
await BackendFixture.EventuallyAsync(() => Task.FromResult(gateway.IsOnline(agent.NodeId)), TimeSpan.FromSeconds(12));
|
||||
}
|
||||
finally
|
||||
{
|
||||
options.MinAgentVersion = null;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", "Slow")]
|
||||
public async Task AnAgentThatRequiresANewerBackend_DoesNotGoOnline_AndKeepsChecking()
|
||||
{
|
||||
IAgentGateway gateway = _backend.App.Services.GetRequiredService<IAgentGateway>();
|
||||
await using AgentHarness agent = await AgentHarness.StartAsync(_backend, config => config.Fleet.MinServerVersion = "999.0.0", waitForConnection: false);
|
||||
await Task.Delay(TimeSpan.FromSeconds(7)); // 至少重试过一次
|
||||
Assert.False(gateway.IsOnline(agent.NodeId));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user