From 2fd3736f7da92ac10614db2e0ab8242ee535b223 Mon Sep 17 00:00:00 2001 From: Dominick Schroer Date: Fri, 23 Jan 2026 10:52:59 -0700 Subject: [PATCH 1/3] fix: make it clear where to configure the agones tls handler --- modules/AgonesAllocator/Project/AgonesAllocator.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/AgonesAllocator/Project/AgonesAllocator.cs b/modules/AgonesAllocator/Project/AgonesAllocator.cs index a95b4fa..e19de73 100644 --- a/modules/AgonesAllocator/Project/AgonesAllocator.cs +++ b/modules/AgonesAllocator/Project/AgonesAllocator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using AgonesAllocatorModule.Client; using AgonesAllocatorModule.Client.Models; @@ -30,7 +31,13 @@ public void Setup(ICloudCodeConfig config) // TODO: Replace with required auth of your service var authProvider = new AnonymousAuthenticationProvider(); - return new HttpClientRequestAdapter(authProvider) + var handler = new HttpClientHandler + { + // TODO: Implement MTLS or other cert validation here + // ServerCertificateCustomValidationCallback = (_, _, _, _) => throw new NotImplementedException() + }; + + return new HttpClientRequestAdapter(authProvider, httpClient: new HttpClient(handler)) { BaseUrl = AllocatorServiceBaseUrl }; @@ -94,7 +101,7 @@ public Task Poll(IExecutionContext context, PollRequest request) { return Task.FromResult(new PollResponse(PollStatus.Allocated) { - AssignmentData = AssignmentData.IpPort((string)request.AllocationData["ip"], (int)request.AllocationData["port"]) + AssignmentData = AssignmentData.IpPort((string)request.AllocationData["ip"], Convert.ToInt32(request.AllocationData["port"])) }); } } From 73a9db03de000e0e53ab26f0d1f96f01f487ca71 Mon Sep 17 00:00:00 2001 From: Dominick Schroer Date: Fri, 23 Jan 2026 11:05:52 -0700 Subject: [PATCH 2/3] allocate on poll so that it can be retried --- .../Project/AgonesAllocator.cs | 49 +++++++++++-------- tests/AllocatorTests/AgonesAllocatorTests.cs | 29 +++++------ 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/modules/AgonesAllocator/Project/AgonesAllocator.cs b/modules/AgonesAllocator/Project/AgonesAllocator.cs index e19de73..dcc3c80 100644 --- a/modules/AgonesAllocator/Project/AgonesAllocator.cs +++ b/modules/AgonesAllocator/Project/AgonesAllocator.cs @@ -50,9 +50,14 @@ public void Setup(ICloudCodeConfig config) /// public class AgonesAllocator(IRequestAdapter requestAdapter, ILogger logger) : IMatchmakerAllocator { - [CloudCodeFunction("Matchmaker_AllocateServer")] - public async Task Allocate(IExecutionContext context, AllocateRequest request) + public Task Allocate(IExecutionContext context, AllocateRequest request) + { + return Task.FromResult(new AllocateResponse(AllocateStatus.Created)); + } + + [CloudCodeFunction("Matchmaker_PollAllocation")] + public async Task Poll(IExecutionContext context, PollRequest request) { var client = new AgonesClient(requestAdapter); @@ -69,39 +74,41 @@ public async Task Allocate(IExecutionContext context, Allocate if (ip == null || port == null) { logger.LogError("Allocation did not return a valid IP or Port"); - return new AllocateResponse(AllocateStatus.Error) + return new PollResponse(PollStatus.Error) { Message = "Allocation did not return a valid IP or Port" }; } - return new AllocateResponse(AllocateStatus.Created) + return new PollResponse(PollStatus.Allocated) { - AllocationData = new Dictionary - { - { "ip", ip }, - { "port", port } - } + AssignmentData = AssignmentData.IpPort(ip, port ?? 0) }; } - catch (Exception e) + catch (ApiException e) { - logger.LogError(e, "Error creating Agones allocation"); - - return new AllocateResponse(AllocateStatus.Error) + // Agones was unable to allocate a server but might succeed in the future + // Wait for the next poll to retry + if (e.ResponseStatusCode == 429) { - Message = $"Error creating Agones allocation: {e}" - }; - } + logger.LogWarning(e, "Error creating Agones allocation"); + return new PollResponse(PollStatus.Pending); + } + return HandlePollError(e); + } + catch (Exception e) + { + return HandlePollError(e); + } } - [CloudCodeFunction("Matchmaker_PollAllocation")] - public Task Poll(IExecutionContext context, PollRequest request) + private PollResponse HandlePollError(Exception e) { - return Task.FromResult(new PollResponse(PollStatus.Allocated) + logger.LogError(e, "Error creating Agones allocation"); + return new PollResponse(PollStatus.Error) { - AssignmentData = AssignmentData.IpPort((string)request.AllocationData["ip"], Convert.ToInt32(request.AllocationData["port"])) - }); + Message = $"Error creating Agones allocation: {e}" + }; } } diff --git a/tests/AllocatorTests/AgonesAllocatorTests.cs b/tests/AllocatorTests/AgonesAllocatorTests.cs index 6adc11c..c469e2c 100644 --- a/tests/AllocatorTests/AgonesAllocatorTests.cs +++ b/tests/AllocatorTests/AgonesAllocatorTests.cs @@ -27,6 +27,16 @@ public AgonesAllocatorTests() [Test] public async Task TestAgonesCanAllocate() + { + var allocation = await _allocator.Allocate(_executionContextMock.Object, new AllocateRequest("1234", + new MatchmakingResults(null, "matchId", "poolId", "poolName", "queueName", new()))); + + Assert.That(allocation.Status, Is.EqualTo(AllocateStatus.Created)); + Assert.That(allocation.Message, Is.Null); + } + + [Test] + public async Task TestAgonesCanPoll() { _requestAdapterMock.Reset(); _requestAdapterMock.Setup(s => s.SerializationWriterFactory.GetSerializationWriter("application/json")) @@ -52,25 +62,8 @@ public async Task TestAgonesCanAllocate() } }); - var allocation = await _allocator.Allocate(_executionContextMock.Object, new AllocateRequest("1234", - new MatchmakingResults(null, "matchId", "poolId", "poolName", "queueName", new()))); - - Assert.That(allocation.Status, Is.EqualTo(AllocateStatus.Created)); - Assert.That(allocation.Message, Is.Null); - Assert.That(allocation.AllocationData, Is.Not.Null); - Assert.That(allocation.AllocationData["ip"], Is.EqualTo("127.0.0.1")); - Assert.That(allocation.AllocationData["port"], Is.EqualTo(1234)); - } - - [Test] - public async Task TestAgonesCanPoll() - { var poll = await _allocator.Poll(_executionContextMock.Object, new PollRequest("1234", - new Dictionary - { - { "ip", "127.0.0.1" }, - { "port", 1234 }, - }, DateTimeOffset.UtcNow)); + new Dictionary(), DateTimeOffset.UtcNow)); Assert.That(poll.Status, Is.EqualTo(PollStatus.Allocated)); Assert.That(poll.Message, Is.Null); From 4c53f8eb758b2231bf2f3215eecff152b58590d4 Mon Sep 17 00:00:00 2001 From: Dominick Schroer Date: Fri, 23 Jan 2026 11:13:20 -0700 Subject: [PATCH 3/3] update documentation to match new config options --- modules/AgonesAllocator/CONFIGURATION.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/AgonesAllocator/CONFIGURATION.md b/modules/AgonesAllocator/CONFIGURATION.md index ae6c04d..b2cd554 100644 --- a/modules/AgonesAllocator/CONFIGURATION.md +++ b/modules/AgonesAllocator/CONFIGURATION.md @@ -18,12 +18,20 @@ Replace with your Agones Allocator Service URL. This should be the base URL of y Find this URL from your Agones installation. Refer to the [Agones Allocator Service documentation](https://agones.dev/site/docs/advanced/allocator-service/) for setup instructions. -### Authentication Provider (line 31) - recommended for production +### Authentication Provider (line 31 & line 36) - recommended for production ```csharp var authProvider = new AnonymousAuthenticationProvider(); // TODO: Replace with required auth of your service ``` +```csharp +var handler = new HttpClientHandler +{ + // TODO: Implement MTLS or other cert validation here + // ServerCertificateCustomValidationCallback = (_, _, _, _) => throw new NotImplementedException() +}; +``` + Replace `AnonymousAuthenticationProvider` with your preferred authentication method. For production deployments, consider using: - mTLS (mutual TLS) authentication - recommended by Agones - Bearer token authentication @@ -31,7 +39,7 @@ Replace `AnonymousAuthenticationProvider` with your preferred authentication met Refer to the [Agones Allocator Service documentation](https://agones.dev/site/docs/advanced/allocator-service/) for authentication options. -### Allocation Request Configuration (line 41) - optional +### Allocation Request Configuration (line 68) - optional ```csharp var allocation = await client.Gameserverallocation.PostAsync(new AllocationAllocationRequest