dev
This commit is contained in:
parent
18126ea763
commit
0cfe60e3ab
22 changed files with 115 additions and 158 deletions
|
@ -232,7 +232,7 @@ public class Client : IFrostFSClient
|
|||
|
||||
private async void CheckFrostFsVersionSupport(Context? ctx = default)
|
||||
{
|
||||
var args = new PrmNodeInfo(ctx);
|
||||
var args = new PrmNodeInfo { Context = ctx };
|
||||
var service = GetNetmapService(args);
|
||||
var localNodeInfo = await service.GetLocalNodeInfoAsync(args);
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using FrostFS.SDK.ClientV2.Parameters;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using Grpc.Core.Interceptors;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using Grpc.Core.Interceptors;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2;
|
||||
|
||||
|
@ -11,9 +12,17 @@ public class Context()
|
|||
private List<Interceptor>? interceptors;
|
||||
|
||||
public CancellationToken CancellationToken { get; set; } = default;
|
||||
|
||||
public TimeSpan Timeout { get; set; } = default;
|
||||
|
||||
public DateTime? Deadline => Timeout.Ticks > 0 ? DateTime.UtcNow.Add(Timeout) : null;
|
||||
|
||||
/// <summary>
|
||||
/// Provide OwnerId and Key can be created from string representaion
|
||||
/// and cached on the client side
|
||||
/// </summary>
|
||||
public Credentials? Credentials { get; set; }
|
||||
|
||||
public Action<CallStatistics>? Callback { get; set; }
|
||||
|
||||
public List<Interceptor> Interceptors
|
11
src/FrostFS.SDK.ClientV2/Parameters/Credentials.cs
Normal file
11
src/FrostFS.SDK.ClientV2/Parameters/Credentials.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using FrostFS.SDK.ModelsV2;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public class Credentials(ECDsa key, OwnerId ownerId)
|
||||
{
|
||||
public ECDsa Key { get; } = key;
|
||||
|
||||
public OwnerId OwnerId { get; } = ownerId;
|
||||
}
|
14
src/FrostFS.SDK.ClientV2/Parameters/PrmBase.cs
Normal file
14
src/FrostFS.SDK.ClientV2/Parameters/PrmBase.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Specialized;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public class PrmBase() : IContext
|
||||
{
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmContainerCreate(ModelsV2.Container container) : IContext
|
||||
public sealed class PrmContainerCreate(ModelsV2.Container container) : PrmBase, ISessionToken
|
||||
{
|
||||
public ModelsV2.Container Container { get; set; } = container;
|
||||
|
||||
|
@ -12,11 +12,7 @@ public sealed class PrmContainerCreate(ModelsV2.Container container) : IContext
|
|||
/// <value>Rules for polling the result</value>
|
||||
public PrmWait? WaitParams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
public string SessionKey { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmContainerDelete(ContainerId containerId, Context? ctx = null) : IContext
|
||||
public sealed class PrmContainerDelete(ContainerId containerId) : PrmBase, ISessionToken
|
||||
{
|
||||
public ContainerId ContainerId { get; set; } = containerId;
|
||||
|
||||
|
@ -12,12 +11,6 @@ public sealed class PrmContainerDelete(ContainerId containerId, Context? ctx = n
|
|||
/// </summary>
|
||||
/// <value>Rules for polling the result</value>
|
||||
public PrmWait? WaitParams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = ctx;
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmContainerGet(ContainerId containerId, Context? ctx = null) : IContext
|
||||
public sealed class PrmContainerGet(ContainerId containerId) : PrmBase
|
||||
{
|
||||
public ContainerId ContainerId { get; set; } = containerId;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = ctx;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,6 @@
|
|||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmContainerGetAll() : IContext
|
||||
public sealed class PrmContainerGetAll() : PrmBase()
|
||||
{
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
}
|
||||
|
|
|
@ -2,13 +2,6 @@
|
|||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmNetmapSnapshot(Context? context = default) : IContext
|
||||
{
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = context;
|
||||
public sealed class PrmNetmapSnapshot() : PrmBase
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
using System.Collections.Specialized;
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmNetworkSettings(Context? context = default) : IContext
|
||||
{
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = context;
|
||||
public sealed class PrmNetworkSettings(Context? context = default) : PrmBase
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
using System.Collections.Specialized;
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmNodeInfo(Context? context = default) : IContext
|
||||
{
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = context;
|
||||
public sealed class PrmNodeInfo() : PrmBase
|
||||
{
|
||||
}
|
||||
|
|
|
@ -3,19 +3,12 @@ using FrostFS.SDK.ModelsV2;
|
|||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmObjectDelete(ContainerId containerId, ObjectId objectId) : IContext, ISessionToken
|
||||
public sealed class PrmObjectDelete(ContainerId containerId, ObjectId objectId) : PrmBase, ISessionToken
|
||||
{
|
||||
public ContainerId ContainerId { get; set; } = containerId;
|
||||
|
||||
public ObjectId ObjectId { get; set; } = objectId;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmObjectGet(ContainerId containerId, ObjectId objectId) : IContext, ISessionToken
|
||||
public sealed class PrmObjectGet(ContainerId containerId, ObjectId objectId) : PrmBase, ISessionToken
|
||||
{
|
||||
public ContainerId ContainerId { get; set; } = containerId;
|
||||
|
||||
public ObjectId ObjectId { get; set; } = objectId;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmObjectHeadGet(ContainerId containerId, ObjectId objectId) : IContext, ISessionToken
|
||||
public sealed class PrmObjectHeadGet(ContainerId containerId, ObjectId objectId) : PrmBase, ISessionToken
|
||||
{
|
||||
public ContainerId ContainerId { get; set; } = containerId;
|
||||
|
||||
public ObjectId ObjectId { get; set; } = objectId;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using FrostFS.SDK.ModelsV2;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmObjectPut : IContext, ISessionToken
|
||||
public sealed class PrmObjectPut : PrmBase, ISessionToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Need to provide values like <c>ContainerId</c> and <c>ObjectType</c> to create and object.
|
||||
|
@ -37,14 +36,6 @@ public sealed class PrmObjectPut : IContext, ISessionToken
|
|||
/// </summary>
|
||||
public byte[]? CustomBuffer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using System.Collections.Generic;
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilter[] filters) : IContext, ISessionToken
|
||||
public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilter[] filters) : PrmBase, ISessionToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines container for the search
|
||||
|
@ -16,15 +15,7 @@ public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilte
|
|||
/// </summary>
|
||||
/// <value>Collection of filters</value>
|
||||
public IEnumerable<IObjectFilter> Filters { get; set; } = filters;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,16 +1,6 @@
|
|||
using System.Collections.Specialized;
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmSessionCreate(ulong expiration, Context? context = default) : IContext
|
||||
public sealed class PrmSessionCreate(ulong expiration, Context? context = default) : PrmBase
|
||||
{
|
||||
public ulong Expiration { get; set; } = expiration;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = context;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
using System.Collections.Specialized;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ModelsV2;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||
|
||||
public sealed class PrmSingleObjectPut(FrostFsObject frostFsObject, Context? context = null) : IContext, ISessionToken
|
||||
public sealed class PrmSingleObjectPut(FrostFsObject frostFsObject) : PrmBase, ISessionToken
|
||||
{
|
||||
public FrostFsObject FrostFsObject { get; set; } = frostFsObject;
|
||||
|
||||
/// <summary>
|
||||
/// FrostFS request X-Headers
|
||||
/// </summary>
|
||||
public NameValueCollection XHeaders { get; set; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public Context? Context { get; set; } = context;
|
||||
|
||||
/// <inheritdoc />
|
||||
public SessionToken? SessionToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -10,11 +10,20 @@ using FrostFS.SDK.Cryptography;
|
|||
using FrostFS.SDK.ModelsV2;
|
||||
using FrostFS.SDK.ClientV2.Parameters;
|
||||
using FrostFS.Refs;
|
||||
using FrostFS.Session;
|
||||
using FrostFS.Status;
|
||||
|
||||
namespace FrostFS.SDK.ClientV2;
|
||||
|
||||
internal class ContainerServiceProvider(ContainerService.ContainerServiceClient service, ClientEnvironment context) : ContextAccessor(context)
|
||||
internal class ContainerServiceProvider(ContainerService.ContainerServiceClient service, ClientEnvironment context) : ContextAccessor(context), ISessionProvider
|
||||
{
|
||||
readonly SessionProvider sessions = new(context);
|
||||
|
||||
public async ValueTask<Session.SessionToken> GetOrCreateSession(ISessionToken args, Context ctx)
|
||||
{
|
||||
return await sessions.GetOrCreateSession(args, ctx);
|
||||
}
|
||||
|
||||
internal async Task<ModelsV2.Container> GetContainerAsync(PrmContainerGet args)
|
||||
{
|
||||
GetRequest request = GetContainerRequest(args.ContainerId.ToMessage(), args.XHeaders);
|
||||
|
@ -57,7 +66,9 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
|||
var grpcContainer = args.Container.ToMessage();
|
||||
grpcContainer.OwnerId = Context.Owner.ToMessage();
|
||||
grpcContainer.Version = Context.Version.ToMessage();
|
||||
|
||||
|
||||
var sessionKey = args.SessionKey.LoadWif();
|
||||
|
||||
var request = new PutRequest
|
||||
{
|
||||
Body = new PutRequest.Types.Body
|
||||
|
@ -82,12 +93,13 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
|||
internal async Task DeleteContainerAsync(PrmContainerDelete args)
|
||||
{
|
||||
var ctx = args.Context!;
|
||||
|
||||
var request = new DeleteRequest
|
||||
{
|
||||
Body = new DeleteRequest.Types.Body
|
||||
{
|
||||
ContainerId = args.ContainerId.ToMessage(),
|
||||
Signature = Context.Key.ECDsaKey.SignRFC6979(args.ContainerId.ToMessage().Value)
|
||||
Signature = ctx.Credentials!.Key.SignRFC6979(args.ContainerId.ToMessage().Value)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -97,6 +109,8 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
|||
|
||||
var response = await service.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||
|
||||
Verifier.CheckResponse(response);
|
||||
|
||||
await WaitForContainer(WaitExpects.Removed, request.Body.ContainerId, args.WaitParams, ctx);
|
||||
|
||||
Verifier.CheckResponse(response);
|
||||
|
|
|
@ -13,6 +13,8 @@ public class ClientEnvironment(Client client, ECDsa key, OwnerId owner, GrpcChan
|
|||
private ArrayPool<byte> _arrayPool;
|
||||
|
||||
internal OwnerId Owner { get; } = owner;
|
||||
|
||||
public ClientKey SessionKey { get; set; }
|
||||
internal GrpcChannel Channel { get; private set; } = channel;
|
||||
internal ModelsV2.Version Version { get; } = version;
|
||||
internal NetworkSettings? NetworkSettings { get; set; }
|
||||
|
|
|
@ -49,4 +49,22 @@ public static class RequestConstructor
|
|||
|
||||
sessionToken.Signature = key.SignMessagePart(sessionToken.Body);
|
||||
}
|
||||
|
||||
public static void CreateContainerTokenContext(this Session.SessionToken sessionToken,
|
||||
ContainerID? containerId,
|
||||
ContainerSessionContext.Types.Verb verb,
|
||||
ECDsa key)
|
||||
{
|
||||
if (sessionToken.Body.Container?.ContainerId != null)
|
||||
return;
|
||||
|
||||
sessionToken.Body.Container = new() { Verb = verb };
|
||||
|
||||
if (containerId != null)
|
||||
sessionToken.Body.Container.ContainerId = containerId;
|
||||
else
|
||||
sessionToken.Body.Container.Wildcard = true;
|
||||
|
||||
sessionToken.Signature = key.SignMessagePart(sessionToken.Body);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ public class SmokeTests
|
|||
|
||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var container = await client.GetContainerAsync(new PrmContainerGet(containerId,ctx));
|
||||
var container = await client.GetContainerAsync(new PrmContainerGet(containerId) { Context = ctx });
|
||||
Assert.NotNull(container);
|
||||
Assert.True(callbackInvoked);
|
||||
|
||||
|
@ -338,7 +338,7 @@ public class SmokeTests
|
|||
|
||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var container = await client.GetContainerAsync(new PrmContainerGet(containerId,ctx));
|
||||
var container = await client.GetContainerAsync(new PrmContainerGet(containerId) { Context = ctx });
|
||||
Assert.NotNull(container);
|
||||
|
||||
var bytes = GetRandomBytes(objectSize);
|
||||
|
@ -417,13 +417,13 @@ public class SmokeTests
|
|||
|
||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
||||
|
||||
var context = new Context
|
||||
var ctx = new Context
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(10),
|
||||
Interceptors = new([new MetricsInterceptor()])
|
||||
};
|
||||
|
||||
var container = await client.GetContainerAsync(new PrmContainerGet(containerId, context));
|
||||
var container = await client.GetContainerAsync(new PrmContainerGet(containerId) { Context = ctx });
|
||||
|
||||
Assert.NotNull(container);
|
||||
|
||||
|
|
Loading…
Reference in a new issue