Skip to content

Commit e5f31ef

Browse files
authored
Follow up #1670: Fix StyleCop issues and improve the code (#1711)
* Code refactoring and improvements * Fix unit tests for ConsulServiceDiscoveryProvider * Add default port * Throw NullRef exception if no client * Fix 'should_not_get' unit test * Add AgentService extensions * Use current naming conventions for unit tests * Fix code smell with methos signature * Encapsulate warning string creation. Create expected value from a hardcoded string in unit tests
1 parent e950cf2 commit e5f31ef

File tree

42 files changed

+252
-326
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+252
-326
lines changed

samples/OcelotServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public MyServiceDiscoveryProvider(IServiceProvider serviceProvider, ServiceProvi
2020
_downstreamRoute = downstreamRoute;
2121
}
2222

23-
public Task<List<Service>> Get()
23+
public Task<List<Service>> GetAsync()
2424
{
2525

2626
// Returns a list of service(s) that match the downstream route passed to the provider

src/Ocelot.Provider.Consul/Consul.cs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,21 @@ public class Consul : IServiceDiscoveryProvider
1414

1515
public Consul(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
1616
{
17-
_logger = factory.CreateLogger<Consul>();
1817
_config = config;
1918
_consul = clientFactory.Get(_config);
19+
_logger = factory.CreateLogger<Consul>();
2020
}
2121

22-
public async Task<List<Service>> Get()
22+
public async Task<List<Service>> GetAsync()
2323
{
2424
var queryResult = await _consul.Health.Service(_config.KeyOfServiceInConsul, string.Empty, true);
2525

2626
var services = new List<Service>();
2727

2828
foreach (var serviceEntry in queryResult.Response)
2929
{
30-
if (IsValid(serviceEntry))
30+
var service = serviceEntry.Service;
31+
if (IsValid(service))
3132
{
3233
var nodes = await _consul.Catalog.Nodes();
3334
if (nodes.Response == null)
@@ -36,14 +37,14 @@ public async Task<List<Service>> Get()
3637
}
3738
else
3839
{
39-
var serviceNode = nodes.Response.FirstOrDefault(n => n.Address == serviceEntry.Service.Address);
40+
var serviceNode = nodes.Response.FirstOrDefault(n => n.Address == service.Address);
4041
services.Add(BuildService(serviceEntry, serviceNode));
4142
}
4243
}
4344
else
4445
{
4546
_logger.LogWarning(
46-
$"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
47+
$"Unable to use service address: '{service.Address}' and port: {service.Port} as it is invalid for the service: '{service.Service}'. Address must contain host only e.g. 'localhost', and port must be greater than 0.");
4748
}
4849
}
4950

@@ -52,27 +53,24 @@ public async Task<List<Service>> Get()
5253

5354
private static Service BuildService(ServiceEntry serviceEntry, Node serviceNode)
5455
{
56+
var service = serviceEntry.Service;
5557
return new Service(
56-
serviceEntry.Service.Service,
57-
new ServiceHostAndPort(serviceNode == null ? serviceEntry.Service.Address : serviceNode.Name,
58-
serviceEntry.Service.Port),
59-
serviceEntry.Service.ID,
60-
GetVersionFromStrings(serviceEntry.Service.Tags),
61-
serviceEntry.Service.Tags ?? Enumerable.Empty<string>());
58+
service.Service,
59+
new ServiceHostAndPort(
60+
serviceNode == null ? service.Address : serviceNode.Name,
61+
service.Port),
62+
service.ID,
63+
GetVersionFromStrings(service.Tags),
64+
service.Tags ?? Enumerable.Empty<string>());
6265
}
6366

64-
private static bool IsValid(ServiceEntry serviceEntry)
65-
{
66-
return !string.IsNullOrEmpty(serviceEntry.Service.Address)
67-
&& !serviceEntry.Service.Address.Contains("http://")
68-
&& !serviceEntry.Service.Address.Contains("https://")
69-
&& serviceEntry.Service.Port > 0;
70-
}
67+
private static bool IsValid(AgentService service)
68+
=> !string.IsNullOrEmpty(service.Address)
69+
&& !service.Address.Contains($"{Uri.UriSchemeHttp}://")
70+
&& !service.Address.Contains($"{Uri.UriSchemeHttps}://")
71+
&& service.Port > 0;
7172

7273
private static string GetVersionFromStrings(IEnumerable<string> strings)
73-
{
74-
return strings
75-
?.FirstOrDefault(x => x.StartsWith(VersionPrefix, StringComparison.Ordinal))
74+
=> strings?.FirstOrDefault(x => x.StartsWith(VersionPrefix, StringComparison.Ordinal))
7675
.TrimStart(VersionPrefix);
77-
}
7876
}

src/Ocelot.Provider.Consul/ConsulClientFactory.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
public class ConsulClientFactory : IConsulClientFactory
44
{
55
public IConsulClient Get(ConsulRegistryConfiguration config)
6+
=> new ConsulClient(c => OverrideConfig(c, config));
7+
8+
private static void OverrideConfig(ConsulClientConfiguration to, ConsulRegistryConfiguration from)
69
{
7-
return new ConsulClient(c =>
8-
{
9-
c.Address = new Uri($"{config.Scheme}://{config.Host}:{config.Port}");
10+
to.Address = new Uri($"{from.Scheme}://{from.Host}:{from.Port}");
1011

11-
if (!string.IsNullOrEmpty(config?.Token)) c.Token = config.Token;
12-
});
12+
if (!string.IsNullOrEmpty(from?.Token))
13+
{
14+
to.Token = from.Token;
15+
}
1316
}
1417
}
Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
using System.Text;
2-
using Microsoft.Extensions.Options;
1+
using Microsoft.Extensions.Options;
32
using Newtonsoft.Json;
43
using Ocelot.Cache;
4+
using Ocelot.Configuration;
55
using Ocelot.Configuration.File;
66
using Ocelot.Configuration.Repository;
77
using Ocelot.Logging;
88
using Ocelot.Responses;
9+
using System.Text;
910

1011
namespace Ocelot.Provider.Consul;
1112

@@ -25,37 +26,32 @@ public ConsulFileConfigurationRepository(
2526
_logger = loggerFactory.CreateLogger<ConsulFileConfigurationRepository>();
2627
_cache = cache;
2728

28-
var serviceDiscoveryProvider = fileConfiguration.Value.GlobalConfiguration.ServiceDiscoveryProvider;
29-
_configurationKey = string.IsNullOrWhiteSpace(serviceDiscoveryProvider.ConfigurationKey)
30-
? "InternalConfiguration"
31-
: serviceDiscoveryProvider.ConfigurationKey;
32-
33-
var config = new ConsulRegistryConfiguration(serviceDiscoveryProvider.Scheme, serviceDiscoveryProvider.Host,
34-
serviceDiscoveryProvider.Port, _configurationKey, serviceDiscoveryProvider.Token);
29+
var provider = fileConfiguration.Value.GlobalConfiguration.ServiceDiscoveryProvider;
30+
_configurationKey = string.IsNullOrWhiteSpace(provider.ConfigurationKey)
31+
? nameof(InternalConfiguration)
32+
: provider.ConfigurationKey;
3533

34+
var config = new ConsulRegistryConfiguration(provider.Scheme, provider.Host,
35+
provider.Port, _configurationKey, provider.Token);
3636
_consul = factory.Get(config);
3737
}
3838

3939
public async Task<Response<FileConfiguration>> Get()
4040
{
4141
var config = _cache.Get(_configurationKey, _configurationKey);
42-
4342
if (config != null)
4443
{
4544
return new OkResponse<FileConfiguration>(config);
4645
}
4746

4847
var queryResult = await _consul.KV.Get(_configurationKey);
49-
5048
if (queryResult.Response == null)
5149
{
5250
return new OkResponse<FileConfiguration>(null);
5351
}
5452

5553
var bytes = queryResult.Response.Value;
56-
5754
var json = Encoding.UTF8.GetString(bytes);
58-
5955
var consulConfig = JsonConvert.DeserializeObject<FileConfiguration>(json);
6056

6157
return new OkResponse<FileConfiguration>(consulConfig);
@@ -64,16 +60,13 @@ public async Task<Response<FileConfiguration>> Get()
6460
public async Task<Response> Set(FileConfiguration ocelotConfiguration)
6561
{
6662
var json = JsonConvert.SerializeObject(ocelotConfiguration, Formatting.Indented);
67-
6863
var bytes = Encoding.UTF8.GetBytes(json);
69-
7064
var kvPair = new KVPair(_configurationKey)
7165
{
7266
Value = bytes,
7367
};
7468

7569
var result = await _consul.KV.Put(kvPair);
76-
7770
if (result.Response)
7871
{
7972
_cache.AddAndDelete(_configurationKey, ocelotConfiguration, TimeSpan.FromSeconds(3), _configurationKey);
@@ -82,6 +75,6 @@ public async Task<Response> Set(FileConfiguration ocelotConfiguration)
8275
}
8376

8477
return new ErrorResponse(new UnableToSetConfigInConsulError(
85-
$"Unable to set FileConfiguration in consul, response status code from consul was {result.StatusCode}"));
78+
$"Unable to set {nameof(FileConfiguration)} in {nameof(Consul)}, response status code from {nameof(Consul)} was {result.StatusCode}"));
8679
}
8780
}

src/Ocelot.Provider.Consul/ConsulMiddlewareConfigurationProvider.cs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ namespace Ocelot.Provider.Consul;
1111

1212
public static class ConsulMiddlewareConfigurationProvider
1313
{
14-
public static OcelotMiddlewareConfigurationDelegate Get = async builder =>
14+
public static OcelotMiddlewareConfigurationDelegate Get { get; } = GetAsync;
15+
16+
private static async Task GetAsync(IApplicationBuilder builder)
1517
{
1618
var fileConfigRepo = builder.ApplicationServices.GetService<IFileConfigurationRepository>();
1719
var fileConfig = builder.ApplicationServices.GetService<IOptionsMonitor<FileConfiguration>>();
@@ -22,34 +24,30 @@ public static class ConsulMiddlewareConfigurationProvider
2224
{
2325
await SetFileConfigInConsul(builder, fileConfigRepo, fileConfig, internalConfigCreator, internalConfigRepo);
2426
}
25-
};
27+
}
2628

2729
private static bool UsingConsul(IFileConfigurationRepository fileConfigRepo)
28-
{
29-
return fileConfigRepo.GetType() == typeof(ConsulFileConfigurationRepository);
30-
}
30+
=> fileConfigRepo.GetType() == typeof(ConsulFileConfigurationRepository);
3131

3232
private static async Task SetFileConfigInConsul(IApplicationBuilder builder,
3333
IFileConfigurationRepository fileConfigRepo, IOptionsMonitor<FileConfiguration> fileConfig,
3434
IInternalConfigurationCreator internalConfigCreator, IInternalConfigurationRepository internalConfigRepo)
3535
{
36-
// get the config from consul.
36+
// Get the config from Consul
3737
var fileConfigFromConsul = await fileConfigRepo.Get();
38-
3938
if (IsError(fileConfigFromConsul))
4039
{
4140
ThrowToStopOcelotStarting(fileConfigFromConsul);
4241
}
4342
else if (ConfigNotStoredInConsul(fileConfigFromConsul))
4443
{
45-
//there was no config in consul set the file in config in consul
44+
// there was no config in Consul set the file in config in Consul
4645
await fileConfigRepo.Set(fileConfig.CurrentValue);
4746
}
4847
else
4948
{
50-
// create the internal config from consul data
49+
// Create the internal config from Consul data
5150
var internalConfig = await internalConfigCreator.Create(fileConfigFromConsul.Data);
52-
5351
if (IsError(internalConfig))
5452
{
5553
ThrowToStopOcelotStarting(internalConfig);
@@ -58,7 +56,6 @@ private static async Task SetFileConfigInConsul(IApplicationBuilder builder,
5856
{
5957
// add the internal config to the internal repo
6058
var response = internalConfigRepo.AddOrReplace(internalConfig.Data);
61-
6259
if (IsError(response))
6360
{
6461
ThrowToStopOcelotStarting(response);
@@ -73,18 +70,11 @@ private static async Task SetFileConfigInConsul(IApplicationBuilder builder,
7370
}
7471

7572
private static void ThrowToStopOcelotStarting(Response config)
76-
{
77-
throw new Exception(
78-
$"Unable to start Ocelot, errors are: {string.Join(',', config.Errors.Select(x => x.ToString()))}");
79-
}
73+
=> throw new Exception($"Unable to start Ocelot, errors are: {string.Join(',', config.Errors.Select(x => x.ToString()))}");
8074

8175
private static bool IsError(Response response)
82-
{
83-
return response == null || response.IsError;
84-
}
76+
=> response == null || response.IsError;
8577

8678
private static bool ConfigNotStoredInConsul(Response<FileConfiguration> fileConfigFromConsul)
87-
{
88-
return fileConfigFromConsul.Data == null;
89-
}
79+
=> fileConfigFromConsul.Data == null;
9080
}

src/Ocelot.Provider.Consul/ConsulProviderFactory.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Ocelot.Provider.Consul;
88
public static class ConsulProviderFactory
99
{
1010
/// <summary>
11-
/// String constant used for provider type definition.
11+
/// String constant used for provider type definition.
1212
/// </summary>
1313
public const string PollConsul = nameof(Provider.Consul.PollConsul);
1414

@@ -32,17 +32,14 @@ private static IServiceDiscoveryProvider CreateProvider(IServiceProvider provide
3232
{
3333
lock (LockObject)
3434
{
35-
var discoveryProvider =
36-
ServiceDiscoveryProviders.FirstOrDefault(x => x.ServiceName == route.ServiceName);
35+
var discoveryProvider = ServiceDiscoveryProviders.FirstOrDefault(x => x.ServiceName == route.ServiceName);
3736
if (discoveryProvider != null)
3837
{
3938
return discoveryProvider;
4039
}
4140

42-
discoveryProvider = new PollConsul(
43-
config.PollingInterval, route.ServiceName, factory, consulProvider);
41+
discoveryProvider = new PollConsul(config.PollingInterval, route.ServiceName, factory, consulProvider);
4442
ServiceDiscoveryProviders.Add(discoveryProvider);
45-
4643
return discoveryProvider;
4744
}
4845
}

src/Ocelot.Provider.Consul/ConsulRegistryConfiguration.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22

33
public class ConsulRegistryConfiguration
44
{
5+
/// <summary>
6+
/// Consul HTTP client default port.
7+
/// <para>
8+
/// HashiCorp Developer docs: <see href="https://developer.hashicorp.com/consul">Consul</see> | <see href="https://developer.hashicorp.com/consul/docs/install/ports">Required Ports</see>.
9+
/// </para>
10+
/// </summary>
11+
public const int DefaultHttpPort = 8500;
12+
513
public ConsulRegistryConfiguration(string scheme, string host, int port, string keyOfServiceInConsul, string token)
614
{
715
Host = string.IsNullOrEmpty(host) ? "localhost" : host;
8-
Port = port > 0 ? port : 8500;
9-
Scheme = string.IsNullOrEmpty(scheme) ? "http" : scheme;
16+
Port = port > 0 ? port : DefaultHttpPort;
17+
Scheme = string.IsNullOrEmpty(scheme) ? Uri.UriSchemeHttp : scheme;
1018
KeyOfServiceInConsul = keyOfServiceInConsul;
1119
Token = token;
1220
}

src/Ocelot.Provider.Consul/OcelotBuilderExtensions.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@ public static class OcelotBuilderExtensions
99
{
1010
public static IOcelotBuilder AddConsul(this IOcelotBuilder builder)
1111
{
12-
builder.Services.AddSingleton(ConsulProviderFactory.Get);
13-
builder.Services.AddSingleton<IConsulClientFactory, ConsulClientFactory>();
14-
builder.Services.RemoveAll(typeof(IFileConfigurationPollerOptions));
15-
builder.Services.AddSingleton<IFileConfigurationPollerOptions, ConsulFileConfigurationPollerOption>();
12+
builder.Services
13+
.AddSingleton(ConsulProviderFactory.Get)
14+
.AddSingleton<IConsulClientFactory, ConsulClientFactory>()
15+
.RemoveAll(typeof(IFileConfigurationPollerOptions))
16+
.AddSingleton<IFileConfigurationPollerOptions, ConsulFileConfigurationPollerOption>();
1617
return builder;
1718
}
1819

1920
public static IOcelotBuilder AddConfigStoredInConsul(this IOcelotBuilder builder)
2021
{
21-
builder.Services.AddSingleton(ConsulMiddlewareConfigurationProvider.Get);
22-
builder.Services.AddHostedService<FileConfigurationPoller>();
23-
builder.Services.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>();
22+
builder.Services
23+
.AddSingleton(ConsulMiddlewareConfigurationProvider.Get)
24+
.AddHostedService<FileConfigurationPoller>()
25+
.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>();
2426
return builder;
2527
}
2628
}

0 commit comments

Comments
 (0)