mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-20 08:02:50 +08:00
wip tests failing
This commit is contained in:
parent
6eed692c29
commit
32551624bb
@ -1,35 +1,35 @@
|
|||||||
namespace Ocelot.Provider.Eureka
|
namespace Ocelot.Provider.Eureka
|
||||||
{
|
{
|
||||||
using ServiceDiscovery.Providers;
|
using Ocelot.ServiceDiscovery.Providers;
|
||||||
using Steeltoe.Common.Discovery;
|
using Steeltoe.Discovery;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Values;
|
using Ocelot.Values;
|
||||||
|
|
||||||
public class Eureka : IServiceDiscoveryProvider
|
public class Eureka : IServiceDiscoveryProvider
|
||||||
{
|
{
|
||||||
private readonly IDiscoveryClient _client;
|
private readonly IDiscoveryClient _client;
|
||||||
private readonly string _serviceName;
|
private readonly string _serviceName;
|
||||||
|
|
||||||
public Eureka(string serviceName, IDiscoveryClient client)
|
public Eureka(string serviceName, IDiscoveryClient client)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_serviceName = serviceName;
|
_serviceName = serviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<Service>> Get()
|
public Task<List<Service>> Get()
|
||||||
{
|
{
|
||||||
var services = new List<Service>();
|
var services = new List<Service>();
|
||||||
|
|
||||||
var instances = _client.GetInstances(_serviceName);
|
var instances = _client.GetInstances(_serviceName);
|
||||||
|
|
||||||
if (instances != null && instances.Any())
|
if (instances != null && instances.Any())
|
||||||
{
|
{
|
||||||
services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>())));
|
services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(services);
|
return Task.FromResult(services);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
namespace Ocelot.Provider.Eureka
|
namespace Ocelot.Provider.Eureka
|
||||||
{
|
{
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using ServiceDiscovery;
|
using Ocelot.ServiceDiscovery;
|
||||||
using Steeltoe.Common.Discovery;
|
using Steeltoe.Discovery;
|
||||||
|
|
||||||
public static class EurekaProviderFactory
|
public static class EurekaProviderFactory
|
||||||
{
|
{
|
||||||
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
|
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
|
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" />
|
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -96,8 +96,13 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/users"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/users"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("UserId: 1231231"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("UserId: 1231231"))
|
||||||
.And(x => _downstreamFinalPath.ShouldBe("/users/1231231"))
|
.And(x => ThenTheDownstreamPathIs("/users/1231231"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheDownstreamPathIs(string path)
|
||||||
|
{
|
||||||
|
_downstreamFinalPath.ShouldBe(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||||
|
@ -1,60 +1,60 @@
|
|||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using IdentityServer4.Models;
|
using IdentityServer4.Models;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.AcceptanceTests
|
namespace Ocelot.AcceptanceTests
|
||||||
{
|
{
|
||||||
using IdentityServer4.Test;
|
using IdentityServer4.Test;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
|
|
||||||
public class ClaimsToQueryStringForwardingTests : IDisposable
|
public class ClaimsToQueryStringForwardingTests : IDisposable
|
||||||
{
|
{
|
||||||
private IWebHost _servicebuilder;
|
private IWebHost _servicebuilder;
|
||||||
private IWebHost _identityServerBuilder;
|
private IWebHost _identityServerBuilder;
|
||||||
private readonly Steps _steps;
|
private readonly Steps _steps;
|
||||||
private Action<IdentityServerAuthenticationOptions> _options;
|
private Action<IdentityServerAuthenticationOptions> _options;
|
||||||
private string _identityServerRootUrl;
|
private string _identityServerRootUrl;
|
||||||
private string _downstreamQueryString;
|
private string _downstreamQueryString;
|
||||||
|
|
||||||
public ClaimsToQueryStringForwardingTests()
|
public ClaimsToQueryStringForwardingTests()
|
||||||
{
|
{
|
||||||
_steps = new Steps();
|
_steps = new Steps();
|
||||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||||
_options = o =>
|
_options = o =>
|
||||||
{
|
{
|
||||||
o.Authority = _identityServerRootUrl;
|
o.Authority = _identityServerRootUrl;
|
||||||
o.ApiName = "api";
|
o.ApiName = "api";
|
||||||
o.RequireHttpsMetadata = false;
|
o.RequireHttpsMetadata = false;
|
||||||
o.SupportedTokens = SupportedTokens.Both;
|
o.SupportedTokens = SupportedTokens.Both;
|
||||||
o.ApiSecret = "secret";
|
o.ApiSecret = "secret";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_response_200_and_foward_claim_as_query_string()
|
public void should_return_response_200_and_foward_claim_as_query_string()
|
||||||
{
|
{
|
||||||
var user = new TestUser()
|
var user = new TestUser()
|
||||||
{
|
{
|
||||||
Username = "test",
|
Username = "test",
|
||||||
Password = "test",
|
Password = "test",
|
||||||
SubjectId = "registered|1231231",
|
SubjectId = "registered|1231231",
|
||||||
Claims = new List<Claim>
|
Claims = new List<Claim>
|
||||||
{
|
{
|
||||||
new Claim("CustomerId", "123"),
|
new Claim("CustomerId", "123"),
|
||||||
new Claim("LocationId", "1")
|
new Claim("LocationId", "1")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,38 +62,38 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
var configuration = new FileConfiguration
|
var configuration = new FileConfiguration
|
||||||
{
|
{
|
||||||
Routes = new List<FileRoute>
|
Routes = new List<FileRoute>
|
||||||
{
|
{
|
||||||
new FileRoute
|
new FileRoute
|
||||||
{
|
{
|
||||||
DownstreamPathTemplate = "/",
|
DownstreamPathTemplate = "/",
|
||||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
{
|
{
|
||||||
new FileHostAndPort
|
new FileHostAndPort
|
||||||
{
|
{
|
||||||
Host = "localhost",
|
Host = "localhost",
|
||||||
Port = port,
|
Port = port,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DownstreamScheme = "http",
|
DownstreamScheme = "http",
|
||||||
UpstreamPathTemplate = "/",
|
UpstreamPathTemplate = "/",
|
||||||
UpstreamHttpMethod = new List<string> { "Get" },
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
AuthenticationOptions = new FileAuthenticationOptions
|
AuthenticationOptions = new FileAuthenticationOptions
|
||||||
{
|
{
|
||||||
AuthenticationProviderKey = "Test",
|
AuthenticationProviderKey = "Test",
|
||||||
AllowedScopes = new List<string>
|
AllowedScopes = new List<string>
|
||||||
{
|
{
|
||||||
"openid", "offline_access", "api"
|
"openid", "offline_access", "api"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AddQueriesToRequest =
|
AddQueriesToRequest =
|
||||||
{
|
{
|
||||||
{"CustomerId", "Claims[CustomerId] > value"},
|
{"CustomerId", "Claims[CustomerId] > value"},
|
||||||
{"LocationId", "Claims[LocationId] > value"},
|
{"LocationId", "Claims[LocationId] > value"},
|
||||||
{"UserType", "Claims[sub] > value[0] > |"},
|
{"UserType", "Claims[sub] > value[0] > |"},
|
||||||
{"UserId", "Claims[sub] > value[1] > |"}
|
{"UserId", "Claims[sub] > value[1] > |"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,21 +106,21 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_response_200_and_foward_claim_as_query_string_and_preserve_original_string()
|
public void should_return_response_200_and_foward_claim_as_query_string_and_preserve_original_string()
|
||||||
{
|
{
|
||||||
var user = new TestUser()
|
var user = new TestUser()
|
||||||
{
|
{
|
||||||
Username = "test",
|
Username = "test",
|
||||||
Password = "test",
|
Password = "test",
|
||||||
SubjectId = "registered|1231231",
|
SubjectId = "registered|1231231",
|
||||||
Claims = new List<Claim>
|
Claims = new List<Claim>
|
||||||
{
|
{
|
||||||
new Claim("CustomerId", "123"),
|
new Claim("CustomerId", "123"),
|
||||||
new Claim("LocationId", "1")
|
new Claim("LocationId", "1")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,38 +128,38 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
var configuration = new FileConfiguration
|
var configuration = new FileConfiguration
|
||||||
{
|
{
|
||||||
Routes = new List<FileRoute>
|
Routes = new List<FileRoute>
|
||||||
{
|
{
|
||||||
new FileRoute
|
new FileRoute
|
||||||
{
|
{
|
||||||
DownstreamPathTemplate = "/",
|
DownstreamPathTemplate = "/",
|
||||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
{
|
{
|
||||||
new FileHostAndPort
|
new FileHostAndPort
|
||||||
{
|
{
|
||||||
Host = "localhost",
|
Host = "localhost",
|
||||||
Port = port,
|
Port = port,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DownstreamScheme = "http",
|
DownstreamScheme = "http",
|
||||||
UpstreamPathTemplate = "/",
|
UpstreamPathTemplate = "/",
|
||||||
UpstreamHttpMethod = new List<string> { "Get" },
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
AuthenticationOptions = new FileAuthenticationOptions
|
AuthenticationOptions = new FileAuthenticationOptions
|
||||||
{
|
{
|
||||||
AuthenticationProviderKey = "Test",
|
AuthenticationProviderKey = "Test",
|
||||||
AllowedScopes = new List<string>
|
AllowedScopes = new List<string>
|
||||||
{
|
{
|
||||||
"openid", "offline_access", "api"
|
"openid", "offline_access", "api"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AddQueriesToRequest =
|
AddQueriesToRequest =
|
||||||
{
|
{
|
||||||
{"CustomerId", "Claims[CustomerId] > value"},
|
{"CustomerId", "Claims[CustomerId] > value"},
|
||||||
{"LocationId", "Claims[LocationId] > value"},
|
{"LocationId", "Claims[LocationId] > value"},
|
||||||
{"UserType", "Claims[sub] > value[0] > |"},
|
{"UserType", "Claims[sub] > value[0] > |"},
|
||||||
{"UserId", "Claims[sub] > value[1] > |"}
|
{"UserId", "Claims[sub] > value[1] > |"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,120 +172,125 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/?test=1&test=2"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/?test=1&test=2"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
||||||
.And(_ => _downstreamQueryString.ShouldBe("?test=1&test=2&CustomerId=123&LocationId=1&UserId=1231231&UserType=registered"))
|
.And(_ => ThenTheQueryStringIs("?test=1&test=2&CustomerId=123&LocationId=1&UserId=1231231&UserType=registered"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
private void ThenTheQueryStringIs(string queryString)
|
||||||
{
|
{
|
||||||
_servicebuilder = new WebHostBuilder()
|
_downstreamQueryString.ShouldBe(queryString);
|
||||||
.UseUrls(url)
|
}
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||||
.UseIISIntegration()
|
{
|
||||||
.UseUrls(url)
|
_servicebuilder = new WebHostBuilder()
|
||||||
.Configure(app =>
|
.UseUrls(url)
|
||||||
{
|
.UseKestrel()
|
||||||
app.Run(async context =>
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
{
|
.UseIISIntegration()
|
||||||
_downstreamQueryString = context.Request.QueryString.Value;
|
.UseUrls(url)
|
||||||
|
.Configure(app =>
|
||||||
StringValues customerId;
|
{
|
||||||
context.Request.Query.TryGetValue("CustomerId", out customerId);
|
app.Run(async context =>
|
||||||
|
{
|
||||||
StringValues locationId;
|
_downstreamQueryString = context.Request.QueryString.Value;
|
||||||
context.Request.Query.TryGetValue("LocationId", out locationId);
|
|
||||||
|
StringValues customerId;
|
||||||
StringValues userType;
|
context.Request.Query.TryGetValue("CustomerId", out customerId);
|
||||||
context.Request.Query.TryGetValue("UserType", out userType);
|
|
||||||
|
StringValues locationId;
|
||||||
StringValues userId;
|
context.Request.Query.TryGetValue("LocationId", out locationId);
|
||||||
context.Request.Query.TryGetValue("UserId", out userId);
|
|
||||||
|
StringValues userType;
|
||||||
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
|
context.Request.Query.TryGetValue("UserType", out userType);
|
||||||
context.Response.StatusCode = statusCode;
|
|
||||||
await context.Response.WriteAsync(responseBody);
|
StringValues userId;
|
||||||
});
|
context.Request.Query.TryGetValue("UserId", out userId);
|
||||||
})
|
|
||||||
.Build();
|
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
|
||||||
|
context.Response.StatusCode = statusCode;
|
||||||
_servicebuilder.Start();
|
await context.Response.WriteAsync(responseBody);
|
||||||
}
|
});
|
||||||
|
})
|
||||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
.Build();
|
||||||
{
|
|
||||||
_identityServerBuilder = new WebHostBuilder()
|
_servicebuilder.Start();
|
||||||
.UseUrls(url)
|
}
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||||
.UseIISIntegration()
|
{
|
||||||
.UseUrls(url)
|
_identityServerBuilder = new WebHostBuilder()
|
||||||
.ConfigureServices(services =>
|
.UseUrls(url)
|
||||||
{
|
.UseKestrel()
|
||||||
services.AddLogging();
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
services.AddIdentityServer()
|
.UseIISIntegration()
|
||||||
.AddDeveloperSigningCredential()
|
.UseUrls(url)
|
||||||
.AddInMemoryApiResources(new List<ApiResource>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
new ApiResource
|
services.AddLogging();
|
||||||
{
|
services.AddIdentityServer()
|
||||||
Name = apiName,
|
.AddDeveloperSigningCredential()
|
||||||
Description = "My API",
|
.AddInMemoryApiResources(new List<ApiResource>
|
||||||
Enabled = true,
|
{
|
||||||
DisplayName = "test",
|
new ApiResource
|
||||||
Scopes = new List<Scope>()
|
{
|
||||||
{
|
Name = apiName,
|
||||||
new Scope("api"),
|
Description = "My API",
|
||||||
new Scope("openid"),
|
Enabled = true,
|
||||||
new Scope("offline_access")
|
DisplayName = "test",
|
||||||
},
|
Scopes = new List<Scope>()
|
||||||
ApiSecrets = new List<Secret>()
|
{
|
||||||
{
|
new Scope("api"),
|
||||||
new Secret
|
new Scope("openid"),
|
||||||
{
|
new Scope("offline_access")
|
||||||
Value = "secret".Sha256()
|
},
|
||||||
}
|
ApiSecrets = new List<Secret>()
|
||||||
},
|
{
|
||||||
UserClaims = new List<string>()
|
new Secret
|
||||||
{
|
{
|
||||||
"CustomerId", "LocationId", "UserType", "UserId"
|
Value = "secret".Sha256()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
UserClaims = new List<string>()
|
||||||
.AddInMemoryClients(new List<Client>
|
{
|
||||||
{
|
"CustomerId", "LocationId", "UserType", "UserId"
|
||||||
new Client
|
}
|
||||||
{
|
}
|
||||||
ClientId = "client",
|
})
|
||||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
.AddInMemoryClients(new List<Client>
|
||||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
{
|
||||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
new Client
|
||||||
AccessTokenType = tokenType,
|
{
|
||||||
Enabled = true,
|
ClientId = "client",
|
||||||
RequireClientSecret = false
|
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||||
}
|
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||||
})
|
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||||
.AddTestUsers(new List<TestUser>
|
AccessTokenType = tokenType,
|
||||||
{
|
Enabled = true,
|
||||||
user
|
RequireClientSecret = false
|
||||||
});
|
}
|
||||||
})
|
})
|
||||||
.Configure(app =>
|
.AddTestUsers(new List<TestUser>
|
||||||
{
|
{
|
||||||
app.UseIdentityServer();
|
user
|
||||||
})
|
});
|
||||||
.Build();
|
})
|
||||||
|
.Configure(app =>
|
||||||
_identityServerBuilder.Start();
|
{
|
||||||
|
app.UseIdentityServer();
|
||||||
_steps.VerifyIdentiryServerStarted(url);
|
})
|
||||||
}
|
.Build();
|
||||||
|
|
||||||
public void Dispose()
|
_identityServerBuilder.Start();
|
||||||
{
|
|
||||||
_servicebuilder?.Dispose();
|
_steps.VerifyIdentiryServerStarted(url);
|
||||||
_steps.Dispose();
|
}
|
||||||
_identityServerBuilder?.Dispose();
|
|
||||||
}
|
public void Dispose()
|
||||||
}
|
{
|
||||||
|
_servicebuilder?.Dispose();
|
||||||
|
_steps.Dispose();
|
||||||
|
_identityServerBuilder?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
.And(x => cache.Count.ShouldBe(1))
|
.And(x => ThenTheCountShouldBe(cache, 1))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,10 +122,15 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
.And(x => cache.Count.ShouldBe(2))
|
.And(x => ThenTheCountShouldBe(cache, 2))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheCountShouldBe(FakeHttpClientCache cache, int count)
|
||||||
|
{
|
||||||
|
cache.Count.ShouldBe(count);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody)
|
private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody)
|
||||||
{
|
{
|
||||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>
|
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||||
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
|
<PackageReference Include="Shouldly" Version="4.0.1" />
|
||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<PackageReference Include="Consul" Version="1.6.1.1" />
|
<PackageReference Include="Consul" Version="1.6.1.1" />
|
||||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
|
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
|
||||||
<PackageReference Include="CacheManager.Serialization.Json" Version="2.0.0-beta-1629" />
|
<PackageReference Include="CacheManager.Serialization.Json" Version="2.0.0-beta-1629" />
|
||||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" />
|
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||||
|
@ -322,7 +322,7 @@
|
|||||||
.When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home"))
|
.When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home"))
|
||||||
.Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
.And(_ => _receivedToken.ShouldBe(token))
|
.And(_ => ThenTheTokenIs(token))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,6 +462,11 @@
|
|||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheTokenIs(string token)
|
||||||
|
{
|
||||||
|
_receivedToken.ShouldBe(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenIAddAServiceBackIn(ServiceEntry serviceEntryTwo)
|
private void WhenIAddAServiceBackIn(ServiceEntry serviceEntryTwo)
|
||||||
|
@ -57,7 +57,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.And(_ => _steps.StartFakeOcelotWithWebSockets())
|
.And(_ => _steps.StartFakeOcelotWithWebSockets())
|
||||||
.And(_ => StartFakeDownstreamService($"http://{downstreamHost}:{downstreamPort}", "/ws"))
|
.And(_ => StartFakeDownstreamService($"http://{downstreamHost}:{downstreamPort}", "/ws"))
|
||||||
.When(_ => StartClient("ws://localhost:5000/"))
|
.When(_ => StartClient("ws://localhost:5000/"))
|
||||||
.Then(_ => _firstRecieved.Count.ShouldBe(10))
|
.Then(_ => ThenTheReceivedCountIs(10))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,8 +323,12 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheReceivedCountIs(int count)
|
||||||
|
{
|
||||||
|
_firstRecieved.Count.ShouldBe(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_serviceHandler?.Dispose();
|
_serviceHandler?.Dispose();
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@ -48,7 +48,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
|
<PackageReference Include="Shouldly" Version="4.0.1" />
|
||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="Microsoft.Data.SQLite" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Data.SQLite" Version="5.0.0" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||||
|
@ -1,299 +1,304 @@
|
|||||||
namespace Ocelot.UnitTests.Consul
|
namespace Ocelot.UnitTests.Consul
|
||||||
{
|
{
|
||||||
using global::Consul;
|
using global::Consul;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Provider.Consul;
|
using Provider.Consul;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Values;
|
using Values;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class ConsulServiceDiscoveryProviderTests : IDisposable
|
public class ConsulServiceDiscoveryProviderTests : IDisposable
|
||||||
{
|
{
|
||||||
private IWebHost _fakeConsulBuilder;
|
private IWebHost _fakeConsulBuilder;
|
||||||
private readonly List<ServiceEntry> _serviceEntries;
|
private readonly List<ServiceEntry> _serviceEntries;
|
||||||
private Consul _provider;
|
private Consul _provider;
|
||||||
private readonly string _serviceName;
|
private readonly string _serviceName;
|
||||||
private readonly int _port;
|
private readonly int _port;
|
||||||
private readonly string _consulHost;
|
private readonly string _consulHost;
|
||||||
private readonly string _consulScheme;
|
private readonly string _consulScheme;
|
||||||
private readonly string _fakeConsulServiceDiscoveryUrl;
|
private readonly string _fakeConsulServiceDiscoveryUrl;
|
||||||
private List<Service> _services;
|
private List<Service> _services;
|
||||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||||
private readonly Mock<IOcelotLogger> _logger;
|
private readonly Mock<IOcelotLogger> _logger;
|
||||||
private string _receivedToken;
|
private string _receivedToken;
|
||||||
private readonly IConsulClientFactory _clientFactory;
|
private readonly IConsulClientFactory _clientFactory;
|
||||||
|
|
||||||
public ConsulServiceDiscoveryProviderTests()
|
public ConsulServiceDiscoveryProviderTests()
|
||||||
{
|
{
|
||||||
_serviceName = "test";
|
_serviceName = "test";
|
||||||
_port = 8500;
|
_port = 8500;
|
||||||
_consulHost = "localhost";
|
_consulHost = "localhost";
|
||||||
_consulScheme = "http";
|
_consulScheme = "http";
|
||||||
_fakeConsulServiceDiscoveryUrl = $"{_consulScheme}://{_consulHost}:{_port}";
|
_fakeConsulServiceDiscoveryUrl = $"{_consulScheme}://{_consulHost}:{_port}";
|
||||||
_serviceEntries = new List<ServiceEntry>();
|
_serviceEntries = new List<ServiceEntry>();
|
||||||
_factory = new Mock<IOcelotLoggerFactory>();
|
_factory = new Mock<IOcelotLoggerFactory>();
|
||||||
_clientFactory = new ConsulClientFactory();
|
_clientFactory = new ConsulClientFactory();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_factory.Setup(x => x.CreateLogger<Consul>()).Returns(_logger.Object);
|
_factory.Setup(x => x.CreateLogger<Consul>()).Returns(_logger.Object);
|
||||||
_factory.Setup(x => x.CreateLogger<PollConsul>()).Returns(_logger.Object);
|
_factory.Setup(x => x.CreateLogger<PollConsul>()).Returns(_logger.Object);
|
||||||
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, null);
|
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, null);
|
||||||
_provider = new Consul(config, _factory.Object, _clientFactory);
|
_provider = new Consul(config, _factory.Object, _clientFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_service_from_consul()
|
||||||
|
{
|
||||||
|
var serviceEntryOne = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "localhost",
|
||||||
|
Port = 50881,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
||||||
|
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
|
||||||
|
.When(x => WhenIGetTheServices())
|
||||||
|
.Then(x => ThenTheCountIs(1))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_use_token()
|
||||||
|
{
|
||||||
|
var token = "test token";
|
||||||
|
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, token);
|
||||||
|
_provider = new Consul(config, _factory.Object, _clientFactory);
|
||||||
|
|
||||||
|
var serviceEntryOne = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "localhost",
|
||||||
|
Port = 50881,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
||||||
|
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
|
||||||
|
.When(_ => WhenIGetTheServices())
|
||||||
|
.Then(_ => ThenTheCountIs(1))
|
||||||
|
.And(_ => ThenTheTokenIs(token))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_return_services_with_invalid_address()
|
||||||
|
{
|
||||||
|
var serviceEntryOne = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "http://localhost",
|
||||||
|
Port = 50881,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var serviceEntryTwo = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "http://localhost",
|
||||||
|
Port = 50888,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
||||||
|
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
||||||
|
.When(x => WhenIGetTheServices())
|
||||||
|
.Then(x => ThenTheCountIs(0))
|
||||||
|
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_return_services_with_empty_address()
|
||||||
|
{
|
||||||
|
var serviceEntryOne = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "",
|
||||||
|
Port = 50881,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var serviceEntryTwo = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = null,
|
||||||
|
Port = 50888,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
||||||
|
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
||||||
|
.When(x => WhenIGetTheServices())
|
||||||
|
.Then(x => ThenTheCountIs(0))
|
||||||
|
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_return_services_with_invalid_port()
|
||||||
|
{
|
||||||
|
var serviceEntryOne = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "localhost",
|
||||||
|
Port = -1,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var serviceEntryTwo = new ServiceEntry()
|
||||||
|
{
|
||||||
|
Service = new AgentService()
|
||||||
|
{
|
||||||
|
Service = _serviceName,
|
||||||
|
Address = "localhost",
|
||||||
|
Port = 0,
|
||||||
|
ID = Guid.NewGuid().ToString(),
|
||||||
|
Tags = new string[0]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
||||||
|
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
||||||
|
.When(x => WhenIGetTheServices())
|
||||||
|
.Then(x => ThenTheCountIs(0))
|
||||||
|
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
|
||||||
|
{
|
||||||
|
_logger.Verify(
|
||||||
|
x => x.LogWarning(
|
||||||
|
"Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
||||||
|
Times.Once);
|
||||||
|
|
||||||
|
_logger.Verify(
|
||||||
|
x => x.LogWarning(
|
||||||
|
"Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress()
|
||||||
|
{
|
||||||
|
_logger.Verify(
|
||||||
|
x => x.LogWarning(
|
||||||
|
"Unable to use service Address: and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
||||||
|
Times.Once);
|
||||||
|
|
||||||
|
_logger.Verify(
|
||||||
|
x => x.LogWarning(
|
||||||
|
"Unable to use service Address: and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
|
||||||
|
{
|
||||||
|
_logger.Verify(
|
||||||
|
x => x.LogWarning(
|
||||||
|
"Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
||||||
|
Times.Once);
|
||||||
|
|
||||||
|
_logger.Verify(
|
||||||
|
x => x.LogWarning(
|
||||||
|
"Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheCountIs(int count)
|
||||||
|
{
|
||||||
|
_services.Count.ShouldBe(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIGetTheServices()
|
||||||
|
{
|
||||||
|
_services = _provider.Get().GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
private void ThenTheTokenIs(string token)
|
||||||
public void should_return_service_from_consul()
|
|
||||||
{
|
{
|
||||||
var serviceEntryOne = new ServiceEntry()
|
_receivedToken.ShouldBe(token);
|
||||||
{
|
}
|
||||||
Service = new AgentService()
|
|
||||||
{
|
private void GivenTheServicesAreRegisteredWithConsul(params ServiceEntry[] serviceEntries)
|
||||||
Service = _serviceName,
|
{
|
||||||
Address = "localhost",
|
foreach (var serviceEntry in serviceEntries)
|
||||||
Port = 50881,
|
{
|
||||||
ID = Guid.NewGuid().ToString(),
|
_serviceEntries.Add(serviceEntry);
|
||||||
Tags = new string[0]
|
}
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url, string serviceName)
|
||||||
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
{
|
||||||
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
|
_fakeConsulBuilder = new WebHostBuilder()
|
||||||
.When(x => WhenIGetTheServices())
|
.UseUrls(url)
|
||||||
.Then(x => ThenTheCountIs(1))
|
.UseKestrel()
|
||||||
.BDDfy();
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
}
|
.UseIISIntegration()
|
||||||
|
.UseUrls(url)
|
||||||
[Fact]
|
.Configure(app =>
|
||||||
public void should_use_token()
|
{
|
||||||
{
|
app.Run(async context =>
|
||||||
var token = "test token";
|
{
|
||||||
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, token);
|
if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
|
||||||
_provider = new Consul(config, _factory.Object, _clientFactory);
|
{
|
||||||
|
if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
|
||||||
var serviceEntryOne = new ServiceEntry()
|
{
|
||||||
{
|
_receivedToken = values.First();
|
||||||
Service = new AgentService()
|
}
|
||||||
{
|
|
||||||
Service = _serviceName,
|
var json = JsonConvert.SerializeObject(_serviceEntries);
|
||||||
Address = "localhost",
|
context.Response.Headers.Add("Content-Type", "application/json");
|
||||||
Port = 50881,
|
await context.Response.WriteAsync(json);
|
||||||
ID = Guid.NewGuid().ToString(),
|
}
|
||||||
Tags = new string[0]
|
});
|
||||||
},
|
})
|
||||||
};
|
.Build();
|
||||||
|
|
||||||
this.Given(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
_fakeConsulBuilder.Start();
|
||||||
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
|
}
|
||||||
.When(_ => WhenIGetTheServices())
|
|
||||||
.Then(_ => ThenTheCountIs(1))
|
public void Dispose()
|
||||||
.And(_ => _receivedToken.ShouldBe(token))
|
{
|
||||||
.BDDfy();
|
_fakeConsulBuilder?.Dispose();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[Fact]
|
}
|
||||||
public void should_not_return_services_with_invalid_address()
|
|
||||||
{
|
|
||||||
var serviceEntryOne = new ServiceEntry()
|
|
||||||
{
|
|
||||||
Service = new AgentService()
|
|
||||||
{
|
|
||||||
Service = _serviceName,
|
|
||||||
Address = "http://localhost",
|
|
||||||
Port = 50881,
|
|
||||||
ID = Guid.NewGuid().ToString(),
|
|
||||||
Tags = new string[0]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var serviceEntryTwo = new ServiceEntry()
|
|
||||||
{
|
|
||||||
Service = new AgentService()
|
|
||||||
{
|
|
||||||
Service = _serviceName,
|
|
||||||
Address = "http://localhost",
|
|
||||||
Port = 50888,
|
|
||||||
ID = Guid.NewGuid().ToString(),
|
|
||||||
Tags = new string[0]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
|
||||||
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
|
||||||
.When(x => WhenIGetTheServices())
|
|
||||||
.Then(x => ThenTheCountIs(0))
|
|
||||||
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_not_return_services_with_empty_address()
|
|
||||||
{
|
|
||||||
var serviceEntryOne = new ServiceEntry()
|
|
||||||
{
|
|
||||||
Service = new AgentService()
|
|
||||||
{
|
|
||||||
Service = _serviceName,
|
|
||||||
Address = "",
|
|
||||||
Port = 50881,
|
|
||||||
ID = Guid.NewGuid().ToString(),
|
|
||||||
Tags = new string[0]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var serviceEntryTwo = new ServiceEntry()
|
|
||||||
{
|
|
||||||
Service = new AgentService()
|
|
||||||
{
|
|
||||||
Service = _serviceName,
|
|
||||||
Address = null,
|
|
||||||
Port = 50888,
|
|
||||||
ID = Guid.NewGuid().ToString(),
|
|
||||||
Tags = new string[0]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
|
||||||
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
|
||||||
.When(x => WhenIGetTheServices())
|
|
||||||
.Then(x => ThenTheCountIs(0))
|
|
||||||
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_not_return_services_with_invalid_port()
|
|
||||||
{
|
|
||||||
var serviceEntryOne = new ServiceEntry()
|
|
||||||
{
|
|
||||||
Service = new AgentService()
|
|
||||||
{
|
|
||||||
Service = _serviceName,
|
|
||||||
Address = "localhost",
|
|
||||||
Port = -1,
|
|
||||||
ID = Guid.NewGuid().ToString(),
|
|
||||||
Tags = new string[0]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var serviceEntryTwo = new ServiceEntry()
|
|
||||||
{
|
|
||||||
Service = new AgentService()
|
|
||||||
{
|
|
||||||
Service = _serviceName,
|
|
||||||
Address = "localhost",
|
|
||||||
Port = 0,
|
|
||||||
ID = Guid.NewGuid().ToString(),
|
|
||||||
Tags = new string[0]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
|
|
||||||
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
|
|
||||||
.When(x => WhenIGetTheServices())
|
|
||||||
.Then(x => ThenTheCountIs(0))
|
|
||||||
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
|
|
||||||
{
|
|
||||||
_logger.Verify(
|
|
||||||
x => x.LogWarning(
|
|
||||||
"Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
|
||||||
Times.Once);
|
|
||||||
|
|
||||||
_logger.Verify(
|
|
||||||
x => x.LogWarning(
|
|
||||||
"Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
|
||||||
Times.Once);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress()
|
|
||||||
{
|
|
||||||
_logger.Verify(
|
|
||||||
x => x.LogWarning(
|
|
||||||
"Unable to use service Address: and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
|
||||||
Times.Once);
|
|
||||||
|
|
||||||
_logger.Verify(
|
|
||||||
x => x.LogWarning(
|
|
||||||
"Unable to use service Address: and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
|
||||||
Times.Once);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
|
|
||||||
{
|
|
||||||
_logger.Verify(
|
|
||||||
x => x.LogWarning(
|
|
||||||
"Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
|
||||||
Times.Once);
|
|
||||||
|
|
||||||
_logger.Verify(
|
|
||||||
x => x.LogWarning(
|
|
||||||
"Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
|
|
||||||
Times.Once);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheCountIs(int count)
|
|
||||||
{
|
|
||||||
_services.Count.ShouldBe(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenIGetTheServices()
|
|
||||||
{
|
|
||||||
_services = _provider.Get().GetAwaiter().GetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheServicesAreRegisteredWithConsul(params ServiceEntry[] serviceEntries)
|
|
||||||
{
|
|
||||||
foreach (var serviceEntry in serviceEntries)
|
|
||||||
{
|
|
||||||
_serviceEntries.Add(serviceEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url, string serviceName)
|
|
||||||
{
|
|
||||||
_fakeConsulBuilder = new WebHostBuilder()
|
|
||||||
.UseUrls(url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.Run(async context =>
|
|
||||||
{
|
|
||||||
if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
|
|
||||||
{
|
|
||||||
if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
|
|
||||||
{
|
|
||||||
_receivedToken = values.First();
|
|
||||||
}
|
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(_serviceEntries);
|
|
||||||
context.Response.Headers.Add("Content-Type", "application/json");
|
|
||||||
await context.Response.WriteAsync(json);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
_fakeConsulBuilder.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_fakeConsulBuilder?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.Repository;
|
using Ocelot.Configuration.Repository;
|
||||||
using Provider.Eureka;
|
using Ocelot.Provider.Eureka;
|
||||||
using Responses;
|
using Ocelot.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using Steeltoe.Common.Discovery;
|
using Steeltoe.Discovery;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Provider.Eureka;
|
using Provider.Eureka;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using Steeltoe.Common.Discovery;
|
using Steeltoe.Discovery;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class EurekaProviderFactoryTests
|
public class EurekaProviderFactoryTests
|
||||||
|
@ -1,117 +1,118 @@
|
|||||||
namespace Ocelot.UnitTests.Eureka
|
namespace Ocelot.UnitTests.Eureka
|
||||||
{
|
{
|
||||||
using Moq;
|
using Moq;
|
||||||
using Provider.Eureka;
|
using Ocelot.Provider.Eureka;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using Steeltoe.Common.Discovery;
|
using Steeltoe.Common.Discovery;
|
||||||
using System;
|
using Steeltoe.Discovery;
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Collections.Generic;
|
||||||
using TestStack.BDDfy;
|
using System.Threading.Tasks;
|
||||||
using Values;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Ocelot.Values;
|
||||||
|
using Xunit;
|
||||||
public class EurekaServiceDiscoveryProviderTests
|
|
||||||
{
|
public class EurekaServiceDiscoveryProviderTests
|
||||||
private readonly Eureka _provider;
|
{
|
||||||
private readonly Mock<IDiscoveryClient> _client;
|
private readonly Eureka _provider;
|
||||||
private readonly string _serviceId;
|
private readonly Mock<IDiscoveryClient> _client;
|
||||||
private List<IServiceInstance> _instances;
|
private readonly string _serviceId;
|
||||||
private List<Service> _result;
|
private List<IServiceInstance> _instances;
|
||||||
|
private List<Service> _result;
|
||||||
public EurekaServiceDiscoveryProviderTests()
|
|
||||||
{
|
public EurekaServiceDiscoveryProviderTests()
|
||||||
_serviceId = "Laura";
|
{
|
||||||
_client = new Mock<IDiscoveryClient>();
|
_serviceId = "Laura";
|
||||||
_provider = new Eureka(_serviceId, _client.Object);
|
_client = new Mock<IDiscoveryClient>();
|
||||||
}
|
_provider = new Eureka(_serviceId, _client.Object);
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_return_empty_services()
|
[Fact]
|
||||||
{
|
public void should_return_empty_services()
|
||||||
this.When(_ => WhenIGet())
|
{
|
||||||
.Then(_ => ThenTheCountIs(0))
|
this.When(_ => WhenIGet())
|
||||||
.BDDfy();
|
.Then(_ => ThenTheCountIs(0))
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_return_service_from_client()
|
[Fact]
|
||||||
{
|
public void should_return_service_from_client()
|
||||||
var instances = new List<IServiceInstance>
|
{
|
||||||
{
|
var instances = new List<IServiceInstance>
|
||||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
{
|
||||||
};
|
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
||||||
|
};
|
||||||
this.Given(_ => GivenThe(instances))
|
|
||||||
.When(_ => WhenIGet())
|
this.Given(_ => GivenThe(instances))
|
||||||
.Then(_ => ThenTheCountIs(1))
|
.When(_ => WhenIGet())
|
||||||
.And(_ => ThenTheClientIsCalledCorrectly())
|
.Then(_ => ThenTheCountIs(1))
|
||||||
.And(_ => ThenTheServiceIsMapped())
|
.And(_ => ThenTheClientIsCalledCorrectly())
|
||||||
.BDDfy();
|
.And(_ => ThenTheServiceIsMapped())
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_return_services_from_client()
|
[Fact]
|
||||||
{
|
public void should_return_services_from_client()
|
||||||
var instances = new List<IServiceInstance>
|
{
|
||||||
{
|
var instances = new List<IServiceInstance>
|
||||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()),
|
{
|
||||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()),
|
||||||
};
|
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
||||||
|
};
|
||||||
this.Given(_ => GivenThe(instances))
|
|
||||||
.When(_ => WhenIGet())
|
this.Given(_ => GivenThe(instances))
|
||||||
.Then(_ => ThenTheCountIs(2))
|
.When(_ => WhenIGet())
|
||||||
.And(_ => ThenTheClientIsCalledCorrectly())
|
.Then(_ => ThenTheCountIs(2))
|
||||||
.BDDfy();
|
.And(_ => ThenTheClientIsCalledCorrectly())
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
private void ThenTheServiceIsMapped()
|
|
||||||
{
|
private void ThenTheServiceIsMapped()
|
||||||
_result[0].HostAndPort.DownstreamHost.ShouldBe("somehost");
|
{
|
||||||
_result[0].HostAndPort.DownstreamPort.ShouldBe(801);
|
_result[0].HostAndPort.DownstreamHost.ShouldBe("somehost");
|
||||||
_result[0].Name.ShouldBe(_serviceId);
|
_result[0].HostAndPort.DownstreamPort.ShouldBe(801);
|
||||||
}
|
_result[0].Name.ShouldBe(_serviceId);
|
||||||
|
}
|
||||||
private void ThenTheCountIs(int expected)
|
|
||||||
{
|
private void ThenTheCountIs(int expected)
|
||||||
_result.Count.ShouldBe(expected);
|
{
|
||||||
}
|
_result.Count.ShouldBe(expected);
|
||||||
|
}
|
||||||
private void ThenTheClientIsCalledCorrectly()
|
|
||||||
{
|
private void ThenTheClientIsCalledCorrectly()
|
||||||
_client.Verify(x => x.GetInstances(_serviceId), Times.Once);
|
{
|
||||||
}
|
_client.Verify(x => x.GetInstances(_serviceId), Times.Once);
|
||||||
|
}
|
||||||
private async Task WhenIGet()
|
|
||||||
{
|
private async Task WhenIGet()
|
||||||
_result = await _provider.Get();
|
{
|
||||||
}
|
_result = await _provider.Get();
|
||||||
|
}
|
||||||
private void GivenThe(List<IServiceInstance> instances)
|
|
||||||
{
|
private void GivenThe(List<IServiceInstance> instances)
|
||||||
_instances = instances;
|
{
|
||||||
_client.Setup(x => x.GetInstances(It.IsAny<string>())).Returns(instances);
|
_instances = instances;
|
||||||
}
|
_client.Setup(x => x.GetInstances(It.IsAny<string>())).Returns(instances);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public class EurekaService : IServiceInstance
|
|
||||||
{
|
public class EurekaService : IServiceInstance
|
||||||
public EurekaService(string serviceId, string host, int port, bool isSecure, Uri uri, IDictionary<string, string> metadata)
|
{
|
||||||
{
|
public EurekaService(string serviceId, string host, int port, bool isSecure, Uri uri, IDictionary<string, string> metadata)
|
||||||
ServiceId = serviceId;
|
{
|
||||||
Host = host;
|
ServiceId = serviceId;
|
||||||
Port = port;
|
Host = host;
|
||||||
IsSecure = isSecure;
|
Port = port;
|
||||||
Uri = uri;
|
IsSecure = isSecure;
|
||||||
Metadata = metadata;
|
Uri = uri;
|
||||||
}
|
Metadata = metadata;
|
||||||
|
}
|
||||||
public string ServiceId { get; }
|
|
||||||
public string Host { get; }
|
public string ServiceId { get; }
|
||||||
public int Port { get; }
|
public string Host { get; }
|
||||||
public bool IsSecure { get; }
|
public int Port { get; }
|
||||||
public Uri Uri { get; }
|
public bool IsSecure { get; }
|
||||||
public IDictionary<string, string> Metadata { get; }
|
public Uri Uri { get; }
|
||||||
}
|
public IDictionary<string, string> Metadata { get; }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,128 +1,129 @@
|
|||||||
namespace Ocelot.UnitTests.Headers
|
namespace Ocelot.UnitTests.Headers
|
||||||
{
|
{
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Ocelot.Configuration.Creator;
|
using Moq;
|
||||||
using Ocelot.Headers;
|
using Ocelot.Configuration.Creator;
|
||||||
using Ocelot.Infrastructure;
|
using Ocelot.Headers;
|
||||||
using Ocelot.Infrastructure.Claims.Parser;
|
using Ocelot.Infrastructure;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Infrastructure.Claims.Parser;
|
||||||
using Responder;
|
using Ocelot.Logging;
|
||||||
using Responses;
|
using Responder;
|
||||||
using Shouldly;
|
using Responses;
|
||||||
using TestStack.BDDfy;
|
using Shouldly;
|
||||||
using Xunit;
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
public class AddHeadersToRequestPlainTests
|
|
||||||
{
|
public class AddHeadersToRequestPlainTests
|
||||||
private readonly AddHeadersToRequest _addHeadersToRequest;
|
{
|
||||||
private HttpContext _context;
|
private readonly AddHeadersToRequest _addHeadersToRequest;
|
||||||
private AddHeader _addedHeader;
|
private HttpContext _context;
|
||||||
private readonly Mock<IPlaceholders> _placeholders;
|
private AddHeader _addedHeader;
|
||||||
private Mock<IOcelotLoggerFactory> _factory;
|
private readonly Mock<IPlaceholders> _placeholders;
|
||||||
private readonly Mock<IOcelotLogger> _logger;
|
private Mock<IOcelotLoggerFactory> _factory;
|
||||||
|
private readonly Mock<IOcelotLogger> _logger;
|
||||||
public AddHeadersToRequestPlainTests()
|
|
||||||
{
|
public AddHeadersToRequestPlainTests()
|
||||||
_placeholders = new Mock<IPlaceholders>();
|
{
|
||||||
_factory = new Mock<IOcelotLoggerFactory>();
|
_placeholders = new Mock<IPlaceholders>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_factory = new Mock<IOcelotLoggerFactory>();
|
||||||
_factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object);
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object);
|
_factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object);
|
||||||
}
|
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object);
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_log_error_if_cannot_find_placeholder()
|
[Fact]
|
||||||
{
|
public void should_log_error_if_cannot_find_placeholder()
|
||||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
|
{
|
||||||
|
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
|
||||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
|
||||||
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||||
.Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}"))
|
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||||
.BDDfy();
|
.Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_add_placeholder_to_downstream_request()
|
[Fact]
|
||||||
{
|
public void should_add_placeholder_to_downstream_request()
|
||||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced"));
|
{
|
||||||
|
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced"));
|
||||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
|
||||||
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced"))
|
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||||
.BDDfy();
|
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced"))
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_add_plain_text_header_to_downstream_request()
|
[Fact]
|
||||||
{
|
public void should_add_plain_text_header_to_downstream_request()
|
||||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
{
|
||||||
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||||
.BDDfy();
|
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
[Fact]
|
|
||||||
public void should_overwrite_existing_header_with_added_header()
|
[Fact]
|
||||||
{
|
public void should_overwrite_existing_header_with_added_header()
|
||||||
this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten"))
|
{
|
||||||
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten"))
|
||||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||||
.BDDfy();
|
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||||
}
|
.BDDfy();
|
||||||
|
}
|
||||||
private void ThenAnErrorIsLogged(string key, string value)
|
|
||||||
{
|
private void ThenAnErrorIsLogged(string key, string value)
|
||||||
_logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once);
|
{
|
||||||
}
|
_logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once);
|
||||||
|
}
|
||||||
private void GivenHttpRequestWithoutHeaders()
|
|
||||||
{
|
private void GivenHttpRequestWithoutHeaders()
|
||||||
_context = new DefaultHttpContext
|
{
|
||||||
{
|
_context = new DefaultHttpContext
|
||||||
Request =
|
{
|
||||||
{
|
Request =
|
||||||
Headers =
|
{
|
||||||
{
|
Headers =
|
||||||
}
|
{
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
|
|
||||||
{
|
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
|
||||||
_context = new DefaultHttpContext
|
{
|
||||||
{
|
_context = new DefaultHttpContext
|
||||||
Request =
|
{
|
||||||
{
|
Request =
|
||||||
Headers =
|
{
|
||||||
{
|
Headers =
|
||||||
{ headerKey, headerValue }
|
{
|
||||||
}
|
{ headerKey, headerValue }
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
private void WhenAddingHeader(string headerKey, string headerValue)
|
|
||||||
{
|
private void WhenAddingHeader(string headerKey, string headerValue)
|
||||||
_addedHeader = new AddHeader(headerKey, headerValue);
|
{
|
||||||
_addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context);
|
_addedHeader = new AddHeader(headerKey, headerValue);
|
||||||
}
|
_addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context);
|
||||||
|
}
|
||||||
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
|
|
||||||
{
|
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
|
||||||
var requestHeaders = _context.Request.Headers;
|
{
|
||||||
requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there.");
|
var requestHeaders = _context.Request.Headers;
|
||||||
var value = requestHeaders[_addedHeader.Key];
|
requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there.");
|
||||||
value.ShouldNotBeNull($"Value of header {_addedHeader.Key} was expected to not be null.");
|
var value = requestHeaders[_addedHeader.Key];
|
||||||
value.ToString().ShouldBe(_addedHeader.Value);
|
value.ShouldNotBe(default(StringValues), $"Value of header {_addedHeader.Key} was expected to not be null.");
|
||||||
}
|
value.ToString().ShouldBe(_addedHeader.Value);
|
||||||
|
}
|
||||||
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
|
|
||||||
{
|
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
|
||||||
var requestHeaders = _context.Request.Headers;
|
{
|
||||||
var value = requestHeaders[_addedHeader.Key];
|
var requestHeaders = _context.Request.Headers;
|
||||||
value.ToString().ShouldBe(expected);
|
var value = requestHeaders[_addedHeader.Key];
|
||||||
}
|
value.ToString().ShouldBe(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,88 +1,88 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
using Ocelot.Infrastructure.RequestData;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Infrastructure
|
namespace Ocelot.UnitTests.Infrastructure
|
||||||
{
|
{
|
||||||
public class HttpDataRepositoryTests
|
public class HttpDataRepositoryTests
|
||||||
{
|
{
|
||||||
private readonly HttpContext _httpContext;
|
private readonly HttpContext _httpContext;
|
||||||
private IHttpContextAccessor _httpContextAccessor;
|
private IHttpContextAccessor _httpContextAccessor;
|
||||||
private readonly HttpDataRepository _httpDataRepository;
|
private readonly HttpDataRepository _httpDataRepository;
|
||||||
private object _result;
|
private object _result;
|
||||||
|
|
||||||
public HttpDataRepositoryTests()
|
public HttpDataRepositoryTests()
|
||||||
{
|
{
|
||||||
_httpContext = new DefaultHttpContext();
|
_httpContext = new DefaultHttpContext();
|
||||||
_httpContextAccessor = new HttpContextAccessor { HttpContext = _httpContext };
|
_httpContextAccessor = new HttpContextAccessor { HttpContext = _httpContext };
|
||||||
_httpDataRepository = new HttpDataRepository(_httpContextAccessor);
|
_httpDataRepository = new HttpDataRepository(_httpContextAccessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO - Additional tests -> Type mistmatch aka Add string, request int
|
TODO - Additional tests -> Type mistmatch aka Add string, request int
|
||||||
TODO - Additional tests -> HttpContent null. This should never happen
|
TODO - Additional tests -> HttpContent null. This should never happen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void get_returns_correct_key_from_http_context()
|
public void get_returns_correct_key_from_http_context()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||||
.When(x => x.GetIsCalledWithKey<string>("key"))
|
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||||
.Then(x => x.ThenTheResultIsAnOkResponse<string>("string"))
|
.Then(x => x.ThenTheResultIsAnOkResponse<string>("string"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
|
public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||||
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
|
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
|
||||||
.Then(x => x.ThenTheResultIsAnErrorReposnse<string>("string1"))
|
.Then(x => x.ThenTheResultIsAnErrorReposnse<string>("string1"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_update()
|
public void should_update()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||||
.And(x => x.UpdateIsCalledWith<string>("key", "new string"))
|
.And(x => x.UpdateIsCalledWith<string>("key", "new string"))
|
||||||
.When(x => x.GetIsCalledWithKey<string>("key"))
|
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||||
.Then(x => x.ThenTheResultIsAnOkResponse<string>("new string"))
|
.Then(x => x.ThenTheResultIsAnOkResponse<string>("new string"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateIsCalledWith<T>(string key, string value)
|
private void UpdateIsCalledWith<T>(string key, string value)
|
||||||
{
|
{
|
||||||
_httpDataRepository.Update(key, value);
|
_httpDataRepository.Update(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenAHttpContextContaining(string key, object o)
|
private void GivenAHttpContextContaining(string key, object o)
|
||||||
{
|
{
|
||||||
_httpContext.Items.Add(key, o);
|
_httpContext.Items.Add(key, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetIsCalledWithKey<T>(string key)
|
private void GetIsCalledWithKey<T>(string key)
|
||||||
{
|
{
|
||||||
_result = _httpDataRepository.Get<T>(key);
|
_result = _httpDataRepository.Get<T>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheResultIsAnErrorReposnse<T>(object resultValue)
|
private void ThenTheResultIsAnErrorReposnse<T>(object resultValue)
|
||||||
{
|
{
|
||||||
_result.ShouldBeOfType<ErrorResponse<T>>();
|
_result.ShouldBeOfType<ErrorResponse<T>>();
|
||||||
((ErrorResponse<T>)_result).Data.ShouldBeNull();
|
((ErrorResponse<T>)_result).Data.ShouldBe(default(T));
|
||||||
((ErrorResponse<T>)_result).IsError.ShouldBe(true);
|
((ErrorResponse<T>)_result).IsError.ShouldBe(true);
|
||||||
((ErrorResponse<T>)_result).Errors.ShouldHaveSingleItem()
|
((ErrorResponse<T>)_result).Errors.ShouldHaveSingleItem()
|
||||||
.ShouldBeOfType<CannotFindDataError>()
|
.ShouldBeOfType<CannotFindDataError>()
|
||||||
.Message.ShouldStartWith("Unable to find data for key: ");
|
.Message.ShouldStartWith("Unable to find data for key: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheResultIsAnOkResponse<T>(object resultValue)
|
private void ThenTheResultIsAnOkResponse<T>(object resultValue)
|
||||||
{
|
{
|
||||||
_result.ShouldBeOfType<OkResponse<T>>();
|
_result.ShouldBeOfType<OkResponse<T>>();
|
||||||
((OkResponse<T>)_result).Data.ShouldBe(resultValue);
|
((OkResponse<T>)_result).Data.ShouldBe(resultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,149 +1,154 @@
|
|||||||
using KubeClient;
|
using KubeClient;
|
||||||
using KubeClient.Models;
|
using KubeClient.Models;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Provider.Kubernetes;
|
using Ocelot.Provider.Kubernetes;
|
||||||
using Ocelot.Values;
|
using Ocelot.Values;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Kubernetes
|
namespace Ocelot.UnitTests.Kubernetes
|
||||||
{
|
{
|
||||||
public class KubeServiceDiscoveryProviderTests : IDisposable
|
public class KubeServiceDiscoveryProviderTests : IDisposable
|
||||||
{
|
{
|
||||||
private IWebHost _fakeKubeBuilder;
|
private IWebHost _fakeKubeBuilder;
|
||||||
private readonly KubernetesServiceDiscoveryProvider _provider;
|
private readonly KubernetesServiceDiscoveryProvider _provider;
|
||||||
private EndpointsV1 _endpointEntries;
|
private EndpointsV1 _endpointEntries;
|
||||||
private readonly string _serviceName;
|
private readonly string _serviceName;
|
||||||
private readonly string _namespaces;
|
private readonly string _namespaces;
|
||||||
private readonly int _port;
|
private readonly int _port;
|
||||||
private readonly string _kubeHost;
|
private readonly string _kubeHost;
|
||||||
private readonly string _fakekubeServiceDiscoveryUrl;
|
private readonly string _fakekubeServiceDiscoveryUrl;
|
||||||
private List<Service> _services;
|
private List<Service> _services;
|
||||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||||
private readonly Mock<IOcelotLogger> _logger;
|
private readonly Mock<IOcelotLogger> _logger;
|
||||||
private string _receivedToken;
|
private string _receivedToken;
|
||||||
private readonly IKubeApiClient _clientFactory;
|
private readonly IKubeApiClient _clientFactory;
|
||||||
|
|
||||||
public KubeServiceDiscoveryProviderTests()
|
public KubeServiceDiscoveryProviderTests()
|
||||||
{
|
{
|
||||||
_serviceName = "test";
|
_serviceName = "test";
|
||||||
_namespaces = "dev";
|
_namespaces = "dev";
|
||||||
_port = 86;
|
_port = 86;
|
||||||
_kubeHost = "localhost";
|
_kubeHost = "localhost";
|
||||||
_fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}";
|
_fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}";
|
||||||
_endpointEntries = new EndpointsV1();
|
_endpointEntries = new EndpointsV1();
|
||||||
_factory = new Mock<IOcelotLoggerFactory>();
|
_factory = new Mock<IOcelotLoggerFactory>();
|
||||||
|
|
||||||
var option = new KubeClientOptions
|
var option = new KubeClientOptions
|
||||||
{
|
{
|
||||||
ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl),
|
ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl),
|
||||||
AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG",
|
AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG",
|
||||||
AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken,
|
AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken,
|
||||||
AllowInsecure = true,
|
AllowInsecure = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
_clientFactory = KubeApiClient.Create(option);
|
_clientFactory = KubeApiClient.Create(option);
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_factory.Setup(x => x.CreateLogger<KubernetesServiceDiscoveryProvider>()).Returns(_logger.Object);
|
_factory.Setup(x => x.CreateLogger<KubernetesServiceDiscoveryProvider>()).Returns(_logger.Object);
|
||||||
var config = new KubeRegistryConfiguration()
|
var config = new KubeRegistryConfiguration()
|
||||||
{
|
{
|
||||||
KeyOfServiceInK8s = _serviceName,
|
KeyOfServiceInK8s = _serviceName,
|
||||||
KubeNamespace = _namespaces,
|
KubeNamespace = _namespaces,
|
||||||
};
|
};
|
||||||
_provider = new KubernetesServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
|
_provider = new KubernetesServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_service_from_k8s()
|
||||||
|
{
|
||||||
|
var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG";
|
||||||
|
var endPointEntryOne = new EndpointsV1
|
||||||
|
{
|
||||||
|
Kind = "endpoint",
|
||||||
|
ApiVersion = "1.0",
|
||||||
|
Metadata = new ObjectMetaV1()
|
||||||
|
{
|
||||||
|
Namespace = "dev",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var endpointSubsetV1 = new EndpointSubsetV1();
|
||||||
|
endpointSubsetV1.Addresses.Add(new EndpointAddressV1()
|
||||||
|
{
|
||||||
|
Ip = "127.0.0.1",
|
||||||
|
Hostname = "localhost",
|
||||||
|
});
|
||||||
|
endpointSubsetV1.Ports.Add(new EndpointPortV1()
|
||||||
|
{
|
||||||
|
Port = 80,
|
||||||
|
});
|
||||||
|
endPointEntryOne.Subsets.Add(endpointSubsetV1);
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl, _serviceName, _namespaces))
|
||||||
|
.And(x => GivenTheServicesAreRegisteredWithKube(endPointEntryOne))
|
||||||
|
.When(x => WhenIGetTheServices())
|
||||||
|
.Then(x => ThenTheCountIs(1))
|
||||||
|
.And(_ => ThenTheTokenIs(token))
|
||||||
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
private void ThenTheTokenIs(string token)
|
||||||
public void should_return_service_from_k8s()
|
|
||||||
{
|
{
|
||||||
var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG";
|
_receivedToken.ShouldBe(token);
|
||||||
var endPointEntryOne = new EndpointsV1
|
}
|
||||||
{
|
|
||||||
Kind = "endpoint",
|
private void ThenTheCountIs(int count)
|
||||||
ApiVersion = "1.0",
|
{
|
||||||
Metadata = new ObjectMetaV1()
|
_services.Count.ShouldBe(count);
|
||||||
{
|
}
|
||||||
Namespace = "dev",
|
|
||||||
},
|
private void WhenIGetTheServices()
|
||||||
};
|
{
|
||||||
var endpointSubsetV1 = new EndpointSubsetV1();
|
_services = _provider.Get().GetAwaiter().GetResult();
|
||||||
endpointSubsetV1.Addresses.Add(new EndpointAddressV1()
|
}
|
||||||
{
|
|
||||||
Ip = "127.0.0.1",
|
private void GivenTheServicesAreRegisteredWithKube(EndpointsV1 endpointEntries)
|
||||||
Hostname = "localhost",
|
{
|
||||||
});
|
_endpointEntries = endpointEntries;
|
||||||
endpointSubsetV1.Ports.Add(new EndpointPortV1()
|
}
|
||||||
{
|
|
||||||
Port = 80,
|
private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces)
|
||||||
});
|
{
|
||||||
endPointEntryOne.Subsets.Add(endpointSubsetV1);
|
_fakeKubeBuilder = new WebHostBuilder()
|
||||||
|
.UseUrls(url)
|
||||||
this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl, _serviceName, _namespaces))
|
.UseKestrel()
|
||||||
.And(x => GivenTheServicesAreRegisteredWithKube(endPointEntryOne))
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.When(x => WhenIGetTheServices())
|
.UseIISIntegration()
|
||||||
.Then(x => ThenTheCountIs(1))
|
.UseUrls(url)
|
||||||
.And(_ => _receivedToken.ShouldBe(token))
|
.Configure(app =>
|
||||||
.BDDfy();
|
{
|
||||||
}
|
app.Run(async context =>
|
||||||
|
{
|
||||||
private void ThenTheCountIs(int count)
|
if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/endpoints/{serviceName}")
|
||||||
{
|
{
|
||||||
_services.Count.ShouldBe(count);
|
if (context.Request.Headers.TryGetValue("Authorization", out var values))
|
||||||
}
|
{
|
||||||
|
_receivedToken = values.First();
|
||||||
private void WhenIGetTheServices()
|
}
|
||||||
{
|
|
||||||
_services = _provider.Get().GetAwaiter().GetResult();
|
var json = JsonConvert.SerializeObject(_endpointEntries);
|
||||||
}
|
context.Response.Headers.Add("Content-Type", "application/json");
|
||||||
|
await context.Response.WriteAsync(json);
|
||||||
private void GivenTheServicesAreRegisteredWithKube(EndpointsV1 endpointEntries)
|
}
|
||||||
{
|
});
|
||||||
_endpointEntries = endpointEntries;
|
})
|
||||||
}
|
.Build();
|
||||||
|
|
||||||
private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces)
|
_fakeKubeBuilder.Start();
|
||||||
{
|
}
|
||||||
_fakeKubeBuilder = new WebHostBuilder()
|
|
||||||
.UseUrls(url)
|
public void Dispose()
|
||||||
.UseKestrel()
|
{
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
_fakeKubeBuilder?.Dispose();
|
||||||
.UseIISIntegration()
|
}
|
||||||
.UseUrls(url)
|
}
|
||||||
.Configure(app =>
|
}
|
||||||
{
|
|
||||||
app.Run(async context =>
|
|
||||||
{
|
|
||||||
if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/endpoints/{serviceName}")
|
|
||||||
{
|
|
||||||
if (context.Request.Headers.TryGetValue("Authorization", out var values))
|
|
||||||
{
|
|
||||||
_receivedToken = values.First();
|
|
||||||
}
|
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(_endpointEntries);
|
|
||||||
context.Response.Headers.Add("Content-Type", "application/json");
|
|
||||||
await context.Response.WriteAsync(json);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
_fakeKubeBuilder.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_fakeKubeBuilder?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@ -67,13 +67,13 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||||
<PackageReference Include="Moq" Version="4.15.2" />
|
<PackageReference Include="Moq" Version="4.15.2" />
|
||||||
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
|
<PackageReference Include="Shouldly" Version="4.0.1" />
|
||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||||
<PackageReference Include="IdentityServer4" Version="3.1.1" />
|
<PackageReference Include="IdentityServer4" Version="3.1.1" />
|
||||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" />
|
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
|
||||||
<PackageReference Include="Consul" Version="1.6.1.1" />
|
<PackageReference Include="Consul" Version="1.6.1.1" />
|
||||||
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
|
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
|
||||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
|
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
|
||||||
|
@ -452,7 +452,7 @@
|
|||||||
foreach (var header in _mappedRequest.Data.Headers)
|
foreach (var header in _mappedRequest.Data.Headers)
|
||||||
{
|
{
|
||||||
var inputHeader = _inputHeaders.First(h => h.Key == header.Key);
|
var inputHeader = _inputHeaders.First(h => h.Key == header.Key);
|
||||||
inputHeader.ShouldNotBeNull();
|
inputHeader.ShouldNotBe(default(KeyValuePair<string, StringValues>));
|
||||||
inputHeader.Value.Count().ShouldBe(header.Value.Count());
|
inputHeader.Value.Count().ShouldBe(header.Value.Count());
|
||||||
foreach (var inputHeaderValue in inputHeader.Value)
|
foreach (var inputHeaderValue in inputHeader.Value)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user