Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxy improvements #2077

Merged
merged 6 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Container-README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ docker run -p 9090:9090 particular/servicepulse:latest
### Environment Variables

- **`SERVICECONTROL_URL`**: _Default_: `http://localhost:33333`. The url to your ServiceControl instance
- **`MONITORING_URL`**: _Default_: `http://localhost:33633`. The url to your monitoring instance
- **`MONITORING_URL`**: _Default_: `http://localhost:33633`. The url to your Monitoring instance
- **`DEFAULT_ROUTE`**: _Default_: `/dashboard`. The default page that should be displayed when visiting the site
- **`SHOW_PENDING_RETRY`** _Default_: `false`. Set to `true` to show details of pending retries
- **`ENABLE_REVERSE_PROXY`** _Default_: `true`. Set to `false` to disable the proxy that forwards requests to the ServiceControl and Monitoring instances

It may be desireable to run the ServiceControl services in an isolated network. When doing so, ServicePulse must be configured to connect to those services using environment variables:

Expand Down
26 changes: 19 additions & 7 deletions src/ServicePulse/ConstantsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,31 @@

class ConstantsFile
{
public static string GetContent()
public static string GetContent(Settings settings)
{
var defaultRoute = Environment.GetEnvironmentVariable("DEFAULT_ROUTE") ?? "/dashboard";
var version = GetVersionInformation();
var showPendingRetry = Environment.GetEnvironmentVariable("SHOW_PENDING_RETRY") ?? "false";

string serviceControlUrl;
string monitoringUrl;

if (settings.EnableReverseProxy)
{
serviceControlUrl = "/api/";
monitoringUrl = "/monitoring-api/";
}
else
{
serviceControlUrl = settings.ServiceControlUri.ToString();
monitoringUrl = settings.MonitoringUri.ToString();
}

var constantsFile = $$"""
window.defaultConfig = {
default_route: '{{defaultRoute}}',
default_route: '{{settings.DefaultRoute}}',
version: '{{version}}',
service_control_url: '/api/',
monitoring_urls: ['/monitoring-api/'],
showPendingRetry: {{showPendingRetry}},
service_control_url: '{{serviceControlUrl}}',
monitoring_urls: ['{{monitoringUrl}}'],
showPendingRetry: {{(settings.ShowPendingRetry ? "true" : "false")}},
}
""";

Expand Down
16 changes: 12 additions & 4 deletions src/ServicePulse/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

var builder = WebApplication.CreateBuilder(args);

var (routes, clusters) = ReverseProxy.GetConfiguration();
builder.Services.AddReverseProxy().LoadFromMemory(routes, clusters);
var settings = Settings.GetFromEnvironmentVariables();

if (settings.EnableReverseProxy)
{
var (routes, clusters) = ReverseProxy.GetConfiguration(settings);
builder.Services.AddReverseProxy().LoadFromMemory(routes, clusters);
}

var app = builder.Build();

Expand All @@ -18,9 +23,12 @@
var staticFileOptions = new StaticFileOptions { FileProvider = fileProvider };
app.UseStaticFiles(staticFileOptions);

app.MapReverseProxy();
if (settings.EnableReverseProxy)
{
app.MapReverseProxy();
}

var constantsFile = ConstantsFile.GetContent();
var constantsFile = ConstantsFile.GetContent(settings);

app.MapGet("/js/app.constants.js", (HttpContext context) =>
{
Expand Down
56 changes: 4 additions & 52 deletions src/ServicePulse/ReverseProxy.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
namespace ServicePulse;

using System.Text.Json;
using Yarp.ReverseProxy.Configuration;
using Yarp.ReverseProxy.Transforms;

static class ReverseProxy
{
public static (List<RouteConfig> routes, List<ClusterConfig> clusters) GetConfiguration()
public static (List<RouteConfig> routes, List<ClusterConfig> clusters) GetConfiguration(Settings settings)
{
var serviceControlUrl = Environment.GetEnvironmentVariable("SERVICECONTROL_URL") ?? "http://localhost:33333";
var serviceControlUri = new Uri(serviceControlUrl);

var monitoringUrls = ParseLegacyMonitoringValue(Environment.GetEnvironmentVariable("MONITORING_URLS"));
var monitoringUrl = Environment.GetEnvironmentVariable("MONITORING_URL");

monitoringUrl ??= monitoringUrls;
monitoringUrl ??= "http://localhost:33633";

var monitoringUri = new Uri(monitoringUrl);

var serviceControlInstance = new ClusterConfig
{
ClusterId = "serviceControlInstance",
Destinations = new Dictionary<string, DestinationConfig>
{
{ "instance", new DestinationConfig { Address = serviceControlUri.GetLeftPart(UriPartial.Authority) } }
{ "instance", new DestinationConfig { Address = settings.ServiceControlUri.ToString() } }
}
};

Expand All @@ -33,7 +21,7 @@ public static (List<RouteConfig> routes, List<ClusterConfig> clusters) GetConfig
ClusterId = "monitoringInstance",
Destinations = new Dictionary<string, DestinationConfig>
{
{ "instance", new DestinationConfig { Address = monitoringUri.GetLeftPart(UriPartial.Authority) } }
{ "instance", new DestinationConfig { Address = settings.MonitoringUri.ToString() } }
}
};

Expand All @@ -45,7 +33,7 @@ public static (List<RouteConfig> routes, List<ClusterConfig> clusters) GetConfig
{
Path = "/api/{**catch-all}"
}
};
}.WithTransformPathRemovePrefix("/api");

var monitoringRoute = new RouteConfig()
{
Expand All @@ -71,40 +59,4 @@ public static (List<RouteConfig> routes, List<ClusterConfig> clusters) GetConfig

return (routes, clusters);
}

static string? ParseLegacyMonitoringValue(string? value)
{
if (value is null)
{
return null;
}

var cleanedValue = value.Replace('\'', '"');
var json = $$"""{"Addresses":{{cleanedValue}}}""";

MonitoringUrls? result;

try
{
result = JsonSerializer.Deserialize<MonitoringUrls>(json);
}
catch (JsonException)
{
return null;
}

var addresses = result?.Addresses;

if (addresses is not null && addresses.Length > 0)
{
return addresses[0];
}

return null;
}

class MonitoringUrls
{
public string[] Addresses { get; set; } = [];
}
}
98 changes: 98 additions & 0 deletions src/ServicePulse/Settings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
namespace ServicePulse;

using System.Text.Json;

class Settings
{
public required Uri ServiceControlUri { get; init; }

public required Uri MonitoringUri { get; init; }

public required string DefaultRoute { get; init; }

public required bool ShowPendingRetry { get; init; }

public required bool EnableReverseProxy { get; init; }

public static Settings GetFromEnvironmentVariables()
{
var serviceControlUrl = Environment.GetEnvironmentVariable("SERVICECONTROL_URL") ?? "http://localhost:33333/api/";

if (!serviceControlUrl.EndsWith("/", StringComparison.Ordinal))
{
serviceControlUrl += "/";
}

if (!serviceControlUrl.EndsWith("api/", StringComparison.Ordinal))
{
serviceControlUrl += "api/";
}

var serviceControlUri = new Uri(serviceControlUrl);

var monitoringUrls = ParseLegacyMonitoringValue(Environment.GetEnvironmentVariable("MONITORING_URLS"));
var monitoringUrl = Environment.GetEnvironmentVariable("MONITORING_URL");

monitoringUrl ??= monitoringUrls;
monitoringUrl ??= "http://localhost:33633/";

var monitoringUri = new Uri(monitoringUrl);

var defaultRoute = Environment.GetEnvironmentVariable("DEFAULT_ROUTE") ?? "/dashboard";

var showPendingRetryValue = Environment.GetEnvironmentVariable("SHOW_PENDING_RETRY");
bool.TryParse(showPendingRetryValue, out var showPendingRetry);

var enableReverseProxyValue = Environment.GetEnvironmentVariable("ENABLE_REVERSE_PROXY");

if (!bool.TryParse(enableReverseProxyValue, out var enableReverseProxy))
{
enableReverseProxy = true;
}

return new Settings
{
ServiceControlUri = serviceControlUri,
MonitoringUri = monitoringUri,
DefaultRoute = defaultRoute,
ShowPendingRetry = showPendingRetry,
EnableReverseProxy = enableReverseProxy
};
}

static string? ParseLegacyMonitoringValue(string? value)
{
if (value is null)
{
return null;
}

var cleanedValue = value.Replace('\'', '"');
var json = $$"""{"Addresses":{{cleanedValue}}}""";

MonitoringUrls? result;

try
{
result = JsonSerializer.Deserialize<MonitoringUrls>(json);
}
catch (JsonException)
{
return null;
}

var addresses = result?.Addresses;

if (addresses is not null && addresses.Length > 0)
{
return addresses[0];
}

return null;
}

class MonitoringUrls
{
public string[] Addresses { get; set; } = [];
}
}