diff --git a/src/SnD.ApiClient/Beast/Base/IBeastClient.cs b/src/SnD.ApiClient/Beast/Base/IBeastClient.cs
deleted file mode 100644
index 19d4fec..0000000
--- a/src/SnD.ApiClient/Beast/Base/IBeastClient.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using SnD.ApiClient.Base.Models;
-using SnD.ApiClient.Beast.Models;
-using SnD.ApiClient.Exceptions;
-
-namespace SnD.ApiClient.Beast.Base;
-
-public interface IBeastClient
-{
- ///
- /// Submit a job to the Beast instance
- ///
- ///
- ///
- ///
- /// defaults to IGNORE
- ///
- /// If there is already a run with the same tag and ConcurrencyStrategy is set to
- public Task SubmitJobAsync(JobRequest jobParams, string submissionConfigurationName,
- CancellationToken cancellationToken, ConcurrencyStrategy? concurrencyStrategy);
-
-
- ///
- /// Awaits a run until it completes with any result or runs out of time set via cancellationToken.
- ///
- ///
- ///
- ///
- ///
- public Task AwaitRunAsync(string requestId, TimeSpan pollInterval, CancellationToken cancellationToken);
-
- ///
- /// Get the state of a Beast job
- ///
- ///
- ///
- ///
- public Task GetJobStateAsync(string requestId, CancellationToken cancellationToken);
-}
diff --git a/src/SnD.ApiClient/Beast/BeastClient.cs b/src/SnD.ApiClient/Beast/BeastClient.cs
deleted file mode 100644
index 13d933d..0000000
--- a/src/SnD.ApiClient/Beast/BeastClient.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-using System.Text;
-using System.Text.Json;
-using System.Text.RegularExpressions;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using SnD.ApiClient.Base;
-using SnD.ApiClient.Base.Models;
-using SnD.ApiClient.Beast.Base;
-using SnD.ApiClient.Beast.Models;
-using SnD.ApiClient.Boxer.Base;
-using SnD.ApiClient.Config;
-using SnD.ApiClient.Exceptions;
-
-namespace SnD.ApiClient.Beast;
-
-public class BeastClient : SndApiClient, IBeastClient
-{
- private readonly Uri baseUri;
-
- private readonly HashSet completedStages = new()
- {
- BeastRequestLifeCycleStage.COMPLETED,
- BeastRequestLifeCycleStage.FAILED,
- BeastRequestLifeCycleStage.STALE,
- BeastRequestLifeCycleStage.SCHEDULING_FAILED,
- BeastRequestLifeCycleStage.SUBMISSION_FAILED
- };
-
- public BeastClient(IOptions beastClientOptions, HttpClient httpClient,
- IJwtTokenExchangeProvider boxerConnector, ILogger logger) : base(httpClient, boxerConnector,
- logger)
- {
- baseUri = new Uri(beastClientOptions.Value.BaseUri
- ?? throw new ArgumentNullException(nameof(BeastClientOptions.BaseUri)));
- }
-
- ///
- public async Task SubmitJobAsync(JobRequest jobParams, string submissionConfigurationName,
- CancellationToken cancellationToken = default, ConcurrencyStrategy? concurrencyStrategy= null)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- concurrencyStrategy ??= ConcurrencyStrategy.IGNORE;
- if (concurrencyStrategy != ConcurrencyStrategy.IGNORE)
- {
- if (string.IsNullOrEmpty(jobParams.ClientTag))
- {
- throw new ArgumentException("You must supply a client tag when using a concurrency strategy");
- }
-
- var existingJobIds = await GetJobIdsByTagAsync(jobParams.ClientTag, cancellationToken);
-
- var incompleteJobs = (await Task.WhenAll(existingJobIds
- .Select(async id => await GetJobStateAsync(id, cancellationToken))))
- .Where(state => !completedStages.Contains(state.LifeCycleStage)).ToArray();
-
- if (incompleteJobs.Any())
- {
- switch (concurrencyStrategy)
- {
- case ConcurrencyStrategy.SKIP:
- throw new ConcurrencyError(concurrencyStrategy.Value, incompleteJobs.First().Id,
- jobParams.ClientTag);
- case ConcurrencyStrategy.AWAIT:
- await Task.WhenAll(incompleteJobs
- .Select(job => AwaitRunAsync(job.Id, TimeSpan.FromSeconds(5), cancellationToken)));
- break;
- case ConcurrencyStrategy.REPLACE:
- throw new NotImplementedException("ConcurrencyStrategy.REPLACE not implemented for BEAST");
- }
- }
- }
- if(Regex.IsMatch(jobParams.ClientTag ?? "", @"[^\w\d\-\._~]"))
- {
- throw new ArgumentException("ClientTag can only contain alphanumeric characters, hyphens, periods, underscores, and tildes");
- }
-
- var requestUri = new Uri(baseUri, new Uri($"job/submit/{submissionConfigurationName}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Post, requestUri)
- {
- Content = new StringContent(JsonSerializer.Serialize(jobParams), Encoding.UTF8, "application/json")
- };
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- return JsonSerializer.Deserialize(
- await response.Content.ReadAsStringAsync(cancellationToken),
- JsonSerializerOptions);
- }
-
- ///
- public async Task AwaitRunAsync(string requestId, TimeSpan pollInterval,
- CancellationToken cancellationToken)
- {
- RequestState result = null;
-
- if (cancellationToken == CancellationToken.None)
- {
- throw new ArgumentException("Cancellation token None is not allowed.");
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- do
- {
- await Task.Delay(pollInterval, cancellationToken);
- result = await GetRequestState(requestId, cancellationToken);
- if (completedStages.Contains(result.LifeCycleStage))
- {
- return result;
- }
- } while (!cancellationToken.IsCancellationRequested);
-
- return result;
- }
-
- ///
- public Task GetJobStateAsync(string requestId, CancellationToken cancellationToken = default)
- {
- return GetRequestState(requestId, cancellationToken);
- }
-
-
- private async Task GetJobIdsByTagAsync(string clientTag, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(baseUri, new Uri($"job/requests/tags/{clientTag}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- return JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(cancellationToken),
- JsonSerializerOptions);
- }
-
- private async Task GetRequestState(string requestId, CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(baseUri, new Uri($"job/requests/{requestId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- return JsonSerializer.Deserialize(
- await response.Content.ReadAsStringAsync(cancellationToken),
- JsonSerializerOptions);
- }
-}
diff --git a/src/SnD.ApiClient/Beast/Models/BeastRequestLifeCycleStage.cs b/src/SnD.ApiClient/Beast/Models/BeastRequestLifeCycleStage.cs
deleted file mode 100644
index dbb91db..0000000
--- a/src/SnD.ApiClient/Beast/Models/BeastRequestLifeCycleStage.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace SnD.ApiClient.Beast.Models;
-
-public enum BeastRequestLifeCycleStage
-{
- NEW,
- QUEUED,
- ALLOCATING,
- ALLOCATED,
- SUBMITTING,
- RUNNING,
- SCHEDULING_FAILED,
- SUBMISSION_FAILED,
- FAILED,
- COMPLETED,
- STALE,
- RETRY
-}
diff --git a/src/SnD.ApiClient/Beast/Models/JobDataSocket.cs b/src/SnD.ApiClient/Beast/Models/JobDataSocket.cs
deleted file mode 100644
index c0912e1..0000000
--- a/src/SnD.ApiClient/Beast/Models/JobDataSocket.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace SnD.ApiClient.Beast.Models;
-
-public sealed class JobDataSocket
-{
- ///
- /// Alias of the data socket
- ///
- public string Alias { get; set; }
-
- ///
- /// Fully qualified path to actual data, i.e. abfss://..., s3://... etc.
- ///
- public string DataPath { get; set; }
-
- ///
- /// Data format, i.e. csv, json, delta etc.
- ///
- public string DataFormat { get; set; }
-}
diff --git a/src/SnD.ApiClient/Beast/Models/JobRequest.cs b/src/SnD.ApiClient/Beast/Models/JobRequest.cs
deleted file mode 100644
index f1179ba..0000000
--- a/src/SnD.ApiClient/Beast/Models/JobRequest.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-namespace SnD.ApiClient.Beast.Models;
-
-///
-/// Job inputs for a Beast job
-///
-public record JobRequest
-{
- ///
- /// Input definitions - where to read data from and in what format
- ///
- public JobDataSocket[] Inputs { get; set; }
-
- ///
- /// Output definitions - where to write data to and in what format
- ///
- public JobDataSocket[] Outputs { get; set; }
-
- ///
- /// Any extra args and their values defined by a job's developer
- ///
- public Dictionary ExtraArgs { get; set; }
-
- ///
- /// Expected number of parallel running tasks in each Spark stage.
- ///
- public int? ExpectedParallelism { get; set; }
-
- ///
- /// Tags to apply when submitting a job, so a client can identify a request w/o knowing the id assigned by Beast
- ///
- public string ClientTag { get; set; }
-}
diff --git a/src/SnD.ApiClient/Beast/Models/RequestBase.cs b/src/SnD.ApiClient/Beast/Models/RequestBase.cs
deleted file mode 100644
index e92bbdf..0000000
--- a/src/SnD.ApiClient/Beast/Models/RequestBase.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace SnD.ApiClient.Beast.Models;
-
-public abstract record RequestBase
-{
- ///
- /// Unique request identifier assigned after successful buffering.
- ///
- public string Id { get; set; }
-
- ///
- /// Request client tag.
- ///
- public string ClientTag { get; set; }
-
- ///
- /// Request last modified timestamp.
- ///
- public DateTimeOffset? LastModified { get; set; }
-}
diff --git a/src/SnD.ApiClient/Beast/Models/RequestState.cs b/src/SnD.ApiClient/Beast/Models/RequestState.cs
deleted file mode 100644
index c4c7c50..0000000
--- a/src/SnD.ApiClient/Beast/Models/RequestState.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace SnD.ApiClient.Beast.Models;
-
-///
-/// Keeps the info of a buffered request
-///
-
-public record RequestState : RequestBase
-{
- ///
- /// IP/API address of a processing cluster.
- ///
- public string ProcessingCluster { get; set; }
-
- ///
- /// Request lifecycle stage.
- ///
- [JsonConverter(typeof(JsonStringEnumConverter))]
- public BeastRequestLifeCycleStage LifeCycleStage { get; set; }
-
- ///
- /// Request identifier in a buffer.
- ///
- public string MessageId { get; set; }
-
- ///
- /// Unique token used to remove request from a buffer.
- ///
- public string Receipt { get; set; }
-
- ///
- /// Request try number.
- ///
- public int? TryNumber { get; set; }
-
- [JsonIgnore]
- public bool IsCompleted =>
- this.LifeCycleStage is BeastRequestLifeCycleStage.FAILED or BeastRequestLifeCycleStage.COMPLETED;
-}
diff --git a/src/SnD.ApiClient/Boxer/Base/IBoxerClaimsClient.cs b/src/SnD.ApiClient/Boxer/Base/IBoxerClaimsClient.cs
deleted file mode 100644
index 2db2dce..0000000
--- a/src/SnD.ApiClient/Boxer/Base/IBoxerClaimsClient.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using SnD.ApiClient.Boxer.Exceptions;
-using SnD.ApiClient.Boxer.Models;
-
-namespace SnD.ApiClient.Boxer.Base;
-
-public interface IBoxerClaimsClient
-{
- ///
- /// Create a jwt-user registration in Boxer for a given user id and provider
- /// If user already exists, the method not do anything and return true
- ///
- ///
- ///
- ///
- /// true if success or if user already exists
- /// Throws if the request to Boxer fails
- public Task CreateUserAsync(string userId, string provider, CancellationToken cancellationToken);
-
- ///
- /// Deletes a user from Boxer by user id and provider (jwt-user registration) and all its claims.
- ///
- ///
- ///
- ///
- ///
- /// Throws if the user is not found under that identity provider
- /// Throws if the request to Boxer fails
- public Task DisassociateUserAsync(string userId, string provider, CancellationToken cancellationToken);
-
- ///
- /// Get claims by user id and provider
- ///
- /// User principal name (UPN) in Boxer
- /// Identity provider (IDP) in Boxer
- /// Cancellation token
- /// Enumerator of object for the user
- /// Throws if the user is not found under that identity provider
- /// Throws if the request to Boxer fails
- public Task> GetUserClaimsAsync(string userId, string provider, CancellationToken cancellationToken);
-
- ///
- /// Set (Update/Edit) claims for user id and provider
- ///
- /// User principal name (UPN) in Boxer
- /// Identity provider (IDP) in Boxer
- /// Claims to set in the form of an enumerator of type
- /// Cancellation token
- /// True if the operation was successful, false otherwise
- /// Throws if the user is not found under that identity provider
- /// Throws if the request to Boxer fails
- public Task PatchUserClaimsAsync(string userId, string provider, IEnumerable claims, CancellationToken cancellationToken);
-
- ///
- /// Delete claims for user id and provider
- /// Note: The method will match claims by user, identity provider and path. It will not match by api methods.
- ///
- /// User principal name (UPN) in Boxer
- /// Identity provider (IDP) in Boxer
- /// Claims to delete in the form of an enumerator of type
- /// Cancellation token
- /// true on success
- /// Throws if the user is not found under that identity provider
- /// Throws if the request to Boxer fails
- public Task DeleteUserClaimsAsync(string userId, string provider, IEnumerable claims, CancellationToken cancellationToken);
-}
diff --git a/src/SnD.ApiClient/Boxer/BoxerClaimsClient.cs b/src/SnD.ApiClient/Boxer/BoxerClaimsClient.cs
deleted file mode 100644
index 26d93d1..0000000
--- a/src/SnD.ApiClient/Boxer/BoxerClaimsClient.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using System.Net;
-using System.Text;
-using System.Text.Json;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using SnD.ApiClient.Base;
-using SnD.ApiClient.Boxer.Base;
-using SnD.ApiClient.Boxer.Exceptions;
-using SnD.ApiClient.Boxer.Extensions;
-using SnD.ApiClient.Boxer.Models;
-using SnD.ApiClient.Config;
-
-namespace SnD.ApiClient.Boxer;
-
-public class BoxerClaimsClient : SndApiClient, IBoxerClaimsClient
-{
- private readonly Uri claimsUri;
-
- public BoxerClaimsClient
- (IOptions boxerClientOptions, HttpClient httpClient,
- IJwtTokenExchangeProvider boxerConnector, ILogger logger) : base(httpClient, boxerConnector,
- logger)
- {
- claimsUri = new Uri(boxerClientOptions.Value.BaseUri
- ?? throw new ArgumentNullException(nameof(BoxerClaimsClientOptions.BaseUri)));
- }
-
- public async Task CreateUserAsync(string userId, string provider, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(claimsUri, new Uri($"claim/{provider}/{userId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
- request.Content = new StringContent("{}", Encoding.UTF8, "application/json");
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- return response.EnsureSuccessStatusCode().IsSuccessStatusCode;
- }
-
- public async Task DisassociateUserAsync(string userId, string provider, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(claimsUri, new Uri($"claim/{provider}/{userId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Delete, requestUri);
- request.Content = new StringContent("{}", Encoding.UTF8, "application/json");
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- return response.StatusCode switch
- {
- HttpStatusCode.NotFound => throw new UserNotFoundException(),
- _ => response.EnsureSuccessStatusCode().IsSuccessStatusCode
- };
- }
-
- public async Task> GetUserClaimsAsync(string userId, string provider,
- CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(claimsUri, new Uri($"claim/{provider}/{userId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- return await response.ExtractClaimsAsync();
- }
-
- public async Task PatchUserClaimsAsync(string userId, string provider, IEnumerable claims,
- CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(claimsUri, new Uri($"claim/{provider}/{userId}", UriKind.Relative));
- var requestBody = BoxerClaimsApiPatchBody.CreateInsertOperation(claims);
- var request = new HttpRequestMessage(HttpMethod.Patch, requestUri);
- request.Content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json");
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- return response.StatusCode switch
- {
- HttpStatusCode.NotFound => throw new UserNotFoundException(),
- _ => response.EnsureSuccessStatusCode().IsSuccessStatusCode
- };
- }
-
- public async Task DeleteUserClaimsAsync(string userId, string provider, IEnumerable claims,
- CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(claimsUri, new Uri($"claim/{provider}/{userId}", UriKind.Relative));
- var requestBody = BoxerClaimsApiPatchBody.CreateDeleteOperation(claims);
- var request = new HttpRequestMessage(HttpMethod.Patch, requestUri);
- request.Content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json");
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- return response.StatusCode switch
- {
- HttpStatusCode.NotFound => throw new UserNotFoundException(),
- _ => response.EnsureSuccessStatusCode().IsSuccessStatusCode
- };
- }
-}
diff --git a/src/SnD.ApiClient/Boxer/BoxerTokenProvider.cs b/src/SnD.ApiClient/Boxer/BoxerTokenProvider.cs
index 711d83e..6551c40 100644
--- a/src/SnD.ApiClient/Boxer/BoxerTokenProvider.cs
+++ b/src/SnD.ApiClient/Boxer/BoxerTokenProvider.cs
@@ -11,7 +11,7 @@ public class BoxerTokenProvider : IJwtTokenExchangeProvider
{
private readonly Uri authProvider;
private readonly Uri baseUri;
- private string token;
+ private string? token;
private readonly HttpClient httpClient;
private readonly ILogger logger;
private readonly Func> getExternalTokenAsync;
@@ -28,7 +28,7 @@ public BoxerTokenProvider(IOptions boxerTokenProvider
{
var authorizationProvider = boxerTokenProviderOptions.Value.IdentityProvider
?? throw new ArgumentNullException(nameof(BoxerTokenProviderOptions.IdentityProvider));
- this.authProvider = new Uri($"token/{authorizationProvider}", UriKind.Relative);
+ this.authProvider = new Uri($"api/v1/token/{authorizationProvider}", UriKind.Relative);
this.baseUri = new Uri(boxerTokenProviderOptions.Value.BaseUri
?? throw new ArgumentException(nameof(BoxerTokenProviderOptions.BaseUri)));
this.httpClient = httpClient;
@@ -54,7 +54,7 @@ public async Task GetTokenAsync(bool refresh, CancellationToken cancella
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", externalToken);
return await httpClient.SendAsync(request, cancellationToken);
});
- this.token = await response.Content.ReadAsStringAsync();
+ this.token = await response.Content.ReadAsStringAsync(cancellationToken);
this.logger.LogInformation("Received boxer token");
}
return this.token;
diff --git a/src/SnD.ApiClient/Boxer/Exceptions/UserNotFoundException.cs b/src/SnD.ApiClient/Boxer/Exceptions/UserNotFoundException.cs
deleted file mode 100644
index 3e86ee6..0000000
--- a/src/SnD.ApiClient/Boxer/Exceptions/UserNotFoundException.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace SnD.ApiClient.Boxer.Exceptions;
-
-///
-/// Exception thrown when a user is not found in Boxer, e.g., when trying to add claims to a user that does not exist
-///
-[ExcludeFromCodeCoverage]
-public class UserNotFoundException : Exception
-{
- ///
- /// Create a new instance of
- ///
- public UserNotFoundException() : base("Requested user not found in Boxer")
- {
- }
-}
diff --git a/src/SnD.ApiClient/Boxer/Extensions/BoxerJwtClaimExtensions.cs b/src/SnD.ApiClient/Boxer/Extensions/BoxerJwtClaimExtensions.cs
deleted file mode 100644
index 33be66d..0000000
--- a/src/SnD.ApiClient/Boxer/Extensions/BoxerJwtClaimExtensions.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Net;
-using System.Text.Json;
-using SnD.ApiClient.Boxer.Exceptions;
-using SnD.ApiClient.Boxer.Models;
-
-namespace SnD.ApiClient.Boxer.Extensions;
-
-public static class BoxerJwtClaimExtensions
-{
- public static async Task> ExtractClaimsAsync(this HttpResponseMessage response)
- {
- return response.StatusCode switch
- {
- HttpStatusCode.NotFound => throw new UserNotFoundException(),
- _ => JsonSerializer.Deserialize(await response.EnsureSuccessStatusCode().Content
- .ReadAsStringAsync()).Claims.Select(c => new BoxerJwtClaim(c.First().Key, c.First().Value))
- };
- }
-}
diff --git a/src/SnD.ApiClient/Boxer/Extensions/StringHttpMethodExtensions.cs b/src/SnD.ApiClient/Boxer/Extensions/StringHttpMethodExtensions.cs
deleted file mode 100644
index 8481c57..0000000
--- a/src/SnD.ApiClient/Boxer/Extensions/StringHttpMethodExtensions.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Collections.Immutable;
-using System.Text.RegularExpressions;
-
-namespace SnD.ApiClient.Boxer.Extensions;
-
-public static class StringHttpMethodExtensions
-{
- ///
- /// Convert a string to a collection of HttpMethod that matches (by regex) the string
- ///
- ///
- ///
- public static IEnumerable ToBoxerHttpMethods(this string httpMethods)
- {
- if (string.IsNullOrWhiteSpace(httpMethods))
- return Enumerable.Empty();
- var regex = new Regex(httpMethods);
- return new[] { HttpMethod.Get, HttpMethod.Post, HttpMethod.Put, HttpMethod.Delete, HttpMethod.Patch }
- .Where(m => regex.IsMatch(m.Method));
- }
-
- ///
- /// Convert a collection of HttpMethod to a regex string that matches the collection
- ///
- ///
- ///
- public static string ToRegexString(this IEnumerable httpMethods)
- {
- var methods = httpMethods.Select(m=>m.Method).ToImmutableSortedSet();
- return methods.IsEmpty ? string.Empty : $"^({string.Join("|", methods)})$";
- }
-}
diff --git a/src/SnD.ApiClient/Boxer/Models/BoxerClaimsApiPatchBody.cs b/src/SnD.ApiClient/Boxer/Models/BoxerClaimsApiPatchBody.cs
deleted file mode 100644
index 41ffdaa..0000000
--- a/src/SnD.ApiClient/Boxer/Models/BoxerClaimsApiPatchBody.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Text.Json.Serialization;
-
-
-namespace SnD.ApiClient.Boxer.Models;
-
-[ExcludeFromCodeCoverage]
-internal class BoxerClaimsApiPatchBody
-{
- private BoxerClaimsApiPatchBody()
- {
- }
-
- public static BoxerClaimsApiPatchBody CreateInsertOperation(IEnumerable claims) =>
- new()
- {
- Operation = "Insert",
- Claims = claims.ToDictionary(c => c.Type, c => c.Value)
- };
-
- public static BoxerClaimsApiPatchBody CreateDeleteOperation(IEnumerable claims) =>
- new()
- {
- Operation = "Delete",
- Claims = claims.ToDictionary(c => c.Type, c => c.Value)
- };
-
- [JsonPropertyName("operation")]
- public string Operation { get; private set; }
-
- [JsonPropertyName("claims")]
- public Dictionary Claims { get; private set; } = new();
-}
diff --git a/src/SnD.ApiClient/Boxer/Models/BoxerJwtClaim.cs b/src/SnD.ApiClient/Boxer/Models/BoxerJwtClaim.cs
deleted file mode 100644
index a3170ae..0000000
--- a/src/SnD.ApiClient/Boxer/Models/BoxerJwtClaim.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Security.Claims;
-using System.Text.Json;
-using SnD.ApiClient.Boxer.Extensions;
-
-namespace SnD.ApiClient.Boxer.Models;
-
-[ExcludeFromCodeCoverage]
-public class BoxerJwtClaim : Claim
-{
- internal BoxerJwtClaim(string type, string value) : base(type, value)
- {
- ApiMethods = value.ToBoxerHttpMethods().ToHashSet();
- Path = type;
- }
-
- ///
- /// Static method to convert a Boxer API Claims response to a collection of BoxerJwtClaim objects
- ///
- ///
- ///
- public static IEnumerable FromBoxerClaimsApiResponse(string response)
- {
- return JsonSerializer.Deserialize(response)
- .Claims.Select(c => new BoxerJwtClaim(c.First().Key, c.First().Value));
- }
-
- ///
- /// Static constructor to create a BoxerJwtClaim from a path and a collection of ApiMethodElement
- ///
- ///
- ///
- ///
- public static BoxerJwtClaim Create(string path, HashSet apiMethods)
- {
- return new BoxerJwtClaim(path, apiMethods.ToRegexString());
- }
-
- ///
- /// API path
- ///
- public readonly string Path;
-
- ///
- /// API methods
- ///
- public readonly HashSet ApiMethods;
-}
diff --git a/src/SnD.ApiClient/Boxer/Models/GetUserClaimsResponse.cs b/src/SnD.ApiClient/Boxer/Models/GetUserClaimsResponse.cs
deleted file mode 100644
index 80ab526..0000000
--- a/src/SnD.ApiClient/Boxer/Models/GetUserClaimsResponse.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace SnD.ApiClient.Boxer.Models;
-
-internal class GetUserClaimsResponse
-{
- [JsonPropertyName("identityProvider")]
- public string IdentityProvider { get; set; }
-
- [JsonPropertyName("userId")]
- public string UserId { get; set; }
-
- [JsonPropertyName("claims")]
- public List> Claims { get; set; }
-
- [JsonPropertyName("billingId")]
- public object BillingId { get; set; }
-}
diff --git a/src/SnD.ApiClient/Config/BeastClientOptions.cs b/src/SnD.ApiClient/Config/BeastClientOptions.cs
deleted file mode 100644
index 4c2d081..0000000
--- a/src/SnD.ApiClient/Config/BeastClientOptions.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace SnD.ApiClient.Config;
-
-public class BeastClientOptions
-{
- ///
- /// Base URI of the Beast instance
- ///
- public string BaseUri { get; set; }
-}
diff --git a/src/SnD.ApiClient/Config/BoxerClaimsClientOptions.cs b/src/SnD.ApiClient/Config/BoxerClaimsClientOptions.cs
index f097300..6efbbf4 100644
--- a/src/SnD.ApiClient/Config/BoxerClaimsClientOptions.cs
+++ b/src/SnD.ApiClient/Config/BoxerClaimsClientOptions.cs
@@ -5,5 +5,5 @@ public class BoxerClaimsClientOptions
///
/// Base URI of the Boxer Claims API instance
///
- public string BaseUri { get; set; }
+ public string? BaseUri { get; set; }
}
diff --git a/src/SnD.ApiClient/Config/BoxerTokenProviderOptions.cs b/src/SnD.ApiClient/Config/BoxerTokenProviderOptions.cs
index b275632..f6099fa 100644
--- a/src/SnD.ApiClient/Config/BoxerTokenProviderOptions.cs
+++ b/src/SnD.ApiClient/Config/BoxerTokenProviderOptions.cs
@@ -5,10 +5,10 @@ public class BoxerTokenProviderOptions
///
/// Base URI of the boxer instance
///
- public string BaseUri { get; set; }
+ public string? BaseUri { get; set; }
///
/// Name of authorization provider
///
- public string IdentityProvider { get; set; }
+ public string? IdentityProvider { get; set; }
}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Config/CrystalClientOptions.cs b/src/SnD.ApiClient/Config/CrystalClientOptions.cs
deleted file mode 100644
index 39fb71a..0000000
--- a/src/SnD.ApiClient/Config/CrystalClientOptions.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace SnD.ApiClient.Config;
-
-public class CrystalClientOptions
-{
- ///
- /// Base URI of the Crystal instance
- ///
- public string BaseUri { get; set; }
-
-
- ///
- /// Api version
- ///
- public string ApiVersion { get; set; }
-}
diff --git a/src/SnD.ApiClient/Config/NexusClientOptions.cs b/src/SnD.ApiClient/Config/NexusClientOptions.cs
index 126b9aa..1865327 100644
--- a/src/SnD.ApiClient/Config/NexusClientOptions.cs
+++ b/src/SnD.ApiClient/Config/NexusClientOptions.cs
@@ -5,7 +5,7 @@ public class NexusClientOptions
///
/// Base URI of the Crystal instance
///
- public string BaseUri { get; set; }
+ public string? BaseUri { get; set; }
///
/// Maximum number of retry attempts for transient failures
diff --git a/src/SnD.ApiClient/Crystal/Base/ICrystalClient.cs b/src/SnD.ApiClient/Crystal/Base/ICrystalClient.cs
deleted file mode 100644
index 23a08d8..0000000
--- a/src/SnD.ApiClient/Crystal/Base/ICrystalClient.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System.Text.Json;
-using SnD.ApiClient.Base.Models;
-using SnD.ApiClient.Crystal.Models;
-using SnD.ApiClient.Crystal.Models.Base;
-using SnD.ApiClient.Exceptions;
-
-namespace SnD.ApiClient.Crystal.Base;
-
-public interface ICrystalClient
-{
- ///
- /// Creates new run for of specified algorithm in Crystal
- ///
- /// Algorithm name
- /// Algorithm payload
- /// Custom configuration for algorithm run
- /// Cancellation token
- /// Instance of object with run ID
- Task CreateRunAsync(string algorithm, JsonElement payload,
- AlgorithmConfiguration customConfiguration, CancellationToken cancellationToken);
-
-
- ///
- /// Creates new run for of specified algorithm in Crystal using tagging and concurrency strategy.
- ///
- /// Algorithm name
- /// Algorithm payload
- /// Custom configuration for algorithm run
- /// Tag for concurrency tracking
- /// Concurrency strategy
- /// Cancellation token
- /// Instance of object with run ID
- /// If there is already a run with the same tag and ConcurrencyStrategy is set to
- Task CreateRunAsync(string algorithm, JsonElement payload,
- AlgorithmConfiguration customConfiguration,
- string tagId, ConcurrencyStrategy concurrencyStrategy,
- CancellationToken cancellationToken);
-
- ///
- /// Query and return result of the run
- ///
- /// Algorithm name
- /// Request ID received form
- /// Cancellation token
- /// RunResult instance
- public Task GetResultAsync(string algorithm, string requestId,
- CancellationToken cancellationToken = default);
-
- ///
- /// Awaits a run until it completes with any result or runs out of time set via cancellationToken.
- /// For some cases this can return a failed result when the algorithm has not been actually executed, for example,
- /// when a submission was lost.
- ///
- /// Algorithm name
- /// Request ID received form
- /// Cancellation token for the operation timeout.
- /// Poll interval to check for run results.
- /// RunResult instance
- public Task AwaitRunAsync(string algorithm, string requestId, TimeSpan pollInterval,
- CancellationToken cancellationToken);
-
- ///
- /// Reads the result of the run and converts it to the specified type using a specified converter function.
- /// If the run is not completed yet or has failed, the method will return default value for the type.
- ///
- /// Algorithm name
- /// Request ID received form
- /// Cancellation token for the operation timeout.
- /// Function to convert bytes from results into TResult
- /// Return type
- ///
- public Task GetResultAsync(string algorithm, string requestId, Func converter,
- CancellationToken cancellationToken = default);
-}
diff --git a/src/SnD.ApiClient/Crystal/CrystalClient.cs b/src/SnD.ApiClient/Crystal/CrystalClient.cs
deleted file mode 100644
index 4180873..0000000
--- a/src/SnD.ApiClient/Crystal/CrystalClient.cs
+++ /dev/null
@@ -1,205 +0,0 @@
-using System.Text;
-using System.Text.Json;
-using System.Text.RegularExpressions;
-using SnD.ApiClient.Crystal.Models;
-using SnD.ApiClient.Crystal.Models.Base;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using SnD.ApiClient.Base;
-using SnD.ApiClient.Base.Models;
-using SnD.ApiClient.Boxer.Base;
-using SnD.ApiClient.Config;
-using SnD.ApiClient.Crystal.Base;
-using SnD.ApiClient.Exceptions;
-
-namespace SnD.ApiClient.Crystal;
-
-public class CrystalClient : SndApiClient, ICrystalClient
-{
- private readonly Uri baseUri;
- private readonly string apiVersion;
-
- private readonly RequestLifeCycleStage[] completedStages =
- {
- RequestLifeCycleStage.FAILED, RequestLifeCycleStage.COMPLETED, RequestLifeCycleStage.DEADLINE_EXCEEDED,
- RequestLifeCycleStage.SCHEDULING_TIMEOUT
- };
-
- public CrystalClient(IOptions crystalClientOptions, HttpClient httpClient,
- IJwtTokenExchangeProvider boxerConnector, ILogger logger) : base(httpClient, boxerConnector,
- logger)
- {
- this.apiVersion = crystalClientOptions.Value.ApiVersion ??
- throw new ArgumentNullException(nameof(CrystalClientOptions.ApiVersion));
- this.baseUri = new Uri(crystalClientOptions.Value.BaseUri
- ?? throw new ArgumentNullException(nameof(CrystalClientOptions.BaseUri)));
- }
-
- ///
- public async Task CreateRunAsync(string algorithm, JsonElement payload,
- AlgorithmConfiguration customConfiguration,
- CancellationToken cancellationToken = default)
- {
- return await RunAsync(algorithm, payload, customConfiguration, cancellationToken);
- }
-
- private async Task RunAsync(string algorithm, JsonElement payload,
- AlgorithmConfiguration customConfiguration,
- CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var requestUri = new Uri(baseUri, new Uri($"algorithm/{this.apiVersion}/run/{algorithm}", UriKind.Relative));
- var algorithmRequest = new AlgorithmRequest
- {
- AlgorithmParameters = payload,
- CustomConfiguration = customConfiguration
- };
- var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
- request.Content =
- new StringContent(JsonSerializer.Serialize(algorithmRequest), Encoding.UTF8, "application/json");
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- var responseString = await response.Content.ReadAsStringAsync();
- return JsonSerializer.Deserialize(responseString, JsonSerializerOptions);
- }
-
- ///
- public async Task CreateRunAsync(string algorithm, JsonElement payload,
- AlgorithmConfiguration customConfiguration, string tagId,
- ConcurrencyStrategy concurrencyStrategy, CancellationToken cancellationToken)
- {
- if (string.IsNullOrEmpty(tagId))
- {
- throw new ArgumentException("You must supply a client tag when using a concurrency strategy");
- }
- if(Regex.IsMatch(tagId, @"[^\w\d\-\._~]"))
- {
- throw new ArgumentException("TagId can only contain alphanumeric characters, hyphens, periods, underscores, and tildes");
- }
-
- if (concurrencyStrategy != ConcurrencyStrategy.IGNORE)
- {
- var runningJobs = await GetJobIdsByTagAsync(algorithm, tagId, cancellationToken);
-
- var incompleteJobs = runningJobs.Where(job => !completedStages.Contains(job.Status)).ToArray();
- if (incompleteJobs.Any())
- {
- switch (concurrencyStrategy)
- {
- case ConcurrencyStrategy.SKIP:
- throw new ConcurrencyError(concurrencyStrategy, incompleteJobs.First().RequestId, tagId);
- case ConcurrencyStrategy.AWAIT:
- await Task.WhenAll(incompleteJobs
- .Select(job =>
- AwaitRunAsync(algorithm, job.RequestId, TimeSpan.FromSeconds(5), cancellationToken)));
- break;
- case ConcurrencyStrategy.REPLACE:
- throw new NotImplementedException("ConcurrencyStrategy.REPLACE not implemented for Crystal");
- }
- }
- }
-
- return await RunAsync(algorithm, payload, customConfiguration, cancellationToken);
- }
-
- ///
- public async Task GetResultAsync(string algorithm, string requestId,
- CancellationToken cancellationToken = default)
- {
- var requestUri = new Uri(baseUri,
- new Uri($"algorithm/{this.apiVersion}/results/{algorithm}/requests/{requestId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- return JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), JsonSerializerOptions);
- }
-
- ///
- public async Task AwaitRunAsync(string algorithm, string requestId, TimeSpan pollInterval,
- CancellationToken cancellationToken)
- {
- var requestUri = new Uri(baseUri,
- new Uri($"algorithm/{this.apiVersion}/results/{algorithm}/requests/{requestId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- RunResult result = null;
-
- if (cancellationToken == CancellationToken.None)
- {
- throw new ArgumentException("Cancellation token None is not allowed.");
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- do
- {
- // Crystal can return 404 in three cases:
- // - Submission is not found
- // - Submission is delayed
- // - Submission was lost
- // For the two latter ones we can wait a bit and see if the situation resolves.
- await Task.Delay(pollInterval, cancellationToken);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
-
- if (!response.IsSuccessStatusCode)
- {
- continue;
- }
-
- result = JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(),
- JsonSerializerOptions);
-
- if (this.completedStages.Contains(result.Status))
- {
- return result;
- }
- } while (!cancellationToken.IsCancellationRequested);
-
- if (result != null && !this.completedStages.Contains(result.Status))
- {
- result = RunResult.TimeoutSubmission(requestId);
- }
-
- return result ?? RunResult.LostSubmission(requestId);
- }
-
- ///
- public async Task GetResultAsync(string algorithm, string requestId,
- Func converter,
- CancellationToken cancellationToken = default)
- {
- var requestUri = new Uri(baseUri,
- new Uri($"algorithm/{this.apiVersion}/results/{algorithm}/requests/{requestId}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- var runResult =
- JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), JsonSerializerOptions);
-
- if (runResult.ResultUri == null)
- {
- return default;
- }
-
- var resultsRequest = new HttpRequestMessage(HttpMethod.Get, runResult.ResultUri);
- var resultData = await SendAnonymousRequestAsync(resultsRequest, cancellationToken);
- resultData.EnsureSuccessStatusCode();
-
- return converter(await resultData.Content.ReadAsByteArrayAsync());
- }
-
-
- private async Task GetJobIdsByTagAsync(string algorithm, string clientTag,
- CancellationToken cancellationToken = default)
- {
- cancellationToken.ThrowIfCancellationRequested();
- var requestUri = new Uri(baseUri,
- new Uri($"algorithm/{apiVersion}/results/{algorithm}/tags/{clientTag}", UriKind.Relative));
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
- var response = await SendAuthenticatedRequestAsync(request, cancellationToken);
- response.EnsureSuccessStatusCode();
- return JsonSerializer.Deserialize(
- await response.Content.ReadAsStringAsync(cancellationToken),
- JsonSerializerOptions);
- }
-}
diff --git a/src/SnD.ApiClient/Crystal/Models/ApiVersions.cs b/src/SnD.ApiClient/Crystal/Models/ApiVersions.cs
deleted file mode 100644
index 09ead4f..0000000
--- a/src/SnD.ApiClient/Crystal/Models/ApiVersions.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace SnD.ApiClient.Crystal.Models;
-
-public class ApiVersions
-{
- ///
- /// Boxer token authentication and updated API for run submission and result read
- ///
- public const string v1_2 = "v1.2";
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmConfiguration.cs b/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmConfiguration.cs
deleted file mode 100644
index 2f52ab0..0000000
--- a/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmConfiguration.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-namespace SnD.ApiClient.Crystal.Models.Base
-{
- ///
- /// Static algorithm configuration.
- ///
- public class AlgorithmConfiguration
- {
- ///
- /// Container image used by this algorithm.
- ///
- public string ImageRepository { get; set; }
-
- ///
- /// Container image registry used by this algorithm.
- ///
- public string ImageRegistry { get; set; }
-
- ///
- /// Image tag (version) used by this algorithm.
- ///
- public string ImageTag { get; set; }
-
- ///
- /// Computation deadline in seconds.
- ///
- public int? DeadlineSeconds { get; set; }
-
- ///
- /// Total number of allowed retries within a deadline.
- ///
- public int? MaximumRetries { get; set; }
-
- ///
- /// Environment variables to be mapped on container.
- ///
- public AlgorithmConfigurationEntry[] Env { get; set; }
-
- ///
- /// Secrets to be mapped as environment variables on the container.
- ///
- public string[] Secrets { get; set; }
-
- ///
- /// Arguments for container entrypoint.
- ///
- public AlgorithmConfigurationEntry[] Args { get; set; }
-
- ///
- /// Max CPU share allowed for this container.
- ///
- public string CpuLimit { get; set; }
-
- ///
- /// Max memory allocation for this container.
- ///
- public string MemoryLimit { get; set; }
-
- ///
- /// Sets the workgroup that an algorithm should run on. Null value will default to a value provided from app config.
- ///
- public string Workgroup { get; set; }
-
- ///
- /// Git tag associated with this configuration.
- ///
- public string Version { get; set; }
-
- ///
- /// Parameters for monitoring of algorithm
- ///
- public HashSet MonitoringParameters { get; set; }
-
- ///
- /// Custom resources for this container (e.g. GPU)
- ///
- public Dictionary CustomResources { get; set; }
-
- }
-}
diff --git a/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmConfigurationEntry.cs b/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmConfigurationEntry.cs
deleted file mode 100644
index e42c808..0000000
--- a/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmConfigurationEntry.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace SnD.ApiClient.Crystal.Models.Base
-{
- public enum AlgorithmConfigurationValueType
- {
- PLAIN,
- RELATIVE_REFERENCE
- }
-
- ///
- /// Named configuration entry.
- ///
- public class AlgorithmConfigurationEntry
- {
- ///
- /// Name of the entry.
- ///
- public string Name { get; set; }
-
- ///
- /// Value of the entry. Can be a plain text or a reference, thus actual value is provided via configuration provider service.
- ///
- public string Value { get; set; }
-
- ///
- /// Type of the entrie's value. Null is added for backwards-compatibility, behaviour is the same as PLAIN.
- ///
- [JsonConverter(typeof(JsonStringEnumConverter))]
- public AlgorithmConfigurationValueType ValueType { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmRequest.cs b/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmRequest.cs
deleted file mode 100644
index 6315adb..0000000
--- a/src/SnD.ApiClient/Crystal/Models/Base/AlgorithmRequest.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Text.Json;
-using System.ComponentModel.DataAnnotations;
-
-namespace SnD.ApiClient.Crystal.Models.Base;
-
-///
-/// Data to be submitted by a client, when doing an algorithm invocation.
-///
-public class AlgorithmRequest
-{
- ///
- /// Algorithm-specific configuration. Must be a JSON-serializable object.
- ///
- [Required]
- public JsonElement AlgorithmParameters { get; set; }
-
- ///
- /// Optional custom configuration to be applied when running this algorithm.
- ///
- public AlgorithmConfiguration CustomConfiguration { get; set; }
-
- ///
- /// Tag for tracking request status
- ///
- public string Tag { get; set; }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Crystal/Models/Base/RequestLifecycleStage.cs b/src/SnD.ApiClient/Crystal/Models/Base/RequestLifecycleStage.cs
deleted file mode 100644
index 427ab4c..0000000
--- a/src/SnD.ApiClient/Crystal/Models/Base/RequestLifecycleStage.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace SnD.ApiClient.Crystal.Models.Base;
-
-///
-/// Request lifecycle stages. Used by metadata store and maintenance service.
-///
-public enum RequestLifeCycleStage
-{
- NEW,
- BUFFERED,
- RUNNING,
- COMPLETED,
- FAILED,
- SCHEDULING_TIMEOUT,
- DEADLINE_EXCEEDED,
- THROTTLED,
- CLIENT_TIMEOUT
-}
diff --git a/src/SnD.ApiClient/Crystal/Models/Base/RunResult.cs b/src/SnD.ApiClient/Crystal/Models/Base/RunResult.cs
deleted file mode 100644
index 0e81ef5..0000000
--- a/src/SnD.ApiClient/Crystal/Models/Base/RunResult.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace SnD.ApiClient.Crystal.Models.Base;
-
-public record RunResult
-{
- ///
- /// Identifier of a request.
- ///
- public string RequestId { get; set; }
-
- ///
- /// Processing status of a request.
- ///
- [JsonConverter(typeof(JsonStringEnumConverter))]
- public RequestLifeCycleStage Status { get; set; }
-
- ///
- /// URI to download request results.
- ///
- public Uri ResultUri { get; set; }
-
- ///
- /// Error to be communicated to a client.
- ///
- public string RunErrorMessage { get; set; }
-
- public static RunResult LostSubmission(string requestId)
- {
- return new RunResult
- {
- RequestId = requestId,
- Status = RequestLifeCycleStage.FAILED,
- ResultUri = null,
- RunErrorMessage = "Submission has been lost or does not exist. Please retry it in a few seconds."
- };
- }
- public static RunResult TimeoutSubmission(string requestId)
- {
- return new RunResult
- {
- RequestId = requestId,
- Status = RequestLifeCycleStage.CLIENT_TIMEOUT,
- ResultUri = null,
- RunErrorMessage = "Submission timed out on the client side, but is still running on the server. Note that it might complete eventually, but the client has chosen to give up due to cancellation policy provided."
- };
- }
-}
diff --git a/src/SnD.ApiClient/Crystal/Models/CreateRunResponse.cs b/src/SnD.ApiClient/Crystal/Models/CreateRunResponse.cs
deleted file mode 100644
index cd7d0bb..0000000
--- a/src/SnD.ApiClient/Crystal/Models/CreateRunResponse.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace SnD.ApiClient.Crystal.Models;
-
-public class CreateRunResponse
-{
- ///
- /// Id of submitted request
- ///
- public string RequestId { get; set; }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Exceptions/ConcurrencyError.cs b/src/SnD.ApiClient/Exceptions/ConcurrencyError.cs
deleted file mode 100644
index f1ef9e3..0000000
--- a/src/SnD.ApiClient/Exceptions/ConcurrencyError.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using SnD.ApiClient.Base.Models;
-
-namespace SnD.ApiClient.Exceptions;
-
-///
-/// Thrown on jobs requested with a concurrency strategy that conflicts with an existing job.
-///
-/// Chosen concurrency strategy
-/// Request id of (one of) the existing job
-/// Client tag for concurrency tracking
-public class ConcurrencyError(ConcurrencyStrategy strategy, string existingRequestId, string clientTag)
- : Exception(
- $"Concurrent request found with client tag {clientTag}, and request id {existingRequestId}. Chosen strategy: {strategy}")
-{
- public ConcurrencyStrategy Strategy { get; } = strategy;
- public string ExistingRequestId { get; } = existingRequestId;
- public string ClientTag { get; } = clientTag;
-}
diff --git a/src/SnD.ApiClient/Extensions/ServiceCollectionExtensions.cs b/src/SnD.ApiClient/Extensions/ServiceCollectionExtensions.cs
index 991a800..2b0642f 100644
--- a/src/SnD.ApiClient/Extensions/ServiceCollectionExtensions.cs
+++ b/src/SnD.ApiClient/Extensions/ServiceCollectionExtensions.cs
@@ -4,13 +4,9 @@
using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Authentication;
using Microsoft.Kiota.Http.HttpClientLibrary;
-using SnD.ApiClient.Beast;
-using SnD.ApiClient.Beast.Base;
using SnD.ApiClient.Boxer;
using SnD.ApiClient.Boxer.Base;
using SnD.ApiClient.Config;
-using SnD.ApiClient.Crystal;
-using SnD.ApiClient.Crystal.Base;
using SnD.ApiClient.Nexus;
using SnD.ApiClient.Nexus.Base;
@@ -52,32 +48,7 @@ public static IServiceCollection AuthorizeWithBoxerOnKubernetes(this IServiceCol
return Task.FromResult(File.ReadAllText("/var/run/secrets/kubernetes.io/serviceaccount/token"));
});
}
-
- ///
- /// Add Crystal connector to DI
- ///
- public static IServiceCollection AddCrystalClient(this IServiceCollection services)
- {
- return services.AddSingleton();
- }
-
- ///
- /// Add Boxer Claims Client to DI
- ///
- public static IServiceCollection AddBoxerClaimsClient(this IServiceCollection services)
- {
- return services.AddSingleton();
- }
-
- ///
- /// Add Beast Client to DI
- ///
- public static IServiceCollection AddBeastClient(this IServiceCollection services)
- {
- return services.AddSingleton();
- }
-
-
+
///
/// Add Authentication provider to DI
///
diff --git a/src/SnD.ApiClient/Nexus/AlgorithmRequestExtensions.cs b/src/SnD.ApiClient/Nexus/AlgorithmRequestExtensions.cs
deleted file mode 100644
index 43daa22..0000000
--- a/src/SnD.ApiClient/Nexus/AlgorithmRequestExtensions.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using KiotaPosts.Client.Models.Models;
-using SnD.ApiClient.Nexus.Models;
-
-namespace SnD.ApiClient.Nexus;
-
-public static class AlgorithmRequestExtensions
-{
- ///
- /// Converts AlgorithmRequest without payload to NexusAlgorithmRequest with payload
- ///
- /// Algorithm request without payload
- /// JSON serialized payload
- /// NexusAlgorithmRequest with payload that can be used to create a new run
- ///
- public static NexusAlgorithmRequest ToNexusAlgorithmRequest(this AlgorithmRequest algorithmRequest, string payload)
- {
- if (algorithmRequest == null)
- {
- throw new ArgumentNullException(nameof(algorithmRequest));
- }
-
- if (payload == null)
- {
- throw new ArgumentNullException(nameof(payload));
- }
-
- return NexusAlgorithmRequest.Create(
- payload,
- algorithmRequest.CustomConfiguration,
- algorithmRequest.ParentRequest,
- algorithmRequest.PayloadValidFor,
- algorithmRequest.RequestApiVersion,
- algorithmRequest.Tag
- );
- }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Nexus/Models/CustomRunConfiguration.cs b/src/SnD.ApiClient/Nexus/Models/CustomRunConfiguration.cs
deleted file mode 100644
index 2d5d1a4..0000000
--- a/src/SnD.ApiClient/Nexus/Models/CustomRunConfiguration.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using KiotaPosts.Client.Models.V1;
-
-namespace SnD.ApiClient.Nexus.Models;
-public class CustomRunConfiguration
-{
- ///
- /// Algorithm version override
- ///
- public string? Version { get; set; }
-
- ///
- /// Workgroup name override
- ///
- public string? WorkgroupName { get; set; }
-
- ///
- /// Workgroup group override
- ///
- public string? WorkgroupGroup { get; set; }
-
- ///
- /// Algorithm workgroup kind override
- ///
- public string? WorkgroupKind { get; set; }
-
- ///
- /// CPU limit override
- ///
- public string? CpuLimit { get; set; }
-
- ///
- /// Memory limit override
- ///
- public string? MemoryLimit { get; set; }
-
- public NexusAlgorithmContainer? Container { get; set; }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Nexus/Models/ParentRequest.cs b/src/SnD.ApiClient/Nexus/Models/ParentRequest.cs
deleted file mode 100644
index 4fa189e..0000000
--- a/src/SnD.ApiClient/Nexus/Models/ParentRequest.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace SnD.ApiClient.Nexus.Models;
-
-public class ParentRequest
-{
- ///
- /// Parent request Algorithm name
- ///
- public string AlgorithmName { get; set; }
-
- ///
- /// Parent request ID
- ///
- public string RequestId { get; set; }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Nexus/Models/RequestMetadata.cs b/src/SnD.ApiClient/Nexus/Models/RequestMetadata.cs
deleted file mode 100644
index d15111c..0000000
--- a/src/SnD.ApiClient/Nexus/Models/RequestMetadata.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-namespace SnD.ApiClient.Nexus.Models;
-
-using System.Collections.Generic;
-
-///
-/// Contains metadata and runtime configuration for an algorithm run request.
-///
-public class RequestMetadata
-{
- ///
- /// The name of the algorithm.
- ///
- public string? Algorithm { get; set; }
-
- ///
- /// The unique identifier of the request.
- ///
- public string? Id { get; set; }
-
- ///
- /// The cause of algorithm failure, if any.
- ///
- public string? AlgorithmFailureCause { get; set; }
-
- ///
- /// Detailed information about the algorithm failure, if any.
- ///
- public string? AlgorithmFailureDetails { get; set; }
-
- ///
- /// The API version used for the request.
- ///
- public string? ApiVersion { get; set; }
-
- ///
- /// The applied configuration for the request.
- ///
- public Dictionary? AppliedConfiguration { get; set; }
-
- ///
- /// Configuration overrides applied to the request.
- ///
- public Dictionary? ConfigurationOverrides { get; set; }
-
- ///
- /// The content hash of the request payload.
- ///
- public string? ContentHash { get; set; }
-
- ///
- /// The unique identifier of the job.
- ///
- public string? JobUid { get; set; }
-
- ///
- /// The last modified timestamp of the request.
- ///
- public string? LastModified { get; set; }
-
- ///
- /// The current lifecycle stage of the request.
- ///
- public string? LifecycleStage { get; set; }
-
- ///
- /// Information about the parent job, if any.
- ///
- public Dictionary? ParentJob { get; set; }
-
- ///
- /// The URI of the request payload.
- ///
- public string? PayloadUri { get; set; }
-
- ///
- /// The validity period for the payload.
- ///
- public string? PayloadValidFor { get; set; }
-
- ///
- /// The timestamp when the request was received.
- ///
- public string? ReceivedAt { get; set; }
-
- ///
- /// The host that received the request.
- ///
- public string? ReceivedByHost { get; set; }
-
- ///
- /// The URI of the result.
- ///
- public string? ResultUri { get; set; }
-
- ///
- /// The timestamp when the request was sent.
- ///
- public string? SentAt { get; set; }
-
- ///
- /// The client-side assigned tag for the request.
- ///
- public string? Tag { get; set; }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Nexus/Models/RunResult.cs b/src/SnD.ApiClient/Nexus/Models/RunResult.cs
deleted file mode 100644
index c35596d..0000000
--- a/src/SnD.ApiClient/Nexus/Models/RunResult.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-namespace SnD.ApiClient.Nexus.Models;
-
-///
-/// C# SDK data structure for RunResult.
-///
-public class RunResult
-{
- ///
- /// The algorithm name.
- ///
- public string? Algorithm { get; set; }
-
- ///
- /// The request identifier.
- ///
- public string? RequestId { get; set; }
-
- ///
- /// The result URI.
- ///
- public string? ResultUri { get; set; }
-
- ///
- /// The run error message.
- ///
- public string? RunErrorMessage { get; set; }
-
- ///
- /// The client error type.
- ///
- public string? ClientErrorType { get; set; }
-
- ///
- /// The client error message.
- ///
- public string? ClientErrorMessage { get; set; }
-
- ///
- /// The run status.
- ///
- public string? Status { get; set; }
-
- ///
- /// Checks if this object is empty (end of the response).
- ///
- /// True if all properties are null; otherwise, false.
- public bool IsEmpty()
- {
- return Algorithm == null
- && RequestId == null
- && ResultUri == null
- && RunErrorMessage == null
- && Status == null
- && ClientErrorType == null
- && ClientErrorMessage == null;
- }
-}
\ No newline at end of file
diff --git a/src/SnD.ApiClient/Nexus/RequestAdapterFactory.cs b/src/SnD.ApiClient/Nexus/RequestAdapterFactory.cs
deleted file mode 100644
index 8ab1f5a..0000000
--- a/src/SnD.ApiClient/Nexus/RequestAdapterFactory.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Microsoft.Extensions.Options;
-using Microsoft.Kiota.Abstractions;
-using Microsoft.Kiota.Abstractions.Authentication;
-using Microsoft.Kiota.Http.HttpClientLibrary;
-using SnD.ApiClient.Config;
-
-namespace SnD.ApiClient.Nexus;
-
-public static class RequestAdapterFactory
-{
- public static IRequestAdapter ToRequestAdapter(this IOptions options,
- IAuthenticationProvider authenticationProvider,
- Func adapterFactory,
- Func httpClientFactory)
- {
- var httpClient = httpClientFactory();
- httpClient.BaseAddress = new Uri(options.Value.BaseUri);
- return adapterFactory(new HttpClientRequestAdapter(authenticationProvider, httpClient: httpClient));
- }
-}
diff --git a/test/SnD.ApiClient.Tests.Acceptance/appsettings.test.json b/test/SnD.ApiClient.Tests.Acceptance/appsettings.test.json
index 2dea489..ad8b0ac 100644
--- a/test/SnD.ApiClient.Tests.Acceptance/appsettings.test.json
+++ b/test/SnD.ApiClient.Tests.Acceptance/appsettings.test.json
@@ -10,14 +10,14 @@
"BaseUri": "",
"IdentityProvider": ""
},
- "UseBoxerTokenProviderOnAzure": false,
"NexusClientOptions": {
"BaseUri": "http://localhost:5555/scheduler",
"MaxRetryAttempts": 3,
"RetryIntervalSeconds": 5
},
- "AcceptanceTestsConfiguration":
+ "AcceptanceTestsConfiguration":
{
+ "UseBoxerTokenProviderOnAzure": false,
"AlgorithmRequest": {},
"AlgorithmName": "hello-world",
"AlgorithmConfiguration": {},
diff --git a/test/SnD.ApiClient.Tests/Boxer/ApiSamples/GetUserSample.json b/test/SnD.ApiClient.Tests/Boxer/ApiSamples/GetUserSample.json
deleted file mode 100644
index d8b63ab..0000000
--- a/test/SnD.ApiClient.Tests/Boxer/ApiSamples/GetUserSample.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "identityProvider": "idp_123",
- "userId": "user_123",
- "claims": [
- {
- "myapi1.com/.*": ".*"
- },
- {
- "myapi2.com/path/.*": ".*"
- }
- ],
- "billingId": null
-}
diff --git a/test/SnD.ApiClient.Tests/Boxer/BoxerClaimsClientTests.cs b/test/SnD.ApiClient.Tests/Boxer/BoxerClaimsClientTests.cs
deleted file mode 100644
index 232935e..0000000
--- a/test/SnD.ApiClient.Tests/Boxer/BoxerClaimsClientTests.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Moq;
-using SnD.ApiClient.Boxer;
-using SnD.ApiClient.Boxer.Base;
-using SnD.ApiClient.Boxer.Models;
-using SnD.ApiClient.Config;
-using Xunit;
-
-namespace SnD.ApiClient.Tests.Boxer;
-
-public class BoxerClaimsClientTests : IClassFixture, IClassFixture
-{
- private readonly IBoxerClaimsClient boxerClaimsClient;
-
- public BoxerClaimsClientTests(MockServiceFixture mockServiceFixture, LoggerFixture loggerFixture)
- {
- var crystalOptions = new BoxerClaimsClientOptions
- { BaseUri = "https://boxer.example.com" };
-
- boxerClaimsClient = new BoxerClaimsClient(Options.Create(crystalOptions),
- mockServiceFixture.BoxerMockHttpClient,
- CreateBoxerClient(mockServiceFixture),
- loggerFixture.Factory.CreateLogger());
- }
-
- private static BoxerTokenProvider CreateBoxerClient(MockServiceFixture mockServiceFixture)
- {
- var boxerOptions = new BoxerTokenProviderOptions
- { IdentityProvider = "example.com", BaseUri = "https://boxer.example.com" };
- var boxerConnector = new BoxerTokenProvider(
- Options.Create(boxerOptions),
- mockServiceFixture.BoxerMockHttpClient,
- Mock.Of>(),
- _ => Task.FromResult(string.Empty));
- return boxerConnector;
- }
-
- [Theory]
- [InlineData(new[] { "GET", "POST" }, "^(GET|POST)$")]
- [InlineData(new[] { "GET", "POST", "PUT" }, "^(GET|POST|PUT)$")]
- [InlineData(new[] { "GET", "POST", "PUT", "PATCH" }, "^(GET|POST|PUT|PATCH)$")]
- [InlineData(new[] { "GET", "POST", "PUT", "PATCH", "DELETE" }, "^(GET|POST|PUT|PATCH|DELETE)$")]
- public void CreateWithSomeMethods(string[] apiMethods, string expectedValue)
- {
- var boxerJwtClaim = BoxerJwtClaim.Create("path", new HashSet(apiMethods.Select(s=>new HttpMethod(s))));
- Assert.Equal("path", boxerJwtClaim.Type);
- Assert.True(apiMethods.All(s => boxerJwtClaim.ApiMethods.Contains(new HttpMethod(s))));
- }
-
- [Fact]
- public void DeserializationTest()
- {
- var apiResponse = File.ReadAllText("Boxer/ApiSamples/GetUserSample.json");
- var boxerJwtClaims = BoxerJwtClaim.FromBoxerClaimsApiResponse(apiResponse).ToArray();
- Assert.Equal(2, boxerJwtClaims.Length);
- Assert.Equal("myapi1.com/.*", boxerJwtClaims.First().Path);
- Assert.Contains(HttpMethod.Get, boxerJwtClaims.First().ApiMethods);
- }
-}
diff --git a/test/SnD.ApiClient.Tests/Crystal/CrystalClientTests.cs b/test/SnD.ApiClient.Tests/Crystal/CrystalClientTests.cs
deleted file mode 100644
index 7567257..0000000
--- a/test/SnD.ApiClient.Tests/Crystal/CrystalClientTests.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using SnD.ApiClient.Crystal.Models;
-using SnD.ApiClient.Crystal.Models.Base;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Moq;
-using SnD.ApiClient.Boxer;
-using SnD.ApiClient.Config;
-using SnD.ApiClient.Crystal;
-using SnD.ApiClient.Crystal.Base;
-using Xunit;
-
-namespace SnD.ApiClient.Tests.Crystal;
-
-public class CrystalClientTests: IClassFixture, IClassFixture
-{
- private readonly ICrystalClient crystalClient;
-
- public CrystalClientTests(MockServiceFixture mockServiceFixture, LoggerFixture loggerFixture)
- {
- var crystalOptions = new CrystalClientOptions
- { BaseUri = "https://crystal.example.com", ApiVersion = ApiVersions.v1_2 };
-
- this.crystalClient = new CrystalClient(Options.Create(crystalOptions),
- mockServiceFixture.CrystalMockHttpClient,
- CreateBoxerClient(mockServiceFixture),
- loggerFixture.Factory.CreateLogger());
- }
-
- private static BoxerTokenProvider CreateBoxerClient(MockServiceFixture mockServiceFixture)
- {
- var boxerOptions = new BoxerTokenProviderOptions
- { IdentityProvider = "example.com", BaseUri = "https://boxer.example.com" };
- var boxerConnector = new BoxerTokenProvider(
- Options.Create(boxerOptions),
- mockServiceFixture.BoxerMockHttpClient,
- Mock.Of>(),
- _ => Task.FromResult(string.Empty));
- return boxerConnector;
- }
-
- [Fact]
- public async Task TestShouldRenewTokenAsync()
- {
- var payload = JsonDocument.Parse("null").RootElement;
- var result = await crystalClient.CreateRunAsync(
- "algorithm",
- payload,
- new AlgorithmConfiguration(),
- CancellationToken.None);
- Assert.NotNull(result);
- Assert.Equal("00000000-0000-0000-0000-000000000000", result!.RequestId);
- }
-
-}
\ No newline at end of file
diff --git a/test/SnD.ApiClient.Tests/SnD.ApiClient.Tests.csproj b/test/SnD.ApiClient.Tests/SnD.ApiClient.Tests.csproj
index df1350f..3ad1751 100644
--- a/test/SnD.ApiClient.Tests/SnD.ApiClient.Tests.csproj
+++ b/test/SnD.ApiClient.Tests/SnD.ApiClient.Tests.csproj
@@ -37,9 +37,6 @@
-
- PreserveNewest
-