[#21] Client: Allows multinenant client
All checks were successful
DCO / DCO (pull_request) Successful in 27s
All checks were successful
DCO / DCO (pull_request) Successful in 27s
Using one client for several owners Signed-off-by: Pavel Gross <p.gross@yando.com>
This commit is contained in:
parent
18126ea763
commit
2a28806ace
30 changed files with 349 additions and 281 deletions
|
@ -35,6 +35,11 @@ public class Client : IFrostFSClient
|
||||||
return new Client(clientOptions, channelOptions);
|
return new Client(clientOptions, channelOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IFrostFSClient GetSingleOwnerInstance(IOptions<SingleOwnerClientSettings> clientOptions, GrpcChannelOptions? channelOptions = null)
|
||||||
|
{
|
||||||
|
return new Client(clientOptions, channelOptions);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For test only. Provide custom implementation or mock object to inject required logic instead of internal gRPC client.
|
/// For test only. Provide custom implementation or mock object to inject required logic instead of internal gRPC client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -46,7 +51,7 @@ public class Client : IFrostFSClient
|
||||||
/// <param name="objectService">Object.ObjectService.ObjectServiceClient implementation</param>
|
/// <param name="objectService">Object.ObjectService.ObjectServiceClient implementation</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IFrostFSClient GetTestInstance(
|
public static IFrostFSClient GetTestInstance(
|
||||||
IOptions<ClientSettings> clientOptions,
|
IOptions<SingleOwnerClientSettings> clientOptions,
|
||||||
GrpcChannelOptions? channelOptions,
|
GrpcChannelOptions? channelOptions,
|
||||||
NetmapService.NetmapServiceClient netmapService,
|
NetmapService.NetmapServiceClient netmapService,
|
||||||
SessionService.SessionServiceClient sessionService,
|
SessionService.SessionServiceClient sessionService,
|
||||||
|
@ -57,18 +62,18 @@ public class Client : IFrostFSClient
|
||||||
}
|
}
|
||||||
|
|
||||||
private Client(
|
private Client(
|
||||||
IOptions<ClientSettings> settings,
|
IOptions<SingleOwnerClientSettings> settings,
|
||||||
GrpcChannelOptions? channelOptions,
|
GrpcChannelOptions? channelOptions,
|
||||||
ContainerService.ContainerServiceClient containerService,
|
ContainerService.ContainerServiceClient containerService,
|
||||||
NetmapService.NetmapServiceClient netmapService,
|
NetmapService.NetmapServiceClient netmapService,
|
||||||
SessionService.SessionServiceClient sessionService,
|
SessionService.SessionServiceClient sessionService,
|
||||||
ObjectService.ObjectServiceClient objectService)
|
ObjectService.ObjectServiceClient objectService)
|
||||||
{
|
{
|
||||||
var ecdsaKey = settings.Value.Key.LoadWif();
|
var ecdsaKey = settings.Value.Key.LoadWif();
|
||||||
OwnerId.FromKey(ecdsaKey);
|
OwnerId.FromKey(ecdsaKey);
|
||||||
|
|
||||||
ClientCtx = new ClientEnvironment(
|
ClientCtx = new ClientEnvironment(
|
||||||
this,
|
client: this,
|
||||||
key: ecdsaKey,
|
key: ecdsaKey,
|
||||||
owner: OwnerId.FromKey(ecdsaKey),
|
owner: OwnerId.FromKey(ecdsaKey),
|
||||||
channel: InitGrpcChannel(settings.Value.Host, channelOptions),
|
channel: InitGrpcChannel(settings.Value.Host, channelOptions),
|
||||||
|
@ -86,6 +91,25 @@ public class Client : IFrostFSClient
|
||||||
|
|
||||||
clientSettings.Validate();
|
clientSettings.Validate();
|
||||||
|
|
||||||
|
var channel = InitGrpcChannel(clientSettings.Host, channelOptions);
|
||||||
|
|
||||||
|
ClientCtx = new ClientEnvironment(
|
||||||
|
this,
|
||||||
|
key: null,
|
||||||
|
owner: null,
|
||||||
|
channel: channel,
|
||||||
|
version: new Version(2, 13));
|
||||||
|
|
||||||
|
// TODO: define timeout logic
|
||||||
|
// CheckFrostFsVersionSupport(new Context { Timeout = TimeSpan.FromSeconds(20) });
|
||||||
|
}
|
||||||
|
|
||||||
|
private Client(IOptions<SingleOwnerClientSettings> options, GrpcChannelOptions? channelOptions)
|
||||||
|
{
|
||||||
|
var clientSettings = (options?.Value) ?? throw new ArgumentException("Options must be initialized");
|
||||||
|
|
||||||
|
clientSettings.Validate();
|
||||||
|
|
||||||
var ecdsaKey = clientSettings.Key.LoadWif();
|
var ecdsaKey = clientSettings.Key.LoadWif();
|
||||||
|
|
||||||
var channel = InitGrpcChannel(clientSettings.Host, channelOptions);
|
var channel = InitGrpcChannel(clientSettings.Host, channelOptions);
|
||||||
|
@ -221,22 +245,22 @@ public class Client : IFrostFSClient
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ToolsImplementation
|
#region ToolsImplementation
|
||||||
public ObjectId CalculateObjectId(ObjectHeader header)
|
public ObjectId CalculateObjectId(ObjectHeader header, Context ctx)
|
||||||
{
|
{
|
||||||
if (header == null)
|
if (header == null)
|
||||||
throw new ArgumentNullException(nameof(header));
|
throw new ArgumentNullException(nameof(header));
|
||||||
|
|
||||||
return ObjectTools.CalculateObjectId(header, ClientCtx);
|
return ObjectTools.CalculateObjectId(header, ctx);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private async void CheckFrostFsVersionSupport(Context? ctx = default)
|
private async void CheckFrostFsVersionSupport(Context? ctx = default)
|
||||||
{
|
{
|
||||||
var args = new PrmNodeInfo(ctx);
|
var args = new PrmNodeInfo { Context = ctx };
|
||||||
var service = GetNetmapService(args);
|
var service = GetNetmapService(args);
|
||||||
var localNodeInfo = await service.GetLocalNodeInfoAsync(args);
|
var localNodeInfo = await service.GetLocalNodeInfoAsync(args);
|
||||||
|
|
||||||
if (!localNodeInfo.Version.IsSupported(ClientCtx.Version))
|
if (!localNodeInfo.Version.IsSupported(args.Context!.Version))
|
||||||
{
|
{
|
||||||
var msg = $"FrostFS {localNodeInfo.Version} is not supported.";
|
var msg = $"FrostFS {localNodeInfo.Version} is not supported.";
|
||||||
throw new ApplicationException(msg);
|
throw new ApplicationException(msg);
|
||||||
|
@ -250,6 +274,31 @@ public class Client : IFrostFSClient
|
||||||
|
|
||||||
ctx.Context ??= new Context();
|
ctx.Context ??= new Context();
|
||||||
|
|
||||||
|
if (ctx.Context.Key == null)
|
||||||
|
{
|
||||||
|
if (ClientCtx.Key == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Key is not initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Context.Key = ClientCtx.Key.ECDsaKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.Context.OwnerId == null)
|
||||||
|
{
|
||||||
|
ctx.Context.OwnerId = ClientCtx.Owner ?? OwnerId.FromKey(ctx.Context.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.Context.Version == null)
|
||||||
|
{
|
||||||
|
if (ClientCtx.Version == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Version is not initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Context.Version = ClientCtx.Version;
|
||||||
|
}
|
||||||
|
|
||||||
CallInvoker? callInvoker = null;
|
CallInvoker? callInvoker = null;
|
||||||
if (ctx.Context.Interceptors != null && ctx.Context.Interceptors.Count > 0)
|
if (ctx.Context.Interceptors != null && ctx.Context.Interceptors.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,6 @@ public interface IFrostFSClient : IDisposable
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Tools
|
#region Tools
|
||||||
ObjectId CalculateObjectId(ObjectHeader header);
|
ObjectId CalculateObjectId(ObjectHeader header, Context ctx);
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
using FrostFS.SDK.Cryptography;
|
||||||
|
using Google.Protobuf;
|
||||||
using Grpc.Core.Interceptors;
|
using Grpc.Core.Interceptors;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
@ -10,8 +13,18 @@ public class Context()
|
||||||
{
|
{
|
||||||
private List<Interceptor>? interceptors;
|
private List<Interceptor>? interceptors;
|
||||||
|
|
||||||
|
private ByteString publicKeyCache;
|
||||||
|
|
||||||
|
public ECDsa Key { get; set; }
|
||||||
|
|
||||||
|
public OwnerId OwnerId { get; set; }
|
||||||
|
|
||||||
|
public ModelsV2.Version Version { get; set; }
|
||||||
|
|
||||||
public CancellationToken CancellationToken { get; set; } = default;
|
public CancellationToken CancellationToken { get; set; } = default;
|
||||||
|
|
||||||
public TimeSpan Timeout { get; set; } = default;
|
public TimeSpan Timeout { get; set; } = default;
|
||||||
|
|
||||||
public DateTime? Deadline => Timeout.Ticks > 0 ? DateTime.UtcNow.Add(Timeout) : null;
|
public DateTime? Deadline => Timeout.Ticks > 0 ? DateTime.UtcNow.Add(Timeout) : null;
|
||||||
|
|
||||||
public Action<CallStatistics>? Callback { get; set; }
|
public Action<CallStatistics>? Callback { get; set; }
|
||||||
|
@ -20,5 +33,18 @@ public class Context()
|
||||||
{
|
{
|
||||||
get { return this.interceptors ??= []; }
|
get { return this.interceptors ??= []; }
|
||||||
set { this.interceptors = value; }
|
set { this.interceptors = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ByteString PublicKeyCache
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (publicKeyCache == null)
|
||||||
|
{
|
||||||
|
publicKeyCache = ByteString.CopyFrom(Key.PublicKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
return publicKeyCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
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;
|
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;
|
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>
|
/// <value>Rules for polling the result</value>
|
||||||
public PrmWait? WaitParams { get; set; }
|
public PrmWait? WaitParams { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public string SessionKey { get; set; }
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
public SessionToken? SessionToken { get; set; }
|
||||||
public Context? Context { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
using System.Collections.Specialized;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using FrostFS.SDK.ModelsV2;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
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;
|
public ContainerId ContainerId { get; set; } = containerId;
|
||||||
|
|
||||||
|
@ -12,12 +11,6 @@ public sealed class PrmContainerDelete(ContainerId containerId, Context? ctx = n
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>Rules for polling the result</value>
|
/// <value>Rules for polling the result</value>
|
||||||
public PrmWait? WaitParams { get; set; }
|
public PrmWait? WaitParams { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
public SessionToken? SessionToken { get; set; }
|
||||||
public Context? Context { get; set; } = ctx;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
using System.Collections.Specialized;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using FrostFS.SDK.ModelsV2;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
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;
|
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;
|
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;
|
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||||
|
|
||||||
public sealed class PrmNetmapSnapshot(Context? context = default) : IContext
|
public sealed class PrmNetmapSnapshot() : PrmBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Context? Context { get; set; } = context;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
using System.Collections.Specialized;
|
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
public sealed class PrmNetworkSettings() : PrmBase
|
||||||
|
{
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
using System.Collections.Specialized;
|
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
public sealed class PrmNodeInfo() : PrmBase
|
||||||
|
{
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,12 @@ using FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
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 ContainerId ContainerId { get; set; } = containerId;
|
||||||
|
|
||||||
public ObjectId ObjectId { get; set; } = objectId;
|
public ObjectId ObjectId { get; set; } = objectId;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Context? Context { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public SessionToken? SessionToken { get; set; }
|
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;
|
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 ContainerId ContainerId { get; set; } = containerId;
|
||||||
|
|
||||||
public ObjectId ObjectId { get; set; } = objectId;
|
public ObjectId ObjectId { get; set; } = objectId;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Context? Context { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public SessionToken? SessionToken { get; set; }
|
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;
|
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 ContainerId ContainerId { get; set; } = containerId;
|
||||||
|
|
||||||
public ObjectId ObjectId { get; set; } = objectId;
|
public ObjectId ObjectId { get; set; } = objectId;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Context? Context { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public SessionToken? SessionToken { get; set; }
|
public SessionToken? SessionToken { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using FrostFS.SDK.ModelsV2;
|
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
namespace FrostFS.SDK.ClientV2.Parameters;
|
||||||
|
|
||||||
public sealed class PrmObjectPut : IContext, ISessionToken
|
public sealed class PrmObjectPut : PrmBase, ISessionToken
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Need to provide values like <c>ContainerId</c> and <c>ObjectType</c> to create and object.
|
/// Need to provide values like <c>ContainerId</c> and <c>ObjectType</c> to create and object.
|
||||||
|
@ -30,21 +30,13 @@ public sealed class PrmObjectPut : IContext, ISessionToken
|
||||||
/// Overrides default size of the buffer for stream transferring.
|
/// Overrides default size of the buffer for stream transferring.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>Size of the buffer</value>
|
/// <value>Size of the buffer</value>
|
||||||
public int BufferMaxSize { get; set; }
|
public int BufferMaxSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows to define a buffer for chunks to manage by the memory allocation and releasing.
|
/// Allows to define a buffer for chunks to manage by the memory allocation and releasing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? CustomBuffer { get; set; }
|
public byte[]? CustomBuffer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FrostFS request X-Headers
|
|
||||||
/// </summary>
|
|
||||||
public NameValueCollection XHeaders { get; set; } = [];
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Context? Context { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public SessionToken? SessionToken { get; set; }
|
public SessionToken? SessionToken { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Generic;
|
||||||
using FrostFS.SDK.ModelsV2;
|
|
||||||
namespace FrostFS.SDK.ClientV2.Parameters;
|
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>
|
/// <summary>
|
||||||
/// Defines container for the search
|
/// Defines container for the search
|
||||||
|
@ -16,15 +15,7 @@ public sealed class PrmObjectSearch(ContainerId containerId, params IObjectFilte
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>Collection of filters</value>
|
/// <value>Collection of filters</value>
|
||||||
public IEnumerable<IObjectFilter> Filters { get; set; } = filters;
|
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 />
|
/// <inheritdoc />
|
||||||
public SessionToken? SessionToken { get; set; }
|
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) : PrmBase
|
||||||
|
|
||||||
public sealed class PrmSessionCreate(ulong expiration, Context? context = default) : IContext
|
|
||||||
{
|
{
|
||||||
public ulong Expiration { get; set; } = expiration;
|
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;
|
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;
|
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 />
|
/// <inheritdoc />
|
||||||
public SessionToken? SessionToken { get; set; }
|
public SessionToken? SessionToken { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
{
|
{
|
||||||
internal async Task<ModelsV2.Container> GetContainerAsync(PrmContainerGet args)
|
internal async Task<ModelsV2.Container> GetContainerAsync(PrmContainerGet args)
|
||||||
{
|
{
|
||||||
GetRequest request = GetContainerRequest(args.ContainerId.ToMessage(), args.XHeaders);
|
GetRequest request = GetContainerRequest(args.ContainerId.ToMessage(), args.XHeaders, args.Context!);
|
||||||
|
|
||||||
var response = await service.GetAsync(request, null, args.Context!.Deadline, args.Context.CancellationToken);
|
var response = await service.GetAsync(request, null, args.Context!.Deadline, args.Context.CancellationToken);
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
{
|
{
|
||||||
Body = new ListRequest.Types.Body
|
Body = new ListRequest.Types.Body
|
||||||
{
|
{
|
||||||
OwnerId = Context.Owner.ToMessage()
|
OwnerId = ctx.OwnerId.ToMessage()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await service.ListAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await service.ListAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -55,20 +55,20 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
{
|
{
|
||||||
var ctx = args.Context!;
|
var ctx = args.Context!;
|
||||||
var grpcContainer = args.Container.ToMessage();
|
var grpcContainer = args.Container.ToMessage();
|
||||||
grpcContainer.OwnerId = Context.Owner.ToMessage();
|
grpcContainer.OwnerId = ctx.OwnerId.ToMessage();
|
||||||
grpcContainer.Version = Context.Version.ToMessage();
|
grpcContainer.Version = ctx.Version.ToMessage();
|
||||||
|
|
||||||
var request = new PutRequest
|
var request = new PutRequest
|
||||||
{
|
{
|
||||||
Body = new PutRequest.Types.Body
|
Body = new PutRequest.Types.Body
|
||||||
{
|
{
|
||||||
Container = grpcContainer,
|
Container = grpcContainer,
|
||||||
Signature = Context.Key.ECDsaKey.SignRFC6979(grpcContainer)
|
Signature = ctx.Key.SignRFC6979(grpcContainer)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await service.PutAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await service.PutAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -87,13 +87,13 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
Body = new DeleteRequest.Types.Body
|
Body = new DeleteRequest.Types.Body
|
||||||
{
|
{
|
||||||
ContainerId = args.ContainerId.ToMessage(),
|
ContainerId = args.ContainerId.ToMessage(),
|
||||||
Signature = Context.Key.ECDsaKey.SignRFC6979(args.ContainerId.ToMessage().Value)
|
Signature = ctx.Key.SignRFC6979(args.ContainerId.ToMessage().Value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
|
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await service.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await service.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
Verifier.CheckResponse(response);
|
Verifier.CheckResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GetRequest GetContainerRequest(ContainerID id, NameValueCollection? xHeaders)
|
private static GetRequest GetContainerRequest(ContainerID id, NameValueCollection? xHeaders, Context ctx)
|
||||||
{
|
{
|
||||||
var request = new GetRequest
|
var request = new GetRequest
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader(xHeaders);
|
request.AddMetaHeader(xHeaders);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ internal class ContainerServiceProvider(ContainerService.ContainerServiceClient
|
||||||
|
|
||||||
private async Task WaitForContainer(WaitExpects expect, ContainerID id, PrmWait? waitParams, Context ctx)
|
private async Task WaitForContainer(WaitExpects expect, ContainerID id, PrmWait? waitParams, Context ctx)
|
||||||
{
|
{
|
||||||
var request = GetContainerRequest(id, null);
|
var request = GetContainerRequest(id, null, ctx);
|
||||||
|
|
||||||
async Task action()
|
async Task action()
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,7 +49,7 @@ internal class NetmapServiceProvider : ContextAccessor
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await netmapServiceClient.LocalNodeInfoAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await netmapServiceClient.LocalNodeInfoAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ internal class NetmapServiceProvider : ContextAccessor
|
||||||
var request = new NetworkInfoRequest();
|
var request = new NetworkInfoRequest();
|
||||||
|
|
||||||
request.AddMetaHeader(null);
|
request.AddMetaHeader(null);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await netmapServiceClient.NetworkInfoAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await netmapServiceClient.NetworkInfoAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ internal class NetmapServiceProvider : ContextAccessor
|
||||||
var request = new NetmapSnapshotRequest();
|
var request = new NetmapSnapshotRequest();
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await netmapServiceClient.NetmapSnapshotAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await netmapServiceClient.NetmapSnapshotAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
|
|
@ -46,11 +46,11 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
sessionToken.CreateObjectTokenContext(
|
sessionToken.CreateObjectTokenContext(
|
||||||
request.Body.Address,
|
request.Body.Address,
|
||||||
ObjectSessionContext.Types.Verb.Head,
|
ObjectSessionContext.Types.Verb.Head,
|
||||||
Context.Key.ECDsaKey);
|
ctx.Key);
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders, sessionToken);
|
request.AddMetaHeader(args.XHeaders, sessionToken);
|
||||||
|
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await client!.HeadAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await client!.HeadAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -80,11 +80,11 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
sessionToken.CreateObjectTokenContext(
|
sessionToken.CreateObjectTokenContext(
|
||||||
request.Body.Address,
|
request.Body.Address,
|
||||||
ObjectSessionContext.Types.Verb.Get,
|
ObjectSessionContext.Types.Verb.Get,
|
||||||
Context.Key.ECDsaKey);
|
ctx.Key);
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders, sessionToken);
|
request.AddMetaHeader(args.XHeaders, sessionToken);
|
||||||
|
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
return await GetObject(request, ctx);
|
return await GetObject(request, ctx);
|
||||||
}
|
}
|
||||||
|
@ -109,10 +109,10 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
sessionToken.CreateObjectTokenContext(
|
sessionToken.CreateObjectTokenContext(
|
||||||
request.Body.Address,
|
request.Body.Address,
|
||||||
ObjectSessionContext.Types.Verb.Delete,
|
ObjectSessionContext.Types.Verb.Delete,
|
||||||
Context.Key.ECDsaKey);
|
ctx.Key);
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders, sessionToken);
|
request.AddMetaHeader(args.XHeaders, sessionToken);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await client.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await client.DeleteAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -139,11 +139,11 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
sessionToken.CreateObjectTokenContext(
|
sessionToken.CreateObjectTokenContext(
|
||||||
new Address { ContainerId = request.Body.ContainerId },
|
new Address { ContainerId = request.Body.ContainerId },
|
||||||
ObjectSessionContext.Types.Verb.Search,
|
ObjectSessionContext.Types.Verb.Search,
|
||||||
Context.Key.ECDsaKey);
|
ctx.Key);
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders, sessionToken);
|
request.AddMetaHeader(args.XHeaders, sessionToken);
|
||||||
|
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var objectsIds = SearchObjects(request, ctx);
|
var objectsIds = SearchObjects(request, ctx);
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
internal async Task<ObjectId> PutSingleObjectAsync(PrmSingleObjectPut args)
|
internal async Task<ObjectId> PutSingleObjectAsync(PrmSingleObjectPut args)
|
||||||
{
|
{
|
||||||
var ctx = args.Context!;
|
var ctx = args.Context!;
|
||||||
var grpcObject = ObjectTools.CreateObject(args.FrostFsObject, env);
|
var grpcObject = ObjectTools.CreateObject(args.FrostFsObject, ctx);
|
||||||
|
|
||||||
var request = new PutSingleRequest
|
var request = new PutSingleRequest
|
||||||
{
|
{
|
||||||
|
@ -192,11 +192,11 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
sessionToken.CreateObjectTokenContext(
|
sessionToken.CreateObjectTokenContext(
|
||||||
new Address { ContainerId = grpcObject.Header.ContainerId, ObjectId = grpcObject.ObjectId},
|
new Address { ContainerId = grpcObject.Header.ContainerId, ObjectId = grpcObject.ObjectId},
|
||||||
ObjectSessionContext.Types.Verb.Put,
|
ObjectSessionContext.Types.Verb.Put,
|
||||||
Context.Key.ECDsaKey);
|
ctx.Key);
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders, sessionToken);
|
request.AddMetaHeader(args.XHeaders, sessionToken);
|
||||||
|
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
var response = await client.PutSingleAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
var response = await client.PutSingleAsync(request, null, ctx.Deadline, ctx.CancellationToken);
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
|
|
||||||
if (args.MaxObjectSizeCache == 0)
|
if (args.MaxObjectSizeCache == 0)
|
||||||
{
|
{
|
||||||
var networkSettings = await Context.Client.GetNetworkSettingsAsync(new PrmNetworkSettings(ctx));
|
var networkSettings = await Context.Client.GetNetworkSettingsAsync(new PrmNetworkSettings() { Context = ctx });
|
||||||
args.MaxObjectSizeCache = (int)networkSettings.MaxObjectSize;
|
args.MaxObjectSizeCache = (int)networkSettings.MaxObjectSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
|
|
||||||
while (objectLimitSize == 0 || sentBytes < objectLimitSize)
|
while (objectLimitSize == 0 || sentBytes < objectLimitSize)
|
||||||
{
|
{
|
||||||
// send chanks limited to default or user's settings
|
// send chunks limited to default or user's settings
|
||||||
var bufferSize = objectLimitSize > 0 ?
|
var bufferSize = objectLimitSize > 0 ?
|
||||||
(int)Math.Min(objectLimitSize - sentBytes, chunkSize)
|
(int)Math.Min(objectLimitSize - sentBytes, chunkSize)
|
||||||
: chunkSize;
|
: chunkSize;
|
||||||
|
@ -350,8 +350,8 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
Chunk = ByteString.CopyFrom(chunkBuffer, 0, bytesCount)
|
Chunk = ByteString.CopyFrom(chunkBuffer, 0, bytesCount)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
chunkRequest.Sign(Context.Key.ECDsaKey);
|
chunkRequest.Sign(ctx.Key);
|
||||||
|
|
||||||
await stream.Write(chunkRequest);
|
await stream.Write(chunkRequest);
|
||||||
}
|
}
|
||||||
|
@ -374,14 +374,14 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
{
|
{
|
||||||
var header = args.Header!;
|
var header = args.Header!;
|
||||||
|
|
||||||
header.OwnerId = Context.Owner;
|
header.OwnerId = ctx.OwnerId;
|
||||||
header.Version = Context.Version;
|
header.Version = ctx.Version;
|
||||||
|
|
||||||
var grpcHeader = header.ToMessage();
|
var grpcHeader = header.ToMessage();
|
||||||
|
|
||||||
if (header.Split != null)
|
if (header.Split != null)
|
||||||
{
|
{
|
||||||
ObjectTools.SetSplitValues(grpcHeader, header.Split, env);
|
ObjectTools.SetSplitValues(grpcHeader, header.Split, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
var oid = new ObjectID { Value = grpcHeader.Sha256() };
|
var oid = new ObjectID { Value = grpcHeader.Sha256() };
|
||||||
|
@ -402,12 +402,12 @@ internal class ObjectServiceProvider(ObjectService.ObjectServiceClient client, C
|
||||||
sessionToken.CreateObjectTokenContext(
|
sessionToken.CreateObjectTokenContext(
|
||||||
new Address { ContainerId = grpcHeader.ContainerId, ObjectId = oid },
|
new Address { ContainerId = grpcHeader.ContainerId, ObjectId = oid },
|
||||||
ObjectSessionContext.Types.Verb.Put,
|
ObjectSessionContext.Types.Verb.Put,
|
||||||
Context.Key.ECDsaKey
|
ctx.Key
|
||||||
);
|
);
|
||||||
|
|
||||||
initRequest.AddMetaHeader(args.XHeaders, sessionToken);
|
initRequest.AddMetaHeader(args.XHeaders, sessionToken);
|
||||||
|
|
||||||
initRequest.Sign(Context.Key.ECDsaKey);
|
initRequest.Sign(ctx.Key);
|
||||||
|
|
||||||
return await PutObjectInit(initRequest, ctx);
|
return await PutObjectInit(initRequest, ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,18 @@ internal class SessionServiceProvider : ContextAccessor
|
||||||
|
|
||||||
internal async Task<SessionToken> CreateSessionAsync(PrmSessionCreate args)
|
internal async Task<SessionToken> CreateSessionAsync(PrmSessionCreate args)
|
||||||
{
|
{
|
||||||
|
var ctx = args.Context!;
|
||||||
var request = new CreateRequest
|
var request = new CreateRequest
|
||||||
{
|
{
|
||||||
Body = new CreateRequest.Types.Body
|
Body = new CreateRequest.Types.Body
|
||||||
{
|
{
|
||||||
OwnerId = Context.Owner.ToMessage(),
|
OwnerId = ctx.OwnerId.ToMessage(),
|
||||||
Expiration = args.Expiration
|
Expiration = args.Expiration
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddMetaHeader(args.XHeaders);
|
request.AddMetaHeader(args.XHeaders);
|
||||||
request.Sign(Context.Key.ECDsaKey);
|
request.Sign(ctx.Key);
|
||||||
|
|
||||||
return await CreateSession(request, args.Context!);
|
return await CreateSession(request, args.Context!);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ internal class SessionProvider(ClientEnvironment env)
|
||||||
{
|
{
|
||||||
if (args.SessionToken is null)
|
if (args.SessionToken is null)
|
||||||
{
|
{
|
||||||
return await env.Client.CreateSessionInternalAsync(new PrmSessionCreate(uint.MaxValue, ctx));
|
return await env.Client.CreateSessionInternalAsync(new PrmSessionCreate(uint.MaxValue) { Context = ctx });
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Session.SessionToken().Deserialize(args.SessionToken.Token);
|
return new Session.SessionToken().Deserialize(args.SessionToken.Token);
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using Google.Protobuf;
|
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
using System;
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
using System.Buffers;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
public class ClientEnvironment(Client client, ECDsa key, OwnerId owner, GrpcChannel channel, ModelsV2.Version version) : IDisposable
|
public class ClientEnvironment(Client client, ECDsa? key, OwnerId? owner, GrpcChannel channel, ModelsV2.Version version) : IDisposable
|
||||||
{
|
{
|
||||||
private ArrayPool<byte> _arrayPool;
|
private ArrayPool<byte> _arrayPool;
|
||||||
|
|
||||||
internal OwnerId Owner { get; } = owner;
|
internal OwnerId? Owner { get; } = owner;
|
||||||
|
|
||||||
internal GrpcChannel Channel { get; private set; } = channel;
|
internal GrpcChannel Channel { get; private set; } = channel;
|
||||||
|
|
||||||
internal ModelsV2.Version Version { get; } = version;
|
internal ModelsV2.Version Version { get; } = version;
|
||||||
|
|
||||||
internal NetworkSettings? NetworkSettings { get; set; }
|
internal NetworkSettings? NetworkSettings { get; set; }
|
||||||
|
|
||||||
internal Client Client { get; } = client;
|
internal Client Client { get; } = client;
|
||||||
|
|
||||||
internal ClientKey Key { get; } = new ClientKey(key);
|
internal ClientKey? Key { get; } = key != null ? new ClientKey(key) : null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom pool is used for predefined sizes of buffers like grpc chunk
|
/// Custom pool is used for predefined sizes of buffers like grpc chunk
|
||||||
|
|
|
@ -7,26 +7,25 @@ using FrostFS.Refs;
|
||||||
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
using FrostFS.SDK.ClientV2.Mappers.GRPC;
|
||||||
using FrostFS.SDK.Cryptography;
|
using FrostFS.SDK.Cryptography;
|
||||||
using FrostFS.SDK.ModelsV2;
|
using FrostFS.SDK.ModelsV2;
|
||||||
using static FrostFS.Object.Header.Types;
|
|
||||||
|
|
||||||
namespace FrostFS.SDK.ClientV2;
|
namespace FrostFS.SDK.ClientV2;
|
||||||
|
|
||||||
internal class ObjectTools
|
internal class ObjectTools
|
||||||
{
|
{
|
||||||
internal static ObjectId CalculateObjectId(ObjectHeader header, ClientEnvironment env)
|
internal static ObjectId CalculateObjectId(ObjectHeader header, Context ctx)
|
||||||
{
|
{
|
||||||
var grpcHeader = CreateHeader(header, [], env);
|
var grpcHeader = CreateHeader(header, [], ctx);
|
||||||
|
|
||||||
if (header.Split != null)
|
if (header.Split != null)
|
||||||
SetSplitValues(grpcHeader, header.Split, env);
|
SetSplitValues(grpcHeader, header.Split, ctx);
|
||||||
|
|
||||||
return new ObjectID { Value = grpcHeader.Sha256() }.ToModel();
|
return new ObjectID { Value = grpcHeader.Sha256() }.ToModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Object.Object CreateObject(FrostFsObject @object, ClientEnvironment env)
|
internal static Object.Object CreateObject(FrostFsObject @object, Context ctx)
|
||||||
{
|
{
|
||||||
@object.Header.OwnerId = env.Owner;
|
@object.Header.OwnerId = ctx.OwnerId;
|
||||||
@object.Header.Version = env.Version;
|
@object.Header.Version = ctx.Version;
|
||||||
|
|
||||||
var grpcHeader = @object.Header.ToMessage();
|
var grpcHeader = @object.Header.ToMessage();
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ internal class ObjectTools
|
||||||
var split = @object.Header.Split;
|
var split = @object.Header.Split;
|
||||||
if (split != null)
|
if (split != null)
|
||||||
{
|
{
|
||||||
SetSplitValues(grpcHeader, split, env);
|
SetSplitValues(grpcHeader, split, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj = new Object.Object
|
var obj = new Object.Object
|
||||||
|
@ -48,14 +47,14 @@ internal class ObjectTools
|
||||||
|
|
||||||
obj.Signature = new Refs.Signature
|
obj.Signature = new Refs.Signature
|
||||||
{
|
{
|
||||||
Key = env.Key.PublicKeyProto,
|
Key = ctx.PublicKeyCache,
|
||||||
Sign = ByteString.CopyFrom(env.Key.ECDsaKey.SignData(obj.ObjectId.ToByteArray())),
|
Sign = ByteString.CopyFrom(ctx.Key.SignData(obj.ObjectId.ToByteArray())),
|
||||||
};
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetSplitValues(Header grpcHeader, ModelsV2.Split split, ClientEnvironment env)
|
internal static void SetSplitValues(Header grpcHeader, ModelsV2.Split split, Context ctx)
|
||||||
{
|
{
|
||||||
grpcHeader.Split = new Header.Types.Split
|
grpcHeader.Split = new Header.Types.Split
|
||||||
{
|
{
|
||||||
|
@ -67,14 +66,14 @@ internal class ObjectTools
|
||||||
|
|
||||||
if (split.ParentHeader is not null)
|
if (split.ParentHeader is not null)
|
||||||
{
|
{
|
||||||
var grpcParentHeader = CreateHeader(split.ParentHeader, [], env);
|
var grpcParentHeader = CreateHeader(split.ParentHeader, [], ctx);
|
||||||
|
|
||||||
grpcHeader.Split.Parent = new ObjectID { Value = grpcParentHeader.Sha256() };
|
grpcHeader.Split.Parent = new ObjectID { Value = grpcParentHeader.Sha256() };
|
||||||
grpcHeader.Split.ParentHeader = grpcParentHeader;
|
grpcHeader.Split.ParentHeader = grpcParentHeader;
|
||||||
grpcHeader.Split.ParentSignature = new Refs.Signature
|
grpcHeader.Split.ParentSignature = new Refs.Signature
|
||||||
{
|
{
|
||||||
Key = env.Key.PublicKeyProto,
|
Key = ctx.PublicKeyCache,
|
||||||
Sign = ByteString.CopyFrom(env.Key.ECDsaKey.SignData(grpcHeader.Split.Parent.ToByteArray())),
|
Sign = ByteString.CopyFrom(ctx.Key.SignData(grpcHeader.Split.Parent.ToByteArray())),
|
||||||
};
|
};
|
||||||
|
|
||||||
split.Parent = grpcHeader.Split.Parent.ToModel();
|
split.Parent = grpcHeader.Split.Parent.ToModel();
|
||||||
|
@ -83,12 +82,12 @@ internal class ObjectTools
|
||||||
grpcHeader.Split.Previous = split.Previous?.ToMessage();
|
grpcHeader.Split.Previous = split.Previous?.ToMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Header CreateHeader(ObjectHeader header, byte[]? payload, ClientEnvironment env)
|
internal static Header CreateHeader(ObjectHeader header, byte[]? payload, Context ctx)
|
||||||
{
|
{
|
||||||
var grpcHeader = header.ToMessage();
|
var grpcHeader = header.ToMessage();
|
||||||
|
|
||||||
grpcHeader.OwnerId = env.Owner.ToMessage();
|
grpcHeader.OwnerId = ctx.OwnerId.ToMessage();
|
||||||
grpcHeader.Version = env.Version.ToMessage();
|
grpcHeader.Version = ctx.Version.ToMessage();
|
||||||
|
|
||||||
if (payload != null) // && payload.Length > 0
|
if (payload != null) // && payload.Length > 0
|
||||||
grpcHeader.PayloadHash = Sha256Checksum(payload);
|
grpcHeader.PayloadHash = Sha256Checksum(payload);
|
||||||
|
|
|
@ -1,28 +1,64 @@
|
||||||
|
using Google.Protobuf;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FrostFS.SDK.ModelsV2;
|
namespace FrostFS.SDK.ModelsV2;
|
||||||
|
|
||||||
public class ClientSettings
|
public class ClientSettings
|
||||||
{
|
{
|
||||||
private static readonly string errorTemplate = "{0} is required parameter";
|
protected static readonly string errorTemplate = "{0} is required parameter";
|
||||||
|
|
||||||
public string Key { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string Host { get; set; } = string.Empty;
|
public string Host { get; set; } = string.Empty;
|
||||||
|
|
||||||
public void Validate()
|
public virtual void Validate()
|
||||||
{
|
{
|
||||||
StringBuilder? error = null;
|
var errors = CheckFields();
|
||||||
|
if (errors != null)
|
||||||
if (string.IsNullOrWhiteSpace(Key))
|
ThrowException(errors);
|
||||||
(error ??= new StringBuilder()).AppendLine(string.Format(errorTemplate, nameof(Key)));
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(Host))
|
|
||||||
(error ??= new StringBuilder()).AppendLine(string.Format(errorTemplate, nameof(Host)));
|
|
||||||
|
|
||||||
if (error != null)
|
|
||||||
throw new ArgumentException(error.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<string>? CheckFields()
|
||||||
|
{
|
||||||
|
List<string>? errors = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Host))
|
||||||
|
(errors ??= []).Add(string.Format(errorTemplate, nameof(Host)));
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void ThrowException(List<string> errors)
|
||||||
|
{
|
||||||
|
StringBuilder messages = new();
|
||||||
|
|
||||||
|
foreach (var error in errors)
|
||||||
|
{
|
||||||
|
messages.AppendLine(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException(messages.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SingleOwnerClientSettings : ClientSettings
|
||||||
|
{
|
||||||
|
public string Key { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public override void Validate()
|
||||||
|
{
|
||||||
|
var errors = CheckFields();
|
||||||
|
if (errors != null)
|
||||||
|
ThrowException(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<string>? CheckFields()
|
||||||
|
{
|
||||||
|
List<string>? errors = base.CheckFields();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Key))
|
||||||
|
(errors ??= []).Add(string.Format(errorTemplate, nameof(Key)));
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -16,12 +16,12 @@ public abstract class ContainerTestsBase
|
||||||
{
|
{
|
||||||
protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||||
|
|
||||||
protected IOptions<ClientSettings> Settings { get; set; }
|
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||||
protected ContainerMocker Mocker { get; set; }
|
protected ContainerMocker Mocker { get; set; }
|
||||||
|
|
||||||
protected ContainerTestsBase()
|
protected ContainerTestsBase()
|
||||||
{
|
{
|
||||||
Settings = Options.Create(new ClientSettings
|
Settings = Options.Create(new SingleOwnerClientSettings
|
||||||
{
|
{
|
||||||
Key = key,
|
Key = key,
|
||||||
Host = "http://localhost:8080"
|
Host = "http://localhost:8080"
|
||||||
|
|
|
@ -19,7 +19,7 @@ public abstract class ObjectTestsBase
|
||||||
{
|
{
|
||||||
protected static readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
protected static readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||||
|
|
||||||
protected IOptions<ClientSettings> Settings { get; set; }
|
protected IOptions<SingleOwnerClientSettings> Settings { get; set; }
|
||||||
protected ContainerId ContainerId { get; set; }
|
protected ContainerId ContainerId { get; set; }
|
||||||
|
|
||||||
protected NetworkMocker NetworkMocker { get; set; } = new NetworkMocker(key);
|
protected NetworkMocker NetworkMocker { get; set; } = new NetworkMocker(key);
|
||||||
|
@ -31,7 +31,7 @@ public abstract class ObjectTestsBase
|
||||||
{
|
{
|
||||||
var ecdsaKey = key.LoadWif();
|
var ecdsaKey = key.LoadWif();
|
||||||
|
|
||||||
Settings = Options.Create(new ClientSettings
|
Settings = Options.Create(new SingleOwnerClientSettings
|
||||||
{
|
{
|
||||||
Key = key,
|
Key = key,
|
||||||
Host = "http://localhost:8080"
|
Host = "http://localhost:8080"
|
||||||
|
@ -71,14 +71,17 @@ public class ObjectTest : ObjectTestsBase
|
||||||
public async void GetObjectTest()
|
public async void GetObjectTest()
|
||||||
{
|
{
|
||||||
var client = GetClient();
|
var client = GetClient();
|
||||||
var objectId = client.CalculateObjectId(Mocker.ObjectHeader!);
|
|
||||||
|
|
||||||
var context = new Context
|
var ecdsaKey = key.LoadWif();
|
||||||
{
|
|
||||||
Timeout = TimeSpan.FromSeconds(2)
|
|
||||||
};
|
|
||||||
|
|
||||||
var result = await client.GetObjectAsync(new PrmObjectGet(ContainerId, objectId) { Context = context });
|
var ctx = new Context {
|
||||||
|
Key = ecdsaKey,
|
||||||
|
OwnerId = OwnerId.FromKey(ecdsaKey),
|
||||||
|
Version = new ModelsV2.Version(2, 13) };
|
||||||
|
|
||||||
|
var objectId = client.CalculateObjectId(Mocker.ObjectHeader!, ctx);
|
||||||
|
|
||||||
|
var result = await client.GetObjectAsync(new PrmObjectGet(ContainerId, objectId) { Context = ctx });
|
||||||
|
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
|
|
@ -13,21 +13,46 @@ using System.Diagnostics;
|
||||||
|
|
||||||
using static FrostFS.Session.SessionToken.Types.Body;
|
using static FrostFS.Session.SessionToken.Types.Body;
|
||||||
using FrostFS.SDK.ClientV2.Parameters;
|
using FrostFS.SDK.ClientV2.Parameters;
|
||||||
|
using FrostFS.SDK.Tests;
|
||||||
|
|
||||||
namespace FrostFS.SDK.SmokeTests;
|
namespace FrostFS.SDK.SmokeTests;
|
||||||
|
|
||||||
public class SmokeTests
|
public abstract class SmokeTestsBase
|
||||||
|
{
|
||||||
|
protected readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
||||||
|
protected readonly string url = "http://172.23.32.4:8080";
|
||||||
|
|
||||||
|
protected ECDsa Key { get; }
|
||||||
|
|
||||||
|
protected OwnerId OwnerId { get; }
|
||||||
|
|
||||||
|
protected ModelsV2.Version Version { get; }
|
||||||
|
|
||||||
|
protected Context Ctx { get; }
|
||||||
|
|
||||||
|
protected SmokeTestsBase()
|
||||||
|
{
|
||||||
|
Key = key.LoadWif();
|
||||||
|
OwnerId = OwnerId.FromKey(Key);
|
||||||
|
Version = new ModelsV2.Version(2, 13);
|
||||||
|
|
||||||
|
Ctx = new Context { Key = Key, OwnerId = OwnerId, Version = Version };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SmokeTests : SmokeTestsBase
|
||||||
{
|
{
|
||||||
private static readonly PrmWait lightWait = new (100, 1);
|
private static readonly PrmWait lightWait = new (100, 1);
|
||||||
private readonly string key = "KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq";
|
|
||||||
private readonly string url = "http://172.23.32.4:8080";
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async void NetworkMapTest()
|
|
||||||
{
|
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
|
||||||
|
|
||||||
var result = await client.GetNetmapSnapshotAsync();
|
[Theory]
|
||||||
|
[InlineData(false)]
|
||||||
|
[InlineData(true)]
|
||||||
|
public async void NetworkMapTest(bool isSingleOnwerClient)
|
||||||
|
{
|
||||||
|
using var client = isSingleOnwerClient ? Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url)) : Client.GetInstance(GetOptions(this.url));
|
||||||
|
|
||||||
|
PrmNetmapSnapshot? prm = isSingleOnwerClient ? default : new () { Context = Ctx };
|
||||||
|
var result = await client.GetNetmapSnapshotAsync(prm);
|
||||||
|
|
||||||
Assert.True(result.Epoch > 0);
|
Assert.True(result.Epoch > 0);
|
||||||
Assert.Single(result.NodeInfoCollection);
|
Assert.Single(result.NodeInfoCollection);
|
||||||
|
@ -41,12 +66,17 @@ public class SmokeTests
|
||||||
Assert.Equal(9, item.Attributes.Count);
|
Assert.Equal(9, item.Attributes.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async void NodeInfoTest()
|
|
||||||
{
|
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
|
||||||
|
|
||||||
var result = await client.GetNodeInfoAsync();
|
[Theory]
|
||||||
|
[InlineData(false)]
|
||||||
|
[InlineData(true)]
|
||||||
|
public async void NodeInfoTest(bool isSingleOnwerClient)
|
||||||
|
{
|
||||||
|
using var client = isSingleOnwerClient ? Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url)) : Client.GetInstance(GetOptions(this.url));
|
||||||
|
|
||||||
|
PrmNodeInfo? prm = isSingleOnwerClient ? default : new() { Context = Ctx };
|
||||||
|
|
||||||
|
var result = await client.GetNodeInfoAsync(prm);
|
||||||
|
|
||||||
Assert.Equal(2, result.Version.Major);
|
Assert.Equal(2, result.Version.Major);
|
||||||
Assert.Equal(13, result.Version.Minor);
|
Assert.Equal(13, result.Version.Minor);
|
||||||
|
@ -64,25 +94,25 @@ public class SmokeTests
|
||||||
Callback = (cs) => Console.WriteLine($"{cs.MethodName} took {cs.ElapsedMicroSeconds} microseconds")
|
Callback = (cs) => Console.WriteLine($"{cs.MethodName} took {cs.ElapsedMicroSeconds} microseconds")
|
||||||
};
|
};
|
||||||
|
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
using var client = Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||||
|
|
||||||
var result = await client.GetNodeInfoAsync();
|
var result = await client.GetNodeInfoAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public async void GetSessionTest()
|
[InlineData(false)]
|
||||||
|
[InlineData(true)]
|
||||||
|
public async void GetSessionTest(bool isSingleOnwerClient)
|
||||||
{
|
{
|
||||||
var ecdsaKey = this.key.LoadWif();
|
using var client = isSingleOnwerClient ? Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url)) : Client.GetInstance(GetOptions(this.url));
|
||||||
|
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
PrmSessionCreate? prm = isSingleOnwerClient ? new PrmSessionCreate(100) : new PrmSessionCreate(100) { Context = Ctx };
|
||||||
|
|
||||||
var token = await client.CreateSessionAsync(new PrmSessionCreate(100));
|
var token = await client.CreateSessionAsync(prm);
|
||||||
|
|
||||||
var session = new Session.SessionToken().Deserialize(token.Token);
|
var session = new Session.SessionToken().Deserialize(token.Token);
|
||||||
|
|
||||||
var owner = OwnerId.FromKey(ecdsaKey);
|
var ownerHash = Base58.Decode(OwnerId.Value);
|
||||||
|
|
||||||
var ownerHash = Base58.Decode(owner.Value);
|
|
||||||
|
|
||||||
Assert.NotNull(session);
|
Assert.NotNull(session);
|
||||||
Assert.Null(session.Body.Container);
|
Assert.Null(session.Body.Container);
|
||||||
|
@ -97,7 +127,7 @@ public class SmokeTests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void CreateObjectWithSessionToken()
|
public async void CreateObjectWithSessionToken()
|
||||||
{
|
{
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
using var client = Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||||
|
|
||||||
await Cleanup(client);
|
await Cleanup(client);
|
||||||
|
|
||||||
|
@ -144,7 +174,7 @@ public class SmokeTests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void FilterTest()
|
public async void FilterTest()
|
||||||
{
|
{
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
using var client = Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||||
|
|
||||||
await Cleanup(client);
|
await Cleanup(client);
|
||||||
|
|
||||||
|
@ -230,7 +260,7 @@ public class SmokeTests
|
||||||
[InlineData(6 * 1024 * 1024 + 100)]
|
[InlineData(6 * 1024 * 1024 + 100)]
|
||||||
public async void SimpleScenarioTest(int objectSize)
|
public async void SimpleScenarioTest(int objectSize)
|
||||||
{
|
{
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
using var client = Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||||
|
|
||||||
await Cleanup(client);
|
await Cleanup(client);
|
||||||
|
|
||||||
|
@ -253,7 +283,7 @@ public class SmokeTests
|
||||||
|
|
||||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
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.NotNull(container);
|
||||||
Assert.True(callbackInvoked);
|
Assert.True(callbackInvoked);
|
||||||
|
|
||||||
|
@ -318,7 +348,7 @@ public class SmokeTests
|
||||||
[InlineData(6 * 1024 * 1024 + 100)]
|
[InlineData(6 * 1024 * 1024 + 100)]
|
||||||
public async void SimpleScenarioWithSessionTest(int objectSize)
|
public async void SimpleScenarioWithSessionTest(int objectSize)
|
||||||
{
|
{
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
using var client = Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||||
|
|
||||||
var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue));
|
var token = await client.CreateSessionAsync(new PrmSessionCreate(int.MaxValue));
|
||||||
|
|
||||||
|
@ -338,7 +368,7 @@ public class SmokeTests
|
||||||
|
|
||||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
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.NotNull(container);
|
||||||
|
|
||||||
var bytes = GetRandomBytes(objectSize);
|
var bytes = GetRandomBytes(objectSize);
|
||||||
|
@ -406,7 +436,7 @@ public class SmokeTests
|
||||||
[InlineData(200)]
|
[InlineData(200)]
|
||||||
public async void ClientCutScenarioTest(int objectSize)
|
public async void ClientCutScenarioTest(int objectSize)
|
||||||
{
|
{
|
||||||
using var client = Client.GetInstance(GetOptions(this.key, this.url));
|
using var client = Client.GetSingleOwnerInstance(GetSingleOwnerOptions(this.key, this.url));
|
||||||
|
|
||||||
await Cleanup(client);
|
await Cleanup(client);
|
||||||
|
|
||||||
|
@ -417,13 +447,13 @@ public class SmokeTests
|
||||||
|
|
||||||
var containerId = await client.CreateContainerAsync(createContainerParam);
|
var containerId = await client.CreateContainerAsync(createContainerParam);
|
||||||
|
|
||||||
var context = new Context
|
var ctx = new Context
|
||||||
{
|
{
|
||||||
Timeout = TimeSpan.FromSeconds(10),
|
Timeout = TimeSpan.FromSeconds(10),
|
||||||
Interceptors = new([new MetricsInterceptor()])
|
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);
|
Assert.NotNull(container);
|
||||||
|
|
||||||
|
@ -499,11 +529,19 @@ public class SmokeTests
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOptions<ClientSettings> GetOptions(string key, string url)
|
private static IOptions<SingleOwnerClientSettings> GetSingleOwnerOptions(string key, string url)
|
||||||
|
{
|
||||||
|
return Options.Create(new SingleOwnerClientSettings
|
||||||
|
{
|
||||||
|
Key = key,
|
||||||
|
Host = url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IOptions<ClientSettings> GetOptions(string url)
|
||||||
{
|
{
|
||||||
return Options.Create(new ClientSettings
|
return Options.Create(new ClientSettings
|
||||||
{
|
{
|
||||||
Key = key,
|
|
||||||
Host = url
|
Host = url
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue