WIP: [#100] types: Make sdk types as protobuf wrappers #100
135 changed files with 2868 additions and 2188 deletions
|
@ -1,34 +1,45 @@
|
|||
package accounting
|
||||
|
||||
import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||
import (
|
||||
accgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// Decimal represents decimal number for accounting operations.
|
||||
//
|
||||
// Decimal is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting.Decimal
|
||||
// Decimal is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accgrpc.Decimal
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
// Instances must be created by NewDecimal() constructor.
|
||||
//
|
||||
// Note that direct typecast is not safe and may result in loss of compatibility:
|
||||
//
|
||||
// _ = Decimal(accounting.Decimal{}) // not recommended
|
||||
type Decimal accounting.Decimal
|
||||
// _ = Decimal(accgrpc.Decimal{}) // not recommended
|
||||
type Decimal struct {
|
||||
decimal *accgrpc.Decimal
|
||||
}
|
||||
|
||||
// ReadFromV2 reads Decimal from the accounting.Decimal message. Checks if the
|
||||
func NewDecimal() Decimal {
|
||||
return Decimal{
|
||||
decimal: &accgrpc.Decimal{},
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFromV2 reads Decimal from the accgrpc.Decimal message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (d *Decimal) ReadFromV2(m accounting.Decimal) error {
|
||||
*d = Decimal(m)
|
||||
return nil
|
||||
func (d *Decimal) ReadFromV2(m *accgrpc.Decimal) {
|
||||
proto.Merge(d.decimal, m)
|
||||
}
|
||||
|
||||
// WriteToV2 writes Decimal to the accounting.Decimal message.
|
||||
// WriteToV2 writes Decimal to the accgrpc.Decimal message.
|
||||
// The message must not be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (d Decimal) WriteToV2(m *accounting.Decimal) {
|
||||
*m = (accounting.Decimal)(d)
|
||||
func (d *Decimal) WriteToV2(m *accgrpc.Decimal) {
|
||||
m.Reset()
|
||||
proto.Merge(m, d.decimal)
|
||||
}
|
||||
|
||||
// Value returns value of the decimal number.
|
||||
|
@ -37,14 +48,14 @@ func (d Decimal) WriteToV2(m *accounting.Decimal) {
|
|||
//
|
||||
// See also SetValue.
|
||||
func (d Decimal) Value() int64 {
|
||||
return (*accounting.Decimal)(&d).GetValue()
|
||||
return d.decimal.GetValue()
|
||||
}
|
||||
|
||||
// SetValue sets value of the decimal number.
|
||||
//
|
||||
// See also Value.
|
||||
func (d *Decimal) SetValue(v int64) {
|
||||
(*accounting.Decimal)(d).SetValue(v)
|
||||
d.decimal.SetValue(v)
|
||||
}
|
||||
|
||||
// Precision returns precision of the decimal number.
|
||||
|
@ -52,13 +63,13 @@ func (d *Decimal) SetValue(v int64) {
|
|||
// Zero Decimal has zero precision.
|
||||
//
|
||||
// See also SetPrecision.
|
||||
func (d Decimal) Precision() uint32 {
|
||||
return (*accounting.Decimal)(&d).GetPrecision()
|
||||
func (d *Decimal) Precision() uint32 {
|
||||
return d.decimal.GetPrecision()
|
||||
}
|
||||
|
||||
// SetPrecision sets precision of the decimal number.
|
||||
//
|
||||
// See also Precision.
|
||||
func (d *Decimal) SetPrecision(p uint32) {
|
||||
(*accounting.Decimal)(d).SetPrecision(p)
|
||||
d.decimal.SetPrecision(p)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package accounting_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||
accgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -11,7 +11,7 @@ import (
|
|||
func TestDecimalData(t *testing.T) {
|
||||
const v, p = 4, 2
|
||||
|
||||
var d accounting.Decimal
|
||||
d := accounting.NewDecimal()
|
||||
|
||||
require.Zero(t, d.Value())
|
||||
require.Zero(t, d.Precision())
|
||||
|
@ -25,21 +25,21 @@ func TestDecimalData(t *testing.T) {
|
|||
|
||||
func TestDecimalMessageV2(t *testing.T) {
|
||||
var (
|
||||
d accounting.Decimal
|
||||
m v2accounting.Decimal
|
||||
d = accounting.NewDecimal()
|
||||
m accgrpc.Decimal
|
||||
)
|
||||
|
||||
m.SetValue(7)
|
||||
m.SetPrecision(8)
|
||||
|
||||
require.NoError(t, d.ReadFromV2(m))
|
||||
d.ReadFromV2(&m)
|
||||
|
||||
require.EqualValues(t, m.GetValue(), d.Value())
|
||||
require.EqualValues(t, m.GetPrecision(), d.Precision())
|
||||
|
||||
var m2 v2accounting.Decimal
|
||||
m2 := new(accgrpc.Decimal)
|
||||
|
||||
d.WriteToV2(&m2)
|
||||
d.WriteToV2(m2)
|
||||
|
||||
require.EqualValues(t, d.Value(), m2.GetValue())
|
||||
require.EqualValues(t, d.Precision(), m2.GetPrecision())
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
// Decimal returns random accounting.Decimal.
|
||||
func Decimal() *accounting.Decimal {
|
||||
var d accounting.Decimal
|
||||
d := accounting.NewDecimal()
|
||||
d.SetValue(rand.Int63())
|
||||
d.SetPrecision(rand.Uint32())
|
||||
|
||||
|
|
137
bearer/bearer.go
137
bearer/bearer.go
|
@ -5,13 +5,15 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Token represents bearer token for object service operations.
|
||||
|
@ -19,26 +21,31 @@ import (
|
|||
// Token is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl.BearerToken
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
// Instances must be created by NewToken() constructor.
|
||||
type Token struct {
|
||||
targetUserSet bool
|
||||
targetUser user.ID
|
||||
|
||||
eaclTableSet bool
|
||||
eaclTable eacl.Table
|
||||
eaclTable *eacl.Table
|
||||
|
||||
lifetimeSet bool
|
||||
iat, nbf, exp uint64
|
||||
|
||||
sigSet bool
|
||||
sig refs.Signature
|
||||
sig *refsgrpc.Signature
|
||||
|
||||
impersonate bool
|
||||
}
|
||||
|
||||
// reads Token from the acl.BearerToken message. If checkFieldPresence is set,
|
||||
func NewToken() Token {
|
||||
return Token{
|
||||
sig: &refsgrpc.Signature{},
|
||||
}
|
||||
}
|
||||
|
||||
// reads Token from the aclgrpc.BearerToken message. If checkFieldPresence is set,
|
||||
// returns an error on absence of any protocol-required field.
|
||||
func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
||||
func (b *Token) readFromV2(m *aclgrpc.BearerToken, checkFieldPresence bool) error {
|
||||
var err error
|
||||
|
||||
body := m.GetBody()
|
||||
|
@ -46,18 +53,18 @@ func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
|||
return errors.New("missing token body")
|
||||
}
|
||||
|
||||
b.impersonate = body.GetImpersonate()
|
||||
b.impersonate = body.GetAllowImpersonate()
|
||||
|
||||
eaclTable := body.GetEACL()
|
||||
if b.eaclTableSet = eaclTable != nil; b.eaclTableSet {
|
||||
b.eaclTable = *eacl.NewTableFromV2(eaclTable)
|
||||
b.eaclTable = nil
|
||||
if eaclTable := body.GetEaclTable(); eaclTable != nil {
|
||||
b.eaclTable = eacl.NewTableFromV2(eaclTable)
|
||||
} else if checkFieldPresence && !b.impersonate {
|
||||
return errors.New("missing eACL table")
|
||||
}
|
||||
|
||||
targetUser := body.GetOwnerID()
|
||||
targetUser := body.GetOwnerId()
|
||||
if b.targetUserSet = targetUser != nil; b.targetUserSet {
|
||||
err = b.targetUser.ReadFromV2(*targetUser)
|
||||
err = b.targetUser.ReadFromV2(targetUser)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid target user: %w", err)
|
||||
}
|
||||
|
@ -74,7 +81,10 @@ func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
|||
|
||||
sig := m.GetSignature()
|
||||
if b.sigSet = sig != nil; sig != nil {
|
||||
b.sig = *sig
|
||||
if b.sig == nil {
|
||||
b.sig = new(refsgrpc.Signature)
|
||||
}
|
||||
proto.Merge(b.sig, sig)
|
||||
} else if checkFieldPresence {
|
||||
return errors.New("missing body signature")
|
||||
}
|
||||
|
@ -82,33 +92,30 @@ func (b *Token) readFromV2(m acl.BearerToken, checkFieldPresence bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ReadFromV2 reads Token from the acl.BearerToken message.
|
||||
// ReadFromV2 reads Token from the aclgrpc.BearerToken message.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (b *Token) ReadFromV2(m acl.BearerToken) error {
|
||||
func (b *Token) ReadFromV2(m *aclgrpc.BearerToken) error {
|
||||
return b.readFromV2(m, true)
|
||||
}
|
||||
|
||||
func (b Token) fillBody() *acl.BearerTokenBody {
|
||||
if !b.eaclTableSet && !b.targetUserSet && !b.lifetimeSet && !b.impersonate {
|
||||
func (b *Token) fillBody() *aclgrpc.BearerToken_Body {
|
||||
if b.eaclTable == nil && !b.targetUserSet && !b.lifetimeSet && !b.impersonate {
|
||||
return nil
|
||||
}
|
||||
|
||||
var body acl.BearerTokenBody
|
||||
|
||||
if b.eaclTableSet {
|
||||
body.SetEACL(b.eaclTable.ToV2())
|
||||
}
|
||||
body := new(aclgrpc.BearerToken_Body)
|
||||
body.SetEaclTable(b.eaclTable.ToV2())
|
||||
|
||||
if b.targetUserSet {
|
||||
var targetUser refs.OwnerID
|
||||
var targetUser refsgrpc.OwnerID
|
||||
b.targetUser.WriteToV2(&targetUser)
|
||||
|
||||
body.SetOwnerID(&targetUser)
|
||||
body.SetOwnerId(&targetUser)
|
||||
}
|
||||
|
||||
if b.lifetimeSet {
|
||||
var lifetime acl.TokenLifetime
|
||||
var lifetime aclgrpc.BearerToken_Body_TokenLifetime
|
||||
lifetime.SetIat(b.iat)
|
||||
lifetime.SetNbf(b.nbf)
|
||||
lifetime.SetExp(b.exp)
|
||||
|
@ -118,24 +125,26 @@ func (b Token) fillBody() *acl.BearerTokenBody {
|
|||
|
||||
body.SetImpersonate(b.impersonate)
|
||||
|
||||
return &body
|
||||
return body
|
||||
}
|
||||
|
||||
func (b Token) signedData() []byte {
|
||||
func (b *Token) signedData() []byte {
|
||||
return b.fillBody().StableMarshal(nil)
|
||||
}
|
||||
|
||||
// WriteToV2 writes Token to the acl.BearerToken message.
|
||||
// WriteToV2 writes Token to the aclgrpc.BearerToken message.
|
||||
// The message must not be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (b Token) WriteToV2(m *acl.BearerToken) {
|
||||
func (b *Token) WriteToV2(m *aclgrpc.BearerToken) {
|
||||
m.Reset()
|
||||
m.SetBody(b.fillBody())
|
||||
|
||||
var sig *refs.Signature
|
||||
var sig *refsgrpc.Signature
|
||||
|
||||
if b.sigSet {
|
||||
sig = &b.sig
|
||||
sig = new(refsgrpc.Signature)
|
||||
proto.Merge(sig, b.sig)
|
||||
}
|
||||
|
||||
m.SetSignature(sig)
|
||||
|
@ -185,7 +194,7 @@ func (b *Token) SetIat(iat uint64) {
|
|||
// Zero Container is invalid in any epoch.
|
||||
//
|
||||
// See also SetExp, SetNbf, SetIat.
|
||||
func (b Token) InvalidAt(epoch uint64) bool {
|
||||
func (b *Token) InvalidAt(epoch uint64) bool {
|
||||
return !b.lifetimeSet || b.nbf > epoch || b.iat > epoch || b.exp < epoch
|
||||
}
|
||||
|
||||
|
@ -198,20 +207,15 @@ func (b Token) InvalidAt(epoch uint64) bool {
|
|||
// FrostFS API V2 protocol.
|
||||
//
|
||||
// See also EACLTable, AssertContainer.
|
||||
func (b *Token) SetEACLTable(table eacl.Table) {
|
||||
func (b *Token) SetEACLTable(table *eacl.Table) {
|
||||
b.eaclTable = table
|
||||
b.eaclTableSet = true
|
||||
}
|
||||
|
||||
// EACLTable returns extended ACL table set by SetEACLTable.
|
||||
//
|
||||
// Zero Token has zero eacl.Table.
|
||||
func (b Token) EACLTable() eacl.Table {
|
||||
if b.eaclTableSet {
|
||||
return b.eaclTable
|
||||
}
|
||||
|
||||
return eacl.Table{}
|
||||
func (b *Token) EACLTable() *eacl.Table {
|
||||
return b.eaclTable
|
||||
}
|
||||
|
||||
// SetImpersonate mark token as impersonate to consider token signer as request owner.
|
||||
|
@ -221,7 +225,7 @@ func (b *Token) SetImpersonate(v bool) {
|
|||
}
|
||||
|
||||
// Impersonate returns true if token is impersonated.
|
||||
func (b Token) Impersonate() bool {
|
||||
func (b *Token) Impersonate() bool {
|
||||
return b.impersonate
|
||||
}
|
||||
|
||||
|
@ -233,8 +237,8 @@ func (b Token) Impersonate() bool {
|
|||
// Zero Token is valid in any container.
|
||||
//
|
||||
// See also SetEACLTable.
|
||||
func (b Token) AssertContainer(cnr cid.ID) bool {
|
||||
if !b.eaclTableSet {
|
||||
func (b *Token) AssertContainer(cnr cid.ID) bool {
|
||||
if b.eaclTable == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -258,7 +262,7 @@ func (b *Token) ForUser(id user.ID) {
|
|||
// Zero Token is available to any user.
|
||||
//
|
||||
// See also ForUser.
|
||||
func (b Token) AssertUser(id user.ID) bool {
|
||||
func (b *Token) AssertUser(id user.ID) bool {
|
||||
return !b.targetUserSet || b.targetUser.Equals(id)
|
||||
}
|
||||
|
||||
|
@ -273,14 +277,17 @@ func (b Token) AssertUser(id user.ID) bool {
|
|||
//
|
||||
// See also VerifySignature, Issuer.
|
||||
func (b *Token) Sign(key ecdsa.PrivateKey) error {
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
err := sig.Calculate(frostfsecdsa.Signer(key), b.signedData())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sig.WriteToV2(&b.sig)
|
||||
if b.sig == nil {
|
||||
b.sig = new(refsgrpc.Signature)
|
||||
}
|
||||
sig.WriteToV2(b.sig)
|
||||
b.sigSet = true
|
||||
|
||||
return nil
|
||||
|
@ -291,12 +298,12 @@ func (b *Token) Sign(key ecdsa.PrivateKey) error {
|
|||
// Zero Token fails the check.
|
||||
//
|
||||
// See also Sign.
|
||||
func (b Token) VerifySignature() bool {
|
||||
func (b *Token) VerifySignature() bool {
|
||||
if !b.sigSet {
|
||||
return false
|
||||
}
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
// TODO: (#233) check owner<->key relation
|
||||
return sig.ReadFromV2(b.sig) == nil && sig.Verify(b.signedData())
|
||||
|
@ -306,8 +313,8 @@ func (b Token) VerifySignature() bool {
|
|||
// (Protocol Buffers V3 with direct field order).
|
||||
//
|
||||
// See also Unmarshal.
|
||||
func (b Token) Marshal() []byte {
|
||||
var m acl.BearerToken
|
||||
func (b *Token) Marshal() []byte {
|
||||
var m aclgrpc.BearerToken
|
||||
b.WriteToV2(&m)
|
||||
|
||||
return m.StableMarshal(nil)
|
||||
|
@ -319,25 +326,29 @@ func (b Token) Marshal() []byte {
|
|||
//
|
||||
// See also Marshal.
|
||||
func (b *Token) Unmarshal(data []byte) error {
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
|
||||
err := m.Unmarshal(data)
|
||||
err := proto.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.readFromV2(m, false)
|
||||
return b.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Token into a JSON format of the FrostFS API protocol
|
||||
// (Protocol Buffers V3 JSON).
|
||||
//
|
||||
// See also UnmarshalJSON.
|
||||
func (b Token) MarshalJSON() ([]byte, error) {
|
||||
var m acl.BearerToken
|
||||
func (b *Token) MarshalJSON() ([]byte, error) {
|
||||
var m aclgrpc.BearerToken
|
||||
b.WriteToV2(&m)
|
||||
|
||||
return m.MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
&m,
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes FrostFS API protocol JSON data into the Token
|
||||
|
@ -345,14 +356,14 @@ func (b Token) MarshalJSON() ([]byte, error) {
|
|||
//
|
||||
// See also MarshalJSON.
|
||||
func (b *Token) UnmarshalJSON(data []byte) error {
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
|
||||
err := m.UnmarshalJSON(data)
|
||||
err := protojson.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.readFromV2(m, false)
|
||||
return b.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// SigningKeyBytes returns issuer's public key in a binary format of
|
||||
|
@ -361,7 +372,7 @@ func (b *Token) UnmarshalJSON(data []byte) error {
|
|||
// Unsigned Token has empty key.
|
||||
//
|
||||
// See also ResolveIssuer.
|
||||
func (b Token) SigningKeyBytes() []byte {
|
||||
func (b *Token) SigningKeyBytes() []byte {
|
||||
if b.sigSet {
|
||||
return b.sig.GetKey()
|
||||
}
|
||||
|
@ -373,7 +384,7 @@ func (b Token) SigningKeyBytes() []byte {
|
|||
// Returns zero user.ID if Token is unsigned or key has incorrect format.
|
||||
//
|
||||
// See also SigningKeyBytes.
|
||||
func ResolveIssuer(b Token) (usr user.ID) {
|
||||
func ResolveIssuer(b *Token) (usr user.ID) {
|
||||
binKey := b.SigningKeyBytes()
|
||||
|
||||
if len(binKey) != 0 {
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
|
@ -16,12 +16,13 @@ import (
|
|||
eacltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// compares binary representations of two eacl.Table instances.
|
||||
func isEqualEACLTables(t1, t2 eacl.Table) bool {
|
||||
func isEqualEACLTables(t1, t2 *eacl.Table) bool {
|
||||
d1, err := t1.Marshal()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -37,7 +38,7 @@ func isEqualEACLTables(t1, t2 eacl.Table) bool {
|
|||
|
||||
func TestToken_SetEACLTable(t *testing.T) {
|
||||
var val bearer.Token
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
filled := bearertest.Token()
|
||||
|
||||
val.WriteToV2(&m)
|
||||
|
@ -58,14 +59,14 @@ func TestToken_SetEACLTable(t *testing.T) {
|
|||
|
||||
// set value
|
||||
|
||||
eaclTable := *eacltest.Table()
|
||||
eaclTable := eacltest.Table()
|
||||
|
||||
val.SetEACLTable(eaclTable)
|
||||
require.True(t, isEqualEACLTables(eaclTable, val.EACLTable()))
|
||||
|
||||
val.WriteToV2(&m)
|
||||
eaclTableV2 := eaclTable.ToV2()
|
||||
require.Equal(t, eaclTableV2, m.GetBody().GetEACL())
|
||||
require.Equal(t, eaclTableV2, m.GetBody().GetEaclTable())
|
||||
|
||||
val2 = filled
|
||||
|
||||
|
@ -83,7 +84,7 @@ func TestToken_SetEACLTable(t *testing.T) {
|
|||
|
||||
func TestToken_ForUser(t *testing.T) {
|
||||
var val bearer.Token
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
filled := bearertest.Token()
|
||||
|
||||
val.WriteToV2(&m)
|
||||
|
@ -115,14 +116,14 @@ func TestToken_ForUser(t *testing.T) {
|
|||
val.ForUser(usr)
|
||||
|
||||
val.WriteToV2(&m)
|
||||
require.Equal(t, usrV2, *m.GetBody().GetOwnerID())
|
||||
require.True(t, proto.Equal(&usrV2, m.GetBody().GetOwnerId()))
|
||||
|
||||
val2 = filled
|
||||
|
||||
require.NoError(t, val2.Unmarshal(val.Marshal()))
|
||||
|
||||
val2.WriteToV2(&m)
|
||||
require.Equal(t, usrV2, *m.GetBody().GetOwnerID())
|
||||
require.True(t, proto.Equal(&usrV2, m.GetBody().GetOwnerId()))
|
||||
|
||||
val2 = filled
|
||||
|
||||
|
@ -132,12 +133,12 @@ func TestToken_ForUser(t *testing.T) {
|
|||
require.NoError(t, val2.UnmarshalJSON(jd))
|
||||
|
||||
val2.WriteToV2(&m)
|
||||
require.Equal(t, usrV2, *m.GetBody().GetOwnerID())
|
||||
require.True(t, proto.Equal(&usrV2, m.GetBody().GetOwnerId()))
|
||||
}
|
||||
|
||||
func testLifetimeClaim(t *testing.T, setter func(*bearer.Token, uint64), getter func(*acl.BearerToken) uint64) {
|
||||
func testLifetimeClaim(t *testing.T, setter func(*bearer.Token, uint64), getter func(*aclgrpc.BearerToken) uint64) {
|
||||
var val bearer.Token
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
filled := bearertest.Token()
|
||||
|
||||
val.WriteToV2(&m)
|
||||
|
@ -188,19 +189,19 @@ func testLifetimeClaim(t *testing.T, setter func(*bearer.Token, uint64), getter
|
|||
|
||||
func TestToken_SetLifetime(t *testing.T) {
|
||||
t.Run("iat", func(t *testing.T) {
|
||||
testLifetimeClaim(t, (*bearer.Token).SetIat, func(token *acl.BearerToken) uint64 {
|
||||
testLifetimeClaim(t, (*bearer.Token).SetIat, func(token *aclgrpc.BearerToken) uint64 {
|
||||
return token.GetBody().GetLifetime().GetIat()
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("nbf", func(t *testing.T) {
|
||||
testLifetimeClaim(t, (*bearer.Token).SetNbf, func(token *acl.BearerToken) uint64 {
|
||||
testLifetimeClaim(t, (*bearer.Token).SetNbf, func(token *aclgrpc.BearerToken) uint64 {
|
||||
return token.GetBody().GetLifetime().GetNbf()
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("exp", func(t *testing.T) {
|
||||
testLifetimeClaim(t, (*bearer.Token).SetExp, func(token *acl.BearerToken) uint64 {
|
||||
testLifetimeClaim(t, (*bearer.Token).SetExp, func(token *aclgrpc.BearerToken) uint64 {
|
||||
return token.GetBody().GetLifetime().GetExp()
|
||||
})
|
||||
})
|
||||
|
@ -230,7 +231,7 @@ func TestToken_AssertContainer(t *testing.T) {
|
|||
|
||||
require.True(t, val.AssertContainer(cnr))
|
||||
|
||||
eaclTable := *eacltest.Table()
|
||||
eaclTable := eacltest.Table()
|
||||
|
||||
eaclTable.SetCID(cidtest.ID())
|
||||
val.SetEACLTable(eaclTable)
|
||||
|
@ -269,7 +270,7 @@ func TestToken_Sign(t *testing.T) {
|
|||
|
||||
require.True(t, val.VerifySignature())
|
||||
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
val.WriteToV2(&m)
|
||||
|
||||
require.NotZero(t, m.GetSignature().GetKey())
|
||||
|
@ -290,24 +291,24 @@ func TestToken_Sign(t *testing.T) {
|
|||
|
||||
func TestToken_ReadFromV2(t *testing.T) {
|
||||
var val bearer.Token
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
|
||||
require.Error(t, val.ReadFromV2(m))
|
||||
require.Error(t, val.ReadFromV2(&m))
|
||||
|
||||
var body acl.BearerTokenBody
|
||||
var body aclgrpc.BearerToken_Body
|
||||
m.SetBody(&body)
|
||||
|
||||
require.Error(t, val.ReadFromV2(m))
|
||||
require.Error(t, val.ReadFromV2(&m))
|
||||
|
||||
eaclTable := eacltest.Table().ToV2()
|
||||
body.SetEACL(eaclTable)
|
||||
body.SetEaclTable(eaclTable)
|
||||
|
||||
require.Error(t, val.ReadFromV2(m))
|
||||
require.Error(t, val.ReadFromV2(&m))
|
||||
|
||||
var lifetime acl.TokenLifetime
|
||||
var lifetime aclgrpc.BearerToken_Body_TokenLifetime
|
||||
body.SetLifetime(&lifetime)
|
||||
|
||||
require.Error(t, val.ReadFromV2(m))
|
||||
require.Error(t, val.ReadFromV2(&m))
|
||||
|
||||
const iat, nbf, exp = 1, 2, 3
|
||||
lifetime.SetIat(iat)
|
||||
|
@ -316,21 +317,21 @@ func TestToken_ReadFromV2(t *testing.T) {
|
|||
|
||||
body.SetLifetime(&lifetime)
|
||||
|
||||
require.Error(t, val.ReadFromV2(m))
|
||||
require.Error(t, val.ReadFromV2(&m))
|
||||
|
||||
var sig refs.Signature
|
||||
m.SetSignature(&sig)
|
||||
|
||||
require.NoError(t, val.ReadFromV2(m))
|
||||
require.NoError(t, val.ReadFromV2(&m))
|
||||
|
||||
body.SetEACL(nil)
|
||||
body.SetEaclTable(nil)
|
||||
body.SetImpersonate(true)
|
||||
require.NoError(t, val.ReadFromV2(m))
|
||||
require.NoError(t, val.ReadFromV2(&m))
|
||||
|
||||
var m2 acl.BearerToken
|
||||
var m2 aclgrpc.BearerToken
|
||||
|
||||
val.WriteToV2(&m2)
|
||||
require.Equal(t, m, m2)
|
||||
require.True(t, proto.Equal(&m, &m2))
|
||||
|
||||
usr, usr2 := *usertest.ID(), *usertest.ID()
|
||||
|
||||
|
@ -340,12 +341,12 @@ func TestToken_ReadFromV2(t *testing.T) {
|
|||
var usrV2 refs.OwnerID
|
||||
usr.WriteToV2(&usrV2)
|
||||
|
||||
body.SetOwnerID(&usrV2)
|
||||
body.SetOwnerId(&usrV2)
|
||||
|
||||
require.NoError(t, val.ReadFromV2(m))
|
||||
require.NoError(t, val.ReadFromV2(&m))
|
||||
|
||||
val.WriteToV2(&m2)
|
||||
require.Equal(t, m, m2)
|
||||
require.True(t, proto.Equal(&m, &m2))
|
||||
|
||||
require.True(t, val.AssertUser(usr))
|
||||
require.False(t, val.AssertUser(usr2))
|
||||
|
@ -361,7 +362,7 @@ func TestToken_ReadFromV2(t *testing.T) {
|
|||
|
||||
s.WriteToV2(&sig)
|
||||
|
||||
require.NoError(t, val.ReadFromV2(m))
|
||||
require.NoError(t, val.ReadFromV2(&m))
|
||||
require.True(t, val.VerifySignature())
|
||||
require.Equal(t, sig.GetKey(), val.SigningKeyBytes())
|
||||
}
|
||||
|
@ -372,9 +373,9 @@ func TestResolveIssuer(t *testing.T) {
|
|||
|
||||
var val bearer.Token
|
||||
|
||||
require.Zero(t, bearer.ResolveIssuer(val))
|
||||
require.Zero(t, bearer.ResolveIssuer(&val))
|
||||
|
||||
var m acl.BearerToken
|
||||
var m aclgrpc.BearerToken
|
||||
|
||||
var sig refs.Signature
|
||||
sig.SetKey([]byte("invalid key"))
|
||||
|
@ -383,12 +384,12 @@ func TestResolveIssuer(t *testing.T) {
|
|||
|
||||
require.NoError(t, val.Unmarshal(m.StableMarshal(nil)))
|
||||
|
||||
require.Zero(t, bearer.ResolveIssuer(val))
|
||||
require.Zero(t, bearer.ResolveIssuer(&val))
|
||||
|
||||
require.NoError(t, val.Sign(k.PrivateKey))
|
||||
|
||||
var usr user.ID
|
||||
user.IDFromKey(&usr, k.PrivateKey.PublicKey)
|
||||
|
||||
require.Equal(t, usr, bearer.ResolveIssuer(val))
|
||||
require.Equal(t, usr, bearer.ResolveIssuer(&val))
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func Token() (t bearer.Token) {
|
|||
t.SetNbf(2)
|
||||
t.SetIat(1)
|
||||
t.ForUser(*usertest.ID())
|
||||
t.SetEACLTable(*eacltest.Table())
|
||||
t.SetEACLTable(eacltest.Table())
|
||||
|
||||
return t
|
||||
}
|
||||
|
|
|
@ -6,21 +6,30 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/tzhash/tz"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// Checksum represents checksum of some digital data.
|
||||
//
|
||||
// Checksum is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Checksum
|
||||
// Checksum is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refsgrpc.Checksum
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
// Instances must be created by NewChecksum() constructor.
|
||||
//
|
||||
// Note that direct typecast is not safe and may result in loss of compatibility:
|
||||
//
|
||||
// _ = Checksum(refs.Checksum{}) // not recommended
|
||||
type Checksum refs.Checksum
|
||||
// _ = Checksum(refsgrpc.Checksum{}) // not recommended
|
||||
type Checksum struct {
|
||||
checksum *refsgrpc.Checksum
|
||||
}
|
||||
|
||||
func NewChecksum() Checksum {
|
||||
return Checksum{
|
||||
checksum: &refsgrpc.Checksum{},
|
||||
}
|
||||
}
|
||||
|
||||
// Type represents the enumeration
|
||||
// of checksum types.
|
||||
|
@ -37,11 +46,11 @@ const (
|
|||
TZ
|
||||
)
|
||||
|
||||
// ReadFromV2 reads Checksum from the refs.Checksum message. Checks if the
|
||||
// ReadFromV2 reads Checksum from the refsgrpc.Checksum message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (c *Checksum) ReadFromV2(m refs.Checksum) error {
|
||||
func (c *Checksum) ReadFromV2(m *refsgrpc.Checksum) error {
|
||||
if len(m.GetSum()) == 0 {
|
||||
return errors.New("missing value")
|
||||
}
|
||||
|
@ -49,20 +58,24 @@ func (c *Checksum) ReadFromV2(m refs.Checksum) error {
|
|||
switch m.GetType() {
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %v", m.GetType())
|
||||
case refs.SHA256, refs.TillichZemor:
|
||||
case refsgrpc.ChecksumType_SHA256, refsgrpc.ChecksumType_TZ:
|
||||
}
|
||||
|
||||
*c = Checksum(m)
|
||||
if c.checksum == nil {
|
||||
c.checksum = new(refsgrpc.Checksum)
|
||||
}
|
||||
proto.Merge(c.checksum, m)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteToV2 writes Checksum to the refs.Checksum message.
|
||||
// WriteToV2 writes Checksum to the refsgrpc.Checksum message.
|
||||
// The message must not be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (c Checksum) WriteToV2(m *refs.Checksum) {
|
||||
*m = (refs.Checksum)(c)
|
||||
func (c *Checksum) WriteToV2(m *refsgrpc.Checksum) {
|
||||
m.Reset()
|
||||
proto.Merge(m, c.checksum)
|
||||
}
|
||||
|
||||
// Type returns checksum type.
|
||||
|
@ -70,12 +83,11 @@ func (c Checksum) WriteToV2(m *refs.Checksum) {
|
|||
// Zero Checksum has Unknown checksum type.
|
||||
//
|
||||
// See also SetTillichZemor and SetSHA256.
|
||||
func (c Checksum) Type() Type {
|
||||
v2 := (refs.Checksum)(c)
|
||||
switch v2.GetType() {
|
||||
case refs.SHA256:
|
||||
func (c *Checksum) Type() Type {
|
||||
switch c.checksum.GetType() {
|
||||
case refsgrpc.ChecksumType_SHA256:
|
||||
return SHA256
|
||||
case refs.TillichZemor:
|
||||
case refsgrpc.ChecksumType_TZ:
|
||||
return TZ
|
||||
default:
|
||||
return Unknown
|
||||
|
@ -88,19 +100,16 @@ func (c Checksum) Type() Type {
|
|||
// Zero Checksum has nil sum.
|
||||
//
|
||||
// See also SetTillichZemor and SetSHA256.
|
||||
func (c Checksum) Value() []byte {
|
||||
v2 := (refs.Checksum)(c)
|
||||
return v2.GetSum()
|
||||
func (c *Checksum) Value() []byte {
|
||||
return c.checksum.GetSum()
|
||||
}
|
||||
|
||||
// SetSHA256 sets checksum to SHA256 hash.
|
||||
//
|
||||
// See also Calculate.
|
||||
func (c *Checksum) SetSHA256(v [sha256.Size]byte) {
|
||||
v2 := (*refs.Checksum)(c)
|
||||
|
||||
v2.SetType(refs.SHA256)
|
||||
v2.SetSum(v[:])
|
||||
c.checksum.SetChecksumType(refsgrpc.ChecksumType_SHA256)
|
||||
c.checksum.SetSum(v[:])
|
||||
}
|
||||
|
||||
// Calculate calculates checksum and sets it
|
||||
|
@ -127,19 +136,16 @@ func Calculate(c *Checksum, t Type, v []byte) {
|
|||
//
|
||||
// See also Calculate.
|
||||
func (c *Checksum) SetTillichZemor(v [tz.Size]byte) {
|
||||
v2 := (*refs.Checksum)(c)
|
||||
|
||||
v2.SetType(refs.TillichZemor)
|
||||
v2.SetSum(v[:])
|
||||
c.checksum.SetChecksumType(refsgrpc.ChecksumType_TZ)
|
||||
c.checksum.SetSum(v[:])
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
//
|
||||
// String is designed to be human-readable, and its format MAY differ between
|
||||
// SDK versions.
|
||||
func (c Checksum) String() string {
|
||||
v2 := (refs.Checksum)(c)
|
||||
return fmt.Sprintf("%s:%s", c.Type(), hex.EncodeToString(v2.GetSum()))
|
||||
func (c *Checksum) String() string {
|
||||
return fmt.Sprintf("%s:%s", c.checksum.GetType(), hex.EncodeToString(c.checksum.GetSum()))
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
|
@ -147,15 +153,15 @@ func (c Checksum) String() string {
|
|||
// String is designed to be human-readable, and its format MAY differ between
|
||||
// SDK versions.
|
||||
func (m Type) String() string {
|
||||
var m2 refs.ChecksumType
|
||||
var m2 refsgrpc.ChecksumType
|
||||
|
||||
switch m {
|
||||
default:
|
||||
m2 = refs.UnknownChecksum
|
||||
m2 = refsgrpc.ChecksumType_CHECKSUM_TYPE_UNSPECIFIED
|
||||
case TZ:
|
||||
m2 = refs.TillichZemor
|
||||
m2 = refsgrpc.ChecksumType_TZ
|
||||
case SHA256:
|
||||
m2 = refs.SHA256
|
||||
m2 = refsgrpc.ChecksumType_SHA256
|
||||
}
|
||||
|
||||
return m2.String()
|
||||
|
|
|
@ -5,13 +5,13 @@ import (
|
|||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/tzhash/tz"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestChecksum(t *testing.T) {
|
||||
var c Checksum
|
||||
c := NewChecksum()
|
||||
|
||||
cSHA256 := [sha256.Size]byte{}
|
||||
_, _ = rand.Read(cSHA256[:])
|
||||
|
@ -21,10 +21,10 @@ func TestChecksum(t *testing.T) {
|
|||
require.Equal(t, SHA256, c.Type())
|
||||
require.Equal(t, cSHA256[:], c.Value())
|
||||
|
||||
var cV2 refs.Checksum
|
||||
var cV2 refsgrpc.Checksum
|
||||
c.WriteToV2(&cV2)
|
||||
|
||||
require.Equal(t, refs.SHA256, cV2.GetType())
|
||||
require.Equal(t, refsgrpc.ChecksumType_SHA256, cV2.GetType())
|
||||
require.Equal(t, cSHA256[:], cV2.GetSum())
|
||||
|
||||
cTZ := [tz.Size]byte{}
|
||||
|
@ -37,7 +37,7 @@ func TestChecksum(t *testing.T) {
|
|||
|
||||
c.WriteToV2(&cV2)
|
||||
|
||||
require.Equal(t, refs.TillichZemor, cV2.GetType())
|
||||
require.Equal(t, refsgrpc.ChecksumType_TZ, cV2.GetType())
|
||||
require.Equal(t, cTZ[:], cV2.GetSum())
|
||||
}
|
||||
|
||||
|
@ -50,16 +50,16 @@ func TestNewChecksum(t *testing.T) {
|
|||
require.Nil(t, chs.Value())
|
||||
|
||||
// convert to v2 message
|
||||
var chsV2 refs.Checksum
|
||||
var chsV2 refsgrpc.Checksum
|
||||
chs.WriteToV2(&chsV2)
|
||||
|
||||
require.Equal(t, refs.UnknownChecksum, chsV2.GetType())
|
||||
require.Equal(t, refsgrpc.ChecksumType_CHECKSUM_TYPE_UNSPECIFIED, chsV2.GetType())
|
||||
require.Nil(t, chsV2.GetSum())
|
||||
})
|
||||
}
|
||||
|
||||
func TestCalculation(t *testing.T) {
|
||||
var c Checksum
|
||||
c := NewChecksum()
|
||||
payload := []byte{0, 1, 2, 3, 4, 5}
|
||||
|
||||
t.Run("SHA256", func(t *testing.T) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
)
|
||||
|
||||
func ExampleCalculate() {
|
||||
|
@ -20,8 +20,8 @@ func ExampleCalculate() {
|
|||
func ExampleChecksum_WriteToV2() {
|
||||
var (
|
||||
csRaw [sha256.Size]byte
|
||||
csV2 refs.Checksum
|
||||
cs Checksum
|
||||
csV2 refsgrpc.Checksum
|
||||
cs = NewChecksum()
|
||||
)
|
||||
|
||||
rand.Read(csRaw[:])
|
||||
|
|
|
@ -13,7 +13,7 @@ func Checksum() checksum.Checksum {
|
|||
|
||||
rand.Read(cs[:])
|
||||
|
||||
var x checksum.Checksum
|
||||
x := checksum.NewChecksum()
|
||||
|
||||
x.SetSHA256(cs)
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ package client
|
|||
import (
|
||||
"context"
|
||||
|
||||
v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
accgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
|
||||
|
@ -33,6 +33,12 @@ type ResBalanceGet struct {
|
|||
amount accounting.Decimal
|
||||
}
|
||||
|
||||
func NewResBalanceGet() ResBalanceGet {
|
||||
return ResBalanceGet{
|
||||
amount: accounting.NewDecimal(),
|
||||
}
|
||||
}
|
||||
|
||||
// Amount returns current amount of funds on the FrostFS account as decimal number.
|
||||
func (x ResBalanceGet) Amount() accounting.Decimal {
|
||||
return x.amount
|
||||
|
@ -57,14 +63,14 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
|
|||
}
|
||||
|
||||
// form request body
|
||||
var accountV2 refs.OwnerID
|
||||
var accountV2 refsgrpc.OwnerID
|
||||
prm.account.WriteToV2(&accountV2)
|
||||
|
||||
var body v2accounting.BalanceRequestBody
|
||||
body.SetOwnerID(&accountV2)
|
||||
var body accgrpc.BalanceRequest_Body
|
||||
body.SetOwnerId(&accountV2)
|
||||
|
||||
// form request
|
||||
var req v2accounting.BalanceRequest
|
||||
var req accgrpc.BalanceRequest
|
||||
|
||||
req.SetBody(&body)
|
||||
|
||||
|
@ -72,7 +78,7 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
|
|||
|
||||
var (
|
||||
cc contextCall
|
||||
res ResBalanceGet
|
||||
res = NewResBalanceGet()
|
||||
)
|
||||
|
||||
c.initCallContext(&cc)
|
||||
|
@ -83,7 +89,7 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
|
|||
return rpcapi.Balance(&c.c, &req, client.WithContext(ctx))
|
||||
}
|
||||
cc.result = func(r responseV2) {
|
||||
resp := r.(*v2accounting.BalanceResponse)
|
||||
resp := r.(*accgrpc.BalanceResponse)
|
||||
|
||||
const fieldBalance = "balance"
|
||||
|
||||
|
@ -93,10 +99,7 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
|
|||
return
|
||||
}
|
||||
|
||||
cc.err = res.amount.ReadFromV2(*bal)
|
||||
if cc.err != nil {
|
||||
cc.err = newErrInvalidResponseField(fieldBalance, cc.err)
|
||||
}
|
||||
res.amount.ReadFromV2(bal)
|
||||
}
|
||||
|
||||
// process call
|
||||
|
|
|
@ -4,14 +4,14 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
)
|
||||
|
||||
// interface of FrostFS API server. Exists for test purposes only.
|
||||
type frostFSAPIServer interface {
|
||||
netMapSnapshot(context.Context, v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error)
|
||||
netMapSnapshot(context.Context, *netmapgrpc.NetmapSnapshotRequest) (*netmapgrpc.NetmapSnapshotResponse, error)
|
||||
}
|
||||
|
||||
// wrapper over real client connection which communicates over FrostFS API protocol.
|
||||
|
@ -25,8 +25,8 @@ func rpcErr(e error) error {
|
|||
|
||||
// executes NetmapService.NetmapSnapshot RPC declared in FrostFS API protocol
|
||||
// using underlying client.Client.
|
||||
func (x *coreServer) netMapSnapshot(ctx context.Context, req v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error) {
|
||||
resp, err := rpcapi.NetMapSnapshot((*client.Client)(x), &req, client.WithContext(ctx))
|
||||
func (x *coreServer) netMapSnapshot(ctx context.Context, req *netmapgrpc.NetmapSnapshotRequest) (*netmapgrpc.NetmapSnapshotResponse, error) {
|
||||
resp, err := rpcapi.NetMapSnapshot((*client.Client)(x), req, client.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, rpcErr(err)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||
v2accounting "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"google.golang.org/grpc"
|
||||
|
|
|
@ -17,15 +17,17 @@ File contains common functionality used for client package testing.
|
|||
|
||||
var key, _ = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
|
||||
var statusErr apistatus.ServerInternal
|
||||
var statusErr = apistatus.NewServerInternal()
|
||||
|
||||
func init() {
|
||||
statusErr.SetMessage("test status error")
|
||||
}
|
||||
|
||||
func assertStatusErr(tb testing.TB, res interface{ Status() apistatus.Status }) {
|
||||
require.IsType(tb, &statusErr, res.Status())
|
||||
require.Equal(tb, statusErr.Message(), res.Status().(*apistatus.ServerInternal).Message())
|
||||
require.IsType(tb, statusErr, res.Status())
|
||||
m := statusErr.Message()
|
||||
r := res.Status()
|
||||
require.Equal(tb, m, r.(apistatus.ServerInternal).Message())
|
||||
}
|
||||
|
||||
func newClient(server frostFSAPIServer) *Client {
|
||||
|
|
|
@ -5,11 +5,13 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
)
|
||||
|
||||
|
@ -53,7 +55,7 @@ func (x *prmCommonMeta) WithXHeaders(hs ...string) {
|
|||
x.xHeaders = hs
|
||||
}
|
||||
|
||||
func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
|
||||
func writeXHeadersToMeta(xHeaders []string, h *sessiongrpc.RequestMetaHeader) {
|
||||
if len(xHeaders) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -62,7 +64,7 @@ func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
|
|||
panic("slice of X-Headers with odd length")
|
||||
}
|
||||
|
||||
hs := make([]v2session.XHeader, len(xHeaders)/2)
|
||||
hs := slices.MakePreallocPointerSlice[sessiongrpc.XHeader](len(xHeaders) / 2)
|
||||
for i := 0; i < len(xHeaders); i += 2 {
|
||||
hs[i].SetKey(xHeaders[i])
|
||||
hs[i].SetValue(xHeaders[i+1])
|
||||
|
@ -139,25 +141,25 @@ type contextCall struct {
|
|||
}
|
||||
|
||||
type request interface {
|
||||
GetMetaHeader() *v2session.RequestMetaHeader
|
||||
SetMetaHeader(*v2session.RequestMetaHeader)
|
||||
SetVerificationHeader(*v2session.RequestVerificationHeader)
|
||||
GetMetaHeader() *sessiongrpc.RequestMetaHeader
|
||||
SetMetaHeader(*sessiongrpc.RequestMetaHeader)
|
||||
SetVerifyHeader(*sessiongrpc.RequestVerificationHeader)
|
||||
}
|
||||
|
||||
// sets needed fields of the request meta header.
|
||||
func (x contextCall) prepareRequest() {
|
||||
meta := x.req.GetMetaHeader()
|
||||
if meta == nil {
|
||||
meta = new(v2session.RequestMetaHeader)
|
||||
meta = new(sessiongrpc.RequestMetaHeader)
|
||||
x.req.SetMetaHeader(meta)
|
||||
}
|
||||
|
||||
if meta.GetTTL() == 0 {
|
||||
meta.SetTTL(2)
|
||||
if meta.GetTtl() == 0 {
|
||||
meta.SetTtl(2)
|
||||
}
|
||||
|
||||
if meta.GetVersion() == nil {
|
||||
var verV2 refs.Version
|
||||
var verV2 refsgrpc.Version
|
||||
version.Current().WriteToV2(&verV2)
|
||||
meta.SetVersion(&verV2)
|
||||
}
|
||||
|
@ -167,8 +169,8 @@ func (x contextCall) prepareRequest() {
|
|||
writeXHeadersToMeta(x.meta.xHeaders, meta)
|
||||
}
|
||||
|
||||
func (c *Client) prepareRequest(req request, meta *v2session.RequestMetaHeader) {
|
||||
ttl := meta.GetTTL()
|
||||
func (c *Client) prepareRequest(req request, meta *sessiongrpc.RequestMetaHeader) {
|
||||
ttl := meta.GetTtl()
|
||||
if ttl == 0 {
|
||||
ttl = 2
|
||||
}
|
||||
|
@ -179,7 +181,7 @@ func (c *Client) prepareRequest(req request, meta *v2session.RequestMetaHeader)
|
|||
version.Current().WriteToV2(verV2)
|
||||
}
|
||||
|
||||
meta.SetTTL(ttl)
|
||||
meta.SetTtl(ttl)
|
||||
meta.SetVersion(verV2)
|
||||
meta.SetNetworkMagic(c.prm.netMagic)
|
||||
|
||||
|
@ -191,7 +193,7 @@ func (c *Client) prepareRequest(req request, meta *v2session.RequestMetaHeader)
|
|||
func (x *contextCall) writeRequest() bool {
|
||||
x.prepareRequest()
|
||||
|
||||
x.req.SetVerificationHeader(nil)
|
||||
x.req.SetVerifyHeader(nil)
|
||||
|
||||
// sign the request
|
||||
x.err = signature.SignServiceMessage(&x.key, x.req)
|
||||
|
@ -220,7 +222,7 @@ func (x *contextCall) processResponse() bool {
|
|||
// call response callback if set
|
||||
if x.callbackResp != nil {
|
||||
x.err = x.callbackResp(ResponseMetaInfo{
|
||||
key: x.resp.GetVerificationHeader().GetBodySignature().GetKey(),
|
||||
key: x.resp.GetVerifyHeader().GetBodySignature().GetKey(),
|
||||
epoch: x.resp.GetMetaHeader().GetEpoch(),
|
||||
})
|
||||
if x.err != nil {
|
||||
|
@ -259,7 +261,7 @@ func (x *contextCall) processResponse() bool {
|
|||
func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) {
|
||||
if c.prm.cbRespInfo != nil {
|
||||
rmi := ResponseMetaInfo{
|
||||
key: resp.GetVerificationHeader().GetBodySignature().GetKey(),
|
||||
key: resp.GetVerifyHeader().GetBodySignature().GetKey(),
|
||||
epoch: resp.GetMetaHeader().GetEpoch(),
|
||||
}
|
||||
if err := c.prm.cbRespInfo(rmi); err != nil {
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
// Returns any network/parsing config errors.
|
||||
//
|
||||
// See also NetworkInfo, container.ApplyNetworkConfig.
|
||||
func SyncContainerWithNetwork(ctx context.Context, cnr *container.Container, c *Client) error {
|
||||
func SyncContainerWithNetwork(ctx context.Context, cnr container.Container, c *Client) error {
|
||||
res, err := c.NetworkInfo(ctx, PrmNetworkInfo{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("network info call: %w", err)
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
|
@ -34,43 +34,43 @@ func (x *PrmContainerDelete) SetContainer(id cid.ID) {
|
|||
x.idSet = true
|
||||
}
|
||||
|
||||
func (x *PrmContainerDelete) buildRequest(c *Client) (*v2container.DeleteRequest, error) {
|
||||
func (x *PrmContainerDelete) buildRequest(c *Client) (*containergrpc.DeleteRequest, error) {
|
||||
if !x.idSet {
|
||||
return nil, errorMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
x.id.WriteToV2(&cidV2)
|
||||
|
||||
// Container contract expects signature of container ID value,
|
||||
// don't get confused with stable marshaled protobuf container.ID structure.
|
||||
data := cidV2.GetValue()
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.key), data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calculate signature: %w", err)
|
||||
}
|
||||
|
||||
var sigv2 refs.Signature
|
||||
var sigv2 refsgrpc.Signature
|
||||
sig.WriteToV2(&sigv2)
|
||||
|
||||
reqBody := new(v2container.DeleteRequestBody)
|
||||
reqBody.SetContainerID(&cidV2)
|
||||
reqBody.SetSignature(&sigv2)
|
||||
reqBody := new(containergrpc.DeleteRequest_Body)
|
||||
reqBody.SetContainerId(&cidV2)
|
||||
reqBody.SetSignature(sigv2.ToRFC6979())
|
||||
|
||||
var meta v2session.RequestMetaHeader
|
||||
var meta sessiongrpc.RequestMetaHeader
|
||||
writeXHeadersToMeta(x.prmCommonMeta.xHeaders, &meta)
|
||||
|
||||
if x.tokSet {
|
||||
var tokv2 v2session.Token
|
||||
var tokv2 sessiongrpc.SessionToken
|
||||
x.tok.WriteToV2(&tokv2)
|
||||
|
||||
meta.SetSessionToken(&tokv2)
|
||||
}
|
||||
|
||||
var req v2container.DeleteRequest
|
||||
var req containergrpc.DeleteRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, &meta)
|
||||
return &req, nil
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
|
@ -30,20 +30,20 @@ func (x *PrmContainerEACL) SetContainer(id cid.ID) {
|
|||
x.idSet = true
|
||||
}
|
||||
|
||||
func (x *PrmContainerEACL) buildRequest(c *Client) (*v2container.GetExtendedACLRequest, error) {
|
||||
func (x *PrmContainerEACL) buildRequest(c *Client) (*containergrpc.GetExtendedACLRequest, error) {
|
||||
if !x.idSet {
|
||||
return nil, errorMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
x.id.WriteToV2(&cidV2)
|
||||
|
||||
reqBody := new(v2container.GetExtendedACLRequestBody)
|
||||
reqBody.SetContainerID(&cidV2)
|
||||
reqBody := new(containergrpc.GetExtendedACLRequest_Body)
|
||||
reqBody.SetContainerId(&cidV2)
|
||||
|
||||
var req v2container.GetExtendedACLRequest
|
||||
var req containergrpc.GetExtendedACLRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, new(v2session.RequestMetaHeader))
|
||||
c.prepareRequest(&req, new(sessiongrpc.RequestMetaHeader))
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResC
|
|||
return &res, err
|
||||
}
|
||||
|
||||
eACL := resp.GetBody().GetEACL()
|
||||
eACL := resp.GetBody().GetEacl()
|
||||
if eACL == nil {
|
||||
return &res, newErrMissingResponseField("eACL")
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
|
@ -31,20 +31,20 @@ func (x *PrmContainerGet) SetContainer(id cid.ID) {
|
|||
x.idSet = true
|
||||
}
|
||||
|
||||
func (x *PrmContainerGet) buildRequest(c *Client) (*v2container.GetRequest, error) {
|
||||
func (x *PrmContainerGet) buildRequest(c *Client) (*containergrpc.GetRequest, error) {
|
||||
if !x.idSet {
|
||||
return nil, errorMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
x.id.WriteToV2(&cidV2)
|
||||
|
||||
reqBody := new(v2container.GetRequestBody)
|
||||
reqBody.SetContainerID(&cidV2)
|
||||
reqBody := new(containergrpc.GetRequest_Body)
|
||||
reqBody.SetContainerId(&cidV2)
|
||||
|
||||
var req v2container.GetRequest
|
||||
var req containergrpc.GetRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, new(v2session.RequestMetaHeader))
|
||||
c.prepareRequest(&req, new(sessiongrpc.RequestMetaHeader))
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
|
@ -52,13 +52,19 @@ func (x *PrmContainerGet) buildRequest(c *Client) (*v2container.GetRequest, erro
|
|||
type ResContainerGet struct {
|
||||
statusRes
|
||||
|
||||
cnr container.Container
|
||||
cnr *container.Container
|
||||
}
|
||||
|
||||
func NewResContainerGet() *ResContainerGet {
|
||||
return &ResContainerGet{
|
||||
cnr: new(container.Container),
|
||||
}
|
||||
}
|
||||
|
||||
// Container returns structured information about the requested container.
|
||||
//
|
||||
// Client doesn't retain value so modification is safe.
|
||||
func (x ResContainerGet) Container() container.Container {
|
||||
func (x *ResContainerGet) Container() *container.Container {
|
||||
return x.cnr
|
||||
}
|
||||
|
||||
|
@ -91,18 +97,18 @@ func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResCon
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var res ResContainerGet
|
||||
res := NewResContainerGet()
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil || !apistatus.IsSuccessful(res.st) {
|
||||
return &res, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cnrV2 := resp.GetBody().GetContainer()
|
||||
if cnrV2 == nil {
|
||||
return &res, errors.New("missing container in response")
|
||||
return nil, errors.New("missing container in response")
|
||||
}
|
||||
if err := res.cnr.ReadFromV2(*cnrV2); err != nil {
|
||||
return &res, fmt.Errorf("invalid container in response: %w", err)
|
||||
if err := res.cnr.ReadFromV2(cnrV2); err != nil {
|
||||
return nil, fmt.Errorf("invalid container in response: %w", err)
|
||||
}
|
||||
return &res, nil
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
|
@ -30,20 +30,20 @@ func (x *PrmContainerList) SetAccount(id user.ID) {
|
|||
x.ownerSet = true
|
||||
}
|
||||
|
||||
func (x *PrmContainerList) buildRequest(c *Client) (*v2container.ListRequest, error) {
|
||||
func (x *PrmContainerList) buildRequest(c *Client) (*containergrpc.ListRequest, error) {
|
||||
if !x.ownerSet {
|
||||
return nil, errorAccountNotSet
|
||||
}
|
||||
|
||||
var ownerV2 refs.OwnerID
|
||||
var ownerV2 refsgrpc.OwnerID
|
||||
x.ownerID.WriteToV2(&ownerV2)
|
||||
|
||||
reqBody := new(v2container.ListRequestBody)
|
||||
reqBody.SetOwnerID(&ownerV2)
|
||||
reqBody := new(containergrpc.ListRequest_Body)
|
||||
reqBody.SetOwnerId(&ownerV2)
|
||||
|
||||
var req v2container.ListRequest
|
||||
var req containergrpc.ListRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, new(v2session.RequestMetaHeader))
|
||||
c.prepareRequest(&req, new(sessiongrpc.RequestMetaHeader))
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,8 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC
|
|||
return &res, err
|
||||
}
|
||||
|
||||
res.ids = make([]cid.ID, len(resp.GetBody().GetContainerIDs()))
|
||||
for i, cidV2 := range resp.GetBody().GetContainerIDs() {
|
||||
res.ids = make([]cid.ID, len(resp.GetBody().GetContainerIds()))
|
||||
for i, cidV2 := range resp.GetBody().GetContainerIds() {
|
||||
if err := res.ids[i].ReadFromV2(cidV2); err != nil {
|
||||
return &res, fmt.Errorf("invalid ID in the response: %w", err)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
|
@ -48,40 +48,40 @@ func (x *PrmContainerPut) WithinSession(s session.Container) {
|
|||
x.sessionSet = true
|
||||
}
|
||||
|
||||
func (x *PrmContainerPut) buildRequest(c *Client) (*v2container.PutRequest, error) {
|
||||
func (x *PrmContainerPut) buildRequest(c *Client) (*containergrpc.PutRequest, error) {
|
||||
if !x.cnrSet {
|
||||
return nil, errorMissingContainer
|
||||
}
|
||||
|
||||
// TODO: check private key is set before forming the request
|
||||
var cnr v2container.Container
|
||||
var cnr containergrpc.Container
|
||||
x.cnr.WriteToV2(&cnr)
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
err := container.CalculateSignature(&sig, x.cnr, c.prm.key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calculate container signature: %w", err)
|
||||
}
|
||||
|
||||
var sigv2 refs.Signature
|
||||
var sigv2 refsgrpc.Signature
|
||||
sig.WriteToV2(&sigv2)
|
||||
|
||||
reqBody := new(v2container.PutRequestBody)
|
||||
reqBody := new(containergrpc.PutRequest_Body)
|
||||
reqBody.SetContainer(&cnr)
|
||||
reqBody.SetSignature(&sigv2)
|
||||
reqBody.SetSignature(sigv2.ToRFC6979())
|
||||
|
||||
var meta v2session.RequestMetaHeader
|
||||
var meta sessiongrpc.RequestMetaHeader
|
||||
writeXHeadersToMeta(x.prmCommonMeta.xHeaders, &meta)
|
||||
|
||||
if x.sessionSet {
|
||||
var tokv2 v2session.Token
|
||||
var tokv2 sessiongrpc.SessionToken
|
||||
x.session.WriteToV2(&tokv2)
|
||||
|
||||
meta.SetSessionToken(&tokv2)
|
||||
}
|
||||
|
||||
var req v2container.PutRequest
|
||||
var req containergrpc.PutRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, &meta)
|
||||
return &req, nil
|
||||
|
@ -144,11 +144,11 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
|
|||
|
||||
const fieldCnrID = "container ID"
|
||||
|
||||
cidV2 := resp.GetBody().GetContainerID()
|
||||
cidV2 := resp.GetBody().GetContainerId()
|
||||
if cidV2 == nil {
|
||||
return &res, newErrMissingResponseField(fieldCnrID)
|
||||
}
|
||||
if err := res.id.ReadFromV2(*cidV2); err != nil {
|
||||
if err := res.id.ReadFromV2(cidV2); err != nil {
|
||||
return &res, newErrInvalidResponseField(fieldCnrID, err)
|
||||
}
|
||||
return &res, nil
|
||||
|
|
|
@ -4,15 +4,15 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
eaclsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ type PrmContainerSetEACL struct {
|
|||
prmCommonMeta
|
||||
|
||||
tableSet bool
|
||||
table eacl.Table
|
||||
table *eaclsdk.Table
|
||||
|
||||
sessionSet bool
|
||||
session session.Container
|
||||
|
@ -29,7 +29,7 @@ type PrmContainerSetEACL struct {
|
|||
|
||||
// SetTable sets eACL table structure to be set for the container.
|
||||
// Required parameter.
|
||||
func (x *PrmContainerSetEACL) SetTable(table eacl.Table) {
|
||||
func (x *PrmContainerSetEACL) SetTable(table *eaclsdk.Table) {
|
||||
x.table = table
|
||||
x.tableSet = true
|
||||
}
|
||||
|
@ -50,14 +50,14 @@ func (x *PrmContainerSetEACL) WithinSession(s session.Container) {
|
|||
x.sessionSet = true
|
||||
}
|
||||
|
||||
func (x *PrmContainerSetEACL) buildRequest(c *Client) (*v2container.SetExtendedACLRequest, error) {
|
||||
func (x *PrmContainerSetEACL) buildRequest(c *Client) (*containergrpc.SetExtendedACLRequest, error) {
|
||||
if !x.tableSet {
|
||||
return nil, errorEACLTableNotSet
|
||||
}
|
||||
|
||||
eaclV2 := x.table.ToV2()
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
err := sig.Calculate(frostfsecdsa.SignerRFC6979(c.prm.key), eaclV2.StableMarshal(nil))
|
||||
if err != nil {
|
||||
|
@ -67,21 +67,21 @@ func (x *PrmContainerSetEACL) buildRequest(c *Client) (*v2container.SetExtendedA
|
|||
var sigv2 refs.Signature
|
||||
sig.WriteToV2(&sigv2)
|
||||
|
||||
reqBody := new(v2container.SetExtendedACLRequestBody)
|
||||
reqBody.SetEACL(eaclV2)
|
||||
reqBody.SetSignature(&sigv2)
|
||||
reqBody := new(containergrpc.SetExtendedACLRequest_Body)
|
||||
reqBody.SetEacl(eaclV2)
|
||||
reqBody.SetSignature(sigv2.ToRFC6979())
|
||||
|
||||
var meta v2session.RequestMetaHeader
|
||||
var meta sessiongrpc.RequestMetaHeader
|
||||
writeXHeadersToMeta(x.prmCommonMeta.xHeaders, &meta)
|
||||
|
||||
if x.sessionSet {
|
||||
var tokv2 v2session.Token
|
||||
var tokv2 sessiongrpc.SessionToken
|
||||
x.session.WriteToV2(&tokv2)
|
||||
|
||||
meta.SetSessionToken(&tokv2)
|
||||
}
|
||||
|
||||
var req v2container.SetExtendedACLRequest
|
||||
var req containergrpc.SetExtendedACLRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, &meta)
|
||||
return &req, nil
|
||||
|
|
|
@ -4,12 +4,13 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
)
|
||||
|
||||
// PrmAnnounceSpace groups parameters of ContainerAnnounceUsedSpace operation.
|
||||
|
@ -27,22 +28,22 @@ func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) {
|
|||
x.announcements = vs
|
||||
}
|
||||
|
||||
func (x *PrmAnnounceSpace) buildRequest(c *Client) (*v2container.AnnounceUsedSpaceRequest, error) {
|
||||
func (x *PrmAnnounceSpace) buildRequest(c *Client) (*containergrpc.AnnounceUsedSpaceRequest, error) {
|
||||
if len(x.announcements) == 0 {
|
||||
return nil, errorMissingAnnouncements
|
||||
}
|
||||
|
||||
v2announce := make([]v2container.UsedSpaceAnnouncement, len(x.announcements))
|
||||
v2announce := slices.MakePreallocPointerSlice[containergrpc.AnnounceUsedSpaceRequest_Body_Announcement](len(x.announcements))
|
||||
for i := range x.announcements {
|
||||
x.announcements[i].WriteToV2(&v2announce[i])
|
||||
x.announcements[i].WriteToV2(v2announce[i])
|
||||
}
|
||||
|
||||
reqBody := new(v2container.AnnounceUsedSpaceRequestBody)
|
||||
reqBody := new(containergrpc.AnnounceUsedSpaceRequest_Body)
|
||||
reqBody.SetAnnouncements(v2announce)
|
||||
|
||||
var req v2container.AnnounceUsedSpaceRequest
|
||||
var req containergrpc.AnnounceUsedSpaceRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, new(v2session.RequestMetaHeader))
|
||||
c.prepareRequest(&req, new(sessiongrpc.RequestMetaHeader))
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
|
@ -19,12 +19,12 @@ type PrmEndpointInfo struct {
|
|||
prmCommonMeta
|
||||
}
|
||||
|
||||
func (x *PrmEndpointInfo) buildRequest(c *Client) (*v2netmap.LocalNodeInfoRequest, error) {
|
||||
meta := new(v2session.RequestMetaHeader)
|
||||
func (x *PrmEndpointInfo) buildRequest(c *Client) (*netmapgrpc.LocalNodeInfoRequest, error) {
|
||||
meta := new(sessiongrpc.RequestMetaHeader)
|
||||
writeXHeadersToMeta(x.xHeaders, meta)
|
||||
|
||||
req := new(v2netmap.LocalNodeInfoRequest)
|
||||
req.SetBody(new(v2netmap.LocalNodeInfoRequestBody))
|
||||
req := new(netmapgrpc.LocalNodeInfoRequest)
|
||||
req.SetBody(new(netmapgrpc.LocalNodeInfoRequest_Body))
|
||||
c.prepareRequest(req, meta)
|
||||
return req, nil
|
||||
}
|
||||
|
@ -94,9 +94,7 @@ func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEnd
|
|||
if verV2 == nil {
|
||||
return nil, newErrMissingResponseField(fieldVersion)
|
||||
}
|
||||
if err := res.version.ReadFromV2(*verV2); err != nil {
|
||||
return nil, newErrInvalidResponseField(fieldVersion, err)
|
||||
}
|
||||
res.version.ReadFromV2(verV2)
|
||||
|
||||
const fieldNodeInfo = "node info"
|
||||
|
||||
|
@ -104,7 +102,7 @@ func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEnd
|
|||
if nodeInfoV2 == nil {
|
||||
return nil, newErrMissingResponseField(fieldNodeInfo)
|
||||
}
|
||||
if err := res.ni.ReadFromV2(*nodeInfoV2); err != nil {
|
||||
if err := res.ni.ReadFromV2(nodeInfoV2); err != nil {
|
||||
return nil, newErrInvalidResponseField(fieldNodeInfo, err)
|
||||
}
|
||||
return &res, nil
|
||||
|
@ -115,12 +113,12 @@ type PrmNetworkInfo struct {
|
|||
prmCommonMeta
|
||||
}
|
||||
|
||||
func (x PrmNetworkInfo) buildRequest(c *Client) (*v2netmap.NetworkInfoRequest, error) {
|
||||
meta := new(v2session.RequestMetaHeader)
|
||||
func (x PrmNetworkInfo) buildRequest(c *Client) (*netmapgrpc.NetworkInfoRequest, error) {
|
||||
meta := new(sessiongrpc.RequestMetaHeader)
|
||||
writeXHeadersToMeta(x.xHeaders, meta)
|
||||
|
||||
var req v2netmap.NetworkInfoRequest
|
||||
req.SetBody(new(v2netmap.NetworkInfoRequestBody))
|
||||
var req netmapgrpc.NetworkInfoRequest
|
||||
req.SetBody(new(netmapgrpc.NetworkInfoRequest_Body))
|
||||
c.prepareRequest(&req, meta)
|
||||
return &req, nil
|
||||
}
|
||||
|
@ -179,7 +177,7 @@ func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetwo
|
|||
if netInfoV2 == nil {
|
||||
return nil, newErrMissingResponseField(fieldNetInfo)
|
||||
}
|
||||
if err := res.info.ReadFromV2(*netInfoV2); err != nil {
|
||||
if err := res.info.ReadFromV2(netInfoV2); err != nil {
|
||||
return nil, newErrInvalidResponseField(fieldNetInfo, err)
|
||||
}
|
||||
return &res, nil
|
||||
|
@ -218,13 +216,13 @@ func (x ResNetMapSnapshot) NetMap() netmap.NetMap {
|
|||
// - global (see Client docs).
|
||||
func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) {
|
||||
// form request body
|
||||
var body v2netmap.SnapshotRequestBody
|
||||
var body netmapgrpc.NetmapSnapshotRequest_Body
|
||||
|
||||
// form meta header
|
||||
var meta v2session.RequestMetaHeader
|
||||
var meta sessiongrpc.RequestMetaHeader
|
||||
|
||||
// form request
|
||||
var req v2netmap.SnapshotRequest
|
||||
var req netmapgrpc.NetmapSnapshotRequest
|
||||
req.SetBody(&body)
|
||||
c.prepareRequest(&req, &meta)
|
||||
|
||||
|
@ -233,7 +231,7 @@ func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResN
|
|||
return nil, fmt.Errorf("sign request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.server.netMapSnapshot(ctx, req)
|
||||
resp, err := c.server.netMapSnapshot(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -250,12 +248,12 @@ func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResN
|
|||
|
||||
const fieldNetMap = "network map"
|
||||
|
||||
netMapV2 := resp.GetBody().NetMap()
|
||||
netMapV2 := resp.GetBody().GetNetmap()
|
||||
if netMapV2 == nil {
|
||||
return nil, newErrMissingResponseField(fieldNetMap)
|
||||
}
|
||||
|
||||
err = res.netMap.ReadFromV2(*netMapV2)
|
||||
err = res.netMap.ReadFromV2(netMapV2)
|
||||
if err != nil {
|
||||
return nil, newErrInvalidResponseField(fieldNetMap, err)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
|
@ -22,11 +22,11 @@ type serverNetMap struct {
|
|||
statusOK bool
|
||||
|
||||
setNetMap bool
|
||||
netMap v2netmap.NetMap
|
||||
netMap netmapgrpc.Netmap
|
||||
}
|
||||
|
||||
func (x *serverNetMap) netMapSnapshot(ctx context.Context, req v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error) {
|
||||
err := signature.VerifyServiceMessage(&req)
|
||||
func (x *serverNetMap) netMapSnapshot(ctx context.Context, req *netmapgrpc.NetmapSnapshotRequest) (*netmapgrpc.NetmapSnapshotResponse, error) {
|
||||
err := signature.VerifyServiceMessage(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -35,19 +35,19 @@ func (x *serverNetMap) netMapSnapshot(ctx context.Context, req v2netmap.Snapshot
|
|||
return nil, x.errTransport
|
||||
}
|
||||
|
||||
var body v2netmap.SnapshotResponseBody
|
||||
var body netmapgrpc.NetmapSnapshotResponse_Body
|
||||
|
||||
if x.setNetMap {
|
||||
body.SetNetMap(&x.netMap)
|
||||
body.SetNetmap(&x.netMap)
|
||||
}
|
||||
|
||||
var meta session.ResponseMetaHeader
|
||||
var meta sessiongrpc.ResponseMetaHeader
|
||||
|
||||
if !x.statusOK {
|
||||
meta.SetStatus(statusErr.ToStatusV2())
|
||||
}
|
||||
|
||||
var resp v2netmap.SnapshotResponse
|
||||
var resp netmapgrpc.NetmapSnapshotResponse
|
||||
resp.SetBody(&body)
|
||||
resp.SetMetaHeader(&meta)
|
||||
|
||||
|
@ -99,13 +99,13 @@ func TestClient_NetMapSnapshot(t *testing.T) {
|
|||
// invalid network map
|
||||
var netMap netmap.NetMap
|
||||
|
||||
var node netmap.NodeInfo
|
||||
node := netmap.NewNodeInfo()
|
||||
// TODO: #260 use instance corrupter
|
||||
|
||||
var nodeV2 v2netmap.NodeInfo
|
||||
var nodeV2 netmapgrpc.NodeInfo
|
||||
|
||||
node.WriteToV2(&nodeV2)
|
||||
require.Error(t, new(netmap.NodeInfo).ReadFromV2(nodeV2))
|
||||
require.Error(t, new(netmap.NodeInfo).ReadFromV2(&nodeV2))
|
||||
|
||||
netMap.SetNodes([]netmap.NodeInfo{node})
|
||||
netMap.WriteToV2(&srv.netMap)
|
||||
|
@ -119,7 +119,7 @@ func TestClient_NetMapSnapshot(t *testing.T) {
|
|||
node.SetNetworkEndpoints("1", "2", "3")
|
||||
|
||||
node.WriteToV2(&nodeV2)
|
||||
require.NoError(t, new(netmap.NodeInfo).ReadFromV2(nodeV2))
|
||||
require.NoError(t, new(netmap.NodeInfo).ReadFromV2(&nodeV2))
|
||||
|
||||
netMap.SetNodes([]netmap.NodeInfo{node})
|
||||
netMap.WriteToV2(&srv.netMap)
|
||||
|
|
|
@ -5,12 +5,12 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
|
@ -21,16 +21,24 @@ import (
|
|||
|
||||
// PrmObjectDelete groups parameters of ObjectDelete operation.
|
||||
type PrmObjectDelete struct {
|
||||
meta v2session.RequestMetaHeader
|
||||
meta *sessiongrpc.RequestMetaHeader
|
||||
|
||||
body v2object.DeleteRequestBody
|
||||
body *objectgrpc.DeleteRequest_Body
|
||||
|
||||
addr v2refs.Address
|
||||
addr *refsgrpc.Address
|
||||
|
||||
keySet bool
|
||||
key ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func NewPrmObjectDelete() PrmObjectDelete {
|
||||
return PrmObjectDelete{
|
||||
meta: &sessiongrpc.RequestMetaHeader{},
|
||||
body: &objectgrpc.DeleteRequest_Body{},
|
||||
addr: &refsgrpc.Address{},
|
||||
}
|
||||
}
|
||||
|
||||
// WithinSession specifies session within which object should be read.
|
||||
//
|
||||
// Creator of the session acquires the authorship of the request.
|
||||
|
@ -38,9 +46,8 @@ type PrmObjectDelete struct {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *PrmObjectDelete) WithinSession(t session.Object) {
|
||||
var tv2 v2session.Token
|
||||
var tv2 sessiongrpc.SessionToken
|
||||
t.WriteToV2(&tv2)
|
||||
|
||||
x.meta.SetSessionToken(&tv2)
|
||||
}
|
||||
|
||||
|
@ -50,7 +57,7 @@ func (x *PrmObjectDelete) WithinSession(t session.Object) {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *PrmObjectDelete) WithBearerToken(t bearer.Token) {
|
||||
var v2token acl.BearerToken
|
||||
var v2token aclgrpc.BearerToken
|
||||
t.WriteToV2(&v2token)
|
||||
x.meta.SetBearerToken(&v2token)
|
||||
}
|
||||
|
@ -58,19 +65,20 @@ func (x *PrmObjectDelete) WithBearerToken(t bearer.Token) {
|
|||
// FromContainer specifies FrostFS container of the object.
|
||||
// Required parameter.
|
||||
func (x *PrmObjectDelete) FromContainer(id cid.ID) {
|
||||
var cidV2 v2refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
id.WriteToV2(&cidV2)
|
||||
|
||||
x.addr.SetContainerID(&cidV2)
|
||||
x.addr.SetContainerId(&cidV2)
|
||||
}
|
||||
|
||||
// ByID specifies identifier of the requested object.
|
||||
// Required parameter.
|
||||
func (x *PrmObjectDelete) ByID(id oid.ID) {
|
||||
var idV2 v2refs.ObjectID
|
||||
var idV2 refsgrpc.ObjectID
|
||||
id.WriteToV2(&idV2)
|
||||
|
||||
x.addr.SetObjectID(&idV2)
|
||||
if x.addr == nil {
|
||||
x.addr = new(refsgrpc.Address)
|
||||
}
|
||||
x.addr.SetObjectId(&idV2)
|
||||
}
|
||||
|
||||
// UseKey specifies private key to sign the requests.
|
||||
|
@ -85,7 +93,7 @@ func (x *PrmObjectDelete) UseKey(key ecdsa.PrivateKey) {
|
|||
//
|
||||
// Slice must not be mutated until the operation completes.
|
||||
func (x *PrmObjectDelete) WithXHeaders(hs ...string) {
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
writeXHeadersToMeta(hs, x.meta)
|
||||
}
|
||||
|
||||
// ResObjectDelete groups resulting values of ObjectDelete operation.
|
||||
|
@ -125,19 +133,23 @@ func (x ResObjectDelete) Tombstone() oid.ID {
|
|||
// - *apistatus.SessionTokenExpired.
|
||||
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
|
||||
switch {
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
case prm.addr.GetContainerId() == nil:
|
||||
return nil, errorMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
case prm.addr.GetObjectId() == nil:
|
||||
return nil, errorMissingObject
|
||||
}
|
||||
|
||||
if prm.body == nil {
|
||||
prm.body = new(objectgrpc.DeleteRequest_Body)
|
||||
}
|
||||
|
||||
// form request body
|
||||
prm.body.SetAddress(&prm.addr)
|
||||
prm.body.SetAddress(prm.addr)
|
||||
|
||||
// form request
|
||||
var req v2object.DeleteRequest
|
||||
req.SetBody(&prm.body)
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
var req objectgrpc.DeleteRequest
|
||||
req.SetBody(prm.body)
|
||||
c.prepareRequest(&req, prm.meta)
|
||||
|
||||
key := c.prm.key
|
||||
if prm.keySet {
|
||||
|
@ -166,12 +178,12 @@ func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObj
|
|||
|
||||
const fieldTombstone = "tombstone"
|
||||
|
||||
idTombV2 := resp.GetBody().GetTombstone().GetObjectID()
|
||||
idTombV2 := resp.GetBody().GetTombstone().GetObjectId()
|
||||
if idTombV2 == nil {
|
||||
return nil, newErrMissingResponseField(fieldTombstone)
|
||||
}
|
||||
|
||||
err = res.tomb.ReadFromV2(*idTombV2)
|
||||
err = res.tomb.ReadFromV2(idTombV2)
|
||||
if err != nil {
|
||||
return nil, newErrInvalidResponseField(fieldTombstone, err)
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
|
@ -24,11 +24,18 @@ import (
|
|||
|
||||
// shared parameters of GET/HEAD/RANGE.
|
||||
type prmObjectRead struct {
|
||||
meta v2session.RequestMetaHeader
|
||||
meta *sessiongrpc.RequestMetaHeader
|
||||
|
||||
raw bool
|
||||
|
||||
addr v2refs.Address
|
||||
addr *refsgrpc.Address
|
||||
}
|
||||
|
||||
func newPrmObjectRead() prmObjectRead {
|
||||
return prmObjectRead{
|
||||
meta: &sessiongrpc.RequestMetaHeader{},
|
||||
addr: &refsgrpc.Address{},
|
||||
}
|
||||
}
|
||||
|
||||
// WithXHeaders specifies list of extended headers (string key-value pairs)
|
||||
|
@ -36,7 +43,7 @@ type prmObjectRead struct {
|
|||
//
|
||||
// Slice must not be mutated until the operation completes.
|
||||
func (x *prmObjectRead) WithXHeaders(hs ...string) {
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
writeXHeadersToMeta(hs, x.meta)
|
||||
}
|
||||
|
||||
// MarkRaw marks an intent to read physically stored object.
|
||||
|
@ -46,7 +53,7 @@ func (x *prmObjectRead) MarkRaw() {
|
|||
|
||||
// MarkLocal tells the server to execute the operation locally.
|
||||
func (x *prmObjectRead) MarkLocal() {
|
||||
x.meta.SetTTL(1)
|
||||
x.meta.SetTtl(1)
|
||||
}
|
||||
|
||||
// WithinSession specifies session within which object should be read.
|
||||
|
@ -56,7 +63,7 @@ func (x *prmObjectRead) MarkLocal() {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *prmObjectRead) WithinSession(t session.Object) {
|
||||
var tokv2 v2session.Token
|
||||
var tokv2 sessiongrpc.SessionToken
|
||||
t.WriteToV2(&tokv2)
|
||||
x.meta.SetSessionToken(&tokv2)
|
||||
}
|
||||
|
@ -67,7 +74,7 @@ func (x *prmObjectRead) WithinSession(t session.Object) {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *prmObjectRead) WithBearerToken(t bearer.Token) {
|
||||
var v2token acl.BearerToken
|
||||
var v2token aclgrpc.BearerToken
|
||||
t.WriteToV2(&v2token)
|
||||
x.meta.SetBearerToken(&v2token)
|
||||
}
|
||||
|
@ -75,17 +82,17 @@ func (x *prmObjectRead) WithBearerToken(t bearer.Token) {
|
|||
// FromContainer specifies FrostFS container of the object.
|
||||
// Required parameter.
|
||||
func (x *prmObjectRead) FromContainer(id cid.ID) {
|
||||
var cnrV2 v2refs.ContainerID
|
||||
var cnrV2 refsgrpc.ContainerID
|
||||
id.WriteToV2(&cnrV2)
|
||||
x.addr.SetContainerID(&cnrV2)
|
||||
x.addr.SetContainerId(&cnrV2)
|
||||
}
|
||||
|
||||
// ByID specifies identifier of the requested object.
|
||||
// Required parameter.
|
||||
func (x *prmObjectRead) ByID(id oid.ID) {
|
||||
var objV2 v2refs.ObjectID
|
||||
var objV2 refsgrpc.ObjectID
|
||||
id.WriteToV2(&objV2)
|
||||
x.addr.SetObjectID(&objV2)
|
||||
x.addr.SetObjectId(&objV2)
|
||||
}
|
||||
|
||||
// PrmObjectGet groups parameters of ObjectGetInit operation.
|
||||
|
@ -95,6 +102,12 @@ type PrmObjectGet struct {
|
|||
key *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func NewPrmObjectGet() PrmObjectGet {
|
||||
return PrmObjectGet{
|
||||
prmObjectRead: newPrmObjectRead(),
|
||||
}
|
||||
}
|
||||
|
||||
// ResObjectGet groups the final result values of ObjectGetInit operation.
|
||||
type ResObjectGet struct {
|
||||
statusRes
|
||||
|
@ -109,7 +122,7 @@ type ObjectReader struct {
|
|||
|
||||
client *Client
|
||||
stream interface {
|
||||
Read(resp *v2object.GetResponse) error
|
||||
Read(resp *objectgrpc.GetResponse) error
|
||||
}
|
||||
|
||||
res ResObjectGet
|
||||
|
@ -129,7 +142,7 @@ func (x *PrmObjectGet) UseKey(key ecdsa.PrivateKey) {
|
|||
// ReadHeader reads header of the object. Result means success.
|
||||
// Failure reason can be received via Close.
|
||||
func (x *ObjectReader) ReadHeader(dst *object.Object) bool {
|
||||
var resp v2object.GetResponse
|
||||
var resp objectgrpc.GetResponse
|
||||
x.err = x.stream.Read(&resp)
|
||||
if x.err != nil {
|
||||
return false
|
||||
|
@ -140,28 +153,28 @@ func (x *ObjectReader) ReadHeader(dst *object.Object) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
var partInit *v2object.GetObjectPartInit
|
||||
var partInit *objectgrpc.GetResponse_Body_Init_
|
||||
|
||||
switch v := resp.GetBody().GetObjectPart().(type) {
|
||||
default:
|
||||
x.err = fmt.Errorf("unexpected message instead of heading part: %T", v)
|
||||
return false
|
||||
case *v2object.SplitInfo:
|
||||
x.err = object.NewSplitInfoError(object.NewSplitInfoFromV2(v))
|
||||
case *objectgrpc.GetResponse_Body_SplitInfo:
|
||||
x.err = object.NewSplitInfoError(object.NewSplitInfoFromV2(v.SplitInfo))
|
||||
return false
|
||||
case *v2object.GetObjectPartInit:
|
||||
case *objectgrpc.GetResponse_Body_Init_:
|
||||
partInit = v
|
||||
}
|
||||
|
||||
var objv2 v2object.Object
|
||||
var objv2 objectgrpc.Object
|
||||
|
||||
objv2.SetObjectID(partInit.GetObjectID())
|
||||
objv2.SetHeader(partInit.GetHeader())
|
||||
objv2.SetSignature(partInit.GetSignature())
|
||||
objv2.SetObjectId(partInit.Init.GetObjectId())
|
||||
objv2.SetHeader(partInit.Init.GetHeader())
|
||||
objv2.SetSignature(partInit.Init.GetSignature())
|
||||
|
||||
x.remainingPayloadLen = int(objv2.GetHeader().GetPayloadLength())
|
||||
|
||||
*dst = *object.NewFromV2(&objv2) // need smth better
|
||||
*dst = *object.NewFromV2(&objv2)
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -182,7 +195,7 @@ func (x *ObjectReader) readChunk(buf []byte) (int, bool) {
|
|||
var lastRead int
|
||||
|
||||
for {
|
||||
var resp v2object.GetResponse
|
||||
var resp objectgrpc.GetResponse
|
||||
x.err = x.stream.Read(&resp)
|
||||
if x.err != nil {
|
||||
return read, false
|
||||
|
@ -194,7 +207,7 @@ func (x *ObjectReader) readChunk(buf []byte) (int, bool) {
|
|||
}
|
||||
|
||||
part := resp.GetBody().GetObjectPart()
|
||||
partChunk, ok := part.(*v2object.GetObjectPartChunk)
|
||||
partChunk, ok := part.(*objectgrpc.GetResponse_Body_Chunk)
|
||||
if !ok {
|
||||
x.err = fmt.Errorf("unexpected message instead of chunk part: %T", part)
|
||||
return read, false
|
||||
|
@ -301,23 +314,23 @@ func (x *ObjectReader) Read(p []byte) (int, error) {
|
|||
func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectReader, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
case prm.addr.GetContainerId() == nil:
|
||||
return nil, errorMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
case prm.addr.GetObjectId() == nil:
|
||||
return nil, errorMissingObject
|
||||
}
|
||||
|
||||
// form request body
|
||||
var body v2object.GetRequestBody
|
||||
var body objectgrpc.GetRequest_Body
|
||||
|
||||
body.SetRaw(prm.raw)
|
||||
body.SetAddress(&prm.addr)
|
||||
body.SetAddress(prm.addr)
|
||||
|
||||
// form request
|
||||
var req v2object.GetRequest
|
||||
var req objectgrpc.GetRequest
|
||||
|
||||
req.SetBody(&body)
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
c.prepareRequest(&req, prm.meta)
|
||||
|
||||
key := prm.key
|
||||
if key == nil {
|
||||
|
@ -353,6 +366,12 @@ type PrmObjectHead struct {
|
|||
key ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func NewPrmObjectHead() PrmObjectHead {
|
||||
return PrmObjectHead{
|
||||
prmObjectRead: newPrmObjectRead(),
|
||||
}
|
||||
}
|
||||
|
||||
// UseKey specifies private key to sign the requests.
|
||||
// If key is not provided, then Client default key is used.
|
||||
func (x *PrmObjectHead) UseKey(key ecdsa.PrivateKey) {
|
||||
|
@ -367,7 +386,7 @@ type ResObjectHead struct {
|
|||
// requested object (response doesn't carry the ID)
|
||||
idObj oid.ID
|
||||
|
||||
hdr *v2object.HeaderWithSignature
|
||||
hdr *objectgrpc.HeaderWithSignature
|
||||
}
|
||||
|
||||
// ReadHeader reads header of the requested object.
|
||||
|
@ -377,7 +396,7 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
var objv2 v2object.Object
|
||||
var objv2 objectgrpc.Object
|
||||
|
||||
objv2.SetHeader(x.hdr.GetHeader())
|
||||
objv2.SetSignature(x.hdr.GetSignature())
|
||||
|
@ -414,19 +433,19 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
|
|||
// - *apistatus.SessionTokenExpired.
|
||||
func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) {
|
||||
switch {
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
case prm.addr.GetContainerId() == nil:
|
||||
return nil, errorMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
case prm.addr.GetObjectId() == nil:
|
||||
return nil, errorMissingObject
|
||||
}
|
||||
|
||||
var body v2object.HeadRequestBody
|
||||
var body objectgrpc.HeadRequest_Body
|
||||
body.SetRaw(prm.raw)
|
||||
body.SetAddress(&prm.addr)
|
||||
body.SetAddress(prm.addr)
|
||||
|
||||
var req v2object.HeadRequest
|
||||
var req objectgrpc.HeadRequest
|
||||
req.SetBody(&body)
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
c.prepareRequest(&req, prm.meta)
|
||||
|
||||
key := c.prm.key
|
||||
if prm.keySet {
|
||||
|
@ -454,15 +473,15 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH
|
|||
return &res, nil
|
||||
}
|
||||
|
||||
_ = res.idObj.ReadFromV2(*prm.addr.GetObjectID())
|
||||
_ = res.idObj.ReadFromV2(prm.addr.GetObjectId())
|
||||
|
||||
switch v := resp.GetBody().GetHeaderPart().(type) {
|
||||
switch v := resp.GetBody().GetHead().(type) {
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected header type %T", v)
|
||||
case *v2object.SplitInfo:
|
||||
return nil, object.NewSplitInfoError(object.NewSplitInfoFromV2(v))
|
||||
case *v2object.HeaderWithSignature:
|
||||
res.hdr = v
|
||||
case *objectgrpc.HeadResponse_Body_SplitInfo:
|
||||
return nil, object.NewSplitInfoError(object.NewSplitInfoFromV2(v.SplitInfo))
|
||||
case *objectgrpc.HeadResponse_Body_Header:
|
||||
res.hdr = v.Header
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
|
@ -474,7 +493,14 @@ type PrmObjectRange struct {
|
|||
|
||||
key *ecdsa.PrivateKey
|
||||
|
||||
rng v2object.Range
|
||||
rng *objectgrpc.Range
|
||||
}
|
||||
|
||||
func NewPrmObjectRange() PrmObjectRange {
|
||||
return PrmObjectRange{
|
||||
prmObjectRead: newPrmObjectRead(),
|
||||
rng: &objectgrpc.Range{},
|
||||
}
|
||||
}
|
||||
|
||||
// SetOffset sets offset of the payload range to be read.
|
||||
|
@ -514,7 +540,7 @@ type ObjectRangeReader struct {
|
|||
err error
|
||||
|
||||
stream interface {
|
||||
Read(resp *v2object.GetRangeResponse) error
|
||||
Read(resp *objectgrpc.GetRangeResponse) error
|
||||
}
|
||||
|
||||
tailPayload []byte
|
||||
|
@ -534,12 +560,12 @@ func (x *ObjectRangeReader) readChunk(buf []byte) (int, bool) {
|
|||
return read, true
|
||||
}
|
||||
|
||||
var partChunk *v2object.GetRangePartChunk
|
||||
var partChunk *objectgrpc.GetRangeResponse_Body_Chunk
|
||||
var chunk []byte
|
||||
var lastRead int
|
||||
|
||||
for {
|
||||
var resp v2object.GetRangeResponse
|
||||
var resp objectgrpc.GetRangeResponse
|
||||
x.err = x.stream.Read(&resp)
|
||||
if x.err != nil {
|
||||
return read, false
|
||||
|
@ -555,10 +581,10 @@ func (x *ObjectRangeReader) readChunk(buf []byte) (int, bool) {
|
|||
default:
|
||||
x.err = fmt.Errorf("unexpected message received: %T", v)
|
||||
return read, false
|
||||
case *v2object.SplitInfo:
|
||||
x.err = object.NewSplitInfoError(object.NewSplitInfoFromV2(v))
|
||||
case *objectgrpc.GetRangeResponse_Body_SplitInfo:
|
||||
x.err = object.NewSplitInfoError(object.NewSplitInfoFromV2(v.SplitInfo))
|
||||
return read, false
|
||||
case *v2object.GetRangePartChunk:
|
||||
case *objectgrpc.GetRangeResponse_Body_Chunk:
|
||||
partChunk = v
|
||||
}
|
||||
|
||||
|
@ -664,26 +690,26 @@ func (x *ObjectRangeReader) Read(p []byte) (int, error) {
|
|||
func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*ObjectRangeReader, error) {
|
||||
// check parameters
|
||||
switch {
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
case prm.addr.GetContainerId() == nil:
|
||||
return nil, errorMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
case prm.addr.GetObjectId() == nil:
|
||||
return nil, errorMissingObject
|
||||
case prm.rng.GetLength() == 0:
|
||||
return nil, errorZeroRangeLength
|
||||
}
|
||||
|
||||
// form request body
|
||||
var body v2object.GetRangeRequestBody
|
||||
var body objectgrpc.GetRangeRequest_Body
|
||||
|
||||
body.SetRaw(prm.raw)
|
||||
body.SetAddress(&prm.addr)
|
||||
body.SetRange(&prm.rng)
|
||||
body.SetAddress(prm.addr)
|
||||
body.SetRange(prm.rng)
|
||||
|
||||
// form request
|
||||
var req v2object.GetRangeRequest
|
||||
var req objectgrpc.GetRangeRequest
|
||||
|
||||
req.SetBody(&body)
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
c.prepareRequest(&req, prm.meta)
|
||||
|
||||
key := prm.key
|
||||
if key == nil {
|
||||
|
|
|
@ -5,44 +5,53 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
)
|
||||
|
||||
// PrmObjectHash groups parameters of ObjectHash operation.
|
||||
type PrmObjectHash struct {
|
||||
meta v2session.RequestMetaHeader
|
||||
meta *sessiongrpc.RequestMetaHeader
|
||||
|
||||
body v2object.GetRangeHashRequestBody
|
||||
body *objectgrpc.GetRangeHashRequest_Body
|
||||
|
||||
csAlgo v2refs.ChecksumType
|
||||
csAlgo refsgrpc.ChecksumType
|
||||
|
||||
addr v2refs.Address
|
||||
addr *refsgrpc.Address
|
||||
|
||||
keySet bool
|
||||
key ecdsa.PrivateKey
|
||||
key *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func NewPrmObjectHash() PrmObjectHash {
|
||||
return PrmObjectHash{
|
||||
meta: &sessiongrpc.RequestMetaHeader{},
|
||||
body: &objectgrpc.GetRangeHashRequest_Body{},
|
||||
addr: &refsgrpc.Address{},
|
||||
}
|
||||
}
|
||||
|
||||
// UseKey specifies private key to sign the requests.
|
||||
// If key is not provided, then Client default key is used.
|
||||
func (x *PrmObjectHash) UseKey(key ecdsa.PrivateKey) {
|
||||
func (x *PrmObjectHash) UseKey(key *ecdsa.PrivateKey) {
|
||||
x.keySet = true
|
||||
x.key = key
|
||||
}
|
||||
|
||||
// MarkLocal tells the server to execute the operation locally.
|
||||
func (x *PrmObjectHash) MarkLocal() {
|
||||
x.meta.SetTTL(1)
|
||||
x.meta.SetTtl(1)
|
||||
}
|
||||
|
||||
// WithinSession specifies session within which object should be read.
|
||||
|
@ -52,9 +61,8 @@ func (x *PrmObjectHash) MarkLocal() {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *PrmObjectHash) WithinSession(t session.Object) {
|
||||
var tv2 v2session.Token
|
||||
var tv2 sessiongrpc.SessionToken
|
||||
t.WriteToV2(&tv2)
|
||||
|
||||
x.meta.SetSessionToken(&tv2)
|
||||
}
|
||||
|
||||
|
@ -64,7 +72,7 @@ func (x *PrmObjectHash) WithinSession(t session.Object) {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *PrmObjectHash) WithBearerToken(t bearer.Token) {
|
||||
var v2token acl.BearerToken
|
||||
var v2token aclgrpc.BearerToken
|
||||
t.WriteToV2(&v2token)
|
||||
x.meta.SetBearerToken(&v2token)
|
||||
}
|
||||
|
@ -72,19 +80,17 @@ func (x *PrmObjectHash) WithBearerToken(t bearer.Token) {
|
|||
// FromContainer specifies FrostFS container of the object.
|
||||
// Required parameter.
|
||||
func (x *PrmObjectHash) FromContainer(id cid.ID) {
|
||||
var cidV2 v2refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
id.WriteToV2(&cidV2)
|
||||
|
||||
x.addr.SetContainerID(&cidV2)
|
||||
x.addr.SetContainerId(&cidV2)
|
||||
}
|
||||
|
||||
// ByID specifies identifier of the requested object.
|
||||
// Required parameter.
|
||||
func (x *PrmObjectHash) ByID(id oid.ID) {
|
||||
var idV2 v2refs.ObjectID
|
||||
var idV2 refsgrpc.ObjectID
|
||||
id.WriteToV2(&idV2)
|
||||
|
||||
x.addr.SetObjectID(&idV2)
|
||||
x.addr.SetObjectId(&idV2)
|
||||
}
|
||||
|
||||
// SetRangeList sets list of ranges in (offset, length) pair format.
|
||||
|
@ -97,7 +103,7 @@ func (x *PrmObjectHash) SetRangeList(r ...uint64) {
|
|||
panic("odd number of range parameters")
|
||||
}
|
||||
|
||||
rs := make([]v2object.Range, ln/2)
|
||||
rs := slices.MakePreallocPointerSlice[objectgrpc.Range](ln / 2)
|
||||
|
||||
for i := 0; i < ln/2; i++ {
|
||||
rs[i].SetOffset(r[2*i])
|
||||
|
@ -112,7 +118,7 @@ func (x *PrmObjectHash) SetRangeList(r ...uint64) {
|
|||
//
|
||||
// By default, SHA256 hash function is used.
|
||||
func (x *PrmObjectHash) TillichZemorAlgo() {
|
||||
x.csAlgo = v2refs.TillichZemor
|
||||
x.csAlgo = refsgrpc.ChecksumType_TZ
|
||||
}
|
||||
|
||||
// UseSalt sets the salt to XOR the data range before hashing.
|
||||
|
@ -127,7 +133,7 @@ func (x *PrmObjectHash) UseSalt(salt []byte) {
|
|||
//
|
||||
// Slice must not be mutated until the operation completes.
|
||||
func (x *PrmObjectHash) WithXHeaders(hs ...string) {
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
writeXHeadersToMeta(hs, x.meta)
|
||||
}
|
||||
|
||||
// ResObjectHash groups resulting values of ObjectHash operation.
|
||||
|
@ -166,31 +172,31 @@ func (x ResObjectHash) Checksums() [][]byte {
|
|||
// - *apistatus.SessionTokenExpired.
|
||||
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
|
||||
switch {
|
||||
case prm.addr.GetContainerID() == nil:
|
||||
case prm.addr.GetContainerId() == nil:
|
||||
return nil, errorMissingContainer
|
||||
case prm.addr.GetObjectID() == nil:
|
||||
case prm.addr.GetObjectId() == nil:
|
||||
return nil, errorMissingObject
|
||||
case len(prm.body.GetRanges()) == 0:
|
||||
return nil, errorMissingRanges
|
||||
}
|
||||
|
||||
prm.body.SetAddress(&prm.addr)
|
||||
if prm.csAlgo == v2refs.UnknownChecksum {
|
||||
prm.body.SetType(v2refs.SHA256)
|
||||
prm.body.SetAddress(prm.addr)
|
||||
if prm.csAlgo == refsgrpc.ChecksumType_CHECKSUM_TYPE_UNSPECIFIED {
|
||||
prm.body.SetType(refsgrpc.ChecksumType_SHA256)
|
||||
} else {
|
||||
prm.body.SetType(prm.csAlgo)
|
||||
}
|
||||
|
||||
var req v2object.GetRangeHashRequest
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
req.SetBody(&prm.body)
|
||||
var req objectgrpc.GetRangeHashRequest
|
||||
c.prepareRequest(&req, prm.meta)
|
||||
req.SetBody(prm.body)
|
||||
|
||||
key := c.prm.key
|
||||
key := &c.prm.key
|
||||
if prm.keySet {
|
||||
key = prm.key
|
||||
}
|
||||
|
||||
err := signature.SignServiceMessage(&key, &req)
|
||||
err := signature.SignServiceMessage(key, &req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sign request: %w", err)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"context"
|
||||
"crypto/ecdsa"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
|
@ -21,13 +21,19 @@ const defaultGRPCPayloadChunkLen = 3 << 20
|
|||
type PrmObjectPutInit struct {
|
||||
copyNum []uint32
|
||||
key *ecdsa.PrivateKey
|
||||
meta v2session.RequestMetaHeader
|
||||
meta *sessiongrpc.RequestMetaHeader
|
||||
maxChunkLen int
|
||||
maxSize uint64
|
||||
epochSource transformer.EpochSource
|
||||
withoutHomomorphicHash bool
|
||||
}
|
||||
|
||||
func NewPrmObjectPutInit() PrmObjectPutInit {
|
||||
return PrmObjectPutInit{
|
||||
meta: new(sessiongrpc.RequestMetaHeader),
|
||||
}
|
||||
}
|
||||
|
||||
// SetCopiesNumber sets number of object copies that is enough to consider put successful.
|
||||
func (x *PrmObjectPutInit) SetCopiesNumber(copiesNumber uint32) {
|
||||
x.copyNum = []uint32{copiesNumber}
|
||||
|
@ -101,7 +107,7 @@ func (x *PrmObjectPutInit) UseKey(key ecdsa.PrivateKey) {
|
|||
// WithBearerToken attaches bearer token to be used for the operation.
|
||||
// Should be called once before any writing steps.
|
||||
func (x *PrmObjectPutInit) WithBearerToken(t bearer.Token) {
|
||||
var v2token acl.BearerToken
|
||||
var v2token aclgrpc.BearerToken
|
||||
t.WriteToV2(&v2token)
|
||||
x.meta.SetBearerToken(&v2token)
|
||||
}
|
||||
|
@ -109,7 +115,7 @@ func (x *PrmObjectPutInit) WithBearerToken(t bearer.Token) {
|
|||
// WithinSession specifies session within which object should be stored.
|
||||
// Should be called once before any writing steps.
|
||||
func (x *PrmObjectPutInit) WithinSession(t session.Object) {
|
||||
var tv2 v2session.Token
|
||||
var tv2 sessiongrpc.SessionToken
|
||||
t.WriteToV2(&tv2)
|
||||
|
||||
x.meta.SetSessionToken(&tv2)
|
||||
|
@ -117,7 +123,7 @@ func (x *PrmObjectPutInit) WithinSession(t session.Object) {
|
|||
|
||||
// MarkLocal tells the server to execute the operation locally.
|
||||
func (x *PrmObjectPutInit) MarkLocal() {
|
||||
x.meta.SetTTL(1)
|
||||
x.meta.SetTtl(1)
|
||||
}
|
||||
|
||||
// WithXHeaders specifies list of extended headers (string key-value pairs)
|
||||
|
@ -125,7 +131,7 @@ func (x *PrmObjectPutInit) MarkLocal() {
|
|||
//
|
||||
// Slice must not be mutated until the operation completes.
|
||||
func (x *PrmObjectPutInit) WithXHeaders(hs ...string) {
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
writeXHeadersToMeta(hs, x.meta)
|
||||
}
|
||||
|
||||
// WithObjectMaxSize specifies max object size value and use it during object splitting.
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
|
@ -16,8 +16,8 @@ import (
|
|||
)
|
||||
|
||||
func (c *Client) objectPutInitRaw(ctx context.Context, prm PrmObjectPutInit) (*objectWriterRaw, error) {
|
||||
var w objectWriterRaw
|
||||
stream, err := rpcapi.PutObject(&c.c, &w.respV2, client.WithContext(ctx))
|
||||
w := newObjectWriterRaw()
|
||||
stream, err := rpcapi.PutObject(&c.c, w.respV2, client.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open stream: %w", err)
|
||||
}
|
||||
|
@ -28,14 +28,16 @@ func (c *Client) objectPutInitRaw(ctx context.Context, prm PrmObjectPutInit) (*o
|
|||
}
|
||||
w.client = c
|
||||
w.stream = stream
|
||||
w.partInit = new(v2object.PutRequest_Body_Init)
|
||||
w.partInit.SetCopiesNumber(prm.copyNum)
|
||||
w.req.SetBody(new(v2object.PutRequestBody))
|
||||
w.req = new(v2object.PutRequest)
|
||||
w.req.SetBody(new(v2object.PutRequest_Body))
|
||||
if prm.maxChunkLen > 0 {
|
||||
w.maxChunkLen = prm.maxChunkLen
|
||||
} else {
|
||||
w.maxChunkLen = defaultGRPCPayloadChunkLen
|
||||
}
|
||||
c.prepareRequest(&w.req, &prm.meta)
|
||||
c.prepareRequest(w.req, prm.meta)
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
|
@ -50,37 +52,50 @@ type objectWriterRaw struct {
|
|||
res ResObjectPut
|
||||
err error
|
||||
chunkCalled bool
|
||||
respV2 v2object.PutResponse
|
||||
req v2object.PutRequest
|
||||
partInit v2object.PutObjectPartInit
|
||||
partChunk v2object.PutObjectPartChunk
|
||||
respV2 *v2object.PutResponse
|
||||
req *v2object.PutRequest
|
||||
partInit *v2object.PutRequest_Body_Init
|
||||
partChunk *v2object.PutRequest_Body_Chunk
|
||||
maxChunkLen int
|
||||
}
|
||||
|
||||
func newObjectWriterRaw() objectWriterRaw {
|
||||
return objectWriterRaw{
|
||||
respV2: &v2object.PutResponse{},
|
||||
req: &v2object.PutRequest{},
|
||||
partInit: &v2object.PutRequest_Body_Init{},
|
||||
partChunk: &v2object.PutRequest_Body_Chunk{},
|
||||
}
|
||||
}
|
||||
|
||||
func (x *objectWriterRaw) WriteHeader(_ context.Context, hdr object.Object) bool {
|
||||
v2Hdr := hdr.ToV2()
|
||||
|
||||
x.partInit.SetObjectID(v2Hdr.GetObjectID())
|
||||
if x.partInit == nil {
|
||||
x.partInit = new(v2object.PutRequest_Body_Init)
|
||||
}
|
||||
|
||||
x.partInit.SetObjectId(v2Hdr.GetObjectId())
|
||||
x.partInit.SetHeader(v2Hdr.GetHeader())
|
||||
x.partInit.SetSignature(v2Hdr.GetSignature())
|
||||
|
||||
x.req.GetBody().SetObjectPart(&x.partInit)
|
||||
x.req.SetVerificationHeader(nil)
|
||||
x.req.GetBody().SetInit(x.partInit)
|
||||
x.req.SetVerifyHeader(nil)
|
||||
|
||||
x.err = signature.SignServiceMessage(x.key, &x.req)
|
||||
x.err = signature.SignServiceMessage(x.key, x.req)
|
||||
if x.err != nil {
|
||||
x.err = fmt.Errorf("sign message: %w", x.err)
|
||||
return false
|
||||
}
|
||||
|
||||
x.err = x.stream.Write(&x.req)
|
||||
x.err = x.stream.Write(x.req)
|
||||
return x.err == nil
|
||||
}
|
||||
|
||||
func (x *objectWriterRaw) WritePayloadChunk(_ context.Context, chunk []byte) bool {
|
||||
if !x.chunkCalled {
|
||||
x.chunkCalled = true
|
||||
x.req.GetBody().SetObjectPart(&x.partChunk)
|
||||
x.req.GetBody().SetChunk(x.partChunk)
|
||||
}
|
||||
|
||||
for ln := len(chunk); ln > 0; ln = len(chunk) {
|
||||
|
@ -98,15 +113,15 @@ func (x *objectWriterRaw) WritePayloadChunk(_ context.Context, chunk []byte) boo
|
|||
// It is mentally assumed that allocating and filling the buffer is better than
|
||||
// synchronous sending, but this needs to be tested.
|
||||
x.partChunk.SetChunk(chunk[:ln])
|
||||
x.req.SetVerificationHeader(nil)
|
||||
x.req.SetVerifyHeader(nil)
|
||||
|
||||
x.err = signature.SignServiceMessage(x.key, &x.req)
|
||||
x.err = signature.SignServiceMessage(x.key, x.req)
|
||||
if x.err != nil {
|
||||
x.err = fmt.Errorf("sign message: %w", x.err)
|
||||
return false
|
||||
}
|
||||
|
||||
x.err = x.stream.Write(&x.req)
|
||||
x.err = x.stream.Write(x.req)
|
||||
if x.err != nil {
|
||||
return false
|
||||
}
|
||||
|
@ -129,7 +144,7 @@ func (x *objectWriterRaw) Close(_ context.Context) (*ResObjectPut, error) {
|
|||
return nil, x.err
|
||||
}
|
||||
|
||||
x.res.st, x.err = x.client.processResponse(&x.respV2)
|
||||
x.res.st, x.err = x.client.processResponse(x.respV2)
|
||||
if x.err != nil {
|
||||
return nil, x.err
|
||||
}
|
||||
|
@ -140,12 +155,12 @@ func (x *objectWriterRaw) Close(_ context.Context) (*ResObjectPut, error) {
|
|||
|
||||
const fieldID = "ID"
|
||||
|
||||
idV2 := x.respV2.GetBody().GetObjectID()
|
||||
idV2 := x.respV2.GetBody().GetObjectId()
|
||||
if idV2 == nil {
|
||||
return nil, newErrMissingResponseField(fieldID)
|
||||
}
|
||||
|
||||
x.err = x.res.obj.ReadFromV2(*idV2)
|
||||
x.err = x.res.obj.ReadFromV2(idV2)
|
||||
if x.err != nil {
|
||||
x.err = newErrInvalidResponseField(fieldID, x.err)
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||
|
@ -18,11 +18,17 @@ import (
|
|||
// PrmObjectPutSingle groups parameters of PutSingle operation.
|
||||
type PrmObjectPutSingle struct {
|
||||
copyNum []uint32
|
||||
meta v2session.RequestMetaHeader
|
||||
object *v2object.Object
|
||||
meta *sessiongrpc.RequestMetaHeader
|
||||
object *objectgrpc.Object
|
||||
key *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func NewPrmObjectPutSingle() PrmObjectPutSingle {
|
||||
return PrmObjectPutSingle{
|
||||
meta: new(sessiongrpc.RequestMetaHeader),
|
||||
}
|
||||
}
|
||||
|
||||
// SetCopiesNumber sets ordered list of minimal required object copies numbers
|
||||
// per placement vector. List's length MUST equal container's placement vector number,
|
||||
// otherwise request will fail.
|
||||
|
@ -39,7 +45,7 @@ func (x *PrmObjectPutSingle) UseKey(key *ecdsa.PrivateKey) {
|
|||
// WithBearerToken attaches bearer token to be used for the operation.
|
||||
// Should be called once before any writing steps.
|
||||
func (x *PrmObjectPutSingle) WithBearerToken(t bearer.Token) {
|
||||
v2token := &acl.BearerToken{}
|
||||
v2token := &aclgrpc.BearerToken{}
|
||||
t.WriteToV2(v2token)
|
||||
x.meta.SetBearerToken(v2token)
|
||||
}
|
||||
|
@ -47,14 +53,14 @@ func (x *PrmObjectPutSingle) WithBearerToken(t bearer.Token) {
|
|||
// WithinSession specifies session within which object should be stored.
|
||||
// Should be called once before any writing steps.
|
||||
func (x *PrmObjectPutSingle) WithinSession(t session.Object) {
|
||||
tv2 := &v2session.Token{}
|
||||
tv2 := &sessiongrpc.SessionToken{}
|
||||
t.WriteToV2(tv2)
|
||||
x.meta.SetSessionToken(tv2)
|
||||
}
|
||||
|
||||
// ExecuteLocal tells the server to execute the operation locally.
|
||||
func (x *PrmObjectPutSingle) ExecuteLocal() {
|
||||
x.meta.SetTTL(1)
|
||||
x.meta.SetTtl(1)
|
||||
}
|
||||
|
||||
// WithXHeaders specifies list of extended headers (string key-value pairs)
|
||||
|
@ -62,11 +68,11 @@ func (x *PrmObjectPutSingle) ExecuteLocal() {
|
|||
//
|
||||
// Slice must not be mutated until the operation completes.
|
||||
func (x *PrmObjectPutSingle) WithXHeaders(hs ...string) {
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
writeXHeadersToMeta(hs, x.meta)
|
||||
}
|
||||
|
||||
// SetObject specifies prepared object to put.
|
||||
func (x *PrmObjectPutSingle) SetObject(o *v2object.Object) {
|
||||
func (x *PrmObjectPutSingle) SetObject(o *objectgrpc.Object) {
|
||||
x.object = o
|
||||
}
|
||||
|
||||
|
@ -82,14 +88,14 @@ type ResObjectPutSingle struct {
|
|||
// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures
|
||||
// codes are returned as error.
|
||||
func (c *Client) ObjectPutSingle(ctx context.Context, prm PrmObjectPutSingle) (*ResObjectPutSingle, error) {
|
||||
body := &v2object.PutSingleRequestBody{}
|
||||
body := &objectgrpc.PutSingleRequest_Body{}
|
||||
body.SetCopiesNumber(prm.copyNum)
|
||||
body.SetObject(prm.object)
|
||||
|
||||
req := &v2object.PutSingleRequest{}
|
||||
req := &objectgrpc.PutSingleRequest{}
|
||||
req.SetBody(body)
|
||||
|
||||
c.prepareRequest(req, &prm.meta)
|
||||
c.prepareRequest(req, prm.meta)
|
||||
|
||||
key := &c.prm.key
|
||||
if prm.key != nil {
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
// PrmObjectSearch groups parameters of ObjectSearch operation.
|
||||
type PrmObjectSearch struct {
|
||||
meta v2session.RequestMetaHeader
|
||||
meta *sessiongrpc.RequestMetaHeader
|
||||
|
||||
key *ecdsa.PrivateKey
|
||||
|
||||
|
@ -34,9 +34,15 @@ type PrmObjectSearch struct {
|
|||
filters object.SearchFilters
|
||||
}
|
||||
|
||||
func NewPrmObjectSearch() PrmObjectSearch {
|
||||
return PrmObjectSearch{
|
||||
meta: &sessiongrpc.RequestMetaHeader{},
|
||||
}
|
||||
}
|
||||
|
||||
// MarkLocal tells the server to execute the operation locally.
|
||||
func (x *PrmObjectSearch) MarkLocal() {
|
||||
x.meta.SetTTL(1)
|
||||
x.meta.SetTtl(1)
|
||||
}
|
||||
|
||||
// WithinSession specifies session within which the search query must be executed.
|
||||
|
@ -46,7 +52,7 @@ func (x *PrmObjectSearch) MarkLocal() {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *PrmObjectSearch) WithinSession(t session.Object) {
|
||||
var tokv2 v2session.Token
|
||||
var tokv2 sessiongrpc.SessionToken
|
||||
t.WriteToV2(&tokv2)
|
||||
x.meta.SetSessionToken(&tokv2)
|
||||
}
|
||||
|
@ -57,7 +63,7 @@ func (x *PrmObjectSearch) WithinSession(t session.Object) {
|
|||
//
|
||||
// Must be signed.
|
||||
func (x *PrmObjectSearch) WithBearerToken(t bearer.Token) {
|
||||
var v2token acl.BearerToken
|
||||
var v2token aclgrpc.BearerToken
|
||||
t.WriteToV2(&v2token)
|
||||
x.meta.SetBearerToken(&v2token)
|
||||
}
|
||||
|
@ -67,7 +73,7 @@ func (x *PrmObjectSearch) WithBearerToken(t bearer.Token) {
|
|||
//
|
||||
// Slice must not be mutated until the operation completes.
|
||||
func (x *PrmObjectSearch) WithXHeaders(hs ...string) {
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
writeXHeadersToMeta(hs, x.meta)
|
||||
}
|
||||
|
||||
// UseKey specifies private key to sign the requests.
|
||||
|
@ -103,9 +109,9 @@ type ObjectListReader struct {
|
|||
err error
|
||||
res ResObjectSearch
|
||||
stream interface {
|
||||
Read(resp *v2object.SearchResponse) error
|
||||
Read(resp *objectgrpc.SearchResponse) error
|
||||
}
|
||||
tail []v2refs.ObjectID
|
||||
tail []*refsgrpc.ObjectID
|
||||
}
|
||||
|
||||
// Read reads another list of the object identifiers. Works similar to
|
||||
|
@ -127,7 +133,7 @@ func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) {
|
|||
}
|
||||
|
||||
for {
|
||||
var resp v2object.SearchResponse
|
||||
var resp objectgrpc.SearchResponse
|
||||
x.err = x.stream.Read(&resp)
|
||||
if x.err != nil {
|
||||
return read, false
|
||||
|
@ -139,7 +145,7 @@ func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) {
|
|||
}
|
||||
|
||||
// read new chunk of objects
|
||||
ids := resp.GetBody().GetIDList()
|
||||
ids := resp.GetBody().GetIdList()
|
||||
if len(ids) == 0 {
|
||||
// just skip empty lists since they are not prohibited by protocol
|
||||
continue
|
||||
|
@ -157,7 +163,7 @@ func (x *ObjectListReader) Read(buf []oid.ID) (int, bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func copyIDBuffers(dst []oid.ID, src []v2refs.ObjectID) int {
|
||||
func copyIDBuffers(dst []oid.ID, src []*refsgrpc.ObjectID) int {
|
||||
var i int
|
||||
for ; i < len(dst) && i < len(src); i++ {
|
||||
_ = dst[i].ReadFromV2(src[i])
|
||||
|
@ -226,18 +232,18 @@ func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*Ob
|
|||
return nil, errorMissingContainer
|
||||
}
|
||||
|
||||
var cidV2 v2refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
prm.cnrID.WriteToV2(&cidV2)
|
||||
|
||||
var body v2object.SearchRequestBody
|
||||
var body objectgrpc.SearchRequest_Body
|
||||
body.SetVersion(1)
|
||||
body.SetContainerID(&cidV2)
|
||||
body.SetContainerId(&cidV2)
|
||||
body.SetFilters(prm.filters.ToV2())
|
||||
|
||||
// init reader
|
||||
var req v2object.SearchRequest
|
||||
var req objectgrpc.SearchRequest
|
||||
req.SetBody(&body)
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
c.prepareRequest(&req, prm.meta)
|
||||
|
||||
key := prm.key
|
||||
if key == nil {
|
||||
|
|
|
@ -7,11 +7,12 @@ import (
|
|||
"io"
|
||||
"testing"
|
||||
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
signatureV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -143,14 +144,14 @@ func (s *singleStreamResponder) Read(resp *v2object.SearchResponse) error {
|
|||
panic("unexpected call to `Read`")
|
||||
}
|
||||
|
||||
var body v2object.SearchResponseBody
|
||||
var body v2object.SearchResponse_Body
|
||||
|
||||
if s.idList[s.n] != nil {
|
||||
ids := make([]refs.ObjectID, len(s.idList[s.n]))
|
||||
ids := slices.MakePreallocPointerSlice[refsgrpc.ObjectID](len(s.idList[s.n]))
|
||||
for i := range s.idList[s.n] {
|
||||
s.idList[s.n][i].WriteToV2(&ids[i])
|
||||
s.idList[s.n][i].WriteToV2(ids[i])
|
||||
}
|
||||
body.SetIDList(ids)
|
||||
body.SetIdList(ids)
|
||||
}
|
||||
resp.SetBody(&body)
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package client
|
||||
|
||||
import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
import (
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
)
|
||||
|
||||
// ResponseMetaInfo groups meta information about any FrostFS API response.
|
||||
type ResponseMetaInfo struct {
|
||||
|
@ -10,8 +12,8 @@ type ResponseMetaInfo struct {
|
|||
}
|
||||
|
||||
type responseV2 interface {
|
||||
GetMetaHeader() *session.ResponseMetaHeader
|
||||
GetVerificationHeader() *session.ResponseVerificationHeader
|
||||
GetMetaHeader() *sessiongrpc.ResponseMetaHeader
|
||||
GetVerifyHeader() *sessiongrpc.ResponseVerificationHeader
|
||||
}
|
||||
|
||||
// ResponderKey returns responder's public key in a binary format.
|
||||
|
|
|
@ -5,11 +5,11 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
v2signature "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
)
|
||||
|
@ -36,7 +36,7 @@ func (x *PrmSessionCreate) UseKey(key ecdsa.PrivateKey) {
|
|||
x.key = key
|
||||
}
|
||||
|
||||
func (x *PrmSessionCreate) buildRequest(c *Client) (*v2session.CreateRequest, error) {
|
||||
func (x *PrmSessionCreate) buildRequest(c *Client) (*sessiongrpc.CreateRequest, error) {
|
||||
ownerKey := c.prm.key.PublicKey
|
||||
if x.keySet {
|
||||
ownerKey = x.key.PublicKey
|
||||
|
@ -44,17 +44,17 @@ func (x *PrmSessionCreate) buildRequest(c *Client) (*v2session.CreateRequest, er
|
|||
var ownerID user.ID
|
||||
user.IDFromKey(&ownerID, ownerKey)
|
||||
|
||||
var ownerIDV2 refs.OwnerID
|
||||
var ownerIDV2 refsgrpc.OwnerID
|
||||
ownerID.WriteToV2(&ownerIDV2)
|
||||
|
||||
reqBody := new(v2session.CreateRequestBody)
|
||||
reqBody.SetOwnerID(&ownerIDV2)
|
||||
reqBody := new(sessiongrpc.CreateRequest_Body)
|
||||
reqBody.SetOwnerId(&ownerIDV2)
|
||||
reqBody.SetExpiration(x.exp)
|
||||
|
||||
var meta v2session.RequestMetaHeader
|
||||
var meta sessiongrpc.RequestMetaHeader
|
||||
writeXHeadersToMeta(x.xHeaders, &meta)
|
||||
|
||||
var req v2session.CreateRequest
|
||||
var req sessiongrpc.CreateRequest
|
||||
req.SetBody(reqBody)
|
||||
c.prepareRequest(&req, &meta)
|
||||
return &req, nil
|
||||
|
@ -102,7 +102,7 @@ func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResS
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := signature.SignServiceMessage(&c.prm.key, req); err != nil {
|
||||
if err := v2signature.SignServiceMessage(&c.prm.key, req); err != nil {
|
||||
return nil, fmt.Errorf("sign request: %w", err)
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResS
|
|||
}
|
||||
|
||||
body := resp.GetBody()
|
||||
res.id = body.GetID()
|
||||
res.id = body.GetId()
|
||||
res.sessionKey = body.GetSessionKey()
|
||||
return &res, nil
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package apistatus
|
|||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
status "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// ServerInternal describes failure statuses related to internal server errors.
|
||||
|
@ -11,19 +13,28 @@ import (
|
|||
//
|
||||
// The status is purely informative, the client should not go into details of the error except for debugging needs.
|
||||
type ServerInternal struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewServerInternal() ServerInternal {
|
||||
return ServerInternal{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
func (x ServerInternal) Error() string {
|
||||
return errMessageStatusV2(
|
||||
globalizeCodeV2(status.Internal, status.GlobalizeCommonFail),
|
||||
x.v2.Message(),
|
||||
x.status.GetMessage(),
|
||||
)
|
||||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ServerInternal) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ServerInternal) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -32,23 +43,23 @@ func (x *ServerInternal) fromStatusV2(st *status.Status) {
|
|||
// - code: INTERNAL;
|
||||
// - string message: empty;
|
||||
// - details: empty.
|
||||
func (x ServerInternal) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(status.Internal, status.GlobalizeCommonFail))
|
||||
return &x.v2
|
||||
func (x ServerInternal) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(status.Internal, status.GlobalizeCommonFail)))
|
||||
return x.status
|
||||
}
|
||||
|
||||
// SetMessage sets message describing internal error.
|
||||
//
|
||||
// Message should be used for debug purposes only.
|
||||
func (x *ServerInternal) SetMessage(msg string) {
|
||||
x.v2.SetMessage(msg)
|
||||
x.status.SetMessage(msg)
|
||||
}
|
||||
|
||||
// Message returns message describing internal server error.
|
||||
//
|
||||
// Message should be used for debug purposes only. By default, it is empty.
|
||||
func (x ServerInternal) Message() string {
|
||||
return x.v2.Message()
|
||||
return x.status.GetMessage()
|
||||
}
|
||||
|
||||
// WriteInternalServerErr writes err message to ServerInternal instance.
|
||||
|
@ -59,19 +70,28 @@ func WriteInternalServerErr(x *ServerInternal, err error) {
|
|||
// WrongMagicNumber describes failure status related to incorrect network magic.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type WrongMagicNumber struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewWrongMagicNumber() WrongMagicNumber {
|
||||
return WrongMagicNumber{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
func (x WrongMagicNumber) Error() string {
|
||||
return errMessageStatusV2(
|
||||
globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail),
|
||||
x.v2.Message(),
|
||||
x.status.GetMessage(),
|
||||
)
|
||||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *WrongMagicNumber) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x WrongMagicNumber) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -80,9 +100,9 @@ func (x *WrongMagicNumber) fromStatusV2(st *status.Status) {
|
|||
// - code: WRONG_MAGIC_NUMBER;
|
||||
// - string message: empty;
|
||||
// - details: empty.
|
||||
func (x WrongMagicNumber) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail))
|
||||
return &x.v2
|
||||
func (x WrongMagicNumber) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail)))
|
||||
return x.status
|
||||
}
|
||||
|
||||
// WriteCorrectMagic writes correct network magic.
|
||||
|
@ -93,13 +113,13 @@ func (x *WrongMagicNumber) WriteCorrectMagic(magic uint64) {
|
|||
binary.BigEndian.PutUint64(buf, magic)
|
||||
|
||||
// create corresponding detail
|
||||
var d status.Detail
|
||||
var d statusgrpc.Status_Detail
|
||||
|
||||
d.SetID(status.DetailIDCorrectMagic)
|
||||
d.SetId(statusgrpc.DetailIDCorrectMagic)
|
||||
d.SetValue(buf)
|
||||
|
||||
// attach the detail
|
||||
x.v2.AppendDetails(d)
|
||||
x.status.AppendDetails(&d)
|
||||
}
|
||||
|
||||
// CorrectMagic returns network magic returned by the server.
|
||||
|
@ -108,9 +128,9 @@ func (x *WrongMagicNumber) WriteCorrectMagic(magic uint64) {
|
|||
// - 0 if number is not presented
|
||||
// - +1 otherwise
|
||||
func (x WrongMagicNumber) CorrectMagic() (magic uint64, ok int8) {
|
||||
x.v2.IterateDetails(func(d *status.Detail) bool {
|
||||
if d.ID() == status.DetailIDCorrectMagic {
|
||||
if val := d.Value(); len(val) == 8 {
|
||||
x.status.IterateDetails(func(d *statusgrpc.Status_Detail) bool {
|
||||
if d.GetId() == statusgrpc.DetailIDCorrectMagic {
|
||||
if val := d.GetValue(); len(val) == 8 {
|
||||
magic = binary.BigEndian.Uint64(val)
|
||||
ok = 1
|
||||
} else {
|
||||
|
@ -127,13 +147,19 @@ func (x WrongMagicNumber) CorrectMagic() (magic uint64, ok int8) {
|
|||
// SignatureVerification describes failure status related to signature verification.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type SignatureVerification struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewSignatureVerification() SignatureVerification {
|
||||
return SignatureVerification{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultSignatureVerificationMsg = "signature verification failed"
|
||||
|
||||
func (x SignatureVerification) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultSignatureVerificationMsg
|
||||
}
|
||||
|
@ -145,8 +171,11 @@ func (x SignatureVerification) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *SignatureVerification) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x SignatureVerification) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -156,14 +185,14 @@ func (x *SignatureVerification) fromStatusV2(st *status.Status) {
|
|||
// - string message: written message via SetMessage or
|
||||
// "signature verification failed" as a default message;
|
||||
// - details: empty.
|
||||
func (x SignatureVerification) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(status.SignatureVerificationFail, status.GlobalizeCommonFail))
|
||||
func (x SignatureVerification) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(status.SignatureVerificationFail, status.GlobalizeCommonFail)))
|
||||
|
||||
if x.v2.Message() == "" {
|
||||
x.v2.SetMessage(defaultSignatureVerificationMsg)
|
||||
if x.status.GetMessage() == "" {
|
||||
x.status.SetMessage(defaultSignatureVerificationMsg)
|
||||
}
|
||||
|
||||
return &x.v2
|
||||
return x.status
|
||||
}
|
||||
|
||||
// SetMessage writes signature verification failure message.
|
||||
|
@ -171,7 +200,7 @@ func (x SignatureVerification) ToStatusV2() *status.Status {
|
|||
//
|
||||
// See also Message.
|
||||
func (x *SignatureVerification) SetMessage(v string) {
|
||||
x.v2.SetMessage(v)
|
||||
x.status.SetMessage(v)
|
||||
}
|
||||
|
||||
// Message returns status message. Zero status returns empty message.
|
||||
|
@ -179,13 +208,19 @@ func (x *SignatureVerification) SetMessage(v string) {
|
|||
//
|
||||
// See also SetMessage.
|
||||
func (x SignatureVerification) Message() string {
|
||||
return x.v2.Message()
|
||||
return x.status.GetMessage()
|
||||
}
|
||||
|
||||
// NodeUnderMaintenance describes failure status for nodes being under maintenance.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type NodeUnderMaintenance struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewNodeUnderMaintenance() NodeUnderMaintenance {
|
||||
return NodeUnderMaintenance{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultNodeUnderMaintenanceMsg = "node is under maintenance"
|
||||
|
@ -203,8 +238,11 @@ func (x NodeUnderMaintenance) Error() string {
|
|||
)
|
||||
}
|
||||
|
||||
func (x *NodeUnderMaintenance) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x NodeUnderMaintenance) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -214,13 +252,13 @@ func (x *NodeUnderMaintenance) fromStatusV2(st *status.Status) {
|
|||
// - string message: written message via SetMessage or
|
||||
// "node is under maintenance" as a default message;
|
||||
// - details: empty.
|
||||
func (x NodeUnderMaintenance) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(status.NodeUnderMaintenance, status.GlobalizeCommonFail))
|
||||
if x.v2.Message() == "" {
|
||||
x.v2.SetMessage(defaultNodeUnderMaintenanceMsg)
|
||||
func (x NodeUnderMaintenance) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(status.NodeUnderMaintenance, status.GlobalizeCommonFail)))
|
||||
if x.status.GetMessage() == "" {
|
||||
x.status.SetMessage(defaultNodeUnderMaintenanceMsg)
|
||||
}
|
||||
|
||||
return &x.v2
|
||||
return x.status
|
||||
}
|
||||
|
||||
// SetMessage writes signature verification failure message.
|
||||
|
@ -228,7 +266,7 @@ func (x NodeUnderMaintenance) ToStatusV2() *status.Status {
|
|||
//
|
||||
// See also Message.
|
||||
func (x *NodeUnderMaintenance) SetMessage(v string) {
|
||||
x.v2.SetMessage(v)
|
||||
x.status.SetMessage(v)
|
||||
}
|
||||
|
||||
// Message returns status message. Zero status returns empty message.
|
||||
|
@ -236,5 +274,5 @@ func (x *NodeUnderMaintenance) SetMessage(v string) {
|
|||
//
|
||||
// See also SetMessage.
|
||||
func (x NodeUnderMaintenance) Message() string {
|
||||
return x.v2.Message()
|
||||
return x.status.GetMessage()
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package apistatus_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -11,17 +11,17 @@ import (
|
|||
func TestServerInternal_Message(t *testing.T) {
|
||||
const msg = "some message"
|
||||
|
||||
var st apistatus.ServerInternal
|
||||
st := apistatus.NewServerInternal()
|
||||
|
||||
res := st.Message()
|
||||
resv2 := apistatus.ToStatusV2(st).Message()
|
||||
resv2 := apistatus.ToStatusV2(st).GetMessage()
|
||||
require.Empty(t, res)
|
||||
require.Empty(t, resv2)
|
||||
|
||||
st.SetMessage(msg)
|
||||
|
||||
res = st.Message()
|
||||
resv2 = apistatus.ToStatusV2(st).Message()
|
||||
resv2 = apistatus.ToStatusV2(st).GetMessage()
|
||||
require.Equal(t, msg, res)
|
||||
require.Equal(t, msg, resv2)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func TestServerInternal_Message(t *testing.T) {
|
|||
func TestWrongMagicNumber_CorrectMagic(t *testing.T) {
|
||||
const magic = 1337
|
||||
|
||||
var st apistatus.WrongMagicNumber
|
||||
st := apistatus.NewWrongMagicNumber()
|
||||
|
||||
res, ok := st.CorrectMagic()
|
||||
require.Zero(t, res)
|
||||
|
@ -42,7 +42,7 @@ func TestWrongMagicNumber_CorrectMagic(t *testing.T) {
|
|||
require.EqualValues(t, 1, ok)
|
||||
|
||||
// corrupt the value
|
||||
apistatus.ToStatusV2(st).IterateDetails(func(d *status.Detail) bool {
|
||||
apistatus.ToStatusV2(st).IterateDetails(func(d *statusgrpc.Status_Detail) bool {
|
||||
d.SetValue([]byte{1, 2, 3}) // any slice with len != 8
|
||||
return true
|
||||
})
|
||||
|
@ -53,13 +53,13 @@ func TestWrongMagicNumber_CorrectMagic(t *testing.T) {
|
|||
|
||||
func TestSignatureVerification(t *testing.T) {
|
||||
t.Run("default", func(t *testing.T) {
|
||||
var st apistatus.SignatureVerification
|
||||
st := apistatus.NewSignatureVerification()
|
||||
|
||||
require.Empty(t, st.Message())
|
||||
})
|
||||
|
||||
t.Run("custom message", func(t *testing.T) {
|
||||
var st apistatus.SignatureVerification
|
||||
st := apistatus.NewSignatureVerification()
|
||||
msg := "some message"
|
||||
|
||||
st.SetMessage(msg)
|
||||
|
@ -67,38 +67,38 @@ func TestSignatureVerification(t *testing.T) {
|
|||
stV2 := st.ToStatusV2()
|
||||
|
||||
require.Equal(t, msg, st.Message())
|
||||
require.Equal(t, msg, stV2.Message())
|
||||
require.Equal(t, msg, stV2.GetMessage())
|
||||
})
|
||||
|
||||
t.Run("empty to V2", func(t *testing.T) {
|
||||
var st apistatus.SignatureVerification
|
||||
st := apistatus.NewSignatureVerification()
|
||||
|
||||
stV2 := st.ToStatusV2()
|
||||
|
||||
require.Equal(t, "signature verification failed", stV2.Message())
|
||||
require.Equal(t, "signature verification failed", stV2.GetMessage())
|
||||
})
|
||||
|
||||
t.Run("non-empty to V2", func(t *testing.T) {
|
||||
var st apistatus.SignatureVerification
|
||||
st := apistatus.NewSignatureVerification()
|
||||
msg := "some other msg"
|
||||
|
||||
st.SetMessage(msg)
|
||||
|
||||
stV2 := st.ToStatusV2()
|
||||
|
||||
require.Equal(t, msg, stV2.Message())
|
||||
require.Equal(t, msg, stV2.GetMessage())
|
||||
})
|
||||
}
|
||||
|
||||
func TestNodeUnderMaintenance(t *testing.T) {
|
||||
t.Run("default", func(t *testing.T) {
|
||||
var st apistatus.NodeUnderMaintenance
|
||||
st := apistatus.NewNodeUnderMaintenance()
|
||||
|
||||
require.Empty(t, st.Message())
|
||||
})
|
||||
|
||||
t.Run("custom message", func(t *testing.T) {
|
||||
var st apistatus.NodeUnderMaintenance
|
||||
st := apistatus.NewNodeUnderMaintenance()
|
||||
msg := "some message"
|
||||
|
||||
st.SetMessage(msg)
|
||||
|
@ -106,25 +106,25 @@ func TestNodeUnderMaintenance(t *testing.T) {
|
|||
stV2 := st.ToStatusV2()
|
||||
|
||||
require.Equal(t, msg, st.Message())
|
||||
require.Equal(t, msg, stV2.Message())
|
||||
require.Equal(t, msg, stV2.GetMessage())
|
||||
})
|
||||
|
||||
t.Run("empty to V2", func(t *testing.T) {
|
||||
var st apistatus.NodeUnderMaintenance
|
||||
st := apistatus.NewNodeUnderMaintenance()
|
||||
|
||||
stV2 := st.ToStatusV2()
|
||||
|
||||
require.Empty(t, "", stV2.Message())
|
||||
require.Empty(t, "", stV2.GetMessage())
|
||||
})
|
||||
|
||||
t.Run("non-empty to V2", func(t *testing.T) {
|
||||
var st apistatus.NodeUnderMaintenance
|
||||
st := apistatus.NewNodeUnderMaintenance()
|
||||
msg := "some other msg"
|
||||
|
||||
st.SetMessage(msg)
|
||||
|
||||
stV2 := st.ToStatusV2()
|
||||
|
||||
require.Equal(t, msg, stV2.Message())
|
||||
require.Equal(t, msg, stV2.GetMessage())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,19 +2,27 @@ package apistatus
|
|||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
status "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// ContainerNotFound describes status of the failure because of the missing container.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type ContainerNotFound struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewContainerNotFound() ContainerNotFound {
|
||||
return ContainerNotFound{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultContainerNotFoundMsg = "container not found"
|
||||
|
||||
func (x ContainerNotFound) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultContainerNotFoundMsg
|
||||
}
|
||||
|
@ -26,8 +34,11 @@ func (x ContainerNotFound) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ContainerNotFound) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ContainerNotFound) fromStatusV2(st *status.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -37,22 +48,28 @@ func (x *ContainerNotFound) fromStatusV2(st *status.Status) {
|
|||
// - string message: "container not found";
|
||||
// - details: empty.
|
||||
func (x ContainerNotFound) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(container.StatusNotFound, container.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultContainerNotFoundMsg)
|
||||
return &x.v2
|
||||
x.status.SetCode(uint32(globalizeCodeV2(container.StatusNotFound, container.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultContainerNotFoundMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// EACLNotFound describes status of the failure because of the missing eACL
|
||||
// table.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type EACLNotFound struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewEACLNotFound() EACLNotFound {
|
||||
return EACLNotFound{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultEACLNotFoundMsg = "eACL not found"
|
||||
|
||||
func (x EACLNotFound) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultEACLNotFoundMsg
|
||||
}
|
||||
|
@ -64,8 +81,11 @@ func (x EACLNotFound) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *EACLNotFound) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x EACLNotFound) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -74,8 +94,8 @@ func (x *EACLNotFound) fromStatusV2(st *status.Status) {
|
|||
// - code: EACL_NOT_FOUND;
|
||||
// - string message: "eACL not found";
|
||||
// - details: empty.
|
||||
func (x EACLNotFound) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(container.StatusEACLNotFound, container.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultEACLNotFoundMsg)
|
||||
return &x.v2
|
||||
func (x EACLNotFound) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(container.StatusEACLNotFound, container.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultEACLNotFoundMsg)
|
||||
return x.status
|
||||
}
|
||||
|
|
|
@ -2,19 +2,26 @@ package apistatus
|
|||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// ObjectLocked describes status of the failure because of the locked object.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type ObjectLocked struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewObjectLocked() ObjectLocked {
|
||||
return ObjectLocked{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultObjectLockedMsg = "object is locked"
|
||||
|
||||
func (x ObjectLocked) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultObjectLockedMsg
|
||||
}
|
||||
|
@ -26,8 +33,11 @@ func (x ObjectLocked) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ObjectLocked) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ObjectLocked) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -36,22 +46,28 @@ func (x *ObjectLocked) fromStatusV2(st *status.Status) {
|
|||
// - code: LOCKED;
|
||||
// - string message: "object is locked";
|
||||
// - details: empty.
|
||||
func (x ObjectLocked) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(object.StatusLocked, object.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultObjectLockedMsg)
|
||||
return &x.v2
|
||||
func (x ObjectLocked) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(object.StatusLocked, object.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultObjectLockedMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// LockNonRegularObject describes status returned on locking the non-regular object.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type LockNonRegularObject struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewLockNonRegularObject() LockNonRegularObject {
|
||||
return LockNonRegularObject{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultLockNonRegularObjectMsg = "locking non-regular object is forbidden"
|
||||
|
||||
func (x LockNonRegularObject) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultLockNonRegularObjectMsg
|
||||
}
|
||||
|
@ -63,8 +79,11 @@ func (x LockNonRegularObject) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *LockNonRegularObject) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x LockNonRegularObject) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -73,22 +92,28 @@ func (x *LockNonRegularObject) fromStatusV2(st *status.Status) {
|
|||
// - code: LOCK_NON_REGULAR_OBJECT;
|
||||
// - string message: "locking non-regular object is forbidden";
|
||||
// - details: empty.
|
||||
func (x LockNonRegularObject) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(object.StatusLockNonRegularObject, object.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultLockNonRegularObjectMsg)
|
||||
return &x.v2
|
||||
func (x LockNonRegularObject) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(object.StatusLockNonRegularObject, object.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultLockNonRegularObjectMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// ObjectAccessDenied describes status of the failure because of the access control violation.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type ObjectAccessDenied struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewObjectAccessDenied() ObjectAccessDenied {
|
||||
return ObjectAccessDenied{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultObjectAccessDeniedMsg = "access to object operation denied"
|
||||
|
||||
func (x ObjectAccessDenied) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultObjectAccessDeniedMsg
|
||||
}
|
||||
|
@ -100,8 +125,11 @@ func (x ObjectAccessDenied) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ObjectAccessDenied) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ObjectAccessDenied) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -110,33 +138,39 @@ func (x *ObjectAccessDenied) fromStatusV2(st *status.Status) {
|
|||
// - code: ACCESS_DENIED;
|
||||
// - string message: "access to object operation denied";
|
||||
// - details: empty.
|
||||
func (x ObjectAccessDenied) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(object.StatusAccessDenied, object.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultObjectAccessDeniedMsg)
|
||||
return &x.v2
|
||||
func (x ObjectAccessDenied) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(object.StatusAccessDenied, object.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultObjectAccessDeniedMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// WriteReason writes human-readable access rejection reason.
|
||||
func (x *ObjectAccessDenied) WriteReason(reason string) {
|
||||
object.WriteAccessDeniedDesc(&x.v2, reason)
|
||||
object.WriteAccessDeniedDesc(x.status, reason)
|
||||
}
|
||||
|
||||
// Reason returns human-readable access rejection reason returned by the server.
|
||||
// Returns empty value is reason is not presented.
|
||||
func (x ObjectAccessDenied) Reason() string {
|
||||
return object.ReadAccessDeniedDesc(x.v2)
|
||||
return object.ReadAccessDeniedDesc(x.status)
|
||||
}
|
||||
|
||||
// ObjectNotFound describes status of the failure because of the missing object.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type ObjectNotFound struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewObjectNotFound() ObjectNotFound {
|
||||
return ObjectNotFound{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultObjectNotFoundMsg = "object not found"
|
||||
|
||||
func (x ObjectNotFound) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultObjectNotFoundMsg
|
||||
}
|
||||
|
@ -148,8 +182,11 @@ func (x ObjectNotFound) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ObjectNotFound) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ObjectNotFound) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -158,22 +195,28 @@ func (x *ObjectNotFound) fromStatusV2(st *status.Status) {
|
|||
// - code: OBJECT_NOT_FOUND;
|
||||
// - string message: "object not found";
|
||||
// - details: empty.
|
||||
func (x ObjectNotFound) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(object.StatusNotFound, object.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultObjectNotFoundMsg)
|
||||
return &x.v2
|
||||
func (x ObjectNotFound) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(object.StatusNotFound, object.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultObjectNotFoundMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// ObjectAlreadyRemoved describes status of the failure because object has been
|
||||
// already removed. Instances provide Status and StatusV2 interfaces.
|
||||
type ObjectAlreadyRemoved struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewObjectAlreadyRemoved() ObjectAlreadyRemoved {
|
||||
return ObjectAlreadyRemoved{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultObjectAlreadyRemovedMsg = "object already removed"
|
||||
|
||||
func (x ObjectAlreadyRemoved) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultObjectAlreadyRemovedMsg
|
||||
}
|
||||
|
@ -185,8 +228,11 @@ func (x ObjectAlreadyRemoved) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ObjectAlreadyRemoved) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ObjectAlreadyRemoved) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -195,23 +241,29 @@ func (x *ObjectAlreadyRemoved) fromStatusV2(st *status.Status) {
|
|||
// - code: OBJECT_ALREADY_REMOVED;
|
||||
// - string message: "object already removed";
|
||||
// - details: empty.
|
||||
func (x ObjectAlreadyRemoved) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(object.StatusAlreadyRemoved, object.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultObjectAlreadyRemovedMsg)
|
||||
return &x.v2
|
||||
func (x ObjectAlreadyRemoved) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(object.StatusAlreadyRemoved, object.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultObjectAlreadyRemovedMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// ObjectOutOfRange describes status of the failure because of the incorrect
|
||||
// provided object ranges.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type ObjectOutOfRange struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewObjectOutOfRange() ObjectOutOfRange {
|
||||
return ObjectOutOfRange{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultObjectOutOfRangeMsg = "out of range"
|
||||
|
||||
func (x ObjectOutOfRange) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultObjectOutOfRangeMsg
|
||||
}
|
||||
|
@ -223,8 +275,11 @@ func (x ObjectOutOfRange) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *ObjectOutOfRange) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x ObjectOutOfRange) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -233,8 +288,8 @@ func (x *ObjectOutOfRange) fromStatusV2(st *status.Status) {
|
|||
// - code: OUT_OF_RANGE;
|
||||
// - string message: "out of range";
|
||||
// - details: empty.
|
||||
func (x ObjectOutOfRange) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(object.StatusOutOfRange, object.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultObjectOutOfRangeMsg)
|
||||
return &x.v2
|
||||
func (x ObjectOutOfRange) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(object.StatusOutOfRange, object.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultObjectOutOfRangeMsg)
|
||||
return x.status
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
func TestObjectAccessDenied_WriteReason(t *testing.T) {
|
||||
const reason = "any reason"
|
||||
|
||||
var st apistatus.ObjectAccessDenied
|
||||
st := apistatus.NewObjectAccessDenied()
|
||||
|
||||
res := st.Reason()
|
||||
require.Empty(t, res)
|
||||
|
|
|
@ -2,19 +2,26 @@ package apistatus
|
|||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// SessionTokenNotFound describes status of the failure because of the missing session token.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type SessionTokenNotFound struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewSessionTokenNotFound() SessionTokenNotFound {
|
||||
return SessionTokenNotFound{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultSessionTokenNotFoundMsg = "session token not found"
|
||||
|
||||
func (x SessionTokenNotFound) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultSessionTokenNotFoundMsg
|
||||
}
|
||||
|
@ -26,8 +33,11 @@ func (x SessionTokenNotFound) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *SessionTokenNotFound) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x SessionTokenNotFound) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -36,22 +46,29 @@ func (x *SessionTokenNotFound) fromStatusV2(st *status.Status) {
|
|||
// - code: TOKEN_NOT_FOUND;
|
||||
// - string message: "session token not found";
|
||||
// - details: empty.
|
||||
func (x SessionTokenNotFound) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(session.StatusTokenNotFound, session.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultSessionTokenNotFoundMsg)
|
||||
return &x.v2
|
||||
func (x SessionTokenNotFound) ToStatusV2() *statusgrpc.Status {
|
||||
x = NewSessionTokenNotFound()
|
||||
x.status.SetCode(uint32(globalizeCodeV2(session.StatusTokenNotFound, session.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultSessionTokenNotFoundMsg)
|
||||
return x.status
|
||||
}
|
||||
|
||||
// SessionTokenExpired describes status of the failure because of the expired session token.
|
||||
// Instances provide Status and StatusV2 interfaces.
|
||||
type SessionTokenExpired struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewSessionTokenExpired() SessionTokenExpired {
|
||||
return SessionTokenExpired{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
const defaultSessionTokenExpiredMsg = "expired session token"
|
||||
|
||||
func (x SessionTokenExpired) Error() string {
|
||||
msg := x.v2.Message()
|
||||
msg := x.status.GetMessage()
|
||||
if msg == "" {
|
||||
msg = defaultSessionTokenExpiredMsg
|
||||
}
|
||||
|
@ -63,8 +80,11 @@ func (x SessionTokenExpired) Error() string {
|
|||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *SessionTokenExpired) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x SessionTokenExpired) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -73,8 +93,8 @@ func (x *SessionTokenExpired) fromStatusV2(st *status.Status) {
|
|||
// - code: TOKEN_EXPIRED;
|
||||
// - string message: "expired session token";
|
||||
// - details: empty.
|
||||
func (x SessionTokenExpired) ToStatusV2() *status.Status {
|
||||
x.v2.SetCode(globalizeCodeV2(session.StatusTokenExpired, session.GlobalizeFail))
|
||||
x.v2.SetMessage(defaultSessionTokenExpiredMsg)
|
||||
return &x.v2
|
||||
func (x SessionTokenExpired) ToStatusV2() *statusgrpc.Status {
|
||||
x.status.SetCode(uint32(globalizeCodeV2(session.StatusTokenExpired, session.GlobalizeFail)))
|
||||
x.status.SetMessage(defaultSessionTokenExpiredMsg)
|
||||
return x.status
|
||||
}
|
||||
|
|
|
@ -2,19 +2,32 @@ package apistatus
|
|||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// SuccessDefaultV2 represents Status instance of default success. Implements StatusV2.
|
||||
type SuccessDefaultV2 struct {
|
||||
isNil bool
|
||||
|
||||
v2 *status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func NewSuccessDefaultV2() SuccessDefaultV2 {
|
||||
return SuccessDefaultV2{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *SuccessDefaultV2) fromStatusV2(st *status.Status) {
|
||||
x.isNil = st == nil
|
||||
x.v2 = st
|
||||
func (x SuccessDefaultV2) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
if x.isNil = st == nil; x.isNil {
|
||||
return
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
||||
// ToStatusV2 implements StatusV2 interface method.
|
||||
|
@ -23,9 +36,9 @@ func (x *SuccessDefaultV2) fromStatusV2(st *status.Status) {
|
|||
// - code: OK;
|
||||
// - string message: empty;
|
||||
// - details: empty.
|
||||
func (x SuccessDefaultV2) ToStatusV2() *status.Status {
|
||||
if x.isNil || x.v2 != nil {
|
||||
return x.v2
|
||||
func (x SuccessDefaultV2) ToStatusV2() *statusgrpc.Status {
|
||||
if x.isNil || x.status != nil {
|
||||
return x.status
|
||||
}
|
||||
|
||||
return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess)
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
package apistatus
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type unrecognizedStatusV2 struct {
|
||||
v2 status.Status
|
||||
status *statusgrpc.Status
|
||||
}
|
||||
|
||||
func newUnrecognizedStatusV2() unrecognizedStatusV2 {
|
||||
return unrecognizedStatusV2{
|
||||
status: new(statusgrpc.Status),
|
||||
}
|
||||
}
|
||||
|
||||
func (x unrecognizedStatusV2) Error() string {
|
||||
return errMessageStatusV2("unrecognized", x.v2.Message())
|
||||
return errMessageStatusV2("unrecognized", x.status.GetMessage())
|
||||
}
|
||||
|
||||
// implements local interface defined in FromStatusV2 func.
|
||||
func (x *unrecognizedStatusV2) fromStatusV2(st *status.Status) {
|
||||
x.v2 = *st
|
||||
func (x unrecognizedStatusV2) fromStatusV2(st *statusgrpc.Status) {
|
||||
if x.status == nil {
|
||||
x.status = new(statusgrpc.Status)
|
||||
}
|
||||
proto.Merge(x.status, st)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
status "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
||||
statusgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc"
|
||||
)
|
||||
|
||||
// StatusV2 defines a variety of Status instances compatible with FrostFS API V2 protocol.
|
||||
|
@ -16,7 +17,7 @@ type StatusV2 interface {
|
|||
Status
|
||||
|
||||
// ToStatusV2 returns the status as git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status.Status message structure.
|
||||
ToStatusV2() *status.Status
|
||||
ToStatusV2() *statusgrpc.Status
|
||||
}
|
||||
|
||||
// FromStatusV2 converts status.Status message structure to Status instance. Inverse to ToStatusV2 operation.
|
||||
|
@ -38,64 +39,64 @@ type StatusV2 interface {
|
|||
// - object.StatusLocked: *ObjectLocked;
|
||||
// - object.StatusLockNonRegularObject: *LockNonRegularObject.
|
||||
// - object.StatusAccessDenied: *ObjectAccessDenied.
|
||||
func FromStatusV2(st *status.Status) Status {
|
||||
func FromStatusV2(st *statusgrpc.Status) Status {
|
||||
var decoder interface {
|
||||
fromStatusV2(*status.Status)
|
||||
fromStatusV2(*statusgrpc.Status)
|
||||
}
|
||||
|
||||
switch code := st.Code(); {
|
||||
switch code := status.Code(st.GetCode()); {
|
||||
case status.IsSuccess(code):
|
||||
//nolint:exhaustive
|
||||
switch status.LocalizeSuccess(&code); code {
|
||||
case status.OK:
|
||||
decoder = new(SuccessDefaultV2)
|
||||
decoder = NewSuccessDefaultV2()
|
||||
}
|
||||
case status.IsCommonFail(code):
|
||||
switch status.LocalizeCommonFail(&code); code {
|
||||
case status.Internal:
|
||||
decoder = new(ServerInternal)
|
||||
decoder = NewServerInternal()
|
||||
case status.WrongMagicNumber:
|
||||
decoder = new(WrongMagicNumber)
|
||||
decoder = NewWrongMagicNumber()
|
||||
case status.SignatureVerificationFail:
|
||||
decoder = new(SignatureVerification)
|
||||
decoder = NewSignatureVerification()
|
||||
case status.NodeUnderMaintenance:
|
||||
decoder = new(NodeUnderMaintenance)
|
||||
decoder = NewNodeUnderMaintenance()
|
||||
}
|
||||
case object.LocalizeFailStatus(&code):
|
||||
switch code {
|
||||
case object.StatusLocked:
|
||||
decoder = new(ObjectLocked)
|
||||
decoder = NewObjectLocked()
|
||||
case object.StatusLockNonRegularObject:
|
||||
decoder = new(LockNonRegularObject)
|
||||
decoder = NewLockNonRegularObject()
|
||||
case object.StatusAccessDenied:
|
||||
decoder = new(ObjectAccessDenied)
|
||||
decoder = NewObjectAccessDenied()
|
||||
case object.StatusNotFound:
|
||||
decoder = new(ObjectNotFound)
|
||||
decoder = NewObjectNotFound()
|
||||
case object.StatusAlreadyRemoved:
|
||||
decoder = new(ObjectAlreadyRemoved)
|
||||
decoder = NewObjectAlreadyRemoved()
|
||||
case object.StatusOutOfRange:
|
||||
decoder = new(ObjectOutOfRange)
|
||||
decoder = NewObjectOutOfRange()
|
||||
}
|
||||
case container.LocalizeFailStatus(&code):
|
||||
//nolint:exhaustive
|
||||
switch code {
|
||||
case container.StatusNotFound:
|
||||
decoder = new(ContainerNotFound)
|
||||
decoder = NewContainerNotFound()
|
||||
case container.StatusEACLNotFound:
|
||||
decoder = new(EACLNotFound)
|
||||
decoder = NewEACLNotFound()
|
||||
}
|
||||
case session.LocalizeFailStatus(&code):
|
||||
//nolint:exhaustive
|
||||
switch code {
|
||||
case session.StatusTokenNotFound:
|
||||
decoder = new(SessionTokenNotFound)
|
||||
decoder = NewSessionTokenNotFound()
|
||||
case session.StatusTokenExpired:
|
||||
decoder = new(SessionTokenExpired)
|
||||
decoder = NewSessionTokenExpired()
|
||||
}
|
||||
}
|
||||
|
||||
if decoder == nil {
|
||||
decoder = new(unrecognizedStatusV2)
|
||||
decoder = newUnrecognizedStatusV2()
|
||||
}
|
||||
|
||||
decoder.fromStatusV2(st)
|
||||
|
@ -108,7 +109,7 @@ func FromStatusV2(st *status.Status) Status {
|
|||
// If argument is the StatusV2 instance, it is converted directly.
|
||||
// Otherwise, successes are converted with status.OK code w/o details and message,
|
||||
// failures - with status.Internal and error text message w/o details.
|
||||
func ToStatusV2(st Status) *status.Status {
|
||||
func ToStatusV2(st Status) *statusgrpc.Status {
|
||||
if v, ok := st.(StatusV2); ok {
|
||||
return v.ToStatusV2()
|
||||
}
|
||||
|
@ -136,10 +137,10 @@ func errMessageStatusV2(code any, msg string) string {
|
|||
return fmt.Sprintf(noMsgFmt, code)
|
||||
}
|
||||
|
||||
func newStatusV2WithLocalCode(code status.Code, globalizer func(*status.Code)) *status.Status {
|
||||
var st status.Status
|
||||
func newStatusV2WithLocalCode(code status.Code, globalizer func(*status.Code)) *statusgrpc.Status {
|
||||
var st statusgrpc.Status
|
||||
|
||||
st.SetCode(globalizeCodeV2(code, globalizer))
|
||||
st.SetCode(uint32(globalizeCodeV2(code, globalizer)))
|
||||
|
||||
return &st
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -13,7 +14,7 @@ func TestToStatusV2(t *testing.T) {
|
|||
|
||||
for _, testItem := range [...]struct {
|
||||
status any // Status or statusConstructor
|
||||
codeV2 uint64
|
||||
codeV2 uint32
|
||||
messageV2 string
|
||||
}{
|
||||
{
|
||||
|
@ -43,7 +44,7 @@ func TestToStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
var st apistatus.ServerInternal
|
||||
st := apistatus.NewServerInternal()
|
||||
|
||||
st.SetMessage("internal error message")
|
||||
|
||||
|
@ -53,7 +54,7 @@ func TestToStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
var st apistatus.WrongMagicNumber
|
||||
st := apistatus.NewWrongMagicNumber()
|
||||
|
||||
st.WriteCorrectMagic(322)
|
||||
|
||||
|
@ -63,19 +64,19 @@ func TestToStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectLocked)
|
||||
return apistatus.NewObjectLocked()
|
||||
}),
|
||||
codeV2: 2050,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.LockNonRegularObject)
|
||||
return apistatus.NewLockNonRegularObject()
|
||||
}),
|
||||
codeV2: 2051,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
var st apistatus.ObjectAccessDenied
|
||||
st := apistatus.NewObjectAccessDenied()
|
||||
|
||||
st.WriteReason("any reason")
|
||||
|
||||
|
@ -85,49 +86,49 @@ func TestToStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectNotFound)
|
||||
return apistatus.NewObjectNotFound()
|
||||
}),
|
||||
codeV2: 2049,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectAlreadyRemoved)
|
||||
return apistatus.NewObjectAlreadyRemoved()
|
||||
}),
|
||||
codeV2: 2052,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectOutOfRange)
|
||||
return apistatus.NewObjectOutOfRange()
|
||||
}),
|
||||
codeV2: 2053,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ContainerNotFound)
|
||||
return apistatus.NewContainerNotFound()
|
||||
}),
|
||||
codeV2: 3072,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.EACLNotFound)
|
||||
return apistatus.NewEACLNotFound()
|
||||
}),
|
||||
codeV2: 3073,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.SessionTokenNotFound)
|
||||
return apistatus.NewSessionTokenNotFound()
|
||||
}),
|
||||
codeV2: 4096,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.SessionTokenExpired)
|
||||
return apistatus.NewSessionTokenExpired()
|
||||
}),
|
||||
codeV2: 4097,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.NodeUnderMaintenance)
|
||||
return apistatus.NewNodeUnderMaintenance()
|
||||
}),
|
||||
codeV2: 1027,
|
||||
},
|
||||
|
@ -143,9 +144,9 @@ func TestToStatusV2(t *testing.T) {
|
|||
stv2 := apistatus.ToStatusV2(st)
|
||||
|
||||
// must generate the same status.Status message
|
||||
require.EqualValues(t, testItem.codeV2, stv2.Code())
|
||||
require.EqualValues(t, testItem.codeV2, stv2.GetCode())
|
||||
if len(testItem.messageV2) > 0 {
|
||||
require.Equal(t, testItem.messageV2, stv2.Message())
|
||||
require.Equal(t, testItem.messageV2, stv2.GetMessage())
|
||||
}
|
||||
|
||||
_, ok := st.(apistatus.StatusV2)
|
||||
|
@ -156,7 +157,7 @@ func TestToStatusV2(t *testing.T) {
|
|||
res := apistatus.ToStatusV2(restored)
|
||||
|
||||
// must generate the same status.Status message
|
||||
require.Equal(t, stv2, res)
|
||||
require.True(t, proto.Equal(stv2, res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +197,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
var st apistatus.ServerInternal
|
||||
st := apistatus.NewServerInternal()
|
||||
|
||||
st.SetMessage("internal error message")
|
||||
|
||||
|
@ -206,7 +207,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
var st apistatus.WrongMagicNumber
|
||||
st := apistatus.NewWrongMagicNumber()
|
||||
|
||||
st.WriteCorrectMagic(322)
|
||||
|
||||
|
@ -216,19 +217,19 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectLocked)
|
||||
return apistatus.NewObjectLocked()
|
||||
}),
|
||||
codeV2: 2050,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.LockNonRegularObject)
|
||||
return apistatus.NewLockNonRegularObject()
|
||||
}),
|
||||
codeV2: 2051,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
var st apistatus.ObjectAccessDenied
|
||||
st := apistatus.NewObjectAccessDenied()
|
||||
|
||||
st.WriteReason("any reason")
|
||||
|
||||
|
@ -238,49 +239,49 @@ func TestFromStatusV2(t *testing.T) {
|
|||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectNotFound)
|
||||
return apistatus.NewObjectNotFound()
|
||||
}),
|
||||
codeV2: 2049,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ObjectAlreadyRemoved)
|
||||
return apistatus.NewObjectAlreadyRemoved()
|
||||
}),
|
||||
codeV2: 2052,
|
||||
},
|
||||
{
|
||||
status: statusConstructor(func() apistatus.Status {
|
||||
return new(apistatus.ObjectOutOfRange)
|
||||
return apistatus.NewObjectOutOfRange()
|
||||
}),
|
||||
codeV2: 2053,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.ContainerNotFound)
|
||||
return apistatus.NewContainerNotFound()
|
||||
}),
|
||||
codeV2: 3072,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.EACLNotFound)
|
||||
return apistatus.NewEACLNotFound()
|
||||
}),
|
||||
codeV2: 3073,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.SessionTokenNotFound)
|
||||
return apistatus.NewSessionTokenNotFound()
|
||||
}),
|
||||
codeV2: 4096,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.SessionTokenExpired)
|
||||
return apistatus.NewSessionTokenExpired()
|
||||
}),
|
||||
codeV2: 4097,
|
||||
},
|
||||
{
|
||||
status: (statusConstructor)(func() apistatus.Status {
|
||||
return new(apistatus.NodeUnderMaintenance)
|
||||
return apistatus.NewNodeUnderMaintenance()
|
||||
}),
|
||||
codeV2: 1027,
|
||||
},
|
||||
|
@ -296,9 +297,9 @@ func TestFromStatusV2(t *testing.T) {
|
|||
stv2 := apistatus.ToStatusV2(st)
|
||||
|
||||
// must generate the same status.Status message
|
||||
require.EqualValues(t, testItem.codeV2, stv2.Code())
|
||||
require.EqualValues(t, testItem.codeV2, stv2.GetCode())
|
||||
if len(testItem.messageV2) > 0 {
|
||||
require.Equal(t, testItem.messageV2, stv2.Message())
|
||||
require.Equal(t, testItem.messageV2, stv2.GetMessage())
|
||||
}
|
||||
|
||||
_, ok := st.(apistatus.StatusV2)
|
||||
|
@ -309,7 +310,7 @@ func TestFromStatusV2(t *testing.T) {
|
|||
res := apistatus.ToStatusV2(restored)
|
||||
|
||||
// must generate the same status.Status message
|
||||
require.Equal(t, stv2, res)
|
||||
require.True(t, proto.Equal(stv2, res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
|
@ -19,10 +19,12 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/google/uuid"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Container represents descriptor of the FrostFS container. Container logically
|
||||
// Container represents descriptor of the FrostFS containergrpc. Container logically
|
||||
// stores FrostFS objects. Container is one of the basic and at the same time
|
||||
// necessary data storage units in the FrostFS. Container includes data about the
|
||||
// owner, rules for placing objects and other information necessary for the
|
||||
|
@ -37,10 +39,16 @@ import (
|
|||
// Instances for existing containers can be initialized using decoding methods
|
||||
// (e.g Unmarshal).
|
||||
//
|
||||
// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container.Container
|
||||
// Container is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/containergrpc.Container
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
type Container struct {
|
||||
v2 container.Container
|
||||
container *containergrpc.Container
|
||||
}
|
||||
|
||||
func NewContainer() Container {
|
||||
return Container{
|
||||
container: &containergrpc.Container{},
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -48,16 +56,16 @@ const (
|
|||
attributeTimestamp = "Timestamp"
|
||||
)
|
||||
|
||||
// reads Container from the container.Container message. If checkFieldPresence is set,
|
||||
// reads Container from the containergrpc.Container message. If checkFieldPresence is set,
|
||||
// returns an error on absence of any protocol-required field.
|
||||
func (x *Container) readFromV2(m container.Container, checkFieldPresence bool) error {
|
||||
func (x *Container) readFromV2(m *containergrpc.Container, checkFieldPresence bool) error {
|
||||
var err error
|
||||
|
||||
ownerV2 := m.GetOwnerID()
|
||||
ownerV2 := m.GetOwnerId()
|
||||
if ownerV2 != nil {
|
||||
var owner user.ID
|
||||
|
||||
err = owner.ReadFromV2(*ownerV2)
|
||||
err = owner.ReadFromV2(ownerV2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid owner: %w", err)
|
||||
}
|
||||
|
@ -88,7 +96,7 @@ func (x *Container) readFromV2(m container.Container, checkFieldPresence bool) e
|
|||
if policyV2 != nil {
|
||||
var policy netmap.PlacementPolicy
|
||||
|
||||
err = policy.ReadFromV2(*policyV2)
|
||||
err = policy.ReadFromV2(policyV2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid placement policy: %w", err)
|
||||
}
|
||||
|
@ -100,12 +108,15 @@ func (x *Container) readFromV2(m container.Container, checkFieldPresence bool) e
|
|||
return err
|
||||
}
|
||||
|
||||
x.v2 = m
|
||||
if x.container == nil {
|
||||
x.container = new(containergrpc.Container)
|
||||
}
|
||||
proto.Merge(x.container, m)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkAttributes(m container.Container) error {
|
||||
func checkAttributes(m *containergrpc.Container) error {
|
||||
attrs := m.GetAttributes()
|
||||
mAttr := make(map[string]struct{}, len(attrs))
|
||||
var key, val string
|
||||
|
@ -141,28 +152,29 @@ func checkAttributes(m container.Container) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ReadFromV2 reads Container from the container.Container message. Checks if the
|
||||
// ReadFromV2 reads Container from the containergrpc.Container message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (x *Container) ReadFromV2(m container.Container) error {
|
||||
func (x *Container) ReadFromV2(m *containergrpc.Container) error {
|
||||
return x.readFromV2(m, true)
|
||||
}
|
||||
|
||||
// WriteToV2 writes Container into the container.Container message.
|
||||
// WriteToV2 writes Container into the containergrpc.Container message.
|
||||
// The message MUST NOT be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x Container) WriteToV2(m *container.Container) {
|
||||
*m = x.v2
|
||||
func (x *Container) WriteToV2(m *containergrpc.Container) {
|
||||
m.Reset()
|
||||
proto.Merge(m, x.container)
|
||||
}
|
||||
|
||||
// Marshal encodes Container into a binary format of the FrostFS API protocol
|
||||
// (Protocol Buffers with direct field order).
|
||||
//
|
||||
// See also Unmarshal.
|
||||
func (x Container) Marshal() []byte {
|
||||
return x.v2.StableMarshal(nil)
|
||||
func (x *Container) Marshal() []byte {
|
||||
return x.container.StableMarshal(nil)
|
||||
}
|
||||
|
||||
// Unmarshal decodes FrostFS API protocol binary format into the Container
|
||||
|
@ -171,22 +183,26 @@ func (x Container) Marshal() []byte {
|
|||
//
|
||||
// See also Marshal.
|
||||
func (x *Container) Unmarshal(data []byte) error {
|
||||
var m container.Container
|
||||
var m containergrpc.Container
|
||||
|
||||
err := m.Unmarshal(data)
|
||||
err := proto.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return x.readFromV2(m, false)
|
||||
return x.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Container into a JSON format of the FrostFS API protocol
|
||||
// (Protocol Buffers JSON).
|
||||
//
|
||||
// See also UnmarshalJSON.
|
||||
func (x Container) MarshalJSON() ([]byte, error) {
|
||||
return x.v2.MarshalJSON()
|
||||
func (x *Container) MarshalJSON() ([]byte, error) {
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
x.container,
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes FrostFS API protocol JSON format into the Container
|
||||
|
@ -194,25 +210,28 @@ func (x Container) MarshalJSON() ([]byte, error) {
|
|||
//
|
||||
// See also MarshalJSON.
|
||||
func (x *Container) UnmarshalJSON(data []byte) error {
|
||||
return x.v2.UnmarshalJSON(data)
|
||||
return protojson.Unmarshal(data, x.container)
|
||||
}
|
||||
|
||||
// Init initializes all internal data of the Container required by FrostFS API
|
||||
// protocol. Init MUST be called when creating a new container. Init SHOULD NOT
|
||||
// protocol. Init MUST be called when creating a new containergrpc. Init SHOULD NOT
|
||||
// be called multiple times. Init SHOULD NOT be called if the Container instance
|
||||
// is used for decoding only.
|
||||
func (x *Container) Init() {
|
||||
if x.container == nil {
|
||||
x.container = new(containergrpc.Container)
|
||||
}
|
||||
|
||||
var ver refs.Version
|
||||
version.Current().WriteToV2(&ver)
|
||||
|
||||
x.v2.SetVersion(&ver)
|
||||
x.container.SetVersion(&ver)
|
||||
|
||||
nonce, err := uuid.New().MarshalBinary()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unexpected error from UUID.MarshalBinary: %v", err))
|
||||
}
|
||||
|
||||
x.v2.SetNonce(nonce)
|
||||
x.container.SetNonce(nonce)
|
||||
}
|
||||
|
||||
// SetOwner specifies the owner of the Container. Each Container has exactly
|
||||
|
@ -224,17 +243,17 @@ func (x *Container) SetOwner(owner user.ID) {
|
|||
var m refs.OwnerID
|
||||
owner.WriteToV2(&m)
|
||||
|
||||
x.v2.SetOwnerID(&m)
|
||||
x.container.SetOwnerId(&m)
|
||||
}
|
||||
|
||||
// Owner returns owner of the Container set using SetOwner.
|
||||
//
|
||||
// Zero Container has no owner which is incorrect according to FrostFS API
|
||||
// protocol.
|
||||
func (x Container) Owner() (res user.ID) {
|
||||
m := x.v2.GetOwnerID()
|
||||
func (x *Container) Owner() (res user.ID) {
|
||||
m := x.container.GetOwnerId()
|
||||
if m != nil {
|
||||
err := res.ReadFromV2(*m)
|
||||
err := res.ReadFromV2(m)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unexpected error from user.ID.ReadFromV2: %v", err))
|
||||
}
|
||||
|
@ -248,15 +267,15 @@ func (x Container) Owner() (res user.ID) {
|
|||
//
|
||||
// See also BasicACL.
|
||||
func (x *Container) SetBasicACL(basicACL acl.Basic) {
|
||||
x.v2.SetBasicACL(basicACL.Bits())
|
||||
x.container.SetBasicAcl(basicACL.Bits())
|
||||
}
|
||||
|
||||
// BasicACL returns basic ACL set using SetBasicACL.
|
||||
//
|
||||
// Zero Container has zero basic ACL which structurally correct but doesn't
|
||||
// make sense since it denies any access to any party.
|
||||
func (x Container) BasicACL() (res acl.Basic) {
|
||||
res.FromBits(x.v2.GetBasicACL())
|
||||
func (x *Container) BasicACL() (res acl.Basic) {
|
||||
res.FromBits(x.container.GetBasicAcl())
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -265,20 +284,19 @@ func (x Container) BasicACL() (res acl.Basic) {
|
|||
//
|
||||
// See also PlacementPolicy.
|
||||
func (x *Container) SetPlacementPolicy(policy netmap.PlacementPolicy) {
|
||||
var m v2netmap.PlacementPolicy
|
||||
var m netmapgrpc.PlacementPolicy
|
||||
policy.WriteToV2(&m)
|
||||
|
||||
x.v2.SetPlacementPolicy(&m)
|
||||
x.container.SetPlacementPolicy(&m)
|
||||
}
|
||||
|
||||
// PlacementPolicy returns placement policy set using SetPlacementPolicy.
|
||||
//
|
||||
// Zero Container has no placement policy which is incorrect according to
|
||||
// FrostFS API protocol.
|
||||
func (x Container) PlacementPolicy() (res netmap.PlacementPolicy) {
|
||||
m := x.v2.GetPlacementPolicy()
|
||||
func (x *Container) PlacementPolicy() (res netmap.PlacementPolicy) {
|
||||
m := x.container.GetPlacementPolicy()
|
||||
if m != nil {
|
||||
err := res.ReadFromV2(*m)
|
||||
err := res.ReadFromV2(m)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unexpected error from PlacementPolicy.ReadFromV2: %v", err))
|
||||
}
|
||||
|
@ -305,7 +323,7 @@ func (x *Container) SetAttribute(key, value string) {
|
|||
panic("empty attribute value")
|
||||
}
|
||||
|
||||
attrs := x.v2.GetAttributes()
|
||||
attrs := x.container.GetAttributes()
|
||||
ln := len(attrs)
|
||||
|
||||
for i := 0; i < ln; i++ {
|
||||
|
@ -315,11 +333,11 @@ func (x *Container) SetAttribute(key, value string) {
|
|||
}
|
||||
}
|
||||
|
||||
attrs = append(attrs, container.Attribute{})
|
||||
attrs = append(attrs, &containergrpc.Container_Attribute{})
|
||||
attrs[ln].SetKey(key)
|
||||
attrs[ln].SetValue(value)
|
||||
|
||||
x.v2.SetAttributes(attrs)
|
||||
x.container.SetAttributes(attrs)
|
||||
}
|
||||
|
||||
// Attribute reads value of the Container attribute by key. Empty result means
|
||||
|
@ -327,7 +345,7 @@ func (x *Container) SetAttribute(key, value string) {
|
|||
//
|
||||
// See also SetAttribute, IterateAttributes, IterateUserAttributes.
|
||||
func (x Container) Attribute(key string) string {
|
||||
attrs := x.v2.GetAttributes()
|
||||
attrs := x.container.GetAttributes()
|
||||
for i := range attrs {
|
||||
if attrs[i].GetKey() == key {
|
||||
return attrs[i].GetValue()
|
||||
|
@ -341,8 +359,8 @@ func (x Container) Attribute(key string) string {
|
|||
// into f. The handler MUST NOT be nil.
|
||||
//
|
||||
// See also SetAttribute, Attribute.
|
||||
func (x Container) IterateAttributes(f func(key, val string)) {
|
||||
attrs := x.v2.GetAttributes()
|
||||
func (x *Container) IterateAttributes(f func(key, val string)) {
|
||||
attrs := x.container.GetAttributes()
|
||||
for i := range attrs {
|
||||
f(attrs[i].GetKey(), attrs[i].GetValue())
|
||||
}
|
||||
|
@ -353,11 +371,11 @@ func (x Container) IterateAttributes(f func(key, val string)) {
|
|||
//
|
||||
// See also SetAttribute, Attribute.
|
||||
func (x Container) IterateUserAttributes(f func(key, val string)) {
|
||||
attrs := x.v2.GetAttributes()
|
||||
attrs := x.container.GetAttributes()
|
||||
for _, attr := range attrs {
|
||||
var key = attr.GetKey()
|
||||
if !strings.HasPrefix(key, container.SysAttributePrefix) &&
|
||||
!strings.HasPrefix(key, container.SysAttributePrefixNeoFS) {
|
||||
if !strings.HasPrefix(key, containergrpc.SysAttributePrefix) &&
|
||||
!strings.HasPrefix(key, containergrpc.SysAttributePrefixNeoFS) {
|
||||
f(key, attr.GetValue())
|
||||
}
|
||||
}
|
||||
|
@ -366,7 +384,7 @@ func (x Container) IterateUserAttributes(f func(key, val string)) {
|
|||
// SetName sets human-readable name of the Container. Name MUST NOT be empty.
|
||||
//
|
||||
// See also Name.
|
||||
func SetName(cnr *Container, name string) {
|
||||
func SetName(cnr Container, name string) {
|
||||
cnr.SetAttribute(attributeName, name)
|
||||
}
|
||||
|
||||
|
@ -380,7 +398,7 @@ func Name(cnr Container) string {
|
|||
// SetCreationTime writes container's creation time in Unix Timestamp format.
|
||||
//
|
||||
// See also CreatedAt.
|
||||
func SetCreationTime(cnr *Container, t time.Time) {
|
||||
func SetCreationTime(cnr Container, t time.Time) {
|
||||
cnr.SetAttribute(attributeTimestamp, strconv.FormatInt(t.Unix(), 10))
|
||||
}
|
||||
|
||||
|
@ -409,16 +427,19 @@ const attributeHomoHashEnabled = "true"
|
|||
// Container data.
|
||||
//
|
||||
// See also IsHomomorphicHashingDisabled.
|
||||
func DisableHomomorphicHashing(cnr *Container) {
|
||||
cnr.SetAttribute(container.SysAttributeHomomorphicHashing, attributeHomoHashEnabled)
|
||||
func DisableHomomorphicHashing(cnr Container) {
|
||||
cnr.SetAttribute(containergrpc.SysAttributeHomomorphicHashing, attributeHomoHashEnabled)
|
||||
}
|
||||
|
||||
// IsHomomorphicHashingDisabled checks if DisableHomomorphicHashing was called.
|
||||
//
|
||||
// Zero Container has enabled hashing.
|
||||
func IsHomomorphicHashingDisabled(cnr Container) bool {
|
||||
return cnr.Attribute(container.SysAttributeHomomorphicHashing) == attributeHomoHashEnabled ||
|
||||
cnr.Attribute(container.SysAttributeHomomorphicHashingNeoFS) == attributeHomoHashEnabled
|
||||
if cnr.container == nil {
|
||||
return false
|
||||
}
|
||||
return cnr.Attribute(containergrpc.SysAttributeHomomorphicHashing) == attributeHomoHashEnabled ||
|
||||
cnr.Attribute(containergrpc.SysAttributeHomomorphicHashingNeoFS) == attributeHomoHashEnabled
|
||||
}
|
||||
|
||||
// Domain represents information about container domain registered in the NNS
|
||||
|
@ -456,20 +477,20 @@ func (x Domain) Zone() string {
|
|||
}
|
||||
|
||||
// WriteDomain writes Domain into the Container. Name MUST NOT be empty.
|
||||
func WriteDomain(cnr *Container, domain Domain) {
|
||||
cnr.SetAttribute(container.SysAttributeName, domain.Name())
|
||||
cnr.SetAttribute(container.SysAttributeZone, domain.Zone())
|
||||
func WriteDomain(cnr Container, domain Domain) {
|
||||
cnr.SetAttribute(containergrpc.SysAttributeName, domain.Name())
|
||||
cnr.SetAttribute(containergrpc.SysAttributeZone, domain.Zone())
|
||||
}
|
||||
|
||||
// ReadDomain reads Domain from the Container. Returns value with empty name
|
||||
// if domain is not specified.
|
||||
func ReadDomain(cnr Container) (res Domain) {
|
||||
if name := cnr.Attribute(container.SysAttributeName); name != "" {
|
||||
if name := cnr.Attribute(containergrpc.SysAttributeName); name != "" {
|
||||
res.SetName(name)
|
||||
res.SetZone(cnr.Attribute(container.SysAttributeZone))
|
||||
} else if name = cnr.Attribute(container.SysAttributeNameNeoFS); name != "" {
|
||||
res.SetZone(cnr.Attribute(containergrpc.SysAttributeZone))
|
||||
} else if name = cnr.Attribute(containergrpc.SysAttributeNameNeoFS); name != "" {
|
||||
res.SetName(name)
|
||||
res.SetZone(cnr.Attribute(container.SysAttributeZoneNeoFS))
|
||||
res.SetZone(cnr.Attribute(containergrpc.SysAttributeZoneNeoFS))
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -488,7 +509,7 @@ func CalculateSignature(dst *frostfscrypto.Signature, cnr Container, signer ecds
|
|||
|
||||
// VerifySignature verifies Container signature calculated using CalculateSignature.
|
||||
// Result means signature correctness.
|
||||
func VerifySignature(sig frostfscrypto.Signature, cnr Container) bool {
|
||||
func VerifySignature(sig *frostfscrypto.Signature, cnr *Container) bool {
|
||||
return sig.Verify(cnr.Marshal())
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
|
@ -20,26 +20,35 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestPlacementPolicyEncoding(t *testing.T) {
|
||||
v := containertest.Container()
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
var v2 container.Container
|
||||
v2 := container.NewContainer()
|
||||
require.NoError(t, v2.Unmarshal(v.Marshal()))
|
||||
|
||||
require.Equal(t, v, v2)
|
||||
var c1, c2 containergrpc.Container
|
||||
v.WriteToV2(&c1)
|
||||
v2.WriteToV2(&c2)
|
||||
|
||||
require.True(t, proto.Equal(&c1, &c2))
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
data, err := v.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
var v2 container.Container
|
||||
v2 := container.NewContainer()
|
||||
require.NoError(t, v2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, v, v2)
|
||||
var c1, c2 containergrpc.Container
|
||||
v.WriteToV2(&c1)
|
||||
v2.WriteToV2(&c2)
|
||||
|
||||
require.True(t, proto.Equal(&c1, &c2))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -48,7 +57,7 @@ func TestContainer_Init(t *testing.T) {
|
|||
|
||||
val.Init()
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
binNonce := msg.GetNonce()
|
||||
|
@ -60,19 +69,26 @@ func TestContainer_Init(t *testing.T) {
|
|||
verV2 := msg.GetVersion()
|
||||
require.NotNil(t, verV2)
|
||||
|
||||
var ver version.Version
|
||||
require.NoError(t, ver.ReadFromV2(*verV2))
|
||||
ver := version.NewVersion()
|
||||
ver.ReadFromV2(verV2)
|
||||
|
||||
require.Equal(t, version.Current(), ver)
|
||||
var v1, v2 refs.Version
|
||||
version.Current().WriteToV2(&v1)
|
||||
ver.WriteToV2(&v2)
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
require.True(t, proto.Equal(&v1, &v2))
|
||||
|
||||
require.Equal(t, val, val2)
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
var c1, c2 containergrpc.Container
|
||||
val.WriteToV2(&c1)
|
||||
val2.WriteToV2(&c2)
|
||||
require.True(t, proto.Equal(&c1, &c2))
|
||||
}
|
||||
|
||||
func TestContainer_Owner(t *testing.T) {
|
||||
var val container.Container
|
||||
val := container.NewContainer()
|
||||
|
||||
require.Zero(t, val.Owner())
|
||||
|
||||
|
@ -82,22 +98,22 @@ func TestContainer_Owner(t *testing.T) {
|
|||
|
||||
val.SetOwner(owner)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
var msgOwner refs.OwnerID
|
||||
owner.WriteToV2(&msgOwner)
|
||||
|
||||
require.Equal(t, &msgOwner, msg.GetOwnerID())
|
||||
require.True(t, proto.Equal(&msgOwner, msg.GetOwnerId()))
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.True(t, val2.Owner().Equals(owner))
|
||||
}
|
||||
|
||||
func TestContainer_BasicACL(t *testing.T) {
|
||||
var val container.Container
|
||||
val := container.NewContainer()
|
||||
|
||||
require.Zero(t, val.BasicACL())
|
||||
|
||||
|
@ -106,19 +122,19 @@ func TestContainer_BasicACL(t *testing.T) {
|
|||
basicACL := containertest.BasicACL()
|
||||
val.SetBasicACL(basicACL)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
require.EqualValues(t, basicACL.Bits(), msg.GetBasicACL())
|
||||
require.EqualValues(t, basicACL.Bits(), msg.GetBasicAcl())
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.Equal(t, basicACL, val2.BasicACL())
|
||||
}
|
||||
|
||||
func TestContainer_PlacementPolicy(t *testing.T) {
|
||||
var val container.Container
|
||||
val := container.NewContainer()
|
||||
|
||||
require.Zero(t, val.PlacementPolicy())
|
||||
|
||||
|
@ -127,30 +143,43 @@ func TestContainer_PlacementPolicy(t *testing.T) {
|
|||
pp := netmaptest.PlacementPolicy()
|
||||
val.SetPlacementPolicy(pp)
|
||||
|
||||
var msgPolicy v2netmap.PlacementPolicy
|
||||
var msgPolicy netmapgrpc.PlacementPolicy
|
||||
pp.WriteToV2(&msgPolicy)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
require.Equal(t, &msgPolicy, msg.GetPlacementPolicy())
|
||||
require.True(t, proto.Equal(&msgPolicy, msg.GetPlacementPolicy()))
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.Equal(t, pp, val2.PlacementPolicy())
|
||||
var p1, p2 netmapgrpc.PlacementPolicy
|
||||
|
||||
pp.WriteToV2(&p1)
|
||||
val2.PlacementPolicy().WriteToV2(&p2)
|
||||
|
||||
require.True(t, proto.Equal(&p1, &p2))
|
||||
}
|
||||
|
||||
func assertContainsAttribute(t *testing.T, m v2container.Container, key, val string) {
|
||||
var msgAttr v2container.Attribute
|
||||
func assertContainsAttribute(t *testing.T, m *containergrpc.Container, key, val string) {
|
||||
var msgAttr containergrpc.Container_Attribute
|
||||
|
||||
msgAttr.SetKey(key)
|
||||
msgAttr.SetValue(val)
|
||||
require.Contains(t, m.GetAttributes(), msgAttr)
|
||||
|
||||
var found bool
|
||||
for _, attr := range m.GetAttributes() {
|
||||
if found = proto.Equal(attr, &msgAttr); found {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.True(t, found, "Attribute has not been found")
|
||||
}
|
||||
|
||||
func TestContainer_Attribute(t *testing.T) {
|
||||
const attrKey1, attrKey2 = v2container.SysAttributePrefix + "key1", v2container.SysAttributePrefixNeoFS + "key2"
|
||||
const attrKey1, attrKey2 = containergrpc.SysAttributePrefix + "key1", containergrpc.SysAttributePrefixNeoFS + "key2"
|
||||
const attrVal1, attrVal2 = "val1", "val2"
|
||||
|
||||
val := containertest.Container()
|
||||
|
@ -164,15 +193,15 @@ func TestContainer_Attribute(t *testing.T) {
|
|||
})
|
||||
require.Equal(t, 1, i)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
require.GreaterOrEqual(t, len(msg.GetAttributes()), 2)
|
||||
assertContainsAttribute(t, msg, attrKey1, attrVal1)
|
||||
assertContainsAttribute(t, msg, attrKey2, attrVal2)
|
||||
assertContainsAttribute(t, &msg, attrKey1, attrVal1)
|
||||
assertContainsAttribute(t, &msg, attrKey2, attrVal2)
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.Equal(t, attrVal1, val2.Attribute(attrKey1))
|
||||
require.Equal(t, attrVal2, val2.Attribute(attrKey2))
|
||||
|
@ -192,31 +221,31 @@ func TestContainer_Attribute(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetName(t *testing.T) {
|
||||
var val container.Container
|
||||
val := container.NewContainer()
|
||||
|
||||
require.Panics(t, func() {
|
||||
container.SetName(&val, "")
|
||||
container.SetName(val, "")
|
||||
})
|
||||
|
||||
val = containertest.Container()
|
||||
|
||||
const name = "some name"
|
||||
|
||||
container.SetName(&val, name)
|
||||
container.SetName(val, name)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
assertContainsAttribute(t, msg, "Name", name)
|
||||
assertContainsAttribute(t, &msg, "Name", name)
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.Equal(t, name, container.Name(val2))
|
||||
}
|
||||
|
||||
func TestSetCreationTime(t *testing.T) {
|
||||
var val container.Container
|
||||
val := container.NewContainer()
|
||||
|
||||
require.Zero(t, container.CreatedAt(val).Unix())
|
||||
|
||||
|
@ -224,15 +253,15 @@ func TestSetCreationTime(t *testing.T) {
|
|||
|
||||
creat := time.Now()
|
||||
|
||||
container.SetCreationTime(&val, creat)
|
||||
container.SetCreationTime(val, creat)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
assertContainsAttribute(t, msg, "Timestamp", strconv.FormatInt(creat.Unix(), 10))
|
||||
assertContainsAttribute(t, &msg, "Timestamp", strconv.FormatInt(creat.Unix(), 10))
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.Equal(t, creat.Unix(), container.CreatedAt(val2).Unix())
|
||||
}
|
||||
|
@ -244,21 +273,21 @@ func TestDisableHomomorphicHashing(t *testing.T) {
|
|||
|
||||
val = containertest.Container()
|
||||
|
||||
container.DisableHomomorphicHashing(&val)
|
||||
container.DisableHomomorphicHashing(val)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
assertContainsAttribute(t, msg, v2container.SysAttributePrefix+"DISABLE_HOMOMORPHIC_HASHING", "true")
|
||||
assertContainsAttribute(t, &msg, containergrpc.SysAttributePrefix+"DISABLE_HOMOMORPHIC_HASHING", "true")
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.True(t, container.IsHomomorphicHashingDisabled(val2))
|
||||
}
|
||||
|
||||
func TestWriteDomain(t *testing.T) {
|
||||
var val container.Container
|
||||
val := container.NewContainer()
|
||||
|
||||
require.Zero(t, container.ReadDomain(val).Name())
|
||||
|
||||
|
@ -269,26 +298,26 @@ func TestWriteDomain(t *testing.T) {
|
|||
var d container.Domain
|
||||
d.SetName(name)
|
||||
|
||||
container.WriteDomain(&val, d)
|
||||
container.WriteDomain(val, d)
|
||||
|
||||
var msg v2container.Container
|
||||
var msg containergrpc.Container
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
assertContainsAttribute(t, msg, v2container.SysAttributeName, name)
|
||||
assertContainsAttribute(t, msg, v2container.SysAttributeZone, "container")
|
||||
assertContainsAttribute(t, &msg, containergrpc.SysAttributeName, name)
|
||||
assertContainsAttribute(t, &msg, containergrpc.SysAttributeZone, "container")
|
||||
|
||||
const zone = "domain zone"
|
||||
|
||||
d.SetZone(zone)
|
||||
|
||||
container.WriteDomain(&val, d)
|
||||
container.WriteDomain(val, d)
|
||||
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
assertContainsAttribute(t, msg, v2container.SysAttributeZone, zone)
|
||||
assertContainsAttribute(t, &msg, containergrpc.SysAttributeZone, zone)
|
||||
|
||||
var val2 container.Container
|
||||
require.NoError(t, val2.ReadFromV2(msg))
|
||||
val2 := container.NewContainer()
|
||||
require.NoError(t, val2.ReadFromV2(&msg))
|
||||
|
||||
require.Equal(t, d, container.ReadDomain(val2))
|
||||
}
|
||||
|
@ -308,7 +337,7 @@ func TestCalculateID(t *testing.T) {
|
|||
require.Equal(t, h[:], msg.GetValue())
|
||||
|
||||
var id2 cid.ID
|
||||
require.NoError(t, id2.ReadFromV2(msg))
|
||||
require.NoError(t, id2.ReadFromV2(&msg))
|
||||
|
||||
require.True(t, container.AssertID(id2, val))
|
||||
}
|
||||
|
@ -319,7 +348,7 @@ func TestCalculateSignature(t *testing.T) {
|
|||
|
||||
val := containertest.Container()
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
require.NoError(t, container.CalculateSignature(&sig, val, key.PrivateKey))
|
||||
|
||||
|
@ -327,7 +356,7 @@ func TestCalculateSignature(t *testing.T) {
|
|||
sig.WriteToV2(&msg)
|
||||
|
||||
var sig2 frostfscrypto.Signature
|
||||
require.NoError(t, sig2.ReadFromV2(msg))
|
||||
require.NoError(t, sig2.ReadFromV2(&msg))
|
||||
|
||||
require.True(t, container.VerifySignature(sig2, val))
|
||||
require.True(t, container.VerifySignature(&sig2, &val))
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"github.com/mr-tron/base58"
|
||||
)
|
||||
|
||||
|
@ -25,7 +25,7 @@ type ID [sha256.Size]byte
|
|||
// to the FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (id *ID) ReadFromV2(m refs.ContainerID) error {
|
||||
func (id *ID) ReadFromV2(m *refs.ContainerID) error {
|
||||
return id.Decode(m.GetValue())
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ func (id *ID) ReadFromV2(m refs.ContainerID) error {
|
|||
//
|
||||
// See also ReadFromV2.
|
||||
func (id ID) WriteToV2(m *refs.ContainerID) {
|
||||
m.Reset()
|
||||
m.SetValue(id[:])
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
"github.com/mr-tron/base58"
|
||||
|
@ -29,7 +29,7 @@ func TestID_ToV2(t *testing.T) {
|
|||
id.WriteToV2(&idV2)
|
||||
|
||||
var newID cid.ID
|
||||
require.NoError(t, newID.ReadFromV2(idV2))
|
||||
require.NoError(t, newID.ReadFromV2(&idV2))
|
||||
|
||||
require.Equal(t, id, newID)
|
||||
require.Equal(t, checksum[:], idV2.GetValue())
|
||||
|
@ -82,7 +82,7 @@ func TestNewFromV2(t *testing.T) {
|
|||
v2 refs.ContainerID
|
||||
)
|
||||
|
||||
require.Error(t, x.ReadFromV2(v2))
|
||||
require.Error(t, x.ReadFromV2(&v2))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
// ApplyNetworkConfig applies network configuration to the
|
||||
// container. Changes the container if it does not satisfy
|
||||
// network configuration.
|
||||
func ApplyNetworkConfig(cnr *Container, cfg netmap.NetworkInfo) {
|
||||
func ApplyNetworkConfig(cnr Container, cfg netmap.NetworkInfo) {
|
||||
if cfg.HomomorphicHashingDisabled() {
|
||||
DisableHomomorphicHashing(cnr)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestContainer_NetworkConfig(t *testing.T) {
|
|||
t.Run("apply", func(t *testing.T) {
|
||||
require.False(t, container.IsHomomorphicHashingDisabled(c))
|
||||
|
||||
container.ApplyNetworkConfig(&c, nc)
|
||||
container.ApplyNetworkConfig(c, nc)
|
||||
|
||||
require.True(t, container.IsHomomorphicHashingDisabled(c))
|
||||
})
|
||||
|
|
|
@ -4,9 +4,10 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// SizeEstimation groups information about estimation of the size of the data
|
||||
|
@ -15,27 +16,36 @@ import (
|
|||
// SizeEstimation is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container.UsedSpaceAnnouncement
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
type SizeEstimation struct {
|
||||
m container.UsedSpaceAnnouncement
|
||||
m *containergrpc.AnnounceUsedSpaceRequest_Body_Announcement
|
||||
}
|
||||
|
||||
func NewSizeEstimation() *SizeEstimation {
|
||||
return &SizeEstimation{
|
||||
m: &containergrpc.AnnounceUsedSpaceRequest_Body_Announcement{},
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFromV2 reads SizeEstimation from the container.UsedSpaceAnnouncement message.
|
||||
// Checks if the message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (x *SizeEstimation) ReadFromV2(m container.UsedSpaceAnnouncement) error {
|
||||
cnrV2 := m.GetContainerID()
|
||||
func (x *SizeEstimation) ReadFromV2(m *containergrpc.AnnounceUsedSpaceRequest_Body_Announcement) error {
|
||||
cnrV2 := m.GetContainerId()
|
||||
if cnrV2 == nil {
|
||||
return errors.New("missing container")
|
||||
}
|
||||
|
||||
var cnr cid.ID
|
||||
|
||||
err := cnr.ReadFromV2(*cnrV2)
|
||||
err := cnr.ReadFromV2(cnrV2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container: %w", err)
|
||||
}
|
||||
|
||||
x.m = m
|
||||
if x.m == nil {
|
||||
x.m = new(containergrpc.AnnounceUsedSpaceRequest_Body_Announcement)
|
||||
}
|
||||
proto.Merge(x.m, m)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -44,8 +54,9 @@ func (x *SizeEstimation) ReadFromV2(m container.UsedSpaceAnnouncement) error {
|
|||
// The message MUST NOT be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x SizeEstimation) WriteToV2(m *container.UsedSpaceAnnouncement) {
|
||||
*m = x.m
|
||||
func (x SizeEstimation) WriteToV2(m *containergrpc.AnnounceUsedSpaceRequest_Body_Announcement) {
|
||||
m.Reset()
|
||||
proto.Merge(m, x.m)
|
||||
}
|
||||
|
||||
// SetEpoch sets epoch when estimation of the container data size was calculated.
|
||||
|
@ -67,10 +78,10 @@ func (x SizeEstimation) Epoch() uint64 {
|
|||
//
|
||||
// See also Container.
|
||||
func (x *SizeEstimation) SetContainer(cnr cid.ID) {
|
||||
var cidV2 refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
cnr.WriteToV2(&cidV2)
|
||||
|
||||
x.m.SetContainerID(&cidV2)
|
||||
x.m.SetContainerId(&cidV2)
|
||||
}
|
||||
|
||||
// Container returns container set using SetContainer.
|
||||
|
@ -78,9 +89,9 @@ func (x *SizeEstimation) SetContainer(cnr cid.ID) {
|
|||
// Zero SizeEstimation is not bound to any container (returns zero) which is
|
||||
// incorrect according to FrostFS API protocol.
|
||||
func (x SizeEstimation) Container() (res cid.ID) {
|
||||
m := x.m.GetContainerID()
|
||||
m := x.m.GetContainerId()
|
||||
if m != nil {
|
||||
err := res.ReadFromV2(*m)
|
||||
err := res.ReadFromV2(m)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("unexpected error from cid.ID.ReadFromV2: %w", err))
|
||||
}
|
||||
|
|
|
@ -4,16 +4,17 @@ import (
|
|||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestSizeEstimation_Epoch(t *testing.T) {
|
||||
var val container.SizeEstimation
|
||||
val := container.NewSizeEstimation()
|
||||
|
||||
require.Zero(t, val.Epoch())
|
||||
|
||||
|
@ -22,14 +23,14 @@ func TestSizeEstimation_Epoch(t *testing.T) {
|
|||
val.SetEpoch(epoch)
|
||||
require.EqualValues(t, epoch, val.Epoch())
|
||||
|
||||
var msg v2container.UsedSpaceAnnouncement
|
||||
var msg containergrpc.AnnounceUsedSpaceRequest_Body_Announcement
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
require.EqualValues(t, epoch, msg.GetEpoch())
|
||||
}
|
||||
|
||||
func TestSizeEstimation_Container(t *testing.T) {
|
||||
var val container.SizeEstimation
|
||||
val := container.NewSizeEstimation()
|
||||
|
||||
require.Zero(t, val.Container())
|
||||
|
||||
|
@ -38,17 +39,17 @@ func TestSizeEstimation_Container(t *testing.T) {
|
|||
val.SetContainer(cnr)
|
||||
require.True(t, val.Container().Equals(cnr))
|
||||
|
||||
var msg v2container.UsedSpaceAnnouncement
|
||||
var msg containergrpc.AnnounceUsedSpaceRequest_Body_Announcement
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
var msgCnr refs.ContainerID
|
||||
var msgCnr refsgrpc.ContainerID
|
||||
cnr.WriteToV2(&msgCnr)
|
||||
|
||||
require.Equal(t, &msgCnr, msg.GetContainerID())
|
||||
require.True(t, proto.Equal(&msgCnr, msg.GetContainerId()))
|
||||
}
|
||||
|
||||
func TestSizeEstimation_Value(t *testing.T) {
|
||||
var val container.SizeEstimation
|
||||
val := container.NewSizeEstimation()
|
||||
|
||||
require.Zero(t, val.Value())
|
||||
|
||||
|
@ -57,7 +58,7 @@ func TestSizeEstimation_Value(t *testing.T) {
|
|||
val.SetValue(value)
|
||||
require.EqualValues(t, value, val.Value())
|
||||
|
||||
var msg v2container.UsedSpaceAnnouncement
|
||||
var msg containergrpc.AnnounceUsedSpaceRequest_Body_Announcement
|
||||
val.WriteToV2(&msg)
|
||||
|
||||
require.EqualValues(t, value, msg.GetUsedSpace())
|
||||
|
@ -66,22 +67,22 @@ func TestSizeEstimation_Value(t *testing.T) {
|
|||
func TestSizeEstimation_ReadFromV2(t *testing.T) {
|
||||
const epoch = 654
|
||||
const value = 903
|
||||
var cnrMsg refs.ContainerID
|
||||
var cnrMsg refsgrpc.ContainerID
|
||||
|
||||
var msg v2container.UsedSpaceAnnouncement
|
||||
msg := new(containergrpc.AnnounceUsedSpaceRequest_Body_Announcement)
|
||||
|
||||
var val container.SizeEstimation
|
||||
val := container.NewSizeEstimation()
|
||||
|
||||
require.Error(t, val.ReadFromV2(msg))
|
||||
|
||||
msg.SetContainerID(&cnrMsg)
|
||||
msg.SetContainerId(&cnrMsg)
|
||||
|
||||
require.Error(t, val.ReadFromV2(msg))
|
||||
|
||||
cnrMsg.SetValue(make([]byte, sha256.Size))
|
||||
|
||||
var cnr cid.ID
|
||||
require.NoError(t, cnr.ReadFromV2(cnrMsg))
|
||||
require.NoError(t, cnr.ReadFromV2(&cnrMsg))
|
||||
|
||||
msg.SetEpoch(epoch)
|
||||
msg.SetUsedSpace(value)
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
func Container() (x container.Container) {
|
||||
owner := usertest.ID()
|
||||
|
||||
x = container.NewContainer()
|
||||
x.Init()
|
||||
x.SetAttribute("some attribute", "value")
|
||||
x.SetOwner(*owner)
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
|
@ -19,7 +19,7 @@ func TestSignature(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
var s frostfscrypto.Signature
|
||||
var m refs.Signature
|
||||
var m = new(refs.Signature)
|
||||
|
||||
for _, f := range []func() frostfscrypto.Signer{
|
||||
func() frostfscrypto.Signer {
|
||||
|
@ -37,7 +37,7 @@ func TestSignature(t *testing.T) {
|
|||
err := s.Calculate(signer, data)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.WriteToV2(&m)
|
||||
s.WriteToV2(m)
|
||||
|
||||
require.NoError(t, s.ReadFromV2(m))
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ On server side:
|
|||
|
||||
// recv msg
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
sig.ReadFromV2(msg)
|
||||
|
||||
// process sig
|
||||
|
|
|
@ -4,7 +4,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// Signature represents a confirmation of data integrity received by the
|
||||
|
@ -16,13 +17,21 @@ import (
|
|||
// Note that direct typecast is not safe and may result in loss of compatibility:
|
||||
//
|
||||
// _ = Signature(refs.Signature{}) // not recommended
|
||||
type Signature refs.Signature
|
||||
type Signature struct {
|
||||
signature *refsgrpc.Signature
|
||||
}
|
||||
|
||||
func NewSignature() Signature {
|
||||
return Signature{
|
||||
signature: &refsgrpc.Signature{},
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFromV2 reads Signature from the refs.Signature message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (x *Signature) ReadFromV2(m refs.Signature) error {
|
||||
func (x *Signature) ReadFromV2(m *refsgrpc.Signature) error {
|
||||
if len(m.GetKey()) == 0 {
|
||||
return errors.New("missing public key")
|
||||
} else if len(m.GetSign()) == 0 {
|
||||
|
@ -33,12 +42,15 @@ func (x *Signature) ReadFromV2(m refs.Signature) error {
|
|||
default:
|
||||
return fmt.Errorf("unsupported scheme %v", m.GetSign())
|
||||
case
|
||||
refs.ECDSA_SHA512,
|
||||
refs.ECDSA_RFC6979_SHA256,
|
||||
refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
|
||||
refsgrpc.SignatureScheme_ECDSA_SHA512,
|
||||
refsgrpc.SignatureScheme_ECDSA_RFC6979_SHA256,
|
||||
refsgrpc.SignatureScheme_ECDSA_RFC6979_SHA256_WALLET_CONNECT:
|
||||
}
|
||||
|
||||
*x = Signature(m)
|
||||
if x.signature == nil {
|
||||
x.signature = new(refsgrpc.Signature)
|
||||
}
|
||||
proto.Merge(x.signature, m)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -47,8 +59,9 @@ func (x *Signature) ReadFromV2(m refs.Signature) error {
|
|||
// The message must not be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x Signature) WriteToV2(m *refs.Signature) {
|
||||
*m = (refs.Signature)(x)
|
||||
func (x *Signature) WriteToV2(m *refsgrpc.Signature) {
|
||||
m.Reset()
|
||||
proto.Merge(m, x.signature)
|
||||
}
|
||||
|
||||
// Calculate signs data using Signer and encodes public key for subsequent
|
||||
|
@ -68,13 +81,12 @@ func (x *Signature) Calculate(signer Signer, data []byte) error {
|
|||
key := make([]byte, pub.MaxEncodedSize())
|
||||
key = key[:pub.Encode(key)]
|
||||
|
||||
m := (*refs.Signature)(x)
|
||||
|
||||
m.SetScheme(refs.SignatureScheme(signer.Scheme()))
|
||||
m := new(refsgrpc.Signature)
|
||||
m.SetScheme(refsgrpc.SignatureScheme(signer.Scheme()))
|
||||
m.SetSign(signature)
|
||||
m.SetKey(key)
|
||||
|
||||
return nil
|
||||
return x.ReadFromV2(m)
|
||||
}
|
||||
|
||||
// Verify verifies data signature using encoded public key. True means valid
|
||||
|
@ -83,20 +95,18 @@ func (x *Signature) Calculate(signer Signer, data []byte) error {
|
|||
// Verify fails if signature scheme is not supported (see RegisterScheme).
|
||||
//
|
||||
// See also Calculate.
|
||||
func (x Signature) Verify(data []byte) bool {
|
||||
m := (*refs.Signature)(&x)
|
||||
|
||||
f, ok := publicKeys[Scheme(m.GetScheme())]
|
||||
func (x *Signature) Verify(data []byte) bool {
|
||||
f, ok := publicKeys[Scheme(x.signature.GetScheme())]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
key := f()
|
||||
|
||||
err := key.Decode(m.GetKey())
|
||||
err := key.Decode(x.signature.GetKey())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return key.Verify(data, m.GetSign())
|
||||
return key.Verify(data, x.signature.GetSign())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package frostfscrypto
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
)
|
||||
|
||||
// Scheme represents digital signature algorithm with fixed cryptographic hash function.
|
||||
|
|
110
eacl/enums.go
110
eacl/enums.go
|
@ -1,7 +1,7 @@
|
|||
package eacl
|
||||
|
||||
import (
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
)
|
||||
|
||||
// Action taken if ContainerEACL record matched request.
|
||||
|
@ -102,23 +102,23 @@ const (
|
|||
)
|
||||
|
||||
// ToV2 converts Action to v2 Action enum value.
|
||||
func (a Action) ToV2() v2acl.Action {
|
||||
func (a Action) ToV2() aclgrpc.Action {
|
||||
switch a {
|
||||
case ActionAllow:
|
||||
return v2acl.ActionAllow
|
||||
return aclgrpc.Action_ALLOW
|
||||
case ActionDeny:
|
||||
return v2acl.ActionDeny
|
||||
return aclgrpc.Action_DENY
|
||||
default:
|
||||
return v2acl.ActionUnknown
|
||||
return aclgrpc.Action_ACTION_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
// ActionFromV2 converts v2 Action enum value to Action.
|
||||
func ActionFromV2(action v2acl.Action) (a Action) {
|
||||
func ActionFromV2(action aclgrpc.Action) (a Action) {
|
||||
switch action {
|
||||
case v2acl.ActionAllow:
|
||||
case aclgrpc.Action_ALLOW:
|
||||
a = ActionAllow
|
||||
case v2acl.ActionDeny:
|
||||
case aclgrpc.Action_DENY:
|
||||
a = ActionDeny
|
||||
default:
|
||||
a = ActionUnknown
|
||||
|
@ -142,7 +142,7 @@ func (a Action) String() string {
|
|||
//
|
||||
// Returns true if s was parsed successfully.
|
||||
func (a *Action) FromString(s string) bool {
|
||||
var g v2acl.Action
|
||||
var g aclgrpc.Action
|
||||
|
||||
ok := g.FromString(s)
|
||||
|
||||
|
@ -154,43 +154,43 @@ func (a *Action) FromString(s string) bool {
|
|||
}
|
||||
|
||||
// ToV2 converts Operation to v2 Operation enum value.
|
||||
func (o Operation) ToV2() v2acl.Operation {
|
||||
func (o Operation) ToV2() aclgrpc.Operation {
|
||||
switch o {
|
||||
case OperationGet:
|
||||
return v2acl.OperationGet
|
||||
return aclgrpc.Operation_GET
|
||||
case OperationHead:
|
||||
return v2acl.OperationHead
|
||||
return aclgrpc.Operation_HEAD
|
||||
case OperationPut:
|
||||
return v2acl.OperationPut
|
||||
return aclgrpc.Operation_PUT
|
||||
case OperationDelete:
|
||||
return v2acl.OperationDelete
|
||||
return aclgrpc.Operation_DELETE
|
||||
case OperationSearch:
|
||||
return v2acl.OperationSearch
|
||||
return aclgrpc.Operation_SEARCH
|
||||
case OperationRange:
|
||||
return v2acl.OperationRange
|
||||
return aclgrpc.Operation_GETRANGE
|
||||
case OperationRangeHash:
|
||||
return v2acl.OperationRangeHash
|
||||
return aclgrpc.Operation_GETRANGEHASH
|
||||
default:
|
||||
return v2acl.OperationUnknown
|
||||
return aclgrpc.Operation_OPERATION_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
// OperationFromV2 converts v2 Operation enum value to Operation.
|
||||
func OperationFromV2(operation v2acl.Operation) (o Operation) {
|
||||
func OperationFromV2(operation aclgrpc.Operation) (o Operation) {
|
||||
switch operation {
|
||||
case v2acl.OperationGet:
|
||||
case aclgrpc.Operation_GET:
|
||||
o = OperationGet
|
||||
case v2acl.OperationHead:
|
||||
case aclgrpc.Operation_HEAD:
|
||||
o = OperationHead
|
||||
case v2acl.OperationPut:
|
||||
case aclgrpc.Operation_PUT:
|
||||
o = OperationPut
|
||||
case v2acl.OperationDelete:
|
||||
case aclgrpc.Operation_DELETE:
|
||||
o = OperationDelete
|
||||
case v2acl.OperationSearch:
|
||||
case aclgrpc.Operation_SEARCH:
|
||||
o = OperationSearch
|
||||
case v2acl.OperationRange:
|
||||
case aclgrpc.Operation_GETRANGE:
|
||||
o = OperationRange
|
||||
case v2acl.OperationRangeHash:
|
||||
case aclgrpc.Operation_GETRANGEHASH:
|
||||
o = OperationRangeHash
|
||||
default:
|
||||
o = OperationUnknown
|
||||
|
@ -219,7 +219,7 @@ func (o Operation) String() string {
|
|||
//
|
||||
// Returns true if s was parsed successfully.
|
||||
func (o *Operation) FromString(s string) bool {
|
||||
var g v2acl.Operation
|
||||
var g aclgrpc.Operation
|
||||
|
||||
ok := g.FromString(s)
|
||||
|
||||
|
@ -231,27 +231,27 @@ func (o *Operation) FromString(s string) bool {
|
|||
}
|
||||
|
||||
// ToV2 converts Role to v2 Role enum value.
|
||||
func (r Role) ToV2() v2acl.Role {
|
||||
func (r Role) ToV2() aclgrpc.Role {
|
||||
switch r {
|
||||
case RoleUser:
|
||||
return v2acl.RoleUser
|
||||
return aclgrpc.Role_USER
|
||||
case RoleSystem:
|
||||
return v2acl.RoleSystem
|
||||
return aclgrpc.Role_SYSTEM
|
||||
case RoleOthers:
|
||||
return v2acl.RoleOthers
|
||||
return aclgrpc.Role_OTHERS
|
||||
default:
|
||||
return v2acl.RoleUnknown
|
||||
return aclgrpc.Role_ROLE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
// RoleFromV2 converts v2 Role enum value to Role.
|
||||
func RoleFromV2(role v2acl.Role) (r Role) {
|
||||
func RoleFromV2(role aclgrpc.Role) (r Role) {
|
||||
switch role {
|
||||
case v2acl.RoleUser:
|
||||
case aclgrpc.Role_USER:
|
||||
r = RoleUser
|
||||
case v2acl.RoleSystem:
|
||||
case aclgrpc.Role_SYSTEM:
|
||||
r = RoleSystem
|
||||
case v2acl.RoleOthers:
|
||||
case aclgrpc.Role_OTHERS:
|
||||
r = RoleOthers
|
||||
default:
|
||||
r = RoleUnknown
|
||||
|
@ -276,7 +276,7 @@ func (r Role) String() string {
|
|||
//
|
||||
// Returns true if s was parsed successfully.
|
||||
func (r *Role) FromString(s string) bool {
|
||||
var g v2acl.Role
|
||||
var g aclgrpc.Role
|
||||
|
||||
ok := g.FromString(s)
|
||||
|
||||
|
@ -288,23 +288,23 @@ func (r *Role) FromString(s string) bool {
|
|||
}
|
||||
|
||||
// ToV2 converts Match to v2 MatchType enum value.
|
||||
func (m Match) ToV2() v2acl.MatchType {
|
||||
func (m Match) ToV2() aclgrpc.MatchType {
|
||||
switch m {
|
||||
case MatchStringEqual:
|
||||
return v2acl.MatchTypeStringEqual
|
||||
return aclgrpc.MatchType_STRING_EQUAL
|
||||
case MatchStringNotEqual:
|
||||
return v2acl.MatchTypeStringNotEqual
|
||||
return aclgrpc.MatchType_STRING_NOT_EQUAL
|
||||
default:
|
||||
return v2acl.MatchTypeUnknown
|
||||
return aclgrpc.MatchType_MATCH_TYPE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
// MatchFromV2 converts v2 MatchType enum value to Match.
|
||||
func MatchFromV2(match v2acl.MatchType) (m Match) {
|
||||
func MatchFromV2(match aclgrpc.MatchType) (m Match) {
|
||||
switch match {
|
||||
case v2acl.MatchTypeStringEqual:
|
||||
case aclgrpc.MatchType_STRING_EQUAL:
|
||||
m = MatchStringEqual
|
||||
case v2acl.MatchTypeStringNotEqual:
|
||||
case aclgrpc.MatchType_STRING_NOT_EQUAL:
|
||||
m = MatchStringNotEqual
|
||||
default:
|
||||
m = MatchUnknown
|
||||
|
@ -328,7 +328,7 @@ func (m Match) String() string {
|
|||
//
|
||||
// Returns true if s was parsed successfully.
|
||||
func (m *Match) FromString(s string) bool {
|
||||
var g v2acl.MatchType
|
||||
var g aclgrpc.MatchType
|
||||
|
||||
ok := g.FromString(s)
|
||||
|
||||
|
@ -340,27 +340,27 @@ func (m *Match) FromString(s string) bool {
|
|||
}
|
||||
|
||||
// ToV2 converts FilterHeaderType to v2 HeaderType enum value.
|
||||
func (h FilterHeaderType) ToV2() v2acl.HeaderType {
|
||||
func (h FilterHeaderType) ToV2() aclgrpc.HeaderType {
|
||||
switch h {
|
||||
case HeaderFromRequest:
|
||||
return v2acl.HeaderTypeRequest
|
||||
return aclgrpc.HeaderType_REQUEST
|
||||
case HeaderFromObject:
|
||||
return v2acl.HeaderTypeObject
|
||||
return aclgrpc.HeaderType_OBJECT
|
||||
case HeaderFromService:
|
||||
return v2acl.HeaderTypeService
|
||||
return aclgrpc.HeaderType_SERVICE
|
||||
default:
|
||||
return v2acl.HeaderTypeUnknown
|
||||
return aclgrpc.HeaderType_HEADER_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
// FilterHeaderTypeFromV2 converts v2 HeaderType enum value to FilterHeaderType.
|
||||
func FilterHeaderTypeFromV2(header v2acl.HeaderType) (h FilterHeaderType) {
|
||||
func FilterHeaderTypeFromV2(header aclgrpc.HeaderType) (h FilterHeaderType) {
|
||||
switch header {
|
||||
case v2acl.HeaderTypeRequest:
|
||||
case aclgrpc.HeaderType_REQUEST:
|
||||
h = HeaderFromRequest
|
||||
case v2acl.HeaderTypeObject:
|
||||
case aclgrpc.HeaderType_OBJECT:
|
||||
h = HeaderFromObject
|
||||
case v2acl.HeaderTypeService:
|
||||
case aclgrpc.HeaderType_SERVICE:
|
||||
h = HeaderFromService
|
||||
default:
|
||||
h = HeaderTypeUnknown
|
||||
|
@ -384,7 +384,7 @@ func (h FilterHeaderType) String() string {
|
|||
//
|
||||
// Returns true if s was parsed successfully.
|
||||
func (h *FilterHeaderType) FromString(s string) bool {
|
||||
var g v2acl.HeaderType
|
||||
var g aclgrpc.HeaderType
|
||||
|
||||
ok := g.FromString(s)
|
||||
|
||||
|
|
|
@ -3,47 +3,47 @@ package eacl_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
eqV2Actions = map[eacl.Action]v2acl.Action{
|
||||
eacl.ActionUnknown: v2acl.ActionUnknown,
|
||||
eacl.ActionAllow: v2acl.ActionAllow,
|
||||
eacl.ActionDeny: v2acl.ActionDeny,
|
||||
eqV2Actions = map[eacl.Action]aclgrpc.Action{
|
||||
eacl.ActionUnknown: aclgrpc.Action_ACTION_UNSPECIFIED,
|
||||
eacl.ActionAllow: aclgrpc.Action_ALLOW,
|
||||
eacl.ActionDeny: aclgrpc.Action_DENY,
|
||||
}
|
||||
|
||||
eqV2Operations = map[eacl.Operation]v2acl.Operation{
|
||||
eacl.OperationUnknown: v2acl.OperationUnknown,
|
||||
eacl.OperationGet: v2acl.OperationGet,
|
||||
eacl.OperationHead: v2acl.OperationHead,
|
||||
eacl.OperationPut: v2acl.OperationPut,
|
||||
eacl.OperationDelete: v2acl.OperationDelete,
|
||||
eacl.OperationSearch: v2acl.OperationSearch,
|
||||
eacl.OperationRange: v2acl.OperationRange,
|
||||
eacl.OperationRangeHash: v2acl.OperationRangeHash,
|
||||
eqV2Operations = map[eacl.Operation]aclgrpc.Operation{
|
||||
eacl.OperationUnknown: aclgrpc.Operation_OPERATION_UNSPECIFIED,
|
||||
eacl.OperationGet: aclgrpc.Operation_GET,
|
||||
eacl.OperationHead: aclgrpc.Operation_HEAD,
|
||||
eacl.OperationPut: aclgrpc.Operation_PUT,
|
||||
eacl.OperationDelete: aclgrpc.Operation_DELETE,
|
||||
eacl.OperationSearch: aclgrpc.Operation_SEARCH,
|
||||
eacl.OperationRange: aclgrpc.Operation_GETRANGE,
|
||||
eacl.OperationRangeHash: aclgrpc.Operation_GETRANGEHASH,
|
||||
}
|
||||
|
||||
eqV2Roles = map[eacl.Role]v2acl.Role{
|
||||
eacl.RoleUnknown: v2acl.RoleUnknown,
|
||||
eacl.RoleUser: v2acl.RoleUser,
|
||||
eacl.RoleSystem: v2acl.RoleSystem,
|
||||
eacl.RoleOthers: v2acl.RoleOthers,
|
||||
eqV2Roles = map[eacl.Role]aclgrpc.Role{
|
||||
eacl.RoleUnknown: aclgrpc.Role_ROLE_UNSPECIFIED,
|
||||
eacl.RoleUser: aclgrpc.Role_USER,
|
||||
eacl.RoleSystem: aclgrpc.Role_SYSTEM,
|
||||
eacl.RoleOthers: aclgrpc.Role_OTHERS,
|
||||
}
|
||||
|
||||
eqV2Matches = map[eacl.Match]v2acl.MatchType{
|
||||
eacl.MatchUnknown: v2acl.MatchTypeUnknown,
|
||||
eacl.MatchStringEqual: v2acl.MatchTypeStringEqual,
|
||||
eacl.MatchStringNotEqual: v2acl.MatchTypeStringNotEqual,
|
||||
eqV2Matches = map[eacl.Match]aclgrpc.MatchType{
|
||||
eacl.MatchUnknown: aclgrpc.MatchType_MATCH_TYPE_UNSPECIFIED,
|
||||
eacl.MatchStringEqual: aclgrpc.MatchType_STRING_EQUAL,
|
||||
eacl.MatchStringNotEqual: aclgrpc.MatchType_STRING_NOT_EQUAL,
|
||||
}
|
||||
|
||||
eqV2HeaderTypes = map[eacl.FilterHeaderType]v2acl.HeaderType{
|
||||
eacl.HeaderTypeUnknown: v2acl.HeaderTypeUnknown,
|
||||
eacl.HeaderFromRequest: v2acl.HeaderTypeRequest,
|
||||
eacl.HeaderFromObject: v2acl.HeaderTypeObject,
|
||||
eacl.HeaderFromService: v2acl.HeaderTypeService,
|
||||
eqV2HeaderTypes = map[eacl.FilterHeaderType]aclgrpc.HeaderType{
|
||||
eacl.HeaderTypeUnknown: aclgrpc.HeaderType_HEADER_UNSPECIFIED,
|
||||
eacl.HeaderFromRequest: aclgrpc.HeaderType_REQUEST,
|
||||
eacl.HeaderFromObject: aclgrpc.HeaderType_OBJECT,
|
||||
eacl.HeaderFromService: aclgrpc.HeaderType_SERVICE,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -56,8 +56,8 @@ func TestAction(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("unknown actions", func(t *testing.T) {
|
||||
require.Equal(t, (eacl.ActionDeny + 1).ToV2(), v2acl.ActionUnknown)
|
||||
require.Equal(t, eacl.ActionFromV2(v2acl.ActionDeny+1), eacl.ActionUnknown)
|
||||
require.Equal(t, (eacl.ActionDeny + 1).ToV2(), aclgrpc.Action_ACTION_UNSPECIFIED)
|
||||
require.Equal(t, eacl.ActionFromV2(aclgrpc.Action_DENY+1), eacl.ActionUnknown)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,8 @@ func TestOperation(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("unknown operations", func(t *testing.T) {
|
||||
require.Equal(t, (eacl.OperationRangeHash + 1).ToV2(), v2acl.OperationUnknown)
|
||||
require.Equal(t, eacl.OperationFromV2(v2acl.OperationRangeHash+1), eacl.OperationUnknown)
|
||||
require.Equal(t, (eacl.OperationRangeHash + 1).ToV2(), aclgrpc.Operation_OPERATION_UNSPECIFIED)
|
||||
require.Equal(t, eacl.OperationFromV2(aclgrpc.Operation_GETRANGEHASH+1), eacl.OperationUnknown)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -84,8 +84,8 @@ func TestRole(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("unknown roles", func(t *testing.T) {
|
||||
require.Equal(t, (eacl.RoleOthers + 1).ToV2(), v2acl.RoleUnknown)
|
||||
require.Equal(t, eacl.RoleFromV2(v2acl.RoleOthers+1), eacl.RoleUnknown)
|
||||
require.Equal(t, (eacl.RoleOthers + 1).ToV2(), aclgrpc.Role_ROLE_UNSPECIFIED)
|
||||
require.Equal(t, eacl.RoleFromV2(aclgrpc.Role_OTHERS+1), eacl.RoleUnknown)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -98,8 +98,8 @@ func TestMatch(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("unknown matches", func(t *testing.T) {
|
||||
require.Equal(t, (eacl.MatchStringNotEqual + 1).ToV2(), v2acl.MatchTypeUnknown)
|
||||
require.Equal(t, eacl.MatchFromV2(v2acl.MatchTypeStringNotEqual+1), eacl.MatchUnknown)
|
||||
require.Equal(t, (eacl.MatchStringNotEqual + 1).ToV2(), aclgrpc.MatchType_MATCH_TYPE_UNSPECIFIED)
|
||||
require.Equal(t, eacl.MatchFromV2(aclgrpc.MatchType_STRING_NOT_EQUAL+1), eacl.MatchUnknown)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,8 @@ func TestFilterHeaderType(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("unknown header types", func(t *testing.T) {
|
||||
require.Equal(t, (eacl.HeaderFromService + 1).ToV2(), v2acl.HeaderTypeUnknown)
|
||||
require.Equal(t, eacl.FilterHeaderTypeFromV2(v2acl.HeaderTypeService+1), eacl.HeaderTypeUnknown)
|
||||
require.Equal(t, (eacl.HeaderFromService + 1).ToV2(), aclgrpc.HeaderType_HEADER_UNSPECIFIED)
|
||||
require.Equal(t, eacl.FilterHeaderTypeFromV2(aclgrpc.HeaderType_SERVICE+1), eacl.HeaderTypeUnknown)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@ package eacl
|
|||
import (
|
||||
"strconv"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Filter defines check conditions if request header is matched or not. Matched
|
||||
|
@ -75,16 +78,16 @@ func (f Filter) From() FilterHeaderType {
|
|||
// ToV2 converts Filter to v2 acl.EACLRecord.Filter message.
|
||||
//
|
||||
// Nil Filter converts to nil.
|
||||
func (f *Filter) ToV2() *v2acl.HeaderFilter {
|
||||
func (f *Filter) ToV2() *aclgrpc.EACLRecord_Filter {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
filter := new(v2acl.HeaderFilter)
|
||||
filter := new(aclgrpc.EACLRecord_Filter)
|
||||
filter.SetValue(f.value.EncodeToString())
|
||||
filter.SetKey(f.key.String())
|
||||
filter.SetMatchType(f.matcher.ToV2())
|
||||
filter.SetHeaderType(f.from.ToV2())
|
||||
filter.SetHeader(f.from.ToV2())
|
||||
|
||||
return filter
|
||||
}
|
||||
|
@ -94,23 +97,23 @@ func (k filterKey) String() string {
|
|||
default:
|
||||
return k.str
|
||||
case fKeyObjVersion:
|
||||
return v2acl.FilterObjectVersion
|
||||
return acl.FilterObjectVersion
|
||||
case fKeyObjID:
|
||||
return v2acl.FilterObjectID
|
||||
return acl.FilterObjectID
|
||||
case fKeyObjContainerID:
|
||||
return v2acl.FilterObjectContainerID
|
||||
return acl.FilterObjectContainerID
|
||||
case fKeyObjOwnerID:
|
||||
return v2acl.FilterObjectOwnerID
|
||||
return acl.FilterObjectOwnerID
|
||||
case fKeyObjCreationEpoch:
|
||||
return v2acl.FilterObjectCreationEpoch
|
||||
return acl.FilterObjectCreationEpoch
|
||||
case fKeyObjPayloadLength:
|
||||
return v2acl.FilterObjectPayloadLength
|
||||
return acl.FilterObjectPayloadLength
|
||||
case fKeyObjPayloadHash:
|
||||
return v2acl.FilterObjectPayloadHash
|
||||
return acl.FilterObjectPayloadHash
|
||||
case fKeyObjType:
|
||||
return v2acl.FilterObjectType
|
||||
return acl.FilterObjectType
|
||||
case fKeyObjHomomorphicHash:
|
||||
return v2acl.FilterObjectHomomorphicHash
|
||||
return acl.FilterObjectHomomorphicHash
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,23 +121,23 @@ func (k *filterKey) fromString(s string) {
|
|||
switch s {
|
||||
default:
|
||||
k.typ, k.str = 0, s
|
||||
case v2acl.FilterObjectVersion:
|
||||
case acl.FilterObjectVersion:
|
||||
k.typ, k.str = fKeyObjVersion, ""
|
||||
case v2acl.FilterObjectID:
|
||||
case acl.FilterObjectID:
|
||||
k.typ, k.str = fKeyObjID, ""
|
||||
case v2acl.FilterObjectContainerID:
|
||||
case acl.FilterObjectContainerID:
|
||||
k.typ, k.str = fKeyObjContainerID, ""
|
||||
case v2acl.FilterObjectOwnerID:
|
||||
case acl.FilterObjectOwnerID:
|
||||
k.typ, k.str = fKeyObjOwnerID, ""
|
||||
case v2acl.FilterObjectCreationEpoch:
|
||||
case acl.FilterObjectCreationEpoch:
|
||||
k.typ, k.str = fKeyObjCreationEpoch, ""
|
||||
case v2acl.FilterObjectPayloadLength:
|
||||
case acl.FilterObjectPayloadLength:
|
||||
k.typ, k.str = fKeyObjPayloadLength, ""
|
||||
case v2acl.FilterObjectPayloadHash:
|
||||
case acl.FilterObjectPayloadHash:
|
||||
k.typ, k.str = fKeyObjPayloadHash, ""
|
||||
case v2acl.FilterObjectType:
|
||||
case acl.FilterObjectType:
|
||||
k.typ, k.str = fKeyObjType, ""
|
||||
case v2acl.FilterObjectHomomorphicHash:
|
||||
case acl.FilterObjectHomomorphicHash:
|
||||
k.typ, k.str = fKeyObjHomomorphicHash, ""
|
||||
}
|
||||
}
|
||||
|
@ -147,11 +150,11 @@ func (k *filterKey) fromString(s string) {
|
|||
// - key: "";
|
||||
// - value: "".
|
||||
func NewFilter() *Filter {
|
||||
return NewFilterFromV2(new(v2acl.HeaderFilter))
|
||||
return NewFilterFromV2(new(aclgrpc.EACLRecord_Filter))
|
||||
}
|
||||
|
||||
// NewFilterFromV2 converts v2 acl.EACLRecord.Filter message to Filter.
|
||||
func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter {
|
||||
func NewFilterFromV2(filter *aclgrpc.EACLRecord_Filter) *Filter {
|
||||
f := new(Filter)
|
||||
|
||||
if filter == nil {
|
||||
|
@ -173,8 +176,8 @@ func (f *Filter) Marshal() ([]byte, error) {
|
|||
|
||||
// Unmarshal unmarshals protobuf binary representation of Filter.
|
||||
func (f *Filter) Unmarshal(data []byte) error {
|
||||
fV2 := new(v2acl.HeaderFilter)
|
||||
if err := fV2.Unmarshal(data); err != nil {
|
||||
fV2 := new(aclgrpc.EACLRecord_Filter)
|
||||
if err := proto.Unmarshal(data, fV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -185,13 +188,17 @@ func (f *Filter) Unmarshal(data []byte) error {
|
|||
|
||||
// MarshalJSON encodes Filter to protobuf JSON format.
|
||||
func (f *Filter) MarshalJSON() ([]byte, error) {
|
||||
return f.ToV2().MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
f.ToV2(),
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Filter from protobuf JSON format.
|
||||
func (f *Filter) UnmarshalJSON(data []byte) error {
|
||||
fV2 := new(v2acl.HeaderFilter)
|
||||
if err := fV2.UnmarshalJSON(data); err != nil {
|
||||
fV2 := new(aclgrpc.EACLRecord_Filter)
|
||||
if err := protojson.Unmarshal(data, fV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"strconv"
|
||||
"testing"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -24,8 +24,8 @@ func TestFilter(t *testing.T) {
|
|||
|
||||
v2 := filter.ToV2()
|
||||
require.NotNil(t, v2)
|
||||
require.Equal(t, v2acl.HeaderTypeObject, v2.GetHeaderType())
|
||||
require.EqualValues(t, v2acl.MatchTypeStringEqual, v2.GetMatchType())
|
||||
require.Equal(t, aclgrpc.HeaderType_OBJECT, v2.GetHeaderType())
|
||||
require.EqualValues(t, aclgrpc.MatchType_STRING_EQUAL, v2.GetMatchType())
|
||||
require.Equal(t, filter.Key(), v2.GetKey())
|
||||
require.Equal(t, filter.Value(), v2.GetValue())
|
||||
|
||||
|
@ -82,8 +82,8 @@ func TestFilter_ToV2(t *testing.T) {
|
|||
|
||||
require.Empty(t, filterV2.GetKey())
|
||||
require.Empty(t, filterV2.GetValue())
|
||||
require.Equal(t, v2acl.HeaderTypeUnknown, filterV2.GetHeaderType())
|
||||
require.Equal(t, v2acl.MatchTypeUnknown, filterV2.GetMatchType())
|
||||
require.Equal(t, aclgrpc.HeaderType_HEADER_UNSPECIFIED, filterV2.GetHeaderType())
|
||||
require.Equal(t, aclgrpc.MatchType_MATCH_TYPE_UNSPECIFIED, filterV2.GetMatchType())
|
||||
})
|
||||
|
||||
t.Run("reserved types", func(t *testing.T) {
|
||||
|
|
|
@ -3,13 +3,16 @@ package eacl
|
|||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Record of the ContainerEACL rule, that defines ContainerEACL action, targets for this action,
|
||||
|
@ -110,8 +113,8 @@ func (r *Record) AddObjectAttributeFilter(m Match, key, value string) {
|
|||
}
|
||||
|
||||
// AddObjectVersionFilter adds filter by object version.
|
||||
func (r *Record) AddObjectVersionFilter(m Match, v *version.Version) {
|
||||
r.addObjectReservedFilter(m, fKeyObjVersion, staticStringer(version.EncodeToString(*v)))
|
||||
func (r *Record) AddObjectVersionFilter(m Match, v version.Version) {
|
||||
r.addObjectReservedFilter(m, fKeyObjVersion, staticStringer(version.EncodeToString(v)))
|
||||
}
|
||||
|
||||
// AddObjectIDFilter adds filter by object ID.
|
||||
|
@ -157,26 +160,26 @@ func (r *Record) AddObjectHomomorphicHashFilter(m Match, h checksum.Checksum) {
|
|||
// ToV2 converts Record to v2 acl.EACLRecord message.
|
||||
//
|
||||
// Nil Record converts to nil.
|
||||
func (r *Record) ToV2() *v2acl.Record {
|
||||
func (r *Record) ToV2() *aclgrpc.EACLRecord {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
v2 := new(v2acl.Record)
|
||||
v2 := new(aclgrpc.EACLRecord)
|
||||
|
||||
if r.targets != nil {
|
||||
targets := make([]v2acl.Target, len(r.targets))
|
||||
targets := slices.MakePreallocPointerSlice[aclgrpc.EACLRecord_Target](len(r.targets))
|
||||
for i := range r.targets {
|
||||
targets[i] = *r.targets[i].ToV2()
|
||||
targets[i] = r.targets[i].ToV2()
|
||||
}
|
||||
|
||||
v2.SetTargets(targets)
|
||||
}
|
||||
|
||||
if r.filters != nil {
|
||||
filters := make([]v2acl.HeaderFilter, len(r.filters))
|
||||
filters := slices.MakePreallocPointerSlice[aclgrpc.EACLRecord_Filter](len(r.filters))
|
||||
for i := range r.filters {
|
||||
filters[i] = *r.filters[i].ToV2()
|
||||
filters[i] = r.filters[i].ToV2()
|
||||
}
|
||||
|
||||
v2.SetFilters(filters)
|
||||
|
@ -211,7 +214,7 @@ func CreateRecord(action Action, operation Operation) *Record {
|
|||
}
|
||||
|
||||
// NewRecordFromV2 converts v2 acl.EACLRecord message to Record.
|
||||
func NewRecordFromV2(record *v2acl.Record) *Record {
|
||||
func NewRecordFromV2(record *aclgrpc.EACLRecord) *Record {
|
||||
r := NewRecord()
|
||||
|
||||
if record == nil {
|
||||
|
@ -226,12 +229,12 @@ func NewRecordFromV2(record *v2acl.Record) *Record {
|
|||
|
||||
r.targets = make([]Target, len(v2targets))
|
||||
for i := range v2targets {
|
||||
r.targets[i] = *NewTargetFromV2(&v2targets[i])
|
||||
r.targets[i] = *NewTargetFromV2(v2targets[i])
|
||||
}
|
||||
|
||||
r.filters = make([]Filter, len(v2filters))
|
||||
for i := range v2filters {
|
||||
r.filters[i] = *NewFilterFromV2(&v2filters[i])
|
||||
r.filters[i] = *NewFilterFromV2(v2filters[i])
|
||||
}
|
||||
|
||||
return r
|
||||
|
@ -244,8 +247,8 @@ func (r *Record) Marshal() ([]byte, error) {
|
|||
|
||||
// Unmarshal unmarshals protobuf binary representation of Record.
|
||||
func (r *Record) Unmarshal(data []byte) error {
|
||||
fV2 := new(v2acl.Record)
|
||||
if err := fV2.Unmarshal(data); err != nil {
|
||||
fV2 := new(aclgrpc.EACLRecord)
|
||||
if err := proto.Unmarshal(data, fV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -256,13 +259,17 @@ func (r *Record) Unmarshal(data []byte) error {
|
|||
|
||||
// MarshalJSON encodes Record to protobuf JSON format.
|
||||
func (r *Record) MarshalJSON() ([]byte, error) {
|
||||
return r.ToV2().MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
r.ToV2(),
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Record from protobuf JSON format.
|
||||
func (r *Record) UnmarshalJSON(data []byte) error {
|
||||
tV2 := new(v2acl.Record)
|
||||
if err := tV2.UnmarshalJSON(data); err != nil {
|
||||
tV2 := new(aclgrpc.EACLRecord)
|
||||
if err := protojson.Unmarshal(data, tV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
|
@ -29,8 +30,8 @@ func TestRecord(t *testing.T) {
|
|||
|
||||
v2 := record.ToV2()
|
||||
require.NotNil(t, v2)
|
||||
require.Equal(t, v2acl.OperationRange, v2.GetOperation())
|
||||
require.Equal(t, v2acl.ActionAllow, v2.GetAction())
|
||||
require.Equal(t, aclgrpc.Operation_GETRANGE, v2.GetOperation())
|
||||
require.Equal(t, aclgrpc.Action_ALLOW, v2.GetAction())
|
||||
require.Len(t, v2.GetFilters(), len(record.Filters()))
|
||||
require.Len(t, v2.GetTargets(), len(record.Targets()))
|
||||
|
||||
|
@ -123,7 +124,7 @@ func TestRecordEncoding(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestRecord_ToV2(t *testing.T) {
|
||||
func TestRecord_ToProtobuf(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *Record
|
||||
|
||||
|
@ -142,8 +143,8 @@ func TestRecord_ToV2(t *testing.T) {
|
|||
// convert to v2 message
|
||||
recordV2 := record.ToV2()
|
||||
|
||||
require.Equal(t, v2acl.OperationUnknown, recordV2.GetOperation())
|
||||
require.Equal(t, v2acl.ActionUnknown, recordV2.GetAction())
|
||||
require.Equal(t, aclgrpc.Operation_OPERATION_UNSPECIFIED, recordV2.GetOperation())
|
||||
require.Equal(t, aclgrpc.Action_ACTION_UNSPECIFIED, recordV2.GetAction())
|
||||
require.Nil(t, recordV2.GetTargets())
|
||||
require.Nil(t, recordV2.GetFilters())
|
||||
})
|
||||
|
@ -170,43 +171,43 @@ func TestReservedRecords(t *testing.T) {
|
|||
value: "bar",
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectVersionFilter(MatchStringEqual, &v) },
|
||||
key: v2acl.FilterObjectVersion,
|
||||
f: func(r *Record) { r.AddObjectVersionFilter(MatchStringEqual, v) },
|
||||
key: acl.FilterObjectVersion,
|
||||
value: v.String(),
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectIDFilter(MatchStringEqual, oid) },
|
||||
key: v2acl.FilterObjectID,
|
||||
key: acl.FilterObjectID,
|
||||
value: oid.EncodeToString(),
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectContainerIDFilter(MatchStringEqual, cid) },
|
||||
key: v2acl.FilterObjectContainerID,
|
||||
key: acl.FilterObjectContainerID,
|
||||
value: cid.EncodeToString(),
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectOwnerIDFilter(MatchStringEqual, ownerid) },
|
||||
key: v2acl.FilterObjectOwnerID,
|
||||
key: acl.FilterObjectOwnerID,
|
||||
value: ownerid.EncodeToString(),
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectCreationEpoch(MatchStringEqual, 100) },
|
||||
key: v2acl.FilterObjectCreationEpoch,
|
||||
key: acl.FilterObjectCreationEpoch,
|
||||
value: "100",
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectPayloadLengthFilter(MatchStringEqual, 5000) },
|
||||
key: v2acl.FilterObjectPayloadLength,
|
||||
key: acl.FilterObjectPayloadLength,
|
||||
value: "5000",
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectPayloadHashFilter(MatchStringEqual, h) },
|
||||
key: v2acl.FilterObjectPayloadHash,
|
||||
key: acl.FilterObjectPayloadHash,
|
||||
value: h.String(),
|
||||
},
|
||||
{
|
||||
f: func(r *Record) { r.AddObjectHomomorphicHashFilter(MatchStringEqual, h) },
|
||||
key: v2acl.FilterObjectHomomorphicHash,
|
||||
key: acl.FilterObjectHomomorphicHash,
|
||||
value: h.String(),
|
||||
},
|
||||
{
|
||||
|
@ -214,7 +215,7 @@ func TestReservedRecords(t *testing.T) {
|
|||
require.True(t, typ.FromString("REGULAR"))
|
||||
r.AddObjectTypeFilter(MatchStringEqual, *typ)
|
||||
},
|
||||
key: v2acl.FilterObjectType,
|
||||
key: acl.FilterObjectType,
|
||||
value: "REGULAR",
|
||||
},
|
||||
{
|
||||
|
@ -222,7 +223,7 @@ func TestReservedRecords(t *testing.T) {
|
|||
require.True(t, typ.FromString("TOMBSTONE"))
|
||||
r.AddObjectTypeFilter(MatchStringEqual, *typ)
|
||||
},
|
||||
key: v2acl.FilterObjectType,
|
||||
key: acl.FilterObjectType,
|
||||
value: "TOMBSTONE",
|
||||
},
|
||||
{
|
||||
|
@ -230,7 +231,7 @@ func TestReservedRecords(t *testing.T) {
|
|||
require.True(t, typ.FromString("STORAGE_GROUP"))
|
||||
r.AddObjectTypeFilter(MatchStringEqual, *typ)
|
||||
},
|
||||
key: v2acl.FilterObjectType,
|
||||
key: acl.FilterObjectType,
|
||||
value: "STORAGE_GROUP",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -4,10 +4,13 @@ import (
|
|||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Table is a group of ContainerEACL records for single container.
|
||||
|
@ -20,7 +23,7 @@ type Table struct {
|
|||
}
|
||||
|
||||
// CID returns identifier of the container that should use given access control rules.
|
||||
func (t Table) CID() (cID cid.ID, isSet bool) {
|
||||
func (t *Table) CID() (cID cid.ID, isSet bool) {
|
||||
if t.cid != nil {
|
||||
cID = *t.cid
|
||||
isSet = true
|
||||
|
@ -35,7 +38,7 @@ func (t *Table) SetCID(cid cid.ID) {
|
|||
}
|
||||
|
||||
// Version returns version of eACL format.
|
||||
func (t Table) Version() version.Version {
|
||||
func (t *Table) Version() version.Version {
|
||||
return t.version
|
||||
}
|
||||
|
||||
|
@ -59,31 +62,31 @@ func (t *Table) AddRecord(r *Record) {
|
|||
// ToV2 converts Table to v2 acl.EACLTable message.
|
||||
//
|
||||
// Nil Table converts to nil.
|
||||
func (t *Table) ToV2() *v2acl.Table {
|
||||
func (t *Table) ToV2() *aclgrpc.EACLTable {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
v2 := new(v2acl.Table)
|
||||
var cidV2 refs.ContainerID
|
||||
v2 := new(aclgrpc.EACLTable)
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
|
||||
if t.cid != nil {
|
||||
t.cid.WriteToV2(&cidV2)
|
||||
v2.SetContainerID(&cidV2)
|
||||
v2.SetContainerId(&cidV2)
|
||||
}
|
||||
|
||||
if t.records != nil {
|
||||
records := make([]v2acl.Record, len(t.records))
|
||||
records := slices.MakePreallocPointerSlice[aclgrpc.EACLRecord](len(t.records))
|
||||
for i := range t.records {
|
||||
records[i] = *t.records[i].ToV2()
|
||||
records[i] = t.records[i].ToV2()
|
||||
}
|
||||
|
||||
v2.SetRecords(records)
|
||||
}
|
||||
|
||||
var verV2 refs.Version
|
||||
t.version.WriteToV2(&verV2)
|
||||
v2.SetVersion(&verV2)
|
||||
verV2 := new(refsgrpc.Version)
|
||||
t.version.WriteToV2(verV2)
|
||||
v2.SetVersion(verV2)
|
||||
|
||||
return v2
|
||||
}
|
||||
|
@ -112,7 +115,7 @@ func CreateTable(cid cid.ID) *Table {
|
|||
}
|
||||
|
||||
// NewTableFromV2 converts v2 acl.EACLTable message to Table.
|
||||
func NewTableFromV2(table *v2acl.Table) *Table {
|
||||
func NewTableFromV2(table *aclgrpc.EACLTable) *Table {
|
||||
t := new(Table)
|
||||
|
||||
if table == nil {
|
||||
|
@ -121,7 +124,7 @@ func NewTableFromV2(table *v2acl.Table) *Table {
|
|||
|
||||
// set version
|
||||
if v := table.GetVersion(); v != nil {
|
||||
ver := version.Version{}
|
||||
ver := version.NewVersion()
|
||||
ver.SetMajor(v.GetMajor())
|
||||
ver.SetMinor(v.GetMinor())
|
||||
|
||||
|
@ -129,7 +132,7 @@ func NewTableFromV2(table *v2acl.Table) *Table {
|
|||
}
|
||||
|
||||
// set container id
|
||||
if id := table.GetContainerID(); id != nil {
|
||||
if id := table.GetContainerId(); id != nil {
|
||||
if t.cid == nil {
|
||||
t.cid = new(cid.ID)
|
||||
}
|
||||
|
@ -145,7 +148,7 @@ func NewTableFromV2(table *v2acl.Table) *Table {
|
|||
t.records = make([]Record, len(v2records))
|
||||
|
||||
for i := range v2records {
|
||||
t.records[i] = *NewRecordFromV2(&v2records[i])
|
||||
t.records[i] = *NewRecordFromV2(v2records[i])
|
||||
}
|
||||
|
||||
return t
|
||||
|
@ -158,8 +161,8 @@ func (t *Table) Marshal() ([]byte, error) {
|
|||
|
||||
// Unmarshal unmarshals protobuf binary representation of Table.
|
||||
func (t *Table) Unmarshal(data []byte) error {
|
||||
fV2 := new(v2acl.Table)
|
||||
if err := fV2.Unmarshal(data); err != nil {
|
||||
fV2 := new(aclgrpc.EACLTable)
|
||||
if err := proto.Unmarshal(data, fV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -176,13 +179,17 @@ func (t *Table) Unmarshal(data []byte) error {
|
|||
|
||||
// MarshalJSON encodes Table to protobuf JSON format.
|
||||
func (t *Table) MarshalJSON() ([]byte, error) {
|
||||
return t.ToV2().MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
t.ToV2(),
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Table from protobuf JSON format.
|
||||
func (t *Table) UnmarshalJSON(data []byte) error {
|
||||
tV2 := new(v2acl.Table)
|
||||
if err := tV2.UnmarshalJSON(data); err != nil {
|
||||
tV2 := new(aclgrpc.EACLTable)
|
||||
if err := protojson.Unmarshal(data, tV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -221,15 +228,15 @@ func EqualTables(t1, t2 Table) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func checkFormat(v2 *v2acl.Table) error {
|
||||
func checkFormat(v2 *aclgrpc.EACLTable) error {
|
||||
var cID cid.ID
|
||||
|
||||
cidV2 := v2.GetContainerID()
|
||||
cidV2 := v2.GetContainerId()
|
||||
if cidV2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := cID.ReadFromV2(*cidV2)
|
||||
err := cID.ReadFromV2(cidV2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert V2 container ID: %w", err)
|
||||
}
|
||||
|
|
|
@ -4,16 +4,17 @@ import (
|
|||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
eacltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
var v version.Version
|
||||
v := version.NewVersion()
|
||||
|
||||
sha := sha256.Sum256([]byte("container id"))
|
||||
id := cidtest.IDWithChecksum(sha)
|
||||
|
@ -30,11 +31,11 @@ func TestTable(t *testing.T) {
|
|||
require.NotNil(t, v2)
|
||||
require.Equal(t, uint32(3), v2.GetVersion().GetMajor())
|
||||
require.Equal(t, uint32(2), v2.GetVersion().GetMinor())
|
||||
require.Equal(t, sha[:], v2.GetContainerID().GetValue())
|
||||
require.Equal(t, sha[:], v2.GetContainerId().GetValue())
|
||||
require.Len(t, v2.GetRecords(), 1)
|
||||
|
||||
newTable := eacl.NewTableFromV2(v2)
|
||||
require.Equal(t, table, newTable)
|
||||
require.True(t, proto.Equal(table.ToV2(), newTable.ToV2()))
|
||||
|
||||
t.Run("new from nil v2 table", func(t *testing.T) {
|
||||
require.Equal(t, new(eacl.Table), eacl.NewTableFromV2(nil))
|
||||
|
@ -110,10 +111,10 @@ func TestTable_ToV2(t *testing.T) {
|
|||
// convert to v2 message
|
||||
tableV2 := table.ToV2()
|
||||
|
||||
var verV2 refs.Version
|
||||
var verV2 refsgrpc.Version
|
||||
version.Current().WriteToV2(&verV2)
|
||||
require.Equal(t, verV2, *tableV2.GetVersion())
|
||||
require.True(t, proto.Equal(&verV2, tableV2.GetVersion()))
|
||||
require.Nil(t, tableV2.GetRecords())
|
||||
require.Nil(t, tableV2.GetContainerID())
|
||||
require.Nil(t, tableV2.GetContainerId())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ import (
|
|||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Target is a group of request senders to match ContainerEACL. Defined by role enum
|
||||
|
@ -90,12 +92,12 @@ func (t Target) Role() Role {
|
|||
// ToV2 converts Target to v2 acl.EACLRecord.Target message.
|
||||
//
|
||||
// Nil Target converts to nil.
|
||||
func (t *Target) ToV2() *v2acl.Target {
|
||||
func (t *Target) ToV2() *aclgrpc.EACLRecord_Target {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
target := new(v2acl.Target)
|
||||
target := new(aclgrpc.EACLRecord_Target)
|
||||
target.SetRole(t.role.ToV2())
|
||||
target.SetKeys(t.keys)
|
||||
|
||||
|
@ -108,11 +110,11 @@ func (t *Target) ToV2() *v2acl.Target {
|
|||
// - role: RoleUnknown;
|
||||
// - keys: nil.
|
||||
func NewTarget() *Target {
|
||||
return NewTargetFromV2(new(v2acl.Target))
|
||||
return NewTargetFromV2(new(aclgrpc.EACLRecord_Target))
|
||||
}
|
||||
|
||||
// NewTargetFromV2 converts v2 acl.EACLRecord.Target message to Target.
|
||||
func NewTargetFromV2(target *v2acl.Target) *Target {
|
||||
func NewTargetFromV2(target *aclgrpc.EACLRecord_Target) *Target {
|
||||
if target == nil {
|
||||
return new(Target)
|
||||
}
|
||||
|
@ -130,8 +132,8 @@ func (t *Target) Marshal() ([]byte, error) {
|
|||
|
||||
// Unmarshal unmarshals protobuf binary representation of Target.
|
||||
func (t *Target) Unmarshal(data []byte) error {
|
||||
fV2 := new(v2acl.Target)
|
||||
if err := fV2.Unmarshal(data); err != nil {
|
||||
fV2 := new(aclgrpc.EACLRecord_Target)
|
||||
if err := proto.Unmarshal(data, fV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -142,13 +144,17 @@ func (t *Target) Unmarshal(data []byte) error {
|
|||
|
||||
// MarshalJSON encodes Target to protobuf JSON format.
|
||||
func (t *Target) MarshalJSON() ([]byte, error) {
|
||||
return t.ToV2().MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
t.ToV2(),
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Target from protobuf JSON format.
|
||||
func (t *Target) UnmarshalJSON(data []byte) error {
|
||||
tV2 := new(v2acl.Target)
|
||||
if err := tV2.UnmarshalJSON(data); err != nil {
|
||||
tV2 := new(aclgrpc.EACLRecord_Target)
|
||||
if err := protojson.Unmarshal(data, tV2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"testing"
|
||||
|
||||
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||
aclgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -21,7 +21,7 @@ func TestTarget(t *testing.T) {
|
|||
|
||||
v2 := target.ToV2()
|
||||
require.NotNil(t, v2)
|
||||
require.Equal(t, v2acl.RoleSystem, v2.GetRole())
|
||||
require.Equal(t, aclgrpc.Role_SYSTEM, v2.GetRole())
|
||||
require.Len(t, v2.GetKeys(), len(pubs))
|
||||
for i, key := range v2.GetKeys() {
|
||||
require.Equal(t, key, (*keys.PublicKey)(pubs[i]).Bytes())
|
||||
|
@ -78,7 +78,7 @@ func TestTarget_ToV2(t *testing.T) {
|
|||
// convert to v2 message
|
||||
targetV2 := target.ToV2()
|
||||
|
||||
require.Equal(t, v2acl.RoleUnknown, targetV2.GetRole())
|
||||
require.Equal(t, aclgrpc.Role_ROLE_UNSPECIFIED, targetV2.GetRole())
|
||||
require.Nil(t, targetV2.GetKeys())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
// Header is an interface of string key-value header.
|
||||
type Header interface {
|
||||
Key() string
|
||||
Value() string
|
||||
GetKey() string
|
||||
GetValue() string
|
||||
}
|
||||
|
||||
// TypedHeaderSource is the interface that wraps
|
||||
|
|
|
@ -71,7 +71,7 @@ func matchFilters(hdrSrc TypedHeaderSource, filters []Filter) int {
|
|||
}
|
||||
|
||||
// check header name
|
||||
if header.Key() != filter.Key() {
|
||||
if header.GetKey() != filter.Key() {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -122,10 +122,10 @@ func targetMatches(unit *ValidationUnit, record *Record) bool {
|
|||
// Maps match type to corresponding function.
|
||||
var mMatchFns = map[Match]func(Header, *Filter) bool{
|
||||
MatchStringEqual: func(header Header, filter *Filter) bool {
|
||||
return header.Value() == filter.Value()
|
||||
return header.GetValue() == filter.Value()
|
||||
},
|
||||
|
||||
MatchStringNotEqual: func(header Header, filter *Filter) bool {
|
||||
return header.Value() != filter.Value()
|
||||
return header.GetValue() != filter.Value()
|
||||
},
|
||||
}
|
||||
|
|
|
@ -214,8 +214,8 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
func (h hdr) Key() string { return h.key }
|
||||
func (h hdr) Value() string { return h.value }
|
||||
func (h hdr) GetKey() string { return h.key }
|
||||
func (h hdr) GetValue() string { return h.value }
|
||||
|
||||
func makeHeaders(kv ...string) []Header {
|
||||
hs := make([]Header, len(kv)/2)
|
||||
|
|
4
go.mod
4
go.mod
|
@ -2,6 +2,8 @@ module git.frostfs.info/TrueCloudLab/frostfs-sdk-go
|
|||
|
||||
go 1.19
|
||||
|
||||
replace git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230704092742-285516a94ebe => git.frostfs.info/aarifullin/frostfs-api-go/v2 v2.15.1-0.20230710090848-bc16a32c24c3
|
||||
|
||||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230704092742-285516a94ebe
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb
|
||||
|
@ -9,6 +11,7 @@ require (
|
|||
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
||||
git.frostfs.info/TrueCloudLab/tzhash v1.8.0
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.2
|
||||
github.com/mr-tron/base58 v1.2.0
|
||||
|
@ -24,7 +27,6 @@ require (
|
|||
github.com/benbjohnson/clock v1.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect
|
||||
|
|
BIN
go.sum
BIN
go.sum
Binary file not shown.
|
@ -40,7 +40,7 @@ type (
|
|||
}
|
||||
|
||||
// weightFunc calculates n's weight.
|
||||
weightFunc = func(NodeInfo) float64
|
||||
weightFunc = func(*NodeInfo) float64
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -55,7 +55,7 @@ var (
|
|||
// newWeightFunc returns weightFunc which multiplies normalized
|
||||
// capacity and price.
|
||||
func newWeightFunc(capNorm, priceNorm normalizer) weightFunc {
|
||||
return func(n NodeInfo) float64 {
|
||||
return func(n *NodeInfo) float64 {
|
||||
return capNorm.Normalize(float64(n.capacity())) * priceNorm.Normalize(float64(n.Price()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package netmap
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/hrw"
|
||||
)
|
||||
|
||||
|
@ -13,10 +13,10 @@ type context struct {
|
|||
netMap NetMap
|
||||
|
||||
// cache of processed filters
|
||||
processedFilters map[string]*netmap.Filter
|
||||
processedFilters map[string]*netmapgrpc.Filter
|
||||
|
||||
// cache of processed selectors
|
||||
processedSelectors map[string]*netmap.Selector
|
||||
processedSelectors map[string]*netmapgrpc.Selector
|
||||
|
||||
// stores results of selector processing
|
||||
selections map[string][]nodes
|
||||
|
@ -57,8 +57,8 @@ var (
|
|||
func newContext(nm NetMap) *context {
|
||||
return &context{
|
||||
netMap: nm,
|
||||
processedFilters: make(map[string]*netmap.Filter),
|
||||
processedSelectors: make(map[string]*netmap.Selector),
|
||||
processedFilters: make(map[string]*netmapgrpc.Filter),
|
||||
processedSelectors: make(map[string]*netmapgrpc.Selector),
|
||||
selections: make(map[string][]nodes),
|
||||
|
||||
numCache: make(map[string]uint64),
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
)
|
||||
|
||||
// mainFilterName is a name of the filter
|
||||
|
@ -22,7 +22,7 @@ func (c *context) processFilters(p PlacementPolicy) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *context) processFilter(f netmap.Filter, top bool) error {
|
||||
func (c *context) processFilter(f *netmapgrpc.Filter, top bool) error {
|
||||
fName := f.GetName()
|
||||
if fName == mainFilterName {
|
||||
return fmt.Errorf("%w: '%s' is reserved", errInvalidFilterName, mainFilterName)
|
||||
|
@ -39,7 +39,7 @@ func (c *context) processFilter(f netmap.Filter, top bool) error {
|
|||
inner := f.GetFilters()
|
||||
|
||||
switch op := f.GetOp(); op {
|
||||
case netmap.AND, netmap.OR, netmap.NOT:
|
||||
case netmapgrpc.Operation_AND, netmapgrpc.Operation_OR, netmapgrpc.Operation_NOT:
|
||||
for i := range inner {
|
||||
if err := c.processFilter(inner[i], false); err != nil {
|
||||
return fmt.Errorf("process inner filter #%d: %w", i, err)
|
||||
|
@ -53,8 +53,8 @@ func (c *context) processFilter(f netmap.Filter, top bool) error {
|
|||
}
|
||||
|
||||
switch op {
|
||||
case netmap.EQ, netmap.NE:
|
||||
case netmap.GT, netmap.GE, netmap.LT, netmap.LE:
|
||||
case netmapgrpc.Operation_EQ, netmapgrpc.Operation_NE:
|
||||
case netmapgrpc.Operation_GT, netmapgrpc.Operation_GE, netmapgrpc.Operation_LT, netmapgrpc.Operation_LE:
|
||||
val := f.GetValue()
|
||||
n, err := strconv.ParseUint(val, 10, 64)
|
||||
if err != nil {
|
||||
|
@ -68,7 +68,7 @@ func (c *context) processFilter(f netmap.Filter, top bool) error {
|
|||
}
|
||||
|
||||
if top {
|
||||
c.processedFilters[fName] = &f
|
||||
c.processedFilters[fName] = f
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -77,40 +77,40 @@ func (c *context) processFilter(f netmap.Filter, top bool) error {
|
|||
// match matches f against b. It returns no errors because
|
||||
// filter should have been parsed during context creation
|
||||
// and missing node properties are considered as a regular fail.
|
||||
func (c *context) match(f *netmap.Filter, b NodeInfo) bool {
|
||||
func (c *context) match(f *netmapgrpc.Filter, b *NodeInfo) bool {
|
||||
switch f.GetOp() {
|
||||
case netmap.NOT:
|
||||
case netmapgrpc.Operation_NOT:
|
||||
inner := f.GetFilters()
|
||||
fSub := &inner[0]
|
||||
fSub := inner[0]
|
||||
if name := inner[0].GetName(); name != "" {
|
||||
fSub = c.processedFilters[name]
|
||||
}
|
||||
return !c.match(fSub, b)
|
||||
case netmap.AND, netmap.OR:
|
||||
case netmapgrpc.Operation_AND, netmapgrpc.Operation_OR:
|
||||
inner := f.GetFilters()
|
||||
for i := range inner {
|
||||
fSub := &inner[i]
|
||||
fSub := inner[i]
|
||||
if name := inner[i].GetName(); name != "" {
|
||||
fSub = c.processedFilters[name]
|
||||
}
|
||||
|
||||
ok := c.match(fSub, b)
|
||||
if ok == (f.GetOp() == netmap.OR) {
|
||||
if ok == (f.GetOp() == netmapgrpc.Operation_OR) {
|
||||
return ok
|
||||
}
|
||||
}
|
||||
|
||||
return f.GetOp() == netmap.AND
|
||||
return f.GetOp() == netmapgrpc.Operation_AND
|
||||
default:
|
||||
return c.matchKeyValue(f, b)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) matchKeyValue(f *netmap.Filter, b NodeInfo) bool {
|
||||
func (c *context) matchKeyValue(f *netmapgrpc.Filter, b *NodeInfo) bool {
|
||||
switch op := f.GetOp(); op {
|
||||
case netmap.EQ:
|
||||
case netmapgrpc.Operation_EQ:
|
||||
return b.Attribute(f.GetKey()) == f.GetValue()
|
||||
case netmap.NE:
|
||||
case netmapgrpc.Operation_NE:
|
||||
return b.Attribute(f.GetKey()) != f.GetValue()
|
||||
default:
|
||||
var attr uint64
|
||||
|
@ -132,13 +132,13 @@ func (c *context) matchKeyValue(f *netmap.Filter, b NodeInfo) bool {
|
|||
}
|
||||
|
||||
switch op {
|
||||
case netmap.GT:
|
||||
case netmapgrpc.Operation_GT:
|
||||
return attr > c.numCache[f.GetValue()]
|
||||
case netmap.GE:
|
||||
case netmapgrpc.Operation_GE:
|
||||
return attr >= c.numCache[f.GetValue()]
|
||||
case netmap.LT:
|
||||
case netmapgrpc.Operation_LT:
|
||||
return attr < c.numCache[f.GetValue()]
|
||||
case netmap.LE:
|
||||
case netmapgrpc.Operation_LE:
|
||||
return attr <= c.numCache[f.GetValue()]
|
||||
default:
|
||||
// do nothing and return false
|
||||
|
|
|
@ -4,17 +4,18 @@ import (
|
|||
"errors"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestContext_ProcessFilters(t *testing.T) {
|
||||
fs := []Filter{
|
||||
newFilter("StorageSSD", "Storage", "SSD", netmap.EQ),
|
||||
newFilter("GoodRating", "Rating", "4", netmap.GE),
|
||||
newFilter("Main", "", "", netmap.AND,
|
||||
newFilter("StorageSSD", "Storage", "SSD", netmapgrpc.Operation_EQ),
|
||||
newFilter("GoodRating", "Rating", "4", netmapgrpc.Operation_GE),
|
||||
newFilter("Main", "", "", netmapgrpc.Operation_AND,
|
||||
newFilter("StorageSSD", "", "", 0),
|
||||
newFilter("", "IntField", "123", netmap.LT),
|
||||
newFilter("", "IntField", "123", netmapgrpc.Operation_LT),
|
||||
newFilter("GoodRating", "", "", 0)),
|
||||
}
|
||||
|
||||
|
@ -23,7 +24,7 @@ func TestContext_ProcessFilters(t *testing.T) {
|
|||
require.NoError(t, c.processFilters(p))
|
||||
require.Equal(t, 3, len(c.processedFilters))
|
||||
for _, f := range fs {
|
||||
require.Equal(t, f.m, *c.processedFilters[f.m.GetName()])
|
||||
require.True(t, proto.Equal(f.m, c.processedFilters[f.m.GetName()]))
|
||||
}
|
||||
|
||||
require.Equal(t, uint64(4), c.numCache[fs[1].m.GetValue()])
|
||||
|
@ -38,24 +39,24 @@ func TestContext_ProcessFiltersInvalid(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
"UnnamedTop",
|
||||
newFilter("", "Storage", "SSD", netmap.EQ),
|
||||
newFilter("", "Storage", "SSD", netmapgrpc.Operation_EQ),
|
||||
errUnnamedTopFilter,
|
||||
},
|
||||
{
|
||||
"InvalidReference",
|
||||
newFilter("Main", "", "", netmap.AND,
|
||||
newFilter("Main", "", "", netmapgrpc.Operation_AND,
|
||||
newFilter("StorageSSD", "", "", 0)),
|
||||
errFilterNotFound,
|
||||
},
|
||||
{
|
||||
"NonEmptyKeyed",
|
||||
newFilter("Main", "Storage", "SSD", netmap.EQ,
|
||||
newFilter("Main", "Storage", "SSD", netmapgrpc.Operation_EQ,
|
||||
newFilter("StorageSSD", "", "", 0)),
|
||||
errNonEmptyFilters,
|
||||
},
|
||||
{
|
||||
"InvalidNumber",
|
||||
newFilter("Main", "Rating", "three", netmap.GE),
|
||||
newFilter("Main", "Rating", "three", netmapgrpc.Operation_GE),
|
||||
errInvalidNumber,
|
||||
},
|
||||
{
|
||||
|
@ -65,7 +66,7 @@ func TestContext_ProcessFiltersInvalid(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"InvalidName",
|
||||
newFilter("*", "Rating", "3", netmap.GE),
|
||||
newFilter("*", "Rating", "3", netmapgrpc.Operation_GE),
|
||||
errInvalidFilterName,
|
||||
},
|
||||
}
|
||||
|
@ -80,16 +81,16 @@ func TestContext_ProcessFiltersInvalid(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFilter_MatchSimple_InvalidOp(t *testing.T) {
|
||||
var b NodeInfo
|
||||
b := NewNodeInfo()
|
||||
b.SetAttribute("Rating", "4")
|
||||
b.SetAttribute("Country", "Germany")
|
||||
|
||||
f := newFilter("Main", "Rating", "5", netmap.EQ)
|
||||
f := newFilter("Main", "Rating", "5", netmapgrpc.Operation_EQ)
|
||||
c := newContext(NetMap{})
|
||||
p := newPlacementPolicy(1, nil, nil, []Filter{f})
|
||||
require.NoError(t, c.processFilters(p))
|
||||
|
||||
// just for the coverage
|
||||
f.m.SetOp(0)
|
||||
require.False(t, c.match(&f.m, b))
|
||||
require.False(t, c.match(f.m, &b))
|
||||
}
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
package netmap
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
func newFilter(name string, k, v string, op netmap.Operation, fs ...Filter) (f Filter) {
|
||||
func newFilter(name string, k, v string, op netmapgrpc.Operation, fs ...Filter) (f Filter) {
|
||||
f = NewFilter()
|
||||
f.SetName(name)
|
||||
f.m.SetKey(k)
|
||||
f.m.SetOp(op)
|
||||
f.m.SetValue(v)
|
||||
inner := make([]netmap.Filter, len(fs))
|
||||
inner := slices.MakePreallocPointerSlice[netmapgrpc.Filter](len(fs))
|
||||
for i := range fs {
|
||||
inner[i] = fs[i].m
|
||||
inner[i] = new(netmapgrpc.Filter)
|
||||
proto.Merge(inner[i], fs[i].m)
|
||||
}
|
||||
f.m.SetFilters(inner)
|
||||
return f
|
||||
}
|
||||
|
||||
func newSelector(name string, attr string, count uint32, filter string, clause func(*Selector)) (s Selector) {
|
||||
s = NewSelector()
|
||||
s.SetName(name)
|
||||
s.SelectByBucketAttribute(attr)
|
||||
s.SetNumberOfNodes(count)
|
||||
|
@ -35,12 +40,14 @@ func newPlacementPolicy(bf uint32, rs []ReplicaDescriptor, ss []Selector, fs []F
|
|||
}
|
||||
|
||||
func newReplica(c uint32, s string) (r ReplicaDescriptor) {
|
||||
r = NewReplicaDescriptor()
|
||||
r.SetNumberOfObjects(c)
|
||||
r.SetSelectorName(s)
|
||||
return r
|
||||
}
|
||||
|
||||
func nodeInfoFromAttributes(props ...string) (n NodeInfo) {
|
||||
n = NewNodeInfo()
|
||||
for i := 0; i < len(props); i += 2 {
|
||||
n.SetAttribute(props[i], props[i+1])
|
||||
}
|
||||
|
|
|
@ -3,14 +3,15 @@ package netmap
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"git.frostfs.info/TrueCloudLab/hrw"
|
||||
)
|
||||
|
||||
// NetMap represents FrostFS network map. It includes information about all
|
||||
// storage nodes registered in FrostFS the network.
|
||||
//
|
||||
// NetMap is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NetMap
|
||||
// NetMap is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmapgrpc.Netmap
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
|
@ -20,13 +21,13 @@ type NetMap struct {
|
|||
nodes []NodeInfo
|
||||
}
|
||||
|
||||
// ReadFromV2 reads NetMap from the netmap.NetMap message. Checks if the
|
||||
// ReadFromV2 reads NetMap from the netmapgrpc.Netmap message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (m *NetMap) ReadFromV2(msg netmap.NetMap) error {
|
||||
func (m *NetMap) ReadFromV2(msg *netmapgrpc.Netmap) error {
|
||||
var err error
|
||||
nodes := msg.Nodes()
|
||||
nodes := msg.GetNodes()
|
||||
|
||||
if nodes == nil {
|
||||
m.nodes = nil
|
||||
|
@ -41,23 +42,23 @@ func (m *NetMap) ReadFromV2(msg netmap.NetMap) error {
|
|||
}
|
||||
}
|
||||
|
||||
m.epoch = msg.Epoch()
|
||||
m.epoch = msg.GetEpoch()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteToV2 writes NetMap to the netmap.NetMap message. The message
|
||||
// WriteToV2 writes NetMap to the netmapgrpc.Netmap message. The message
|
||||
// MUST NOT be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (m NetMap) WriteToV2(msg *netmap.NetMap) {
|
||||
var nodes []netmap.NodeInfo
|
||||
func (m NetMap) WriteToV2(msg *netmapgrpc.Netmap) {
|
||||
msg.Reset()
|
||||
var nodes []*netmapgrpc.NodeInfo
|
||||
|
||||
if m.nodes != nil {
|
||||
nodes = make([]netmap.NodeInfo, len(m.nodes))
|
||||
|
||||
nodes = slices.MakePreallocPointerSlice[netmapgrpc.NodeInfo](len(m.nodes))
|
||||
for i := range m.nodes {
|
||||
m.nodes[i].WriteToV2(&nodes[i])
|
||||
m.nodes[i].WriteToV2(nodes[i])
|
||||
}
|
||||
|
||||
msg.SetNodes(nodes)
|
||||
|
@ -117,7 +118,7 @@ func (n nodes) Hash() uint64 {
|
|||
func (n nodes) weights(wf weightFunc) []float64 {
|
||||
w := make([]float64, 0, len(n))
|
||||
for i := range n {
|
||||
w = append(w, wf(n[i]))
|
||||
w = append(w, wf(&n[i]))
|
||||
}
|
||||
|
||||
return w
|
||||
|
@ -189,11 +190,11 @@ func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, e
|
|||
sName := p.replicas[i].GetSelector()
|
||||
if sName == "" {
|
||||
if len(p.selectors) == 0 {
|
||||
var s netmap.Selector
|
||||
var s netmapgrpc.Selector
|
||||
s.SetCount(p.replicas[i].GetCount())
|
||||
s.SetFilter(mainFilterName)
|
||||
|
||||
nodes, err := c.getSelection(s)
|
||||
nodes, err := c.getSelection(&s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -221,7 +222,7 @@ func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, e
|
|||
}
|
||||
|
||||
if p.unique {
|
||||
nodes, err := c.getSelection(*c.processedSelectors[sName])
|
||||
nodes, err := c.getSelection(c.processedSelectors[sName])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@ package netmap_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -19,15 +20,16 @@ func TestNetMapNodes(t *testing.T) {
|
|||
nm.SetNodes(nodes)
|
||||
require.ElementsMatch(t, nodes, nm.Nodes())
|
||||
|
||||
nodesV2 := make([]v2netmap.NodeInfo, len(nodes))
|
||||
nodesV2 := slices.MakePreallocPointerSlice[netmapgrpc.NodeInfo](len(nodes))
|
||||
|
||||
for i := range nodes {
|
||||
nodes[i].WriteToV2(&nodesV2[i])
|
||||
nodes[i].WriteToV2(nodesV2[i])
|
||||
}
|
||||
|
||||
var m v2netmap.NetMap
|
||||
var m netmapgrpc.Netmap
|
||||
nm.WriteToV2(&m)
|
||||
|
||||
require.ElementsMatch(t, nodesV2, m.Nodes())
|
||||
require.ElementsMatch(t, nodesV2, m.GetNodes())
|
||||
}
|
||||
|
||||
func TestNetMap_SetEpoch(t *testing.T) {
|
||||
|
@ -40,8 +42,8 @@ func TestNetMap_SetEpoch(t *testing.T) {
|
|||
nm.SetEpoch(e)
|
||||
require.EqualValues(t, e, nm.Epoch())
|
||||
|
||||
var m v2netmap.NetMap
|
||||
var m netmapgrpc.Netmap
|
||||
nm.WriteToV2(&m)
|
||||
|
||||
require.EqualValues(t, e, m.Epoch())
|
||||
require.EqualValues(t, e, m.GetEpoch())
|
||||
}
|
||||
|
|
|
@ -6,25 +6,32 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// NetworkInfo groups information about the FrostFS network state. Mainly used to
|
||||
// describe the current state of the network.
|
||||
//
|
||||
// NetworkInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NetworkInfo
|
||||
// NetworkInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmapgrpc.NetworkInfo
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
// Instances must be created by NewNetworkInfo() constructor.
|
||||
type NetworkInfo struct {
|
||||
m netmap.NetworkInfo
|
||||
m *netmapgrpc.NetworkInfo
|
||||
}
|
||||
|
||||
// reads NetworkInfo from netmap.NetworkInfo message. If checkFieldPresence is set,
|
||||
func NewNetworkInfo() NetworkInfo {
|
||||
return NetworkInfo{
|
||||
m: &netmapgrpc.NetworkInfo{},
|
||||
}
|
||||
}
|
||||
|
||||
// reads NetworkInfo from netmapgrpc.NetworkInfo message. If checkFieldPresence is set,
|
||||
// returns an error on absence of any protocol-required field. Verifies format of any
|
||||
// presented field according to FrostFS API V2 protocol.
|
||||
func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool) error {
|
||||
func (x *NetworkInfo) readFromV2(m *netmapgrpc.NetworkInfo, checkFieldPresence bool) error {
|
||||
c := m.GetNetworkConfig()
|
||||
if checkFieldPresence && c == nil {
|
||||
return errors.New("missing network config")
|
||||
|
@ -37,7 +44,7 @@ func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool)
|
|||
var err error
|
||||
mNames := make(map[string]struct{}, c.NumberOfParameters())
|
||||
|
||||
c.IterateParameters(func(prm *netmap.NetworkParameter) bool {
|
||||
c.IterateParameters(func(prm *netmapgrpc.NetworkConfig_Parameter) bool {
|
||||
name := string(prm.GetKey())
|
||||
|
||||
_, was := mNames[name]
|
||||
|
@ -80,25 +87,29 @@ func (x *NetworkInfo) readFromV2(m netmap.NetworkInfo, checkFieldPresence bool)
|
|||
return err
|
||||
}
|
||||
|
||||
x.m = m
|
||||
if x.m == nil {
|
||||
x.m = new(netmapgrpc.NetworkInfo)
|
||||
}
|
||||
proto.Merge(x.m, m)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadFromV2 reads NetworkInfo from the netmap.NetworkInfo message. Checks if the
|
||||
// ReadFromV2 reads NetworkInfo from the netmapgrpc.NetworkInfo message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (x *NetworkInfo) ReadFromV2(m netmap.NetworkInfo) error {
|
||||
func (x *NetworkInfo) ReadFromV2(m *netmapgrpc.NetworkInfo) error {
|
||||
return x.readFromV2(m, true)
|
||||
}
|
||||
|
||||
// WriteToV2 writes NetworkInfo to the netmap.NetworkInfo message. The message
|
||||
// WriteToV2 writes NetworkInfo to the netmapgrpc.NetworkInfo message. The message
|
||||
// MUST NOT be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x NetworkInfo) WriteToV2(m *netmap.NetworkInfo) {
|
||||
*m = x.m
|
||||
func (x *NetworkInfo) WriteToV2(m *netmapgrpc.NetworkInfo) {
|
||||
m.Reset()
|
||||
proto.Merge(m, x.m)
|
||||
}
|
||||
|
||||
// CurrentEpoch returns epoch set using SetCurrentEpoch.
|
||||
|
@ -116,7 +127,7 @@ func (x *NetworkInfo) SetCurrentEpoch(epoch uint64) {
|
|||
// MagicNumber returns magic number set using SetMagicNumber.
|
||||
//
|
||||
// Zero NetworkInfo has zero magic.
|
||||
func (x NetworkInfo) MagicNumber() uint64 {
|
||||
func (x *NetworkInfo) MagicNumber() uint64 {
|
||||
return x.m.GetMagicNumber()
|
||||
}
|
||||
|
||||
|
@ -128,7 +139,7 @@ func (x *NetworkInfo) SetMagicNumber(epoch uint64) {
|
|||
}
|
||||
|
||||
// MsPerBlock returns network parameter set using SetMsPerBlock.
|
||||
func (x NetworkInfo) MsPerBlock() int64 {
|
||||
func (x *NetworkInfo) MsPerBlock() int64 {
|
||||
return x.m.GetMsPerBlock()
|
||||
}
|
||||
|
||||
|
@ -142,13 +153,13 @@ func (x *NetworkInfo) SetMsPerBlock(v int64) {
|
|||
func (x *NetworkInfo) setConfig(name string, val []byte) {
|
||||
c := x.m.GetNetworkConfig()
|
||||
if c == nil {
|
||||
c = new(netmap.NetworkConfig)
|
||||
c = new(netmapgrpc.NetworkConfig)
|
||||
|
||||
var prm netmap.NetworkParameter
|
||||
var prm netmapgrpc.NetworkConfig_Parameter
|
||||
prm.SetKey([]byte(name))
|
||||
prm.SetValue(val)
|
||||
|
||||
c.SetParameters(prm)
|
||||
c.SetParameters([]*netmapgrpc.NetworkConfig_Parameter{&prm})
|
||||
|
||||
x.m.SetNetworkConfig(c)
|
||||
|
||||
|
@ -156,30 +167,30 @@ func (x *NetworkInfo) setConfig(name string, val []byte) {
|
|||
}
|
||||
|
||||
found := false
|
||||
prms := make([]netmap.NetworkParameter, 0, c.NumberOfParameters())
|
||||
prms := make([]*netmapgrpc.NetworkConfig_Parameter, 0, c.NumberOfParameters())
|
||||
|
||||
c.IterateParameters(func(prm *netmap.NetworkParameter) bool {
|
||||
c.IterateParameters(func(prm *netmapgrpc.NetworkConfig_Parameter) bool {
|
||||
found = bytes.Equal(prm.GetKey(), []byte(name))
|
||||
if found {
|
||||
prm.SetValue(val)
|
||||
} else {
|
||||
prms = append(prms, *prm)
|
||||
prms = append(prms, prm)
|
||||
}
|
||||
|
||||
return found
|
||||
})
|
||||
|
||||
if !found {
|
||||
prms = append(prms, netmap.NetworkParameter{})
|
||||
prms = append(prms, &netmapgrpc.NetworkConfig_Parameter{})
|
||||
prms[len(prms)-1].SetKey([]byte(name))
|
||||
prms[len(prms)-1].SetValue(val)
|
||||
|
||||
c.SetParameters(prms...)
|
||||
c.SetParameters(prms)
|
||||
}
|
||||
}
|
||||
|
||||
func (x NetworkInfo) configValue(name string) (res []byte) {
|
||||
x.m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool {
|
||||
func (x *NetworkInfo) configValue(name string) (res []byte) {
|
||||
x.m.GetNetworkConfig().IterateParameters(func(prm *netmapgrpc.NetworkConfig_Parameter) bool {
|
||||
if string(prm.GetKey()) == name {
|
||||
res = prm.GetValue()
|
||||
|
||||
|
@ -221,7 +232,7 @@ func (x *NetworkInfo) RawNetworkParameter(name string) []byte {
|
|||
func (x *NetworkInfo) IterateRawNetworkParameters(f func(name string, value []byte)) {
|
||||
c := x.m.GetNetworkConfig()
|
||||
|
||||
c.IterateParameters(func(prm *netmap.NetworkParameter) bool {
|
||||
c.IterateParameters(func(prm *netmapgrpc.NetworkConfig_Parameter) bool {
|
||||
name := string(prm.GetKey())
|
||||
switch name {
|
||||
default:
|
||||
|
@ -282,7 +293,7 @@ func decodeConfigValueBool(val []byte) (bool, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (x NetworkInfo) configUint64(name string) uint64 {
|
||||
func (x *NetworkInfo) configUint64(name string) uint64 {
|
||||
val := x.configValue(name)
|
||||
if val == nil {
|
||||
return 0
|
||||
|
@ -298,7 +309,7 @@ func (x NetworkInfo) configUint64(name string) uint64 {
|
|||
return res
|
||||
}
|
||||
|
||||
func (x NetworkInfo) configBool(name string) bool {
|
||||
func (x *NetworkInfo) configBool(name string) bool {
|
||||
val := x.configValue(name)
|
||||
if val == nil {
|
||||
return false
|
||||
|
@ -326,7 +337,7 @@ func (x *NetworkInfo) SetAuditFee(fee uint64) {
|
|||
// AuditFee returns audit fee set using SetAuditFee.
|
||||
//
|
||||
// Zero NetworkInfo has zero audit fee.
|
||||
func (x NetworkInfo) AuditFee() uint64 {
|
||||
func (x *NetworkInfo) AuditFee() uint64 {
|
||||
return x.configUint64(configAuditFee)
|
||||
}
|
||||
|
||||
|
@ -343,7 +354,7 @@ func (x *NetworkInfo) SetStoragePrice(price uint64) {
|
|||
// StoragePrice returns storage price set using SetStoragePrice.
|
||||
//
|
||||
// Zero NetworkInfo has zero storage price.
|
||||
func (x NetworkInfo) StoragePrice() uint64 {
|
||||
func (x *NetworkInfo) StoragePrice() uint64 {
|
||||
return x.configUint64(configStoragePrice)
|
||||
}
|
||||
|
||||
|
@ -360,7 +371,7 @@ func (x *NetworkInfo) SetContainerFee(fee uint64) {
|
|||
// ContainerFee returns container fee set using SetContainerFee.
|
||||
//
|
||||
// Zero NetworkInfo has zero container fee.
|
||||
func (x NetworkInfo) ContainerFee() uint64 {
|
||||
func (x *NetworkInfo) ContainerFee() uint64 {
|
||||
return x.configUint64(configContainerFee)
|
||||
}
|
||||
|
||||
|
@ -377,7 +388,7 @@ func (x *NetworkInfo) SetNamedContainerFee(fee uint64) {
|
|||
// NamedContainerFee returns container fee set using SetNamedContainerFee.
|
||||
//
|
||||
// Zero NetworkInfo has zero container fee.
|
||||
func (x NetworkInfo) NamedContainerFee() uint64 {
|
||||
func (x *NetworkInfo) NamedContainerFee() uint64 {
|
||||
return x.configUint64(configNamedContainerFee)
|
||||
}
|
||||
|
||||
|
@ -394,7 +405,7 @@ func (x *NetworkInfo) SetEpochDuration(blocks uint64) {
|
|||
// EpochDuration returns epoch duration set using SetEpochDuration.
|
||||
//
|
||||
// Zero NetworkInfo has zero iteration number.
|
||||
func (x NetworkInfo) EpochDuration() uint64 {
|
||||
func (x *NetworkInfo) EpochDuration() uint64 {
|
||||
return x.configUint64(configEpochDuration)
|
||||
}
|
||||
|
||||
|
@ -410,7 +421,7 @@ func (x *NetworkInfo) SetIRCandidateFee(fee uint64) {
|
|||
// IRCandidateFee returns IR entrance fee set using SetIRCandidateFee.
|
||||
//
|
||||
// Zero NetworkInfo has zero fee.
|
||||
func (x NetworkInfo) IRCandidateFee() uint64 {
|
||||
func (x *NetworkInfo) IRCandidateFee() uint64 {
|
||||
return x.configUint64(configIRCandidateFee)
|
||||
}
|
||||
|
||||
|
@ -480,6 +491,6 @@ func (x *NetworkInfo) AllowMaintenanceMode() {
|
|||
// maintenance mode for storage nodes.
|
||||
//
|
||||
// Zero NetworkInfo has disallows maintenance mode.
|
||||
func (x NetworkInfo) MaintenanceModeAllowed() bool {
|
||||
func (x *NetworkInfo) MaintenanceModeAllowed() bool {
|
||||
return x.configBool(configMaintenanceModeAllowed)
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ import (
|
|||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
. "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNetworkInfo_CurrentEpoch(t *testing.T) {
|
||||
var x NetworkInfo
|
||||
x := NewNetworkInfo()
|
||||
|
||||
require.Zero(t, x.CurrentEpoch())
|
||||
|
||||
|
@ -20,14 +20,14 @@ func TestNetworkInfo_CurrentEpoch(t *testing.T) {
|
|||
|
||||
require.EqualValues(t, e, x.CurrentEpoch())
|
||||
|
||||
var m netmap.NetworkInfo
|
||||
var m netmapgrpc.NetworkInfo
|
||||
x.WriteToV2(&m)
|
||||
|
||||
require.EqualValues(t, e, m.GetCurrentEpoch())
|
||||
}
|
||||
|
||||
func TestNetworkInfo_MagicNumber(t *testing.T) {
|
||||
var x NetworkInfo
|
||||
x := NewNetworkInfo()
|
||||
|
||||
require.Zero(t, x.MagicNumber())
|
||||
|
||||
|
@ -37,14 +37,14 @@ func TestNetworkInfo_MagicNumber(t *testing.T) {
|
|||
|
||||
require.EqualValues(t, magic, x.MagicNumber())
|
||||
|
||||
var m netmap.NetworkInfo
|
||||
var m netmapgrpc.NetworkInfo
|
||||
x.WriteToV2(&m)
|
||||
|
||||
require.EqualValues(t, magic, m.GetMagicNumber())
|
||||
}
|
||||
|
||||
func TestNetworkInfo_MsPerBlock(t *testing.T) {
|
||||
var x NetworkInfo
|
||||
x := NewNetworkInfo()
|
||||
|
||||
require.Zero(t, x.MsPerBlock())
|
||||
|
||||
|
@ -54,7 +54,7 @@ func TestNetworkInfo_MsPerBlock(t *testing.T) {
|
|||
|
||||
require.EqualValues(t, ms, x.MsPerBlock())
|
||||
|
||||
var m netmap.NetworkInfo
|
||||
var m netmapgrpc.NetworkInfo
|
||||
x.WriteToV2(&m)
|
||||
|
||||
require.EqualValues(t, ms, m.GetMsPerBlock())
|
||||
|
@ -66,19 +66,19 @@ func testConfigValue(t *testing.T,
|
|||
val1, val2 any,
|
||||
v2Key string, v2Val func(val any) []byte,
|
||||
) {
|
||||
var x NetworkInfo
|
||||
x := NewNetworkInfo()
|
||||
|
||||
require.Zero(t, getter(x))
|
||||
|
||||
checkVal := func(exp any) {
|
||||
require.EqualValues(t, exp, getter(x))
|
||||
|
||||
var m netmap.NetworkInfo
|
||||
var m netmapgrpc.NetworkInfo
|
||||
x.WriteToV2(&m)
|
||||
|
||||
require.EqualValues(t, 1, m.GetNetworkConfig().NumberOfParameters())
|
||||
found := false
|
||||
m.GetNetworkConfig().IterateParameters(func(prm *netmap.NetworkParameter) bool {
|
||||
m.GetNetworkConfig().IterateParameters(func(prm *netmapgrpc.NetworkConfig_Parameter) bool {
|
||||
require.False(t, found)
|
||||
require.Equal(t, []byte(v2Key), prm.GetKey())
|
||||
require.Equal(t, v2Val(exp), prm.GetValue())
|
||||
|
|
|
@ -7,9 +7,11 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
"git.frostfs.info/TrueCloudLab/hrw"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// NodeInfo groups information about FrostFS storage node which is reflected
|
||||
|
@ -18,26 +20,31 @@ import (
|
|||
// about the nodes is available to all network participants to work with the network
|
||||
// map (mainly to comply with container storage policies).
|
||||
//
|
||||
// NodeInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.NodeInfo
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
// NodeInfo is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmapgrpc.NodeInfo
|
||||
// message. See ReadFromV2V2 / WriteToV2V2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
// Instances must be created by NewNodeInfo() constructor.
|
||||
type NodeInfo struct {
|
||||
m netmap.NodeInfo
|
||||
m *netmapgrpc.NodeInfo
|
||||
hash uint64
|
||||
}
|
||||
|
||||
// reads NodeInfo from netmap.NodeInfo message. If checkFieldPresence is set,
|
||||
func NewNodeInfo() NodeInfo {
|
||||
return NodeInfo{
|
||||
m: &netmapgrpc.NodeInfo{},
|
||||
}
|
||||
}
|
||||
|
||||
// reads NodeInfo from netmapgrpc.NodeInfo message. If checkFieldPresence is set,
|
||||
// returns an error on absence of any protocol-required field. Verifies format of any
|
||||
// presented field according to FrostFS API V2 protocol.
|
||||
func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error {
|
||||
func (x *NodeInfo) readFromV2(m *netmapgrpc.NodeInfo, checkFieldPresence bool) error {
|
||||
var err error
|
||||
|
||||
binPublicKey := m.GetPublicKey()
|
||||
if checkFieldPresence && len(binPublicKey) == 0 {
|
||||
return errors.New("missing public key")
|
||||
}
|
||||
|
||||
if checkFieldPresence && m.NumberOfAddresses() <= 0 {
|
||||
return errors.New("missing network endpoints")
|
||||
}
|
||||
|
@ -71,34 +78,38 @@ func (x *NodeInfo) readFromV2(m netmap.NodeInfo, checkFieldPresence bool) error
|
|||
}
|
||||
}
|
||||
|
||||
x.m = m
|
||||
if x.m == nil {
|
||||
x.m = new(netmapgrpc.NodeInfo)
|
||||
}
|
||||
proto.Merge(x.m, m)
|
||||
x.hash = hrw.Hash(binPublicKey)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadFromV2 reads NodeInfo from the netmap.NodeInfo message. Checks if the
|
||||
// ReadFromV2V2 reads NodeInfo from the netmapgrpc.NodeInfo message. Checks if the
|
||||
// message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (x *NodeInfo) ReadFromV2(m netmap.NodeInfo) error {
|
||||
// See also WriteToV2V2.
|
||||
func (x *NodeInfo) ReadFromV2(m *netmapgrpc.NodeInfo) error {
|
||||
return x.readFromV2(m, true)
|
||||
}
|
||||
|
||||
// WriteToV2 writes NodeInfo to the netmap.NodeInfo message. The message MUST NOT
|
||||
// WriteToV2V2 writes NodeInfo to the netmapgrpc.NodeInfo message. The message MUST NOT
|
||||
// be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x NodeInfo) WriteToV2(m *netmap.NodeInfo) {
|
||||
*m = x.m
|
||||
// See also ReadFromV2V2.
|
||||
func (x *NodeInfo) WriteToV2(m *netmapgrpc.NodeInfo) {
|
||||
m.Reset()
|
||||
proto.Merge(m, x.m)
|
||||
}
|
||||
|
||||
// Marshal encodes NodeInfo into a binary format of the FrostFS API protocol
|
||||
// (Protocol Buffers with direct field order).
|
||||
//
|
||||
// See also Unmarshal.
|
||||
func (x NodeInfo) Marshal() []byte {
|
||||
var m netmap.NodeInfo
|
||||
func (x *NodeInfo) Marshal() []byte {
|
||||
var m netmapgrpc.NodeInfo
|
||||
x.WriteToV2(&m)
|
||||
|
||||
return m.StableMarshal(nil)
|
||||
|
@ -110,25 +121,25 @@ func (x NodeInfo) Marshal() []byte {
|
|||
//
|
||||
// See also Marshal.
|
||||
func (x *NodeInfo) Unmarshal(data []byte) error {
|
||||
var m netmap.NodeInfo
|
||||
var m netmapgrpc.NodeInfo
|
||||
|
||||
err := m.Unmarshal(data)
|
||||
err := proto.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return x.readFromV2(m, false)
|
||||
return x.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes NodeInfo into a JSON format of the FrostFS API protocol
|
||||
// (Protocol Buffers JSON).
|
||||
//
|
||||
// See also UnmarshalJSON.
|
||||
func (x NodeInfo) MarshalJSON() ([]byte, error) {
|
||||
var m netmap.NodeInfo
|
||||
func (x *NodeInfo) MarshalJSON() ([]byte, error) {
|
||||
var m netmapgrpc.NodeInfo
|
||||
x.WriteToV2(&m)
|
||||
|
||||
return m.MarshalJSON()
|
||||
return protojson.Marshal(&m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes FrostFS API protocol JSON format into the NodeInfo
|
||||
|
@ -136,14 +147,14 @@ func (x NodeInfo) MarshalJSON() ([]byte, error) {
|
|||
//
|
||||
// See also MarshalJSON.
|
||||
func (x *NodeInfo) UnmarshalJSON(data []byte) error {
|
||||
var m netmap.NodeInfo
|
||||
var m netmapgrpc.NodeInfo
|
||||
|
||||
err := m.UnmarshalJSON(data)
|
||||
err := protojson.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return x.readFromV2(m, false)
|
||||
return x.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// SetPublicKey sets binary-encoded public key bound to the node. The key
|
||||
|
@ -182,7 +193,7 @@ func StringifyPublicKey(node NodeInfo) string {
|
|||
//
|
||||
// See also IterateNetworkEndpoints.
|
||||
func (x *NodeInfo) SetNetworkEndpoints(v ...string) {
|
||||
x.m.SetAddresses(v...)
|
||||
x.m.SetAddresses(v)
|
||||
}
|
||||
|
||||
// NumberOfNetworkEndpoints returns number of network endpoints announced by the node.
|
||||
|
@ -206,7 +217,7 @@ func (x NodeInfo) IterateNetworkEndpoints(f func(string) bool) {
|
|||
|
||||
// IterateNetworkEndpoints is an extra-sugared function over IterateNetworkEndpoints
|
||||
// method which allows to unconditionally iterate over all node's network endpoints.
|
||||
func IterateNetworkEndpoints(node NodeInfo, f func(string)) {
|
||||
func IterateNetworkEndpoints(node *NodeInfo, f func(string)) {
|
||||
node.IterateNetworkEndpoints(func(addr string) bool {
|
||||
f(addr)
|
||||
return false
|
||||
|
@ -231,7 +242,7 @@ func (x NodeInfo) Hash() uint64 {
|
|||
// x1 is less than x2 if it has less Hash().
|
||||
//
|
||||
// Method is needed for internal placement needs.
|
||||
func less(x1, x2 NodeInfo) bool {
|
||||
func less(x1, x2 *NodeInfo) bool {
|
||||
return x1.Hash() < x2.Hash()
|
||||
}
|
||||
|
||||
|
@ -248,7 +259,7 @@ func (x *NodeInfo) SetPrice(price uint64) {
|
|||
// Price returns price set using SetPrice.
|
||||
//
|
||||
// Zero NodeInfo has zero price.
|
||||
func (x NodeInfo) Price() uint64 {
|
||||
func (x *NodeInfo) Price() uint64 {
|
||||
val := x.Attribute(attrPrice)
|
||||
if val == "" {
|
||||
return 0
|
||||
|
@ -271,7 +282,7 @@ func (x *NodeInfo) SetCapacity(capacity uint64) {
|
|||
// capacity returns capacity set using SetCapacity.
|
||||
//
|
||||
// Zero NodeInfo has zero capacity.
|
||||
func (x NodeInfo) capacity() uint64 {
|
||||
func (x *NodeInfo) capacity() uint64 {
|
||||
val := x.Attribute(attrCapacity)
|
||||
if val == "" {
|
||||
return 0
|
||||
|
@ -302,7 +313,7 @@ func (x *NodeInfo) SetLOCODE(locode string) {
|
|||
//
|
||||
// Zero NodeInfo has empty location code which is invalid according to
|
||||
// FrostFS API system requirement.
|
||||
func (x NodeInfo) LOCODE() string {
|
||||
func (x *NodeInfo) LOCODE() string {
|
||||
return x.Attribute(attrUNLOCODE)
|
||||
}
|
||||
|
||||
|
@ -397,13 +408,13 @@ func (x NodeInfo) ExternalAddresses() []string {
|
|||
// NumberOfAttributes returns number of attributes announced by the node.
|
||||
//
|
||||
// See also SetAttribute.
|
||||
func (x NodeInfo) NumberOfAttributes() int {
|
||||
func (x *NodeInfo) NumberOfAttributes() int {
|
||||
return len(x.m.GetAttributes())
|
||||
}
|
||||
|
||||
// IterateAttributes iterates over all node attributes and passes the into f.
|
||||
// Handler MUST NOT be nil.
|
||||
func (x NodeInfo) IterateAttributes(f func(key, value string)) {
|
||||
func (x *NodeInfo) IterateAttributes(f func(key, value string)) {
|
||||
a := x.m.GetAttributes()
|
||||
for i := range a {
|
||||
f(a[i].GetKey(), a[i].GetValue())
|
||||
|
@ -427,16 +438,19 @@ func (x *NodeInfo) SetAttribute(key, value string) {
|
|||
}
|
||||
}
|
||||
|
||||
a = append(a, netmap.Attribute{})
|
||||
a = append(a, &netmapgrpc.NodeInfo_Attribute{})
|
||||
a[len(a)-1].SetKey(key)
|
||||
a[len(a)-1].SetValue(value)
|
||||
|
||||
if x.m == nil {
|
||||
x.m = new(netmapgrpc.NodeInfo)
|
||||
}
|
||||
x.m.SetAttributes(a)
|
||||
}
|
||||
|
||||
// Attribute returns value of the node attribute set using SetAttribute by the
|
||||
// given key. Returns empty string if attribute is missing.
|
||||
func (x NodeInfo) Attribute(key string) string {
|
||||
func (x *NodeInfo) Attribute(key string) string {
|
||||
a := x.m.GetAttributes()
|
||||
for i := range a {
|
||||
if a[i].GetKey() == key {
|
||||
|
@ -473,7 +487,7 @@ func (x *NodeInfo) SortAttributes() {
|
|||
// information about itself in the network map, this action is interpreted as
|
||||
// an intention to leave the network.
|
||||
func (x *NodeInfo) SetOffline() {
|
||||
x.m.SetState(netmap.Offline)
|
||||
x.m.SetState(netmapgrpc.NodeInfo_OFFLINE)
|
||||
}
|
||||
|
||||
// IsOffline checks if the node is in the "offline" state.
|
||||
|
@ -482,8 +496,8 @@ func (x *NodeInfo) SetOffline() {
|
|||
// mean online).
|
||||
//
|
||||
// See also SetOffline.
|
||||
func (x NodeInfo) IsOffline() bool {
|
||||
return x.m.GetState() == netmap.Offline
|
||||
func (x *NodeInfo) IsOffline() bool {
|
||||
return x.m.GetState() == netmapgrpc.NodeInfo_OFFLINE
|
||||
}
|
||||
|
||||
// SetOnline sets the state of the node to "online". When a node updates
|
||||
|
@ -492,7 +506,7 @@ func (x NodeInfo) IsOffline() bool {
|
|||
//
|
||||
// See also IsOnline.
|
||||
func (x *NodeInfo) SetOnline() {
|
||||
x.m.SetState(netmap.Online)
|
||||
x.m.SetState(netmapgrpc.NodeInfo_ONLINE)
|
||||
}
|
||||
|
||||
// IsOnline checks if the node is in the "online" state.
|
||||
|
@ -501,8 +515,8 @@ func (x *NodeInfo) SetOnline() {
|
|||
// mean offline).
|
||||
//
|
||||
// See also SetOnline.
|
||||
func (x NodeInfo) IsOnline() bool {
|
||||
return x.m.GetState() == netmap.Online
|
||||
func (x *NodeInfo) IsOnline() bool {
|
||||
return x.m.GetState() == netmapgrpc.NodeInfo_ONLINE
|
||||
}
|
||||
|
||||
// SetMaintenance sets the state of the node to "maintenance". When a node updates
|
||||
|
@ -511,7 +525,7 @@ func (x NodeInfo) IsOnline() bool {
|
|||
//
|
||||
// See also IsMaintenance.
|
||||
func (x *NodeInfo) SetMaintenance() {
|
||||
x.m.SetState(netmap.Maintenance)
|
||||
x.m.SetState(netmapgrpc.NodeInfo_MAINTENANCE)
|
||||
}
|
||||
|
||||
// IsMaintenance checks if the node is in the "maintenance" state.
|
||||
|
@ -519,6 +533,6 @@ func (x *NodeInfo) SetMaintenance() {
|
|||
// Zero NodeInfo has undefined state.
|
||||
//
|
||||
// See also SetMaintenance.
|
||||
func (x NodeInfo) IsMaintenance() bool {
|
||||
return x.m.GetState() == netmap.Maintenance
|
||||
func (x *NodeInfo) IsMaintenance() bool {
|
||||
return x.m.GetState() == netmapgrpc.NodeInfo_MAINTENANCE
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
func TestNodeInfo_SetAttribute(t *testing.T) {
|
||||
var n NodeInfo
|
||||
n := NewNodeInfo()
|
||||
|
||||
const key = "some key"
|
||||
val := "some value"
|
||||
|
@ -24,7 +24,7 @@ func TestNodeInfo_SetAttribute(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNodeInfo_Status(t *testing.T) {
|
||||
var n NodeInfo
|
||||
n := NewNodeInfo()
|
||||
|
||||
require.False(t, n.IsOnline())
|
||||
require.False(t, n.IsOffline())
|
||||
|
@ -47,7 +47,7 @@ func TestNodeInfo_Status(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNodeInfo_ExternalAddr(t *testing.T) {
|
||||
var n NodeInfo
|
||||
n := NewNodeInfo()
|
||||
|
||||
require.Empty(t, n.ExternalAddresses())
|
||||
require.Panics(t, func() { n.SetExternalAddresses() })
|
||||
|
|
197
netmap/policy.go
197
netmap/policy.go
|
@ -7,32 +7,34 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/parser"
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// PlacementPolicy declares policy to store objects in the FrostFS container.
|
||||
// Within itself, PlacementPolicy represents a set of rules to select a subset
|
||||
// of nodes from FrostFS network map - node-candidates for object storage.
|
||||
//
|
||||
// PlacementPolicy is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap.PlacementPolicy
|
||||
// PlacementPolicy is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmapgrpc.PlacementPolicy
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
type PlacementPolicy struct {
|
||||
backupFactor uint32
|
||||
|
||||
filters []netmap.Filter
|
||||
filters []*netmapgrpc.Filter
|
||||
|
||||
selectors []netmap.Selector
|
||||
selectors []*netmapgrpc.Selector
|
||||
|
||||
replicas []netmap.Replica
|
||||
replicas []*netmapgrpc.Replica
|
||||
|
||||
unique bool
|
||||
}
|
||||
|
||||
func (p *PlacementPolicy) readFromV2(m netmap.PlacementPolicy, checkFieldPresence bool) error {
|
||||
func (p *PlacementPolicy) readFromV2(m *netmapgrpc.PlacementPolicy, checkFieldPresence bool) error {
|
||||
p.replicas = m.GetReplicas()
|
||||
if checkFieldPresence && len(p.replicas) == 0 {
|
||||
return errors.New("missing replicas")
|
||||
|
@ -51,7 +53,7 @@ func (p *PlacementPolicy) readFromV2(m netmap.PlacementPolicy, checkFieldPresenc
|
|||
//
|
||||
// See also Unmarshal.
|
||||
func (p PlacementPolicy) Marshal() []byte {
|
||||
var m netmap.PlacementPolicy
|
||||
var m netmapgrpc.PlacementPolicy
|
||||
p.WriteToV2(&m)
|
||||
|
||||
return m.StableMarshal(nil)
|
||||
|
@ -63,14 +65,14 @@ func (p PlacementPolicy) Marshal() []byte {
|
|||
//
|
||||
// See also Marshal.
|
||||
func (p *PlacementPolicy) Unmarshal(data []byte) error {
|
||||
var m netmap.PlacementPolicy
|
||||
var m netmapgrpc.PlacementPolicy
|
||||
|
||||
err := m.Unmarshal(data)
|
||||
err := proto.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.readFromV2(m, false)
|
||||
return p.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes PlacementPolicy into a JSON format of the FrostFS API
|
||||
|
@ -78,10 +80,14 @@ func (p *PlacementPolicy) Unmarshal(data []byte) error {
|
|||
//
|
||||
// See also UnmarshalJSON.
|
||||
func (p PlacementPolicy) MarshalJSON() ([]byte, error) {
|
||||
var m netmap.PlacementPolicy
|
||||
var m netmapgrpc.PlacementPolicy
|
||||
p.WriteToV2(&m)
|
||||
|
||||
return m.MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
&m,
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes FrostFS API protocol JSON format into the PlacementPolicy
|
||||
|
@ -89,21 +95,21 @@ func (p PlacementPolicy) MarshalJSON() ([]byte, error) {
|
|||
//
|
||||
// See also MarshalJSON.
|
||||
func (p *PlacementPolicy) UnmarshalJSON(data []byte) error {
|
||||
var m netmap.PlacementPolicy
|
||||
var m netmapgrpc.PlacementPolicy
|
||||
|
||||
err := m.UnmarshalJSON(data)
|
||||
err := protojson.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.readFromV2(m, false)
|
||||
return p.readFromV2(&m, false)
|
||||
}
|
||||
|
||||
// ReadFromV2 reads PlacementPolicy from the netmap.PlacementPolicy message.
|
||||
// ReadFromV2 reads PlacementPolicy from the netmapgrpc.PlacementPolicy message.
|
||||
// Checks if the message conforms to FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (p *PlacementPolicy) ReadFromV2(m netmap.PlacementPolicy) error {
|
||||
func (p *PlacementPolicy) ReadFromV2(m *netmapgrpc.PlacementPolicy) error {
|
||||
return p.readFromV2(m, true)
|
||||
}
|
||||
|
||||
|
@ -111,7 +117,8 @@ func (p *PlacementPolicy) ReadFromV2(m netmap.PlacementPolicy) error {
|
|||
// The message must not be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (p PlacementPolicy) WriteToV2(m *netmap.PlacementPolicy) {
|
||||
func (p PlacementPolicy) WriteToV2(m *netmapgrpc.PlacementPolicy) {
|
||||
m.Reset()
|
||||
m.SetContainerBackupFactor(p.backupFactor)
|
||||
m.SetFilters(p.filters)
|
||||
m.SetSelectors(p.selectors)
|
||||
|
@ -122,7 +129,13 @@ func (p PlacementPolicy) WriteToV2(m *netmap.PlacementPolicy) {
|
|||
// ReplicaDescriptor replica descriptor characterizes replicas of objects from
|
||||
// the subset selected by a particular Selector.
|
||||
type ReplicaDescriptor struct {
|
||||
m netmap.Replica
|
||||
m *netmapgrpc.Replica
|
||||
}
|
||||
|
||||
func NewReplicaDescriptor() ReplicaDescriptor {
|
||||
return ReplicaDescriptor{
|
||||
m: new(netmapgrpc.Replica),
|
||||
}
|
||||
}
|
||||
|
||||
// SetNumberOfObjects sets number of object replicas.
|
||||
|
@ -133,7 +146,7 @@ func (r *ReplicaDescriptor) SetNumberOfObjects(c uint32) {
|
|||
// NumberOfObjects returns number set using SetNumberOfObjects.
|
||||
//
|
||||
// Zero ReplicaDescriptor has zero number of objects.
|
||||
func (r ReplicaDescriptor) NumberOfObjects() uint32 {
|
||||
func (r *ReplicaDescriptor) NumberOfObjects() uint32 {
|
||||
return r.m.GetCount()
|
||||
}
|
||||
|
||||
|
@ -151,10 +164,11 @@ func (r *ReplicaDescriptor) SetSelectorName(s string) {
|
|||
func (p *PlacementPolicy) AddReplicas(rs ...ReplicaDescriptor) {
|
||||
off := len(p.replicas)
|
||||
|
||||
p.replicas = append(p.replicas, make([]netmap.Replica, len(rs))...)
|
||||
p.replicas = append(p.replicas, make([]*netmapgrpc.Replica, len(rs))...)
|
||||
|
||||
for i := range rs {
|
||||
p.replicas[off+i] = rs[i].m
|
||||
p.replicas[off+i] = new(netmapgrpc.Replica)
|
||||
proto.Merge(p.replicas[off+i], rs[i].m)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +207,13 @@ func (p *PlacementPolicy) SetUnique(b bool) {
|
|||
// Selector describes the bucket selection operator: choose a number of nodes
|
||||
// from the bucket taking the nearest nodes to the related container by hash distance.
|
||||
type Selector struct {
|
||||
m netmap.Selector
|
||||
m *netmapgrpc.Selector
|
||||
}
|
||||
|
||||
func NewSelector() Selector {
|
||||
return Selector{
|
||||
m: new(netmapgrpc.Selector),
|
||||
}
|
||||
}
|
||||
|
||||
// SetName sets name with which the Selector can be referenced.
|
||||
|
@ -224,7 +244,7 @@ func (s *Selector) SelectByBucketAttribute(bucket string) {
|
|||
//
|
||||
// See also SelectByBucketAttribute.
|
||||
func (s *Selector) SelectSame() {
|
||||
s.m.SetClause(netmap.Same)
|
||||
s.m.SetClause(netmapgrpc.Clause_SAME)
|
||||
}
|
||||
|
||||
// SelectDistinct makes selection algorithm to select only nodes having the different values
|
||||
|
@ -234,7 +254,7 @@ func (s *Selector) SelectSame() {
|
|||
//
|
||||
// See also SelectByBucketAttribute.
|
||||
func (s *Selector) SelectDistinct() {
|
||||
s.m.SetClause(netmap.Distinct)
|
||||
s.m.SetClause(netmapgrpc.Clause_DISTINCT)
|
||||
}
|
||||
|
||||
// SetFilterName sets reference to pre-filtering nodes for selection.
|
||||
|
@ -253,16 +273,23 @@ func (s *Selector) SetFilterName(f string) {
|
|||
func (p *PlacementPolicy) AddSelectors(ss ...Selector) {
|
||||
off := len(p.selectors)
|
||||
|
||||
p.selectors = append(p.selectors, make([]netmap.Selector, len(ss))...)
|
||||
p.selectors = append(p.selectors, make([]*netmapgrpc.Selector, len(ss))...)
|
||||
|
||||
for i := range ss {
|
||||
p.selectors[off+i] = ss[i].m
|
||||
p.selectors[off+i] = new(netmapgrpc.Selector)
|
||||
proto.Merge(p.selectors[off+i], ss[i].m)
|
||||
}
|
||||
}
|
||||
|
||||
// Filter contains rules for filtering the node sets.
|
||||
type Filter struct {
|
||||
m netmap.Filter
|
||||
m *netmapgrpc.Filter
|
||||
}
|
||||
|
||||
func NewFilter() Filter {
|
||||
return Filter{
|
||||
m: new(netmapgrpc.Filter),
|
||||
}
|
||||
}
|
||||
|
||||
// SetName sets name with which the Filter can be referenced or, for inner filters,
|
||||
|
@ -274,7 +301,7 @@ func (x *Filter) SetName(name string) {
|
|||
x.m.SetName(name)
|
||||
}
|
||||
|
||||
func (x *Filter) setAttribute(key string, op netmap.Operation, val string) {
|
||||
func (x *Filter) setAttribute(key string, op netmapgrpc.Operation, val string) {
|
||||
x.m.SetKey(key)
|
||||
x.m.SetOp(op)
|
||||
x.m.SetValue(val)
|
||||
|
@ -284,14 +311,14 @@ func (x *Filter) setAttribute(key string, op netmap.Operation, val string) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) Equal(key, value string) {
|
||||
x.setAttribute(key, netmap.EQ, value)
|
||||
x.setAttribute(key, netmapgrpc.Operation_EQ, value)
|
||||
}
|
||||
|
||||
// NotEqual applies the rule to accept only nodes with the distinct attribute value.
|
||||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) NotEqual(key, value string) {
|
||||
x.setAttribute(key, netmap.NE, value)
|
||||
x.setAttribute(key, netmapgrpc.Operation_NE, value)
|
||||
}
|
||||
|
||||
// NumericGT applies the rule to accept only nodes with the numeric attribute
|
||||
|
@ -299,7 +326,7 @@ func (x *Filter) NotEqual(key, value string) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) NumericGT(key string, num int64) {
|
||||
x.setAttribute(key, netmap.GT, strconv.FormatInt(num, 10))
|
||||
x.setAttribute(key, netmapgrpc.Operation_GT, strconv.FormatInt(num, 10))
|
||||
}
|
||||
|
||||
// NumericGE applies the rule to accept only nodes with the numeric attribute
|
||||
|
@ -307,7 +334,7 @@ func (x *Filter) NumericGT(key string, num int64) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) NumericGE(key string, num int64) {
|
||||
x.setAttribute(key, netmap.GE, strconv.FormatInt(num, 10))
|
||||
x.setAttribute(key, netmapgrpc.Operation_GE, strconv.FormatInt(num, 10))
|
||||
}
|
||||
|
||||
// NumericLT applies the rule to accept only nodes with the numeric attribute
|
||||
|
@ -315,7 +342,7 @@ func (x *Filter) NumericGE(key string, num int64) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) NumericLT(key string, num int64) {
|
||||
x.setAttribute(key, netmap.LT, strconv.FormatInt(num, 10))
|
||||
x.setAttribute(key, netmapgrpc.Operation_LT, strconv.FormatInt(num, 10))
|
||||
}
|
||||
|
||||
// NumericLE applies the rule to accept only nodes with the numeric attribute
|
||||
|
@ -323,19 +350,20 @@ func (x *Filter) NumericLT(key string, num int64) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) NumericLE(key string, num int64) {
|
||||
x.setAttribute(key, netmap.LE, strconv.FormatInt(num, 10))
|
||||
x.setAttribute(key, netmapgrpc.Operation_LE, strconv.FormatInt(num, 10))
|
||||
}
|
||||
|
||||
func (x *Filter) setInnerFilters(op netmap.Operation, filters []Filter) {
|
||||
func (x *Filter) setInnerFilters(op netmapgrpc.Operation, filters []Filter) {
|
||||
x.setAttribute("", op, "")
|
||||
|
||||
inner := x.m.GetFilters()
|
||||
if rem := len(filters) - len(inner); rem > 0 {
|
||||
inner = append(inner, make([]netmap.Filter, rem)...)
|
||||
inner = append(inner, make([]*netmapgrpc.Filter, rem)...)
|
||||
}
|
||||
|
||||
for i := range filters {
|
||||
inner[i] = filters[i].m
|
||||
inner[i] = new(netmapgrpc.Filter)
|
||||
proto.Merge(inner[i], filters[i].m)
|
||||
}
|
||||
|
||||
x.m.SetFilters(inner)
|
||||
|
@ -346,7 +374,7 @@ func (x *Filter) setInnerFilters(op netmap.Operation, filters []Filter) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) LogicalOR(filters ...Filter) {
|
||||
x.setInnerFilters(netmap.OR, filters)
|
||||
x.setInnerFilters(netmapgrpc.Operation_OR, filters)
|
||||
}
|
||||
|
||||
// LogicalAND applies the rule to accept only nodes which satisfy all the given
|
||||
|
@ -354,7 +382,7 @@ func (x *Filter) LogicalOR(filters ...Filter) {
|
|||
//
|
||||
// Method SHOULD NOT be called along with other similar methods.
|
||||
func (x *Filter) LogicalAND(filters ...Filter) {
|
||||
x.setInnerFilters(netmap.AND, filters)
|
||||
x.setInnerFilters(netmapgrpc.Operation_AND, filters)
|
||||
}
|
||||
|
||||
// AddFilters adds a Filter bunch that will be applied when selecting nodes.
|
||||
|
@ -363,10 +391,11 @@ func (x *Filter) LogicalAND(filters ...Filter) {
|
|||
func (p *PlacementPolicy) AddFilters(fs ...Filter) {
|
||||
off := len(p.filters)
|
||||
|
||||
p.filters = append(p.filters, make([]netmap.Filter, len(fs))...)
|
||||
p.filters = append(p.filters, make([]*netmapgrpc.Filter, len(fs))...)
|
||||
|
||||
for i := range fs {
|
||||
p.filters[off+i] = fs[i].m
|
||||
p.filters[off+i] = new(netmapgrpc.Filter)
|
||||
proto.Merge(p.filters[off+i], fs[i].m)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,7 +422,6 @@ func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) {
|
|||
} else {
|
||||
_, err = w.WriteString(fmt.Sprintf("%sREP %d", delim, c))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -402,8 +430,7 @@ func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) {
|
|||
}
|
||||
|
||||
if p.backupFactor > 0 {
|
||||
_, err = w.WriteString(fmt.Sprintf("\nCBF %d", p.backupFactor))
|
||||
if err != nil {
|
||||
if _, err = w.WriteString(fmt.Sprintf("\nCBF %d", p.backupFactor)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -411,8 +438,7 @@ func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) {
|
|||
var s string
|
||||
|
||||
for i := range p.selectors {
|
||||
_, err = w.WriteString(fmt.Sprintf("\nSELECT %d", p.selectors[i].GetCount()))
|
||||
if err != nil {
|
||||
if _, err = w.WriteString(fmt.Sprintf("\nSELECT %d", p.selectors[i].GetCount())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -420,43 +446,38 @@ func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) {
|
|||
var clause string
|
||||
|
||||
switch p.selectors[i].GetClause() {
|
||||
case netmap.Same:
|
||||
case netmapgrpc.Clause_SAME:
|
||||
clause = "SAME "
|
||||
case netmap.Distinct:
|
||||
case netmapgrpc.Clause_DISTINCT:
|
||||
clause = "DISTINCT "
|
||||
default:
|
||||
clause = ""
|
||||
}
|
||||
|
||||
_, err = w.WriteString(fmt.Sprintf(" IN %s%s", clause, s))
|
||||
if err != nil {
|
||||
if _, err = w.WriteString(fmt.Sprintf(" IN %s%s", clause, s)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if s = p.selectors[i].GetFilter(); s != "" {
|
||||
_, err = w.WriteString(" FROM " + s)
|
||||
if err != nil {
|
||||
if _, err = w.WriteString(" FROM " + s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if s = p.selectors[i].GetName(); s != "" {
|
||||
_, err = w.WriteString(" AS " + s)
|
||||
if err != nil {
|
||||
if _, err = w.WriteString(" AS " + s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range p.filters {
|
||||
_, err = w.WriteString("\nFILTER ")
|
||||
if err != nil {
|
||||
if _, err = w.WriteString("\nFILTER "); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeFilterStringTo(w, p.filters[i])
|
||||
if err != nil {
|
||||
if err = writeFilterStringTo(w, p.filters[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -464,7 +485,7 @@ func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func writeFilterStringTo(w io.StringWriter, f netmap.Filter) error {
|
||||
func writeFilterStringTo(w io.StringWriter, f *netmapgrpc.Filter) error {
|
||||
var err error
|
||||
var s string
|
||||
op := f.GetOp()
|
||||
|
@ -484,7 +505,7 @@ func writeFilterStringTo(w io.StringWriter, f netmap.Filter) error {
|
|||
|
||||
inner := f.GetFilters()
|
||||
|
||||
if op == netmap.NOT {
|
||||
if op == netmapgrpc.Operation_NOT {
|
||||
_, err = w.WriteString(op.String() + " (")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -595,15 +616,16 @@ func (p *policyVisitor) VisitPolicy(ctx *parser.PolicyContext) any {
|
|||
pl.unique = ctx.UNIQUE() != nil
|
||||
|
||||
repStmts := ctx.AllRepStmt()
|
||||
pl.replicas = make([]netmap.Replica, 0, len(repStmts))
|
||||
pl.replicas = make([]*netmapgrpc.Replica, 0, len(repStmts))
|
||||
|
||||
for _, r := range repStmts {
|
||||
res, ok := r.Accept(p).(*netmap.Replica)
|
||||
res, ok := r.Accept(p).(*netmapgrpc.Replica)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
pl.replicas = append(pl.replicas, *res)
|
||||
cloned := new(netmapgrpc.Replica)
|
||||
proto.Merge(cloned, res)
|
||||
pl.replicas = append(pl.replicas, cloned)
|
||||
}
|
||||
|
||||
if cbfStmt := ctx.CbfStmt(); cbfStmt != nil {
|
||||
|
@ -615,22 +637,29 @@ func (p *policyVisitor) VisitPolicy(ctx *parser.PolicyContext) any {
|
|||
}
|
||||
|
||||
selStmts := ctx.AllSelectStmt()
|
||||
pl.selectors = make([]netmap.Selector, 0, len(selStmts))
|
||||
pl.selectors = make([]*netmapgrpc.Selector, 0, len(selStmts))
|
||||
|
||||
for _, s := range selStmts {
|
||||
res, ok := s.Accept(p).(*netmap.Selector)
|
||||
res, ok := s.Accept(p).(*netmapgrpc.Selector)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
pl.selectors = append(pl.selectors, *res)
|
||||
cloned := new(netmapgrpc.Selector)
|
||||
proto.Merge(cloned, res)
|
||||
pl.selectors = append(pl.selectors, cloned)
|
||||
}
|
||||
|
||||
filtStmts := ctx.AllFilterStmt()
|
||||
pl.filters = make([]netmap.Filter, 0, len(filtStmts))
|
||||
pl.filters = make([]*netmapgrpc.Filter, 0, len(filtStmts))
|
||||
|
||||
for _, f := range filtStmts {
|
||||
pl.filters = append(pl.filters, *f.Accept(p).(*netmap.Filter))
|
||||
res, ok := f.Accept(p).(*netmapgrpc.Filter)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
cloned := new(netmapgrpc.Filter)
|
||||
proto.Merge(cloned, res)
|
||||
pl.filters = append(pl.filters, cloned)
|
||||
}
|
||||
|
||||
return pl
|
||||
|
@ -652,7 +681,7 @@ func (p *policyVisitor) VisitRepStmt(ctx *parser.RepStmtContext) any {
|
|||
return p.reportError(errInvalidNumber)
|
||||
}
|
||||
|
||||
rs := new(netmap.Replica)
|
||||
rs := new(netmapgrpc.Replica)
|
||||
rs.SetCount(uint32(num))
|
||||
|
||||
if sel := ctx.GetSelector(); sel != nil {
|
||||
|
@ -669,7 +698,7 @@ func (p *policyVisitor) VisitSelectStmt(ctx *parser.SelectStmtContext) any {
|
|||
return p.reportError(errInvalidNumber)
|
||||
}
|
||||
|
||||
s := new(netmap.Selector)
|
||||
s := new(netmapgrpc.Selector)
|
||||
s.SetCount(uint32(res))
|
||||
|
||||
if clStmt := ctx.Clause(); clStmt != nil {
|
||||
|
@ -690,7 +719,7 @@ func (p *policyVisitor) VisitSelectStmt(ctx *parser.SelectStmtContext) any {
|
|||
|
||||
// VisitFilterStmt implements parser.QueryVisitor interface.
|
||||
func (p *policyVisitor) VisitFilterStmt(ctx *parser.FilterStmtContext) any {
|
||||
f := p.VisitFilterExpr(ctx.GetExpr().(*parser.FilterExprContext)).(*netmap.Filter)
|
||||
f := p.VisitFilterExpr(ctx.GetExpr().(*parser.FilterExprContext)).(*netmapgrpc.Filter)
|
||||
f.SetName(ctx.GetName().GetText())
|
||||
return f
|
||||
}
|
||||
|
@ -704,18 +733,18 @@ func (p *policyVisitor) VisitFilterExpr(ctx *parser.FilterExprContext) any {
|
|||
return inner.Accept(p)
|
||||
}
|
||||
|
||||
f := new(netmap.Filter)
|
||||
f := new(netmapgrpc.Filter)
|
||||
op := operationFromString(ctx.GetOp().GetText())
|
||||
f.SetOp(op)
|
||||
|
||||
if op == netmap.NOT {
|
||||
f1 := *ctx.GetF1().Accept(p).(*netmap.Filter)
|
||||
f.SetFilters([]netmap.Filter{f1})
|
||||
if op == netmapgrpc.Operation_NOT {
|
||||
f1 := ctx.GetF1().Accept(p).(*netmapgrpc.Filter)
|
||||
f.SetFilters([]*netmapgrpc.Filter{f1})
|
||||
return f
|
||||
}
|
||||
|
||||
f1 := *ctx.GetF1().Accept(p).(*netmap.Filter)
|
||||
f2 := *ctx.GetF2().Accept(p).(*netmap.Filter)
|
||||
f1 := ctx.GetF1().Accept(p).(*netmapgrpc.Filter)
|
||||
f2 := ctx.GetF2().Accept(p).(*netmapgrpc.Filter)
|
||||
|
||||
// Consider f1=(.. AND ..) AND f2. This can be merged because our AND operation
|
||||
// is of arbitrary arity. ANTLR generates left-associative parse-tree by default.
|
||||
|
@ -724,7 +753,7 @@ func (p *policyVisitor) VisitFilterExpr(ctx *parser.FilterExprContext) any {
|
|||
return f
|
||||
}
|
||||
|
||||
f.SetFilters([]netmap.Filter{f1, f2})
|
||||
f.SetFilters([]*netmapgrpc.Filter{f1, f2})
|
||||
|
||||
return f
|
||||
}
|
||||
|
@ -754,7 +783,7 @@ func (p *policyVisitor) VisitFilterValue(ctx *parser.FilterValueContext) any {
|
|||
|
||||
// VisitExpr implements parser.QueryVisitor interface.
|
||||
func (p *policyVisitor) VisitExpr(ctx *parser.ExprContext) any {
|
||||
f := new(netmap.Filter)
|
||||
f := new(netmapgrpc.Filter)
|
||||
if flt := ctx.GetFilter(); flt != nil {
|
||||
f.SetName(flt.GetText())
|
||||
return f
|
||||
|
@ -799,7 +828,7 @@ func validatePolicy(p PlacementPolicy) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func clauseFromString(s string) (c netmap.Clause) {
|
||||
func clauseFromString(s string) (c netmapgrpc.Clause) {
|
||||
if !c.FromString(strings.ToUpper(s)) {
|
||||
// Such errors should be handled by ANTLR code thus this panic.
|
||||
panic(fmt.Errorf("BUG: invalid clause: %s", c))
|
||||
|
@ -808,7 +837,7 @@ func clauseFromString(s string) (c netmap.Clause) {
|
|||
return
|
||||
}
|
||||
|
||||
func operationFromString(s string) (op netmap.Operation) {
|
||||
func operationFromString(s string) (op netmapgrpc.Operation) {
|
||||
if !op.FromString(strings.ToUpper(s)) {
|
||||
// Such errors should be handled by ANTLR code thus this panic.
|
||||
panic(fmt.Errorf("BUG: invalid operation: %s", op))
|
||||
|
|
|
@ -4,9 +4,11 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
. "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
|
@ -65,7 +67,11 @@ func TestPlacementPolicyEncoding(t *testing.T) {
|
|||
var v2 PlacementPolicy
|
||||
require.NoError(t, v2.Unmarshal(v.Marshal()))
|
||||
|
||||
require.Equal(t, v, v2)
|
||||
var p1, p2 netmapgrpc.PlacementPolicy
|
||||
v.WriteToV2(&p1)
|
||||
v2.WriteToV2(&p2)
|
||||
|
||||
require.True(t, proto.Equal(&p1, &p2))
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
|
@ -75,6 +81,10 @@ func TestPlacementPolicyEncoding(t *testing.T) {
|
|||
var v2 PlacementPolicy
|
||||
require.NoError(t, v2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, v, v2)
|
||||
var p1, p2 netmapgrpc.PlacementPolicy
|
||||
v.WriteToV2(&p1)
|
||||
v2.WriteToV2(&p2)
|
||||
|
||||
require.True(t, proto.Equal(&p1, &p2))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/hrw"
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ func (c *context) processSelectors(p PlacementPolicy) error {
|
|||
|
||||
sName := p.selectors[i].GetName()
|
||||
|
||||
c.processedSelectors[sName] = &p.selectors[i]
|
||||
c.processedSelectors[sName] = p.selectors[i]
|
||||
|
||||
result, err := c.getSelection(p.selectors[i])
|
||||
if err != nil {
|
||||
|
@ -36,9 +36,9 @@ func (c *context) processSelectors(p PlacementPolicy) error {
|
|||
|
||||
// calcNodesCount returns number of buckets and minimum number of nodes in every bucket
|
||||
// for the given selector.
|
||||
func calcNodesCount(s netmap.Selector) (int, int) {
|
||||
func calcNodesCount(s *netmapgrpc.Selector) (int, int) {
|
||||
switch s.GetClause() {
|
||||
case netmap.Same:
|
||||
case netmapgrpc.Clause_SAME:
|
||||
return 1, int(s.GetCount())
|
||||
default:
|
||||
return int(s.GetCount()), 1
|
||||
|
@ -48,7 +48,7 @@ func calcNodesCount(s netmap.Selector) (int, int) {
|
|||
// calcBucketWeight computes weight for a node bucket.
|
||||
func calcBucketWeight(ns nodes, a aggregator, wf weightFunc) float64 {
|
||||
for i := range ns {
|
||||
a.Add(wf(ns[i]))
|
||||
a.Add(wf(&ns[i]))
|
||||
}
|
||||
|
||||
return a.Compute()
|
||||
|
@ -56,7 +56,7 @@ func calcBucketWeight(ns nodes, a aggregator, wf weightFunc) float64 {
|
|||
|
||||
// getSelection returns nodes grouped by s.attribute.
|
||||
// Last argument specifies if more buckets can be used to fulfill CBF.
|
||||
func (c *context) getSelection(s netmap.Selector) ([]nodes, error) {
|
||||
func (c *context) getSelection(s *netmapgrpc.Selector) ([]nodes, error) {
|
||||
bucketCount, nodesInBucket := calcNodesCount(s)
|
||||
buckets := c.getSelectionBase(s)
|
||||
|
||||
|
@ -71,7 +71,7 @@ func (c *context) getSelection(s netmap.Selector) ([]nodes, error) {
|
|||
if len(c.hrwSeed) == 0 {
|
||||
if s.GetAttribute() == "" {
|
||||
sort.Slice(buckets, func(i, j int) bool {
|
||||
return less(buckets[i].nodes[0], buckets[j].nodes[0])
|
||||
return less(&buckets[i].nodes[0], &buckets[j].nodes[0])
|
||||
})
|
||||
} else {
|
||||
sort.Slice(buckets, func(i, j int) bool {
|
||||
|
@ -131,7 +131,7 @@ type nodeAttrPair struct {
|
|||
|
||||
// getSelectionBase returns nodes grouped by selector attribute.
|
||||
// It it guaranteed that each pair will contain at least one node.
|
||||
func (c *context) getSelectionBase(s netmap.Selector) []nodeAttrPair {
|
||||
func (c *context) getSelectionBase(s *netmapgrpc.Selector) []nodeAttrPair {
|
||||
fName := s.GetFilter()
|
||||
f := c.processedFilters[fName]
|
||||
isMain := fName == mainFilterName
|
||||
|
@ -143,7 +143,7 @@ func (c *context) getSelectionBase(s netmap.Selector) []nodeAttrPair {
|
|||
if c.usedNodes[c.netMap.nodes[i].hash] {
|
||||
continue
|
||||
}
|
||||
if isMain || c.match(f, c.netMap.nodes[i]) {
|
||||
if isMain || c.match(f, &c.netMap.nodes[i]) {
|
||||
if attr == "" {
|
||||
// Default attribute is transparent identifier which is different for every node.
|
||||
result = append(result, nodeAttrPair{attr: "", nodes: nodes{c.netMap.nodes[i]}})
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"strconv"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/hrw"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ func BenchmarkHRWSort(b *testing.B) {
|
|||
key := make([]byte, 33)
|
||||
rand.Read(key)
|
||||
|
||||
var node NodeInfo
|
||||
node := NewNodeInfo()
|
||||
node.SetPrice(1)
|
||||
node.SetCapacity(100)
|
||||
node.SetPublicKey(key)
|
||||
|
@ -85,7 +85,7 @@ func BenchmarkHRWSort(b *testing.B) {
|
|||
b.StartTimer()
|
||||
|
||||
sort.Slice(vectors, func(i, j int) bool {
|
||||
return less(vectors[i][0], vectors[j][0])
|
||||
return less(&vectors[i][0], &vectors[j][0])
|
||||
})
|
||||
hrw.SortSliceByWeightIndex(realNodes, weights, pivot)
|
||||
}
|
||||
|
@ -103,8 +103,8 @@ func BenchmarkPolicyHRWType(b *testing.B) {
|
|||
newSelector("loc1", "Location", 1, "loc1", (*Selector).SelectSame),
|
||||
newSelector("loc2", "Location", 1, "loc2", (*Selector).SelectSame)},
|
||||
[]Filter{
|
||||
newFilter("loc1", "Location", "Shanghai", netmap.EQ),
|
||||
newFilter("loc2", "Location", "Shanghai", netmap.NE),
|
||||
newFilter("loc1", "Location", "Shanghai", netmapgrpc.Operation_EQ),
|
||||
newFilter("loc2", "Location", "Shanghai", netmapgrpc.Operation_NE),
|
||||
})
|
||||
|
||||
nodes := make([]NodeInfo, netmapSize)
|
||||
|
@ -148,8 +148,8 @@ func TestPlacementPolicy_DeterministicOrder(t *testing.T) {
|
|||
newSelector("loc1", "Location", 1, "loc1", (*Selector).SelectSame),
|
||||
newSelector("loc2", "Location", 1, "loc2", (*Selector).SelectSame)},
|
||||
[]Filter{
|
||||
newFilter("loc1", "Location", "Shanghai", netmap.EQ),
|
||||
newFilter("loc2", "Location", "Shanghai", netmap.NE),
|
||||
newFilter("loc1", "Location", "Shanghai", netmapgrpc.Operation_EQ),
|
||||
newFilter("loc2", "Location", "Shanghai", netmapgrpc.Operation_NE),
|
||||
})
|
||||
|
||||
nodeList := make([]NodeInfo, netmapSize)
|
||||
|
@ -204,8 +204,8 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) {
|
|||
newSelector("Main", "Country", 3, "*", (*Selector).SelectDistinct),
|
||||
},
|
||||
[]Filter{
|
||||
newFilter("FromRU", "Country", "Russia", netmap.EQ),
|
||||
newFilter("Good", "Rating", "4", netmap.GE),
|
||||
newFilter("FromRU", "Country", "Russia", netmapgrpc.Operation_EQ),
|
||||
newFilter("Good", "Rating", "4", netmapgrpc.Operation_GE),
|
||||
})
|
||||
nodes := []NodeInfo{
|
||||
nodeInfoFromAttributes("Country", "Russia", "Rating", "1", "City", "SPB"),
|
||||
|
@ -231,7 +231,7 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) {
|
|||
for _, s := range p.selectors {
|
||||
sel := c.selections[s.GetName()]
|
||||
s := c.processedSelectors[s.GetName()]
|
||||
bucketCount, nodesInBucket := calcNodesCount(*s)
|
||||
bucketCount, nodesInBucket := calcNodesCount(s)
|
||||
nodesInBucket *= int(c.cbf)
|
||||
targ := fmt.Sprintf("selector '%s'", s.GetName())
|
||||
require.Equal(t, bucketCount, len(sel), targ)
|
||||
|
@ -239,7 +239,7 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) {
|
|||
for _, res := range sel {
|
||||
require.Equal(t, nodesInBucket, len(res), targ)
|
||||
for j := range res {
|
||||
require.True(t, fName == mainFilterName || c.match(c.processedFilters[fName], res[j]), targ)
|
||||
require.True(t, fName == mainFilterName || c.match(c.processedFilters[fName], &res[j]), targ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -288,10 +288,10 @@ func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) {
|
|||
newSelector("ExceptRU", "City", 2, "ExceptRU", (*Selector).SelectSame),
|
||||
},
|
||||
[]Filter{
|
||||
newFilter("ExceptRU", "", "", netmap.NOT,
|
||||
newFilter("", "", "", netmap.AND,
|
||||
newFilter("", "City", "Lyon", netmap.EQ),
|
||||
newFilter("", "Rating", "10", netmap.LE),
|
||||
newFilter("ExceptRU", "", "", netmapgrpc.Operation_NOT,
|
||||
newFilter("", "", "", netmapgrpc.Operation_AND,
|
||||
newFilter("", "City", "Lyon", netmapgrpc.Operation_EQ),
|
||||
newFilter("", "Rating", "10", netmapgrpc.Operation_LE),
|
||||
),
|
||||
),
|
||||
})
|
||||
|
@ -319,7 +319,7 @@ func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) {
|
|||
for _, s := range p.selectors {
|
||||
sel := c.selections[s.GetName()]
|
||||
s := c.processedSelectors[s.GetName()]
|
||||
bucketCount, nodesInBucket := calcNodesCount(*s)
|
||||
bucketCount, nodesInBucket := calcNodesCount(s)
|
||||
nodesInBucket *= int(c.cbf)
|
||||
targ := fmt.Sprintf("selector '%s'", s.GetName())
|
||||
require.Equal(t, bucketCount, len(sel), targ)
|
||||
|
@ -327,7 +327,7 @@ func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) {
|
|||
for _, res := range sel {
|
||||
require.Equal(t, nodesInBucket, len(res), targ)
|
||||
for j := range res {
|
||||
require.True(t, fName == mainFilterName || c.match(c.processedFilters[fName], res[j]), targ)
|
||||
require.True(t, fName == mainFilterName || c.match(c.processedFilters[fName], &res[j]), targ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) {
|
|||
|
||||
func TestSelector_SetName(t *testing.T) {
|
||||
const name = "some name"
|
||||
var s Selector
|
||||
s := NewSelector()
|
||||
|
||||
require.Zero(t, s.m.GetName())
|
||||
|
||||
|
@ -345,7 +345,7 @@ func TestSelector_SetName(t *testing.T) {
|
|||
|
||||
func TestSelector_SetNumberOfNodes(t *testing.T) {
|
||||
const num = 3
|
||||
var s Selector
|
||||
s := NewSelector()
|
||||
|
||||
require.Zero(t, s.m.GetCount())
|
||||
|
||||
|
@ -355,20 +355,20 @@ func TestSelector_SetNumberOfNodes(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSelectorClauses(t *testing.T) {
|
||||
var s Selector
|
||||
s := NewSelector()
|
||||
|
||||
require.Equal(t, netmap.UnspecifiedClause, s.m.GetClause())
|
||||
require.Equal(t, netmapgrpc.Clause_CLAUSE_UNSPECIFIED, s.m.GetClause())
|
||||
|
||||
s.SelectDistinct()
|
||||
require.Equal(t, netmap.Distinct, s.m.GetClause())
|
||||
require.Equal(t, netmapgrpc.Clause_DISTINCT, s.m.GetClause())
|
||||
|
||||
s.SelectSame()
|
||||
require.Equal(t, netmap.Same, s.m.GetClause())
|
||||
require.Equal(t, netmapgrpc.Clause_SAME, s.m.GetClause())
|
||||
}
|
||||
|
||||
func TestSelector_SelectByBucketAttribute(t *testing.T) {
|
||||
const attr = "some attribute"
|
||||
var s Selector
|
||||
s := NewSelector()
|
||||
|
||||
require.Zero(t, s.m.GetAttribute())
|
||||
|
||||
|
@ -378,7 +378,7 @@ func TestSelector_SelectByBucketAttribute(t *testing.T) {
|
|||
|
||||
func TestSelector_SetFilterName(t *testing.T) {
|
||||
const fName = "some filter"
|
||||
var s Selector
|
||||
s := NewSelector()
|
||||
|
||||
require.Zero(t, s.m.GetFilter())
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
)
|
||||
|
||||
func filter(withInner bool) (x netmap.Filter) {
|
||||
x = netmap.NewFilter()
|
||||
x.SetName("name")
|
||||
if withInner {
|
||||
x.LogicalOR(filter(false), filter(false))
|
||||
|
@ -24,6 +25,7 @@ func Filter() netmap.Filter {
|
|||
|
||||
// Replica returns random netmap.ReplicaDescriptor.
|
||||
func Replica() (x netmap.ReplicaDescriptor) {
|
||||
x = netmap.NewReplicaDescriptor()
|
||||
x.SetNumberOfObjects(666)
|
||||
x.SetSelectorName("selector")
|
||||
|
||||
|
@ -32,6 +34,7 @@ func Replica() (x netmap.ReplicaDescriptor) {
|
|||
|
||||
// Selector returns random netmap.Selector.
|
||||
func Selector() (x netmap.Selector) {
|
||||
x = netmap.NewSelector()
|
||||
x.SetNumberOfNodes(11)
|
||||
x.SetName("name")
|
||||
x.SetFilterName("filter")
|
||||
|
@ -53,6 +56,7 @@ func PlacementPolicy() (p netmap.PlacementPolicy) {
|
|||
|
||||
// NetworkInfo returns random netmap.NetworkInfo.
|
||||
func NetworkInfo() (x netmap.NetworkInfo) {
|
||||
x = netmap.NewNetworkInfo()
|
||||
x.SetCurrentEpoch(21)
|
||||
x.SetMagicNumber(32)
|
||||
x.SetMsPerBlock(43)
|
||||
|
@ -69,6 +73,7 @@ func NetworkInfo() (x netmap.NetworkInfo) {
|
|||
|
||||
// NodeInfo returns random netmap.NodeInfo.
|
||||
func NodeInfo() (x netmap.NodeInfo) {
|
||||
x = netmap.NewNodeInfo()
|
||||
key := make([]byte, 33)
|
||||
rand.Read(key)
|
||||
|
||||
|
|
|
@ -1,17 +1,28 @@
|
|||
package object
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Attribute represents v2-compatible object attribute.
|
||||
type Attribute object.Attribute
|
||||
type Attribute struct {
|
||||
attribute *objectgrpc.Header_Attribute
|
||||
}
|
||||
|
||||
// NewAttributeFromV2 wraps v2 Attribute message to Attribute.
|
||||
//
|
||||
// Nil object.Attribute converts to nil.
|
||||
func NewAttributeFromV2(aV2 *object.Attribute) *Attribute {
|
||||
return (*Attribute)(aV2)
|
||||
// Nil objectgrpc.Header_Attribute converts to nil.
|
||||
func NewAttributeFromV2(a *objectgrpc.Header_Attribute) *Attribute {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
attr := Attribute{
|
||||
attribute: &objectgrpc.Header_Attribute{},
|
||||
}
|
||||
proto.Merge(attr.attribute, a)
|
||||
return &attr
|
||||
}
|
||||
|
||||
// NewAttribute creates and initializes blank Attribute.
|
||||
|
@ -22,52 +33,59 @@ func NewAttributeFromV2(aV2 *object.Attribute) *Attribute {
|
|||
// - key: "";
|
||||
// - value: "".
|
||||
func NewAttribute() *Attribute {
|
||||
return NewAttributeFromV2(new(object.Attribute))
|
||||
return NewAttributeFromV2(new(objectgrpc.Header_Attribute))
|
||||
}
|
||||
|
||||
// Key returns key to the object attribute.
|
||||
func (a *Attribute) Key() string {
|
||||
return (*object.Attribute)(a).GetKey()
|
||||
func (a *Attribute) GetKey() string {
|
||||
return a.attribute.GetKey()
|
||||
}
|
||||
|
||||
// SetKey sets key to the object attribute.
|
||||
func (a *Attribute) SetKey(v string) {
|
||||
(*object.Attribute)(a).SetKey(v)
|
||||
a.attribute.SetKey(v)
|
||||
}
|
||||
|
||||
// Value return value of the object attribute.
|
||||
func (a *Attribute) Value() string {
|
||||
return (*object.Attribute)(a).GetValue()
|
||||
func (a *Attribute) GetValue() string {
|
||||
return a.attribute.GetValue()
|
||||
}
|
||||
|
||||
// SetValue sets value of the object attribute.
|
||||
func (a *Attribute) SetValue(v string) {
|
||||
(*object.Attribute)(a).SetValue(v)
|
||||
a.attribute.SetValue(v)
|
||||
}
|
||||
|
||||
// ToV2 converts Attribute to v2 Attribute message.
|
||||
//
|
||||
// Nil Attribute converts to nil.
|
||||
func (a *Attribute) ToV2() *object.Attribute {
|
||||
return (*object.Attribute)(a)
|
||||
func (a *Attribute) ToV2() *objectgrpc.Header_Attribute {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
return a.attribute
|
||||
}
|
||||
|
||||
// Marshal marshals Attribute into a protobuf binary form.
|
||||
func (a *Attribute) Marshal() ([]byte, error) {
|
||||
return (*object.Attribute)(a).StableMarshal(nil), nil
|
||||
return a.attribute.StableMarshal(nil), nil
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of Attribute.
|
||||
func (a *Attribute) Unmarshal(data []byte) error {
|
||||
return (*object.Attribute)(a).Unmarshal(data)
|
||||
return proto.Unmarshal(data, a.attribute)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Attribute to protobuf JSON format.
|
||||
func (a *Attribute) MarshalJSON() ([]byte, error) {
|
||||
return (*object.Attribute)(a).MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
a.attribute,
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Attribute from protobuf JSON format.
|
||||
func (a *Attribute) UnmarshalJSON(data []byte) error {
|
||||
return (*object.Attribute)(a).UnmarshalJSON(data)
|
||||
return protojson.Unmarshal(data, a.attribute)
|
||||
}
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
package object
|
||||
package object_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAttribute(t *testing.T) {
|
||||
key, val := "some key", "some value"
|
||||
|
||||
a := NewAttribute()
|
||||
a := object.NewAttribute()
|
||||
a.SetKey(key)
|
||||
a.SetValue(val)
|
||||
|
||||
require.Equal(t, key, a.Key())
|
||||
require.Equal(t, val, a.Value())
|
||||
require.Equal(t, key, a.GetKey())
|
||||
require.Equal(t, val, a.GetValue())
|
||||
|
||||
aV2 := a.ToV2()
|
||||
|
||||
|
@ -24,7 +25,7 @@ func TestAttribute(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAttributeEncoding(t *testing.T) {
|
||||
a := NewAttribute()
|
||||
a := object.NewAttribute()
|
||||
a.SetKey("key")
|
||||
a.SetValue("value")
|
||||
|
||||
|
@ -32,7 +33,7 @@ func TestAttributeEncoding(t *testing.T) {
|
|||
data, err := a.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
a2 := NewAttribute()
|
||||
a2 := object.NewAttribute()
|
||||
require.NoError(t, a2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, a, a2)
|
||||
|
@ -42,7 +43,7 @@ func TestAttributeEncoding(t *testing.T) {
|
|||
data, err := a.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
a2 := NewAttribute()
|
||||
a2 := object.NewAttribute()
|
||||
require.NoError(t, a2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, a, a2)
|
||||
|
@ -51,15 +52,15 @@ func TestAttributeEncoding(t *testing.T) {
|
|||
|
||||
func TestNewAttributeFromV2(t *testing.T) {
|
||||
t.Run("from nil", func(t *testing.T) {
|
||||
var x *object.Attribute
|
||||
var x *objectgrpc.Header_Attribute
|
||||
|
||||
require.Nil(t, NewAttributeFromV2(x))
|
||||
require.Nil(t, object.NewAttributeFromV2(x))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAttribute_ToV2(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *Attribute
|
||||
var x *object.Attribute
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
})
|
||||
|
@ -67,11 +68,11 @@ func TestAttribute_ToV2(t *testing.T) {
|
|||
|
||||
func TestNewAttribute(t *testing.T) {
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
a := NewAttribute()
|
||||
a := object.NewAttribute()
|
||||
|
||||
// check initial values
|
||||
require.Empty(t, a.Key())
|
||||
require.Empty(t, a.Value())
|
||||
require.Empty(t, a.GetKey())
|
||||
require.Empty(t, a.GetValue())
|
||||
|
||||
// convert to v2 message
|
||||
aV2 := a.ToV2()
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
|
@ -22,7 +21,7 @@ var (
|
|||
// CalculatePayloadChecksum calculates and returns checksum of
|
||||
// object payload bytes.
|
||||
func CalculatePayloadChecksum(payload []byte) checksum.Checksum {
|
||||
var res checksum.Checksum
|
||||
res := checksum.NewChecksum()
|
||||
checksum.Calculate(&res, checksum.SHA256, payload)
|
||||
|
||||
return res
|
||||
|
@ -114,21 +113,21 @@ func CalculateAndSetSignature(key ecdsa.PrivateKey, obj *Object) error {
|
|||
|
||||
// VerifyIDSignature verifies object ID signature.
|
||||
func (o *Object) VerifyIDSignature() bool {
|
||||
m := (*object.Object)(o)
|
||||
m := o.object
|
||||
|
||||
sigV2 := m.GetSignature()
|
||||
if sigV2 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
idV2 := m.GetObjectID()
|
||||
idV2 := m.GetObjectId()
|
||||
if idV2 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
return sig.ReadFromV2(*sigV2) == nil && sig.Verify(idV2.StableMarshal(nil))
|
||||
return sig.ReadFromV2(sigV2) == nil && sig.Verify(idV2.StableMarshal(nil))
|
||||
}
|
||||
|
||||
// SetIDWithSignature sets object identifier and signature.
|
||||
|
|
|
@ -29,10 +29,10 @@ func TestVerificationFields(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
corrupt: func() {
|
||||
payload[0]++
|
||||
obj.object.Payload[0]++
|
||||
},
|
||||
restore: func() {
|
||||
payload[0]--
|
||||
obj.object.Payload[0]--
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -45,10 +45,10 @@ func TestVerificationFields(t *testing.T) {
|
|||
},
|
||||
{
|
||||
corrupt: func() {
|
||||
obj.ToV2().GetObjectID().GetValue()[0]++
|
||||
obj.ToV2().GetObjectId().GetValue()[0]++
|
||||
},
|
||||
restore: func() {
|
||||
obj.ToV2().GetObjectID().GetValue()[0]--
|
||||
obj.ToV2().GetObjectId().GetValue()[0]--
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -5,44 +5,45 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Address represents global object identifier in FrostFS network. Each object
|
||||
// belongs to exactly one container and is uniquely addressed within the container.
|
||||
//
|
||||
// Address is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Address
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
// Address is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refsgrpc.Address
|
||||
// message. See ReadFrom / WriteTo methods.
|
||||
//
|
||||
// Instances can be created using built-in var declaration.
|
||||
type Address struct {
|
||||
cnr cid.ID
|
||||
cnr cidSDK.ID
|
||||
|
||||
obj ID
|
||||
}
|
||||
|
||||
// ReadFromV2 reads Address from the refs.Address message. Returns an error if
|
||||
// ReadFrom reads Address from the refsgrpc.Address message. Returns an error if
|
||||
// the message is malformed according to the FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (x *Address) ReadFromV2(m refs.Address) error {
|
||||
cnr := m.GetContainerID()
|
||||
// See also WriteTo.
|
||||
func (x *Address) ReadFromV2(m *refsgrpc.Address) error {
|
||||
cnr := m.GetContainerId()
|
||||
if cnr == nil {
|
||||
return errors.New("missing container ID")
|
||||
}
|
||||
|
||||
obj := m.GetObjectID()
|
||||
obj := m.GetObjectId()
|
||||
if obj == nil {
|
||||
return errors.New("missing object ID")
|
||||
}
|
||||
|
||||
err := x.cnr.ReadFromV2(*cnr)
|
||||
err := x.cnr.ReadFromV2(cnr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container ID: %w", err)
|
||||
}
|
||||
|
||||
err = x.obj.ReadFromV2(*obj)
|
||||
err = x.obj.ReadFromV2(obj)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid object ID: %w", err)
|
||||
}
|
||||
|
@ -50,19 +51,20 @@ func (x *Address) ReadFromV2(m refs.Address) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// WriteToV2 writes Address to the refs.Address message.
|
||||
// WriteTo writes Address to the refsgrpc.Address message.
|
||||
// The message must not be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x Address) WriteToV2(m *refs.Address) {
|
||||
var obj refs.ObjectID
|
||||
// See also ReadFrom.
|
||||
func (x Address) WriteToV2(m *refsgrpc.Address) {
|
||||
m.Reset()
|
||||
var obj refsgrpc.ObjectID
|
||||
x.obj.WriteToV2(&obj)
|
||||
|
||||
var cnr refs.ContainerID
|
||||
var cnr refsgrpc.ContainerID
|
||||
x.cnr.WriteToV2(&cnr)
|
||||
|
||||
m.SetObjectID(&obj)
|
||||
m.SetContainerID(&cnr)
|
||||
m.SetObjectId(&obj)
|
||||
m.SetContainerId(&cnr)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Address into a JSON format of the FrostFS API protocol
|
||||
|
@ -70,10 +72,10 @@ func (x Address) WriteToV2(m *refs.Address) {
|
|||
//
|
||||
// See also UnmarshalJSON.
|
||||
func (x Address) MarshalJSON() ([]byte, error) {
|
||||
var m refs.Address
|
||||
var m refsgrpc.Address
|
||||
x.WriteToV2(&m)
|
||||
|
||||
return m.MarshalJSON()
|
||||
return protojson.Marshal(&m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes FrostFS API protocol JSON format into the Address
|
||||
|
@ -81,14 +83,14 @@ func (x Address) MarshalJSON() ([]byte, error) {
|
|||
//
|
||||
// See also MarshalJSON.
|
||||
func (x *Address) UnmarshalJSON(data []byte) error {
|
||||
var m refs.Address
|
||||
var m refsgrpc.Address
|
||||
|
||||
err := m.UnmarshalJSON(data)
|
||||
err := protojson.Unmarshal(data, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return x.ReadFromV2(m)
|
||||
return x.ReadFromV2(&m)
|
||||
}
|
||||
|
||||
// Container returns unique identifier of the FrostFS object container.
|
||||
|
@ -97,14 +99,14 @@ func (x *Address) UnmarshalJSON(data []byte) error {
|
|||
// API protocol.
|
||||
//
|
||||
// See also SetContainer.
|
||||
func (x Address) Container() cid.ID {
|
||||
func (x Address) Container() cidSDK.ID {
|
||||
return x.cnr
|
||||
}
|
||||
|
||||
// SetContainer sets unique identifier of the FrostFS object container.
|
||||
//
|
||||
// See also Container.
|
||||
func (x *Address) SetContainer(id cid.ID) {
|
||||
func (x *Address) SetContainer(id cidSDK.ID) {
|
||||
x.cnr = id
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@ package oid_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestAddress_SetContainer(t *testing.T) {
|
||||
|
@ -32,38 +33,38 @@ func TestAddress_SetObject(t *testing.T) {
|
|||
require.Equal(t, obj, x.Object())
|
||||
}
|
||||
|
||||
func TestAddress_ReadFromV2(t *testing.T) {
|
||||
func TestAddress_ReadFrom(t *testing.T) {
|
||||
var x oid.Address
|
||||
var xV2 refs.Address
|
||||
|
||||
require.Error(t, x.ReadFromV2(xV2))
|
||||
require.Error(t, x.ReadFromV2(&xV2))
|
||||
|
||||
var cnrV2 refs.ContainerID
|
||||
xV2.SetContainerID(&cnrV2)
|
||||
xV2.SetContainerId(&cnrV2)
|
||||
|
||||
require.Error(t, x.ReadFromV2(xV2))
|
||||
require.Error(t, x.ReadFromV2(&xV2))
|
||||
|
||||
cnr := cidtest.ID()
|
||||
cnr.WriteToV2(&cnrV2)
|
||||
|
||||
require.Error(t, x.ReadFromV2(xV2))
|
||||
require.Error(t, x.ReadFromV2(&xV2))
|
||||
|
||||
var objV2 refs.ObjectID
|
||||
xV2.SetObjectID(&objV2)
|
||||
xV2.SetObjectId(&objV2)
|
||||
|
||||
require.Error(t, x.ReadFromV2(xV2))
|
||||
require.Error(t, x.ReadFromV2(&xV2))
|
||||
|
||||
obj := oidtest.ID()
|
||||
obj.WriteToV2(&objV2)
|
||||
|
||||
require.NoError(t, x.ReadFromV2(xV2))
|
||||
require.NoError(t, x.ReadFromV2(&xV2))
|
||||
require.Equal(t, cnr, x.Container())
|
||||
require.Equal(t, obj, x.Object())
|
||||
|
||||
var xV2To refs.Address
|
||||
x.WriteToV2(&xV2To)
|
||||
|
||||
require.Equal(t, xV2, xV2To)
|
||||
require.True(t, proto.Equal(&xV2, &xV2To))
|
||||
}
|
||||
|
||||
func TestAddress_DecodeString(t *testing.T) {
|
||||
|
|
|
@ -5,10 +5,12 @@ import (
|
|||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/mr-tron/base58"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// ID represents FrostFS object identifier in a container.
|
||||
|
@ -27,7 +29,7 @@ type ID [sha256.Size]byte
|
|||
// the message is malformed according to the FrostFS API V2 protocol.
|
||||
//
|
||||
// See also WriteToV2.
|
||||
func (id *ID) ReadFromV2(m refs.ObjectID) error {
|
||||
func (id *ID) ReadFromV2(m *refs.ObjectID) error {
|
||||
return id.Decode(m.GetValue())
|
||||
}
|
||||
|
||||
|
@ -36,6 +38,7 @@ func (id *ID) ReadFromV2(m refs.ObjectID) error {
|
|||
//
|
||||
// See also ReadFromV2.
|
||||
func (id ID) WriteToV2(m *refs.ObjectID) {
|
||||
m.Reset()
|
||||
m.SetValue(id[:])
|
||||
}
|
||||
|
||||
|
@ -123,7 +126,7 @@ func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (frostfscrypto.Signature
|
|||
return frostfscrypto.Signature{}, fmt.Errorf("marshal ID: %w", err)
|
||||
}
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
sig := frostfscrypto.NewSignature()
|
||||
|
||||
return sig, sig.Calculate(frostfsecdsa.Signer(key), data)
|
||||
}
|
||||
|
@ -139,7 +142,7 @@ func (id ID) Marshal() ([]byte, error) {
|
|||
// Unmarshal unmarshals protobuf binary representation of ID.
|
||||
func (id *ID) Unmarshal(data []byte) error {
|
||||
var v2 refs.ObjectID
|
||||
if err := v2.Unmarshal(data); err != nil {
|
||||
if err := proto.Unmarshal(data, &v2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -153,13 +156,13 @@ func (id ID) MarshalJSON() ([]byte, error) {
|
|||
var v2 refs.ObjectID
|
||||
v2.SetValue(id[:])
|
||||
|
||||
return v2.MarshalJSON()
|
||||
return protojson.Marshal(&v2)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes ID from protobuf JSON format.
|
||||
func (id *ID) UnmarshalJSON(data []byte) error {
|
||||
var v2 refs.ObjectID
|
||||
if err := v2.UnmarshalJSON(data); err != nil {
|
||||
if err := protojson.Unmarshal(data, &v2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"strconv"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -142,7 +142,7 @@ func TestNewIDFromV2(t *testing.T) {
|
|||
v2 refs.ObjectID
|
||||
)
|
||||
|
||||
require.Error(t, x.ReadFromV2(v2))
|
||||
require.Error(t, x.ReadFromV2(&v2))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
package object
|
||||
|
||||
import (
|
||||
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
v2lock "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/lock/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
)
|
||||
|
||||
// Lock represents record with locked objects. It is compatible with
|
||||
// FrostFS API V2 protocol.
|
||||
//
|
||||
// Lock instance can be written to the Object, see WriteLock/ReadLock.
|
||||
type Lock v2object.Lock
|
||||
type Lock struct {
|
||||
lock *v2lock.Lock
|
||||
}
|
||||
|
||||
func NewLock() *Lock {
|
||||
return &Lock{
|
||||
lock: &v2lock.Lock{},
|
||||
}
|
||||
}
|
||||
|
||||
// WriteLock writes Lock to the Object, and sets its type to TypeLock.
|
||||
// The object must not be nil.
|
||||
|
@ -26,13 +35,13 @@ func WriteLock(obj *Object, l Lock) {
|
|||
// if object has TypeLock type.
|
||||
//
|
||||
// See also WriteLock.
|
||||
func ReadLock(l *Lock, obj Object) error {
|
||||
func ReadLock(l *Lock, obj *Object) error {
|
||||
return l.Unmarshal(obj.Payload())
|
||||
}
|
||||
|
||||
// NumberOfMembers returns number of members in lock list.
|
||||
func (x Lock) NumberOfMembers() int {
|
||||
return (*v2object.Lock)(&x).NumberOfMembers()
|
||||
return x.lock.NumberOfMembers()
|
||||
}
|
||||
|
||||
// ReadMembers reads list of locked members.
|
||||
|
@ -41,7 +50,7 @@ func (x Lock) NumberOfMembers() int {
|
|||
func (x Lock) ReadMembers(buf []oid.ID) {
|
||||
var i int
|
||||
|
||||
(*v2object.Lock)(&x).IterateMembers(func(idV2 refs.ObjectID) {
|
||||
x.lock.IterateMembers(func(idV2 *refsgrpc.ObjectID) {
|
||||
_ = buf[i].ReadFromV2(idV2)
|
||||
i++
|
||||
})
|
||||
|
@ -49,25 +58,34 @@ func (x Lock) ReadMembers(buf []oid.ID) {
|
|||
|
||||
// WriteMembers writes list of locked members.
|
||||
func (x *Lock) WriteMembers(ids []oid.ID) {
|
||||
var members []refs.ObjectID
|
||||
var members []*refsgrpc.ObjectID
|
||||
|
||||
if ids != nil {
|
||||
members = make([]refs.ObjectID, len(ids))
|
||||
|
||||
members = slices.MakePreallocPointerSlice[refsgrpc.ObjectID](len(ids))
|
||||
for i := range ids {
|
||||
ids[i].WriteToV2(&members[i])
|
||||
ids[i].WriteToV2(members[i])
|
||||
}
|
||||
}
|
||||
|
||||
(*v2object.Lock)(x).SetMembers(members)
|
||||
if x.lock == nil {
|
||||
x.lock = new(v2lock.Lock)
|
||||
}
|
||||
x.lock.SetMembers(members)
|
||||
}
|
||||
|
||||
func (x *Lock) ToV2() *v2lock.Lock {
|
||||
return x.lock
|
||||
}
|
||||
|
||||
// Marshal encodes the Lock into a FrostFS protocol binary format.
|
||||
func (x Lock) Marshal() []byte {
|
||||
return (*v2object.Lock)(&x).StableMarshal(nil)
|
||||
return x.lock.StableMarshal(nil)
|
||||
}
|
||||
|
||||
// Unmarshal decodes the Lock from its FrostFS protocol binary representation.
|
||||
func (x *Lock) Unmarshal(data []byte) error {
|
||||
return (*v2object.Lock)(x).Unmarshal(data)
|
||||
if x.lock == nil {
|
||||
x.lock = new(v2lock.Lock)
|
||||
}
|
||||
return x.lock.Unmarshal(data)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestLockEncoding(t *testing.T) {
|
||||
|
@ -14,26 +15,26 @@ func TestLockEncoding(t *testing.T) {
|
|||
t.Run("binary", func(t *testing.T) {
|
||||
data := l.Marshal()
|
||||
|
||||
var l2 object.Lock
|
||||
l2 := object.NewLock()
|
||||
require.NoError(t, l2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, l, l2)
|
||||
require.True(t, proto.Equal(l.ToV2(), l2.ToV2()))
|
||||
})
|
||||
}
|
||||
|
||||
func TestWriteLock(t *testing.T) {
|
||||
l := *objecttest.Lock()
|
||||
var o object.Object
|
||||
o := object.New()
|
||||
|
||||
object.WriteLock(&o, l)
|
||||
object.WriteLock(o, l)
|
||||
|
||||
var l2 object.Lock
|
||||
l2 := object.NewLock()
|
||||
|
||||
require.NoError(t, object.ReadLock(&l2, o))
|
||||
require.Equal(t, l, l2)
|
||||
require.NoError(t, object.ReadLock(l2, o))
|
||||
require.True(t, proto.Equal(l.ToV2(), l2.ToV2()))
|
||||
|
||||
// corrupt payload
|
||||
o.Payload()[0]++
|
||||
|
||||
require.Error(t, object.ReadLock(&l2, o))
|
||||
require.Error(t, object.ReadLock(l2, o))
|
||||
}
|
||||
|
|
311
object/object.go
311
object/object.go
|
@ -4,31 +4,37 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
objectgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||
refsgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc"
|
||||
sessiongrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/util/slices"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
// Object represents in-memory structure of the FrostFS object.
|
||||
// Object represents in-memory structure of the FrostFS objectgrpc.
|
||||
// Type is compatible with FrostFS API V2 protocol.
|
||||
//
|
||||
// Instance can be created depending on scenario:
|
||||
// - InitCreation (an object to be placed in container);
|
||||
// - New (blank instance, usually needed for decoding);
|
||||
// - NewFromV2 (when working under FrostFS API V2 protocol).
|
||||
type Object object.Object
|
||||
type Object struct {
|
||||
object *objectgrpc.Object
|
||||
}
|
||||
|
||||
// RequiredFields contains the minimum set of object data that must be set
|
||||
// by the FrostFS user at the stage of creation.
|
||||
type RequiredFields struct {
|
||||
// Identifier of the FrostFS container associated with the object.
|
||||
// Identifier of the FrostFS container associated with the objectgrpc.
|
||||
Container cid.ID
|
||||
|
||||
// Object owner's user ID in the FrostFS system.
|
||||
|
@ -43,45 +49,52 @@ func InitCreation(dst *Object, rf RequiredFields) {
|
|||
}
|
||||
|
||||
// NewFromV2 wraps v2 Object message to Object.
|
||||
func NewFromV2(oV2 *object.Object) *Object {
|
||||
return (*Object)(oV2)
|
||||
func NewFromV2(obj *objectgrpc.Object) *Object {
|
||||
objSDK := &Object{
|
||||
object: new(objectgrpc.Object),
|
||||
}
|
||||
proto.Merge(objSDK.object, obj)
|
||||
return objSDK
|
||||
}
|
||||
|
||||
// New creates and initializes blank Object.
|
||||
//
|
||||
// Works similar as NewFromV2(new(Object)).
|
||||
func New() *Object {
|
||||
return NewFromV2(new(object.Object))
|
||||
return NewFromV2(new(objectgrpc.Object))
|
||||
}
|
||||
|
||||
// ToV2 converts Object to v2 Object message.
|
||||
func (o *Object) ToV2() *object.Object {
|
||||
return (*object.Object)(o)
|
||||
func (o *Object) ToV2() *objectgrpc.Object {
|
||||
return o.object
|
||||
}
|
||||
|
||||
// MarshalHeaderJSON marshals object's header
|
||||
// into JSON format.
|
||||
func (o *Object) MarshalHeaderJSON() ([]byte, error) {
|
||||
return (*object.Object)(o).GetHeader().MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
o.object.GetHeader(),
|
||||
)
|
||||
}
|
||||
|
||||
func (o *Object) setHeaderField(setter func(*object.Header)) {
|
||||
obj := (*object.Object)(o)
|
||||
h := obj.GetHeader()
|
||||
func (o *Object) setHeaderField(setter func(*objectgrpc.Header)) {
|
||||
h := o.object.GetHeader()
|
||||
|
||||
if h == nil {
|
||||
h = new(object.Header)
|
||||
obj.SetHeader(h)
|
||||
h = new(objectgrpc.Header)
|
||||
o.object.SetHeader(h)
|
||||
}
|
||||
|
||||
setter(h)
|
||||
}
|
||||
|
||||
func (o *Object) setSplitFields(setter func(*object.SplitHeader)) {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
func (o *Object) setSplitFields(setter func(*objectgrpc.Header_Split)) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
split := h.GetSplit()
|
||||
if split == nil {
|
||||
split = new(object.SplitHeader)
|
||||
split = new(objectgrpc.Header_Split)
|
||||
h.SetSplit(split)
|
||||
}
|
||||
|
||||
|
@ -91,9 +104,9 @@ func (o *Object) setSplitFields(setter func(*object.SplitHeader)) {
|
|||
|
||||
// ID returns object identifier.
|
||||
func (o *Object) ID() (v oid.ID, isSet bool) {
|
||||
v2 := (*object.Object)(o)
|
||||
if id := v2.GetObjectID(); id != nil {
|
||||
_ = v.ReadFromV2(*v2.GetObjectID())
|
||||
v2 := o.object
|
||||
if id := v2.GetObjectId(); id != nil {
|
||||
_ = v.ReadFromV2(v2.GetObjectId())
|
||||
isSet = true
|
||||
}
|
||||
|
||||
|
@ -102,89 +115,88 @@ func (o *Object) ID() (v oid.ID, isSet bool) {
|
|||
|
||||
// SetID sets object identifier.
|
||||
func (o *Object) SetID(v oid.ID) {
|
||||
var v2 refs.ObjectID
|
||||
var v2 refsgrpc.ObjectID
|
||||
v.WriteToV2(&v2)
|
||||
|
||||
(*object.Object)(o).
|
||||
SetObjectID(&v2)
|
||||
o.object.SetObjectId(&v2)
|
||||
}
|
||||
|
||||
// Signature returns signature of the object identifier.
|
||||
func (o *Object) Signature() *frostfscrypto.Signature {
|
||||
sigv2 := (*object.Object)(o).GetSignature()
|
||||
sigv2 := o.object.GetSignature()
|
||||
if sigv2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var sig frostfscrypto.Signature
|
||||
_ = sig.ReadFromV2(*sigv2) // FIXME(@cthulhu-rider): #226 handle error
|
||||
sig := frostfscrypto.NewSignature()
|
||||
_ = sig.ReadFromV2(sigv2) // FIXME(@cthulhu-rider): #226 handle error
|
||||
|
||||
return &sig
|
||||
}
|
||||
|
||||
// SetSignature sets signature of the object identifier.
|
||||
func (o *Object) SetSignature(v *frostfscrypto.Signature) {
|
||||
var sigv2 *refs.Signature
|
||||
var sigv2 *refsgrpc.Signature
|
||||
|
||||
if v != nil {
|
||||
sigv2 = new(refs.Signature)
|
||||
sigv2 = new(refsgrpc.Signature)
|
||||
|
||||
v.WriteToV2(sigv2)
|
||||
}
|
||||
|
||||
(*object.Object)(o).SetSignature(sigv2)
|
||||
o.object.SetSignature(sigv2)
|
||||
}
|
||||
|
||||
// Payload returns payload bytes.
|
||||
func (o *Object) Payload() []byte {
|
||||
return (*object.Object)(o).GetPayload()
|
||||
return o.object.GetPayload()
|
||||
}
|
||||
|
||||
// SetPayload sets payload bytes.
|
||||
func (o *Object) SetPayload(v []byte) {
|
||||
(*object.Object)(o).SetPayload(v)
|
||||
o.object.SetPayload(v)
|
||||
}
|
||||
|
||||
// Version returns version of the object.
|
||||
// Version returns version of the objectgrpc.
|
||||
func (o *Object) Version() *version.Version {
|
||||
var ver version.Version
|
||||
if verV2 := (*object.Object)(o).GetHeader().GetVersion(); verV2 != nil {
|
||||
_ = ver.ReadFromV2(*verV2) // FIXME(@cthulhu-rider): #226 handle error
|
||||
ver := version.NewVersion()
|
||||
if verV2 := o.object.GetHeader().GetVersion(); verV2 != nil {
|
||||
ver.ReadFromV2(verV2)
|
||||
}
|
||||
return &ver
|
||||
}
|
||||
|
||||
// SetVersion sets version of the object.
|
||||
func (o *Object) SetVersion(v *version.Version) {
|
||||
var verV2 refs.Version
|
||||
// SetVersion sets version of the objectgrpc.
|
||||
func (o *Object) SetVersion(v version.Version) {
|
||||
var verV2 refsgrpc.Version
|
||||
v.WriteToV2(&verV2)
|
||||
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetVersion(&verV2)
|
||||
})
|
||||
}
|
||||
|
||||
// PayloadSize returns payload length of the object.
|
||||
// PayloadSize returns payload length of the objectgrpc.
|
||||
func (o *Object) PayloadSize() uint64 {
|
||||
return (*object.Object)(o).
|
||||
return o.object.
|
||||
GetHeader().
|
||||
GetPayloadLength()
|
||||
}
|
||||
|
||||
// SetPayloadSize sets payload length of the object.
|
||||
// SetPayloadSize sets payload length of the objectgrpc.
|
||||
func (o *Object) SetPayloadSize(v uint64) {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetPayloadLength(v)
|
||||
})
|
||||
}
|
||||
|
||||
// ContainerID returns identifier of the related container.
|
||||
func (o *Object) ContainerID() (v cid.ID, isSet bool) {
|
||||
v2 := (*object.Object)(o)
|
||||
v2 := o.object
|
||||
|
||||
cidV2 := v2.GetHeader().GetContainerID()
|
||||
cidV2 := v2.GetHeader().GetContainerId()
|
||||
if cidV2 != nil {
|
||||
_ = v.ReadFromV2(*cidV2)
|
||||
_ = v.ReadFromV2(cidV2)
|
||||
isSet = true
|
||||
}
|
||||
|
||||
|
@ -193,21 +205,25 @@ func (o *Object) ContainerID() (v cid.ID, isSet bool) {
|
|||
|
||||
// SetContainerID sets identifier of the related container.
|
||||
func (o *Object) SetContainerID(v cid.ID) {
|
||||
var cidV2 refs.ContainerID
|
||||
var cidV2 refsgrpc.ContainerID
|
||||
v.WriteToV2(&cidV2)
|
||||
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
h.SetContainerID(&cidV2)
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetContainerId(&cidV2)
|
||||
})
|
||||
}
|
||||
|
||||
func (o *Object) Equal(o1 *Object) bool {
|
||||
return proto.Equal(o.object, o1.object)
|
||||
}
|
||||
|
||||
// OwnerID returns identifier of the object owner.
|
||||
func (o *Object) OwnerID() *user.ID {
|
||||
var id user.ID
|
||||
|
||||
m := (*object.Object)(o).GetHeader().GetOwnerID()
|
||||
m := o.object.GetHeader().GetOwnerId()
|
||||
if m != nil {
|
||||
_ = id.ReadFromV2(*m)
|
||||
_ = id.ReadFromV2(m)
|
||||
}
|
||||
|
||||
return &id
|
||||
|
@ -215,40 +231,40 @@ func (o *Object) OwnerID() *user.ID {
|
|||
|
||||
// SetOwnerID sets identifier of the object owner.
|
||||
func (o *Object) SetOwnerID(v *user.ID) {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
var m refs.OwnerID
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
var m refsgrpc.OwnerID
|
||||
v.WriteToV2(&m)
|
||||
|
||||
h.SetOwnerID(&m)
|
||||
h.SetOwnerId(&m)
|
||||
})
|
||||
}
|
||||
|
||||
// CreationEpoch returns epoch number in which object was created.
|
||||
func (o *Object) CreationEpoch() uint64 {
|
||||
return (*object.Object)(o).
|
||||
return o.object.
|
||||
GetHeader().
|
||||
GetCreationEpoch()
|
||||
}
|
||||
|
||||
// SetCreationEpoch sets epoch number in which object was created.
|
||||
func (o *Object) SetCreationEpoch(v uint64) {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetCreationEpoch(v)
|
||||
})
|
||||
}
|
||||
|
||||
// PayloadChecksum returns checksum of the object payload and
|
||||
// bool that indicates checksum presence in the object.
|
||||
// bool that indicates checksum presence in the objectgrpc.
|
||||
//
|
||||
// Zero Object does not have payload checksum.
|
||||
//
|
||||
// See also SetPayloadChecksum.
|
||||
func (o *Object) PayloadChecksum() (checksum.Checksum, bool) {
|
||||
var v checksum.Checksum
|
||||
v2 := (*object.Object)(o)
|
||||
v := checksum.NewChecksum()
|
||||
v2 := o.object
|
||||
|
||||
if hash := v2.GetHeader().GetPayloadHash(); hash != nil {
|
||||
_ = v.ReadFromV2(*hash) // FIXME(@cthulhu-rider): #226 handle error
|
||||
_ = v.ReadFromV2(hash) // FIXME(@cthulhu-rider): #226 handle error
|
||||
return v, true
|
||||
}
|
||||
|
||||
|
@ -259,26 +275,26 @@ func (o *Object) PayloadChecksum() (checksum.Checksum, bool) {
|
|||
//
|
||||
// See also PayloadChecksum.
|
||||
func (o *Object) SetPayloadChecksum(v checksum.Checksum) {
|
||||
var v2 refs.Checksum
|
||||
var v2 refsgrpc.Checksum
|
||||
v.WriteToV2(&v2)
|
||||
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetPayloadHash(&v2)
|
||||
})
|
||||
}
|
||||
|
||||
// PayloadHomomorphicHash returns homomorphic hash of the object
|
||||
// payload and bool that indicates checksum presence in the object.
|
||||
// payload and bool that indicates checksum presence in the objectgrpc.
|
||||
//
|
||||
// Zero Object does not have payload homomorphic checksum.
|
||||
//
|
||||
// See also SetPayloadHomomorphicHash.
|
||||
func (o *Object) PayloadHomomorphicHash() (checksum.Checksum, bool) {
|
||||
var v checksum.Checksum
|
||||
v2 := (*object.Object)(o)
|
||||
v := checksum.NewChecksum()
|
||||
v2 := o.object
|
||||
|
||||
if hash := v2.GetHeader().GetHomomorphicHash(); hash != nil {
|
||||
_ = v.ReadFromV2(*hash) // FIXME(@cthulhu-rider): #226 handle error
|
||||
_ = v.ReadFromV2(hash) // FIXME(@cthulhu-rider): #226 handle error
|
||||
return v, true
|
||||
}
|
||||
|
||||
|
@ -289,24 +305,24 @@ func (o *Object) PayloadHomomorphicHash() (checksum.Checksum, bool) {
|
|||
//
|
||||
// See also PayloadHomomorphicHash.
|
||||
func (o *Object) SetPayloadHomomorphicHash(v checksum.Checksum) {
|
||||
var v2 refs.Checksum
|
||||
var v2 refsgrpc.Checksum
|
||||
v.WriteToV2(&v2)
|
||||
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetHomomorphicHash(&v2)
|
||||
})
|
||||
}
|
||||
|
||||
// Attributes returns object attributes.
|
||||
func (o *Object) Attributes() []Attribute {
|
||||
attrs := (*object.Object)(o).
|
||||
attrs := o.object.
|
||||
GetHeader().
|
||||
GetAttributes()
|
||||
|
||||
res := make([]Attribute, len(attrs))
|
||||
|
||||
for i := range attrs {
|
||||
res[i] = *NewAttributeFromV2(&attrs[i])
|
||||
res[i] = *NewAttributeFromV2(attrs[i])
|
||||
}
|
||||
|
||||
return res
|
||||
|
@ -314,43 +330,42 @@ func (o *Object) Attributes() []Attribute {
|
|||
|
||||
// SetAttributes sets object attributes.
|
||||
func (o *Object) SetAttributes(v ...Attribute) {
|
||||
attrs := make([]object.Attribute, len(v))
|
||||
|
||||
attrs := slices.MakePreallocPointerSlice[objectgrpc.Header_Attribute](len(v))
|
||||
for i := range v {
|
||||
attrs[i] = *v[i].ToV2()
|
||||
attrs[i] = v[i].ToV2()
|
||||
}
|
||||
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetAttributes(attrs)
|
||||
})
|
||||
}
|
||||
|
||||
// PreviousID returns identifier of the previous sibling object.
|
||||
// PreviousID returns identifier of the previous sibling objectgrpc.
|
||||
func (o *Object) PreviousID() (v oid.ID, isSet bool) {
|
||||
v2 := (*object.Object)(o)
|
||||
v2 := o.object
|
||||
|
||||
v2Prev := v2.GetHeader().GetSplit().GetPrevious()
|
||||
if v2Prev != nil {
|
||||
_ = v.ReadFromV2(*v2Prev)
|
||||
_ = v.ReadFromV2(v2Prev)
|
||||
isSet = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetPreviousID sets identifier of the previous sibling object.
|
||||
// SetPreviousID sets identifier of the previous sibling objectgrpc.
|
||||
func (o *Object) SetPreviousID(v oid.ID) {
|
||||
var v2 refs.ObjectID
|
||||
var v2 refsgrpc.ObjectID
|
||||
v.WriteToV2(&v2)
|
||||
|
||||
o.setSplitFields(func(split *object.SplitHeader) {
|
||||
o.setSplitFields(func(split *objectgrpc.Header_Split) {
|
||||
split.SetPrevious(&v2)
|
||||
})
|
||||
}
|
||||
|
||||
// Children return list of the identifiers of the child objects.
|
||||
func (o *Object) Children() []oid.ID {
|
||||
v2 := (*object.Object)(o)
|
||||
v2 := o.object
|
||||
ids := v2.GetHeader().GetSplit().GetChildren()
|
||||
|
||||
var (
|
||||
|
@ -368,23 +383,21 @@ func (o *Object) Children() []oid.ID {
|
|||
|
||||
// SetChildren sets list of the identifiers of the child objects.
|
||||
func (o *Object) SetChildren(v ...oid.ID) {
|
||||
var (
|
||||
v2 refs.ObjectID
|
||||
ids = make([]refs.ObjectID, len(v))
|
||||
)
|
||||
ids := make([]*refsgrpc.ObjectID, len(v))
|
||||
|
||||
for i := range v {
|
||||
var v2 refsgrpc.ObjectID
|
||||
v[i].WriteToV2(&v2)
|
||||
ids[i] = v2
|
||||
ids[i] = &v2
|
||||
}
|
||||
|
||||
o.setSplitFields(func(split *object.SplitHeader) {
|
||||
o.setSplitFields(func(split *objectgrpc.Header_Split) {
|
||||
split.SetChildren(ids)
|
||||
})
|
||||
}
|
||||
|
||||
// NotificationInfo groups information about object notification
|
||||
// that can be written to object.
|
||||
// that can be written to objectgrpc.
|
||||
//
|
||||
// Topic is an optional field.
|
||||
type NotificationInfo struct {
|
||||
|
@ -420,7 +433,7 @@ func (n *NotificationInfo) SetTopic(topic string) {
|
|||
// Returns any error that appeared during notification
|
||||
// information parsing.
|
||||
func (o *Object) NotificationInfo() (*NotificationInfo, error) {
|
||||
ni, err := object.GetNotificationInfo((*object.Object)(o))
|
||||
ni, err := object.GetNotificationInfo(o.object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -432,53 +445,53 @@ func (o *Object) NotificationInfo() (*NotificationInfo, error) {
|
|||
|
||||
// SetNotification writes NotificationInfo to the object structure.
|
||||
func (o *Object) SetNotification(ni NotificationInfo) {
|
||||
object.WriteNotificationInfo((*object.Object)(o), ni.ni)
|
||||
object.WriteNotificationInfo(o.object, ni.ni)
|
||||
}
|
||||
|
||||
// SplitID return split identity of split object. If object is not split
|
||||
// SplitID return split identity of split objectgrpc. If object is not split
|
||||
// returns nil.
|
||||
func (o *Object) SplitID() *SplitID {
|
||||
return NewSplitIDFromV2(
|
||||
(*object.Object)(o).
|
||||
o.object.
|
||||
GetHeader().
|
||||
GetSplit().
|
||||
GetSplitID(),
|
||||
GetSplitId(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetSplitID sets split identifier for the split object.
|
||||
// SetSplitID sets split identifier for the split objectgrpc.
|
||||
func (o *Object) SetSplitID(id *SplitID) {
|
||||
o.setSplitFields(func(split *object.SplitHeader) {
|
||||
split.SetSplitID(id.ToV2())
|
||||
o.setSplitFields(func(split *objectgrpc.Header_Split) {
|
||||
split.SetSplitId(id.ToV2())
|
||||
})
|
||||
}
|
||||
|
||||
// ParentID returns identifier of the parent object.
|
||||
// ParentID returns identifier of the parent objectgrpc.
|
||||
func (o *Object) ParentID() (v oid.ID, isSet bool) {
|
||||
v2 := (*object.Object)(o)
|
||||
v2 := o.object
|
||||
|
||||
v2Par := v2.GetHeader().GetSplit().GetParent()
|
||||
if v2Par != nil {
|
||||
_ = v.ReadFromV2(*v2Par)
|
||||
_ = v.ReadFromV2(v2Par)
|
||||
isSet = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetParentID sets identifier of the parent object.
|
||||
// SetParentID sets identifier of the parent objectgrpc.
|
||||
func (o *Object) SetParentID(v oid.ID) {
|
||||
var v2 refs.ObjectID
|
||||
var v2 refsgrpc.ObjectID
|
||||
v.WriteToV2(&v2)
|
||||
|
||||
o.setSplitFields(func(split *object.SplitHeader) {
|
||||
o.setSplitFields(func(split *objectgrpc.Header_Split) {
|
||||
split.SetParent(&v2)
|
||||
})
|
||||
}
|
||||
|
||||
// Parent returns parent object w/o payload.
|
||||
func (o *Object) Parent() *Object {
|
||||
h := (*object.Object)(o).
|
||||
h := o.object.
|
||||
GetHeader().
|
||||
GetSplit()
|
||||
|
||||
|
@ -489,8 +502,8 @@ func (o *Object) Parent() *Object {
|
|||
return nil
|
||||
}
|
||||
|
||||
oV2 := new(object.Object)
|
||||
oV2.SetObjectID(h.GetParent())
|
||||
oV2 := new(objectgrpc.Object)
|
||||
oV2.SetObjectId(h.GetParent())
|
||||
oV2.SetSignature(parSig)
|
||||
oV2.SetHeader(parHdr)
|
||||
|
||||
|
@ -499,21 +512,21 @@ func (o *Object) Parent() *Object {
|
|||
|
||||
// SetParent sets parent object w/o payload.
|
||||
func (o *Object) SetParent(v *Object) {
|
||||
o.setSplitFields(func(split *object.SplitHeader) {
|
||||
split.SetParent((*object.Object)(v).GetObjectID())
|
||||
split.SetParentSignature((*object.Object)(v).GetSignature())
|
||||
split.SetParentHeader((*object.Object)(v).GetHeader())
|
||||
o.setSplitFields(func(split *objectgrpc.Header_Split) {
|
||||
split.SetParent(v.object.GetObjectId())
|
||||
split.SetParentSignature(v.object.GetSignature())
|
||||
split.SetParentHeader(v.object.GetHeader())
|
||||
})
|
||||
}
|
||||
|
||||
func (o *Object) initRelations() {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
h.SetSplit(new(object.SplitHeader))
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetSplit(new(objectgrpc.Header_Split))
|
||||
})
|
||||
}
|
||||
|
||||
func (o *Object) resetRelations() {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetSplit(nil)
|
||||
})
|
||||
}
|
||||
|
@ -521,26 +534,26 @@ func (o *Object) resetRelations() {
|
|||
// SessionToken returns token of the session
|
||||
// within which object was created.
|
||||
func (o *Object) SessionToken() *session.Object {
|
||||
tokv2 := (*object.Object)(o).GetHeader().GetSessionToken()
|
||||
tokv2 := o.object.GetHeader().GetSessionToken()
|
||||
if tokv2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var res session.Object
|
||||
res := session.NewObject()
|
||||
|
||||
_ = res.ReadFromV2(*tokv2)
|
||||
_ = res.ReadFromV2(tokv2)
|
||||
|
||||
return &res
|
||||
return res
|
||||
}
|
||||
|
||||
// SetSessionToken sets token of the session
|
||||
// within which object was created.
|
||||
func (o *Object) SetSessionToken(v *session.Object) {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
var tokv2 *v2session.Token
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
var tokv2 *sessiongrpc.SessionToken
|
||||
|
||||
if v != nil {
|
||||
tokv2 = new(v2session.Token)
|
||||
tokv2 = new(sessiongrpc.SessionToken)
|
||||
v.WriteToV2(tokv2)
|
||||
}
|
||||
|
||||
|
@ -551,32 +564,29 @@ func (o *Object) SetSessionToken(v *session.Object) {
|
|||
// Type returns type of the object.
|
||||
func (o *Object) Type() Type {
|
||||
return TypeFromV2(
|
||||
(*object.Object)(o).
|
||||
o.object.
|
||||
GetHeader().
|
||||
GetObjectType(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetType sets type of the object.
|
||||
// SetType sets type of the objectgrpc.
|
||||
func (o *Object) SetType(v Type) {
|
||||
o.setHeaderField(func(h *object.Header) {
|
||||
o.setHeaderField(func(h *objectgrpc.Header) {
|
||||
h.SetObjectType(v.ToV2())
|
||||
})
|
||||
}
|
||||
|
||||
// CutPayload returns Object w/ empty payload.
|
||||
//
|
||||
// Changes of non-payload fields affect source object.
|
||||
// CutPayload returns Object with empty payload.
|
||||
func (o *Object) CutPayload() *Object {
|
||||
ov2 := new(object.Object)
|
||||
*ov2 = *(*object.Object)(o)
|
||||
ov2.SetPayload(nil)
|
||||
|
||||
return (*Object)(ov2)
|
||||
ov2 := New()
|
||||
proto.Merge(ov2.object, o.object)
|
||||
ov2.object.SetPayload(nil)
|
||||
return ov2
|
||||
}
|
||||
|
||||
func (o *Object) HasParent() bool {
|
||||
return (*object.Object)(o).
|
||||
return o.object.
|
||||
GetHeader().
|
||||
GetSplit() != nil
|
||||
}
|
||||
|
@ -593,72 +603,79 @@ func (o *Object) InitRelations() {
|
|||
|
||||
// Marshal marshals object into a protobuf binary form.
|
||||
func (o *Object) Marshal() ([]byte, error) {
|
||||
return (*object.Object)(o).StableMarshal(nil), nil
|
||||
return o.object.StableMarshal(nil), nil
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of object.
|
||||
func (o *Object) Unmarshal(data []byte) error {
|
||||
err := (*object.Object)(o).Unmarshal(data)
|
||||
if o.object == nil {
|
||||
o.object = new(objectgrpc.Object)
|
||||
}
|
||||
err := proto.Unmarshal(data, o.object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return formatCheck((*object.Object)(o))
|
||||
return formatCheck(o.object)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes object to protobuf JSON format.
|
||||
func (o *Object) MarshalJSON() ([]byte, error) {
|
||||
return (*object.Object)(o).MarshalJSON()
|
||||
return protojson.MarshalOptions{
|
||||
EmitUnpopulated: true,
|
||||
}.Marshal(
|
||||
o.object,
|
||||
)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes object from protobuf JSON format.
|
||||
func (o *Object) UnmarshalJSON(data []byte) error {
|
||||
err := (*object.Object)(o).UnmarshalJSON(data)
|
||||
err := protojson.Unmarshal(data, o.object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return formatCheck((*object.Object)(o))
|
||||
return formatCheck(o.object)
|
||||
}
|
||||
|
||||
var errOIDNotSet = errors.New("object ID is not set")
|
||||
var errCIDNotSet = errors.New("container ID is not set")
|
||||
|
||||
func formatCheck(v2 *object.Object) error {
|
||||
func formatCheck(v2 *objectgrpc.Object) error {
|
||||
var (
|
||||
oID oid.ID
|
||||
cID cid.ID
|
||||
)
|
||||
|
||||
oidV2 := v2.GetObjectID()
|
||||
oidV2 := v2.GetObjectId()
|
||||
if oidV2 == nil {
|
||||
return errOIDNotSet
|
||||
}
|
||||
|
||||
err := oID.ReadFromV2(*oidV2)
|
||||
err := oID.ReadFromV2(oidV2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert V2 object ID: %w", err)
|
||||
}
|
||||
|
||||
cidV2 := v2.GetHeader().GetContainerID()
|
||||
cidV2 := v2.GetHeader().GetContainerId()
|
||||
if cidV2 == nil {
|
||||
return errCIDNotSet
|
||||
}
|
||||
|
||||
err = cID.ReadFromV2(*cidV2)
|
||||
err = cID.ReadFromV2(cidV2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert V2 container ID: %w", err)
|
||||
}
|
||||
|
||||
if prev := v2.GetHeader().GetSplit().GetPrevious(); prev != nil {
|
||||
err = oID.ReadFromV2(*prev)
|
||||
err = oID.ReadFromV2(prev)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert previous object ID: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if parent := v2.GetHeader().GetSplit().GetParent(); parent != nil {
|
||||
err = oID.ReadFromV2(*parent)
|
||||
err = oID.ReadFromV2(parent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert parent object ID: %w", err)
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue