Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions src/Ocelot.Provider.Kubernetes/EndPointClientV1.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using HTTPlease;
using KubeClient.Http;
using KubeClient.Models;
using KubeClient.ResourceClients;
using Ocelot.Provider.Kubernetes.Interfaces;
Expand All @@ -7,11 +7,10 @@ namespace Ocelot.Provider.Kubernetes;

public class EndPointClientV1 : KubeResourceClient, IEndPointClient
{
private readonly HttpRequest _collection;
private static readonly HttpRequest Collection = KubeRequest.Create("api/v1/namespaces/{Namespace}/endpoints/{ServiceName}");

public EndPointClientV1(IKubeApiClient client) : base(client)
{
_collection = KubeRequest.Create("api/v1/namespaces/{Namespace}/endpoints/{ServiceName}");
}

public async Task<EndpointsV1> GetAsync(string serviceName, string kubeNamespace = null, CancellationToken cancellationToken = default)
Expand All @@ -21,17 +20,14 @@ public async Task<EndpointsV1> GetAsync(string serviceName, string kubeNamespace
throw new ArgumentNullException(nameof(serviceName));
}

var request = _collection
var request = Collection
.WithTemplateParameters(new
{
Namespace = kubeNamespace ?? KubeClient.DefaultNamespace,
ServiceName = serviceName,
});

var response = await Http.GetAsync(request, cancellationToken);

return response.IsSuccessStatusCode
? await response.ReadContentAsAsync<EndpointsV1>()
: null;
return await Http.GetAsync(request, cancellationToken)
.ReadContentAsObjectV1Async<EndpointsV1>(operationDescription: $"get {nameof(EndpointsV1)}");
}
}
41 changes: 38 additions & 3 deletions src/Ocelot.Provider.Kubernetes/Kube.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Ocelot.Provider.Kubernetes;
/// </remarks>
public class Kube : IServiceDiscoveryProvider
{
private static readonly (string ResourceKind, string ResourceApiVersion) EndPointsKubeKind = KubeObjectV1.GetKubeKind<EndpointsV1>();

private readonly KubeRegistryConfiguration _configuration;
private readonly IOcelotLogger _logger;
private readonly IKubeApiClient _kubeApi;
Expand Down Expand Up @@ -46,9 +48,42 @@ public virtual async Task<List<Service>> GetAsync()
.ToList();
}

private Task<EndpointsV1> GetEndpoint() => _kubeApi
.ResourceClient<IEndPointClient>(client => new EndPointClientV1(client))
.GetAsync(_configuration.KeyOfServiceInK8s, _configuration.KubeNamespace);
private async Task<EndpointsV1> GetEndpoint()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved this logic here because it keeps the resource-client implementation cleaner (since it wouldn't otherwise be clear to someone who's not seen this code before what the lifetime of the resource client is, vs the lifetime of the containing type or its logger).

{
string serviceName = _configuration.KeyOfServiceInK8s;
string kubeNamespace = _configuration.KubeNamespace;

try
{
return await _kubeApi
.ResourceClient<IEndPointClient>(client => new EndPointClientV1(client))
.GetAsync(serviceName, kubeNamespace);
}
catch (KubeApiException kubeApiError)
{
_logger.LogError(() =>
{
StatusV1 errorResponse = kubeApiError.Status;
string httpStatusCode = "Unknown";
if (kubeApiError.InnerException is HttpRequestException httpRequestError)
{
httpStatusCode = httpRequestError.StatusCode.ToString();
}

return $"Failed to retrieve {EndPointsKubeKind.ResourceApiVersion}/{EndPointsKubeKind.ResourceKind} {serviceName} in namespace {kubeNamespace} ({httpStatusCode}/{errorResponse.Status}/{errorResponse.Reason}): {errorResponse.Message}";
}, kubeApiError);
}
catch (HttpRequestException unexpectedRequestError)
{
_logger.LogError(() => $"Failed to retrieve {EndPointsKubeKind.ResourceApiVersion}/{EndPointsKubeKind.ResourceKind} {serviceName} in namespace {kubeNamespace} ({unexpectedRequestError.HttpRequestError}/{unexpectedRequestError.StatusCode}).", unexpectedRequestError);
}
catch (Exception unexpectedError)
{
_logger.LogError(() => $"Failed to retrieve {EndPointsKubeKind.ResourceApiVersion}/{EndPointsKubeKind.ResourceKind} {serviceName} in namespace {kubeNamespace} (an unexpected error occurred).", unexpectedError);
}

return null;
}

private bool CheckErroneousState(EndpointsV1 endpoint)
=> (endpoint?.Subsets?.Count ?? 0) == 0; // null or count is zero
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
<NoWarn>1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="KubeClient" Version="2.5.12" />
<PackageReference Include="KubeClient.Extensions.DependencyInjection" Version="2.5.12" />
<PackageReference Include="KubeClient" Version="3.0.0" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it should be 3.0.1 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, fair call - I'd only just published that; will pull in the new version 🙂

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm - just before I push this change, I thought I'd better check - KubeClient 3.0.1 requires Microsoft.Extensions.* 9.0.3 (Ocelot's test projects currently use 9.0.1; tried upgrading, and all are tests still passing, but it's your call if you want me to upgrade).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please go ahead and upgrade. Anyway, before the release I'll upgrade all packs

<PackageReference Include="KubeClient.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down