Skip to content

Commit

Permalink
Provide X-Version response header for API endpoints (#1355)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkerkhove authored Nov 18, 2020
1 parent 7e6cebe commit 457d354
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog/content/experimental/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ version:
- {{% tag added %}} New validation rule to ensure declarative or dynamic discovery for metrics to scrape are configured
- {{% tag added %}} New System API endpoint giving runtime information ([docs](https://promitor.io/operations/#system)
| [#1208](https://github.com/tomkerkhove/promitor/issues/1208))
- {{% tag added %}} Provide `X-Version` response header for API endpoints ([#1209](https://github.com/tomkerkhove/promitor/issues/1209))
- {{% tag added %}} Provide capability to tweak liveness/readines probes in Helm charts ([#1350](https://github.com/tomkerkhove/promitor/issues/1350))
- {{% tag changed %}} Show Promitor version during startup
- {{% tag changed %}} Provide capability to scrape all queues in Azure Service Bus, instead of having to declare the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Promitor.Agents.Core.Middleware;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerUI;

Expand All @@ -8,6 +9,16 @@ namespace Microsoft.AspNetCore.Builder
// ReSharper disable once InconsistentNaming
public static class IApplicationBuilderExtensions
{
/// <summary>
/// Adds middleware to automatically add the version in our responses
/// </summary>
public static IApplicationBuilder UseVersionMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<AgentVersionMiddleware>();

return app;
}

/// <summary>
/// Add support for Open API with API explorer
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions src/Promitor.Agents.Core/HttpHeaders.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Promitor.Agents.Core
{
public class HttpHeaders
{
public const string AgentVersion = "X-Version";
}
}
41 changes: 41 additions & 0 deletions src/Promitor.Agents.Core/Middleware/AgentVersionMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Promitor.Core;

namespace Promitor.Agents.Core.Middleware
{
public class AgentVersionMiddleware
{
private readonly RequestDelegate _next;

/// <summary>
/// Initializes a new instance of the <see cref="AgentVersionMiddleware" /> class which automatically adds the version of the agent to all HTTP responses
/// </summary>
/// <param name="next">The next <see cref="RequestDelegate" /> in the ASP.NET Core request pipeline.</param>
/// <exception cref="System.ArgumentNullException">When the <paramref name="next" /> is <c>null</c>.</exception>
public AgentVersionMiddleware(RequestDelegate next)
{
_next = next;
}

/// <summary>
/// Invoke the middleware to automatically add version to HTTP responses.
/// </summary>
/// <param name="httpContext">The context for the current HTTP request.</param>
public async Task Invoke(HttpContext httpContext)
{
var version = Version.Get();

httpContext.Response.OnStarting(state =>
{
var context = (HttpContext)state;
context.Response.Headers.TryAdd(HttpHeaders.AgentVersion, version);

return Task.CompletedTask;
}, httpContext);

await _next(httpContext);
}
}
}
1 change: 1 addition & 0 deletions src/Promitor.Agents.ResourceDiscovery/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseExceptionHandling();
app.UseRequestTracking();
app.UseHttpCorrelation();
app.UseVersionMiddleware();
app.UseRouting();

app.ExposeOpenApiUi(ApiName);
Expand Down
2 changes: 2 additions & 0 deletions src/Promitor.Agents.Scraper/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseExceptionHandling()
.UseRequestTracking()
.UseHttpCorrelation()
.UseVersionMiddleware()
.UseRouting()
.UseMetricSinks(Configuration)
.ExposeOpenApiUi()
.UseEndpoints(endpoints => endpoints.MapControllers());

UseSerilog(ComponentName, app.ApplicationServices);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Net;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Promitor.Agents.Core;
using Promitor.Tests.Integration.Clients;
using Xunit;
using Xunit.Abstractions;
Expand All @@ -24,6 +26,8 @@ public async Task Health_Get_ReturnsOk()

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Promitor.Agents.Core;
using Promitor.Agents.ResourceDiscovery.Configuration;
using Promitor.Tests.Integration.Clients;
using Xunit;
Expand Down Expand Up @@ -33,5 +35,20 @@ public async Task ResourceDiscoveryGroup_GetAll_ReturnsValidList()
Assert.NotNull(resourceDiscoveryGroups);
Assert.NotEmpty(resourceDiscoveryGroups);
}

[Fact]
public async Task ResourceDiscoveryGroup_SuccessfulCall_ReturnsVersionHeader()
{
// Arrange
var resourceDiscoveryClient = new ResourceDiscoveryClient(Configuration, Logger);

// Act
var response = await resourceDiscoveryClient.GetResourceDiscoveryGroupsAsync();

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ public class ResourceDiscoveryIntegrationTest: IntegrationTest
public ResourceDiscoveryIntegrationTest(ITestOutputHelper testOutput) : base(testOutput)
{
}

public string ExpectedVersion => Configuration["Agents:ResourceDiscovery:Expectations:Version"];
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Bogus;
using Newtonsoft.Json;
using Promitor.Agents.Core;
using Promitor.Agents.ResourceDiscovery.Graph.Model;
using Promitor.Tests.Integration.Clients;
using Xunit;
Expand Down Expand Up @@ -31,6 +33,24 @@ public async Task ResourceDiscovery_GetForUnexistingResourceDiscoveryGroup_Retur

// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}

[Fact]
public async Task ResourceDiscovery_SuccessfulCall_ReturnsVersionHeader()
{
// Arrange
const string resourceDiscoveryGroupName = "logic-apps-unfiltered";
var resourceDiscoveryClient = new ResourceDiscoveryClient(Configuration, Logger);

// Act
var response = await resourceDiscoveryClient.GetDiscoveredResourcesAsync(resourceDiscoveryGroupName);

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Net;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Promitor.Agents.Core;
using Promitor.Agents.Core.Contracts;
using Promitor.Tests.Integration.Clients;
using Xunit;
Expand All @@ -19,7 +21,6 @@ public SystemTests(ITestOutputHelper testOutput)
public async Task System_GetInfo_ReturnsOk()
{
// Arrange
var expectedVersion = Configuration["Agents:ResourceDiscovery:Expectations:Version"];
var resourceDiscoveryClient = new ResourceDiscoveryClient(Configuration, Logger);

// Act
Expand All @@ -31,7 +32,9 @@ public async Task System_GetInfo_ReturnsOk()
Assert.NotEmpty(rawPayload);
var systemInfo = JsonConvert.DeserializeObject<SystemInfo>(rawPayload);
Assert.NotNull(systemInfo);
Assert.Equal(expectedVersion, systemInfo.Version);
Assert.Equal(ExpectedVersion, systemInfo.Version);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Net;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Promitor.Agents.Core;
using Promitor.Tests.Integration.Clients;
using Xunit;
using Xunit.Abstractions;
Expand All @@ -24,6 +26,8 @@ public async Task Health_Get_ReturnsOk()

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ public class ScraperIntegrationTest: IntegrationTest
public ScraperIntegrationTest(ITestOutputHelper testOutput) : base(testOutput)
{
}

public string ExpectedVersion => Configuration["Agents:Scraper:Expectations:Version"];
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Net;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Promitor.Agents.Core;
using Promitor.Agents.Core.Contracts;
using Promitor.Tests.Integration.Clients;
using Xunit;
Expand All @@ -19,7 +21,6 @@ public SystemTests(ITestOutputHelper testOutput)
public async Task System_GetInfo_ReturnsOk()
{
// Arrange
var expectedVersion = Configuration["Agents:Scraper:Expectations:Version"];
var resourceDiscoveryClient = new ScraperClient(Configuration, Logger);

// Act
Expand All @@ -31,7 +32,9 @@ public async Task System_GetInfo_ReturnsOk()
Assert.NotEmpty(rawPayload);
var systemInfo = JsonConvert.DeserializeObject<SystemInfo>(rawPayload);
Assert.NotNull(systemInfo);
Assert.Equal(expectedVersion, systemInfo.Version);
Assert.Equal(ExpectedVersion, systemInfo.Version);
Assert.True(response.Headers.Contains(HttpHeaders.AgentVersion));
Assert.Equal(ExpectedVersion, response.Headers.GetValues(HttpHeaders.AgentVersion).First());
}
}
}

0 comments on commit 457d354

Please sign in to comment.