forked from TrueCloudLab/frostfs-sdk-go
[#60] container: move package from neofs-api-go
Also, remove deprecated methods and types. Close #60. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
8d313dbd5d
commit
73686827d3
10 changed files with 1012 additions and 0 deletions
77
container/announcement.go
Normal file
77
container/announcement.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
)
|
||||
|
||||
// UsedSpaceAnnouncement is an announcement message used by storage nodes to
|
||||
// estimate actual container sizes.
|
||||
type UsedSpaceAnnouncement container.UsedSpaceAnnouncement
|
||||
|
||||
// NewAnnouncement initialize empty UsedSpaceAnnouncement message.
|
||||
//
|
||||
// Defaults:
|
||||
// - epoch: 0;
|
||||
// - usedSpace: 0;
|
||||
// - cid: nil.
|
||||
func NewAnnouncement() *UsedSpaceAnnouncement {
|
||||
return NewAnnouncementFromV2(new(container.UsedSpaceAnnouncement))
|
||||
}
|
||||
|
||||
// NewAnnouncementFromV2 wraps protocol dependent version of
|
||||
// UsedSpaceAnnouncement message.
|
||||
//
|
||||
// Nil container.UsedSpaceAnnouncement converts to nil.
|
||||
func NewAnnouncementFromV2(v *container.UsedSpaceAnnouncement) *UsedSpaceAnnouncement {
|
||||
return (*UsedSpaceAnnouncement)(v)
|
||||
}
|
||||
|
||||
// Epoch of the announcement.
|
||||
func (a *UsedSpaceAnnouncement) Epoch() uint64 {
|
||||
return (*container.UsedSpaceAnnouncement)(a).GetEpoch()
|
||||
}
|
||||
|
||||
// SetEpoch sets announcement epoch value.
|
||||
func (a *UsedSpaceAnnouncement) SetEpoch(epoch uint64) {
|
||||
(*container.UsedSpaceAnnouncement)(a).SetEpoch(epoch)
|
||||
}
|
||||
|
||||
// ContainerID of the announcement.
|
||||
func (a *UsedSpaceAnnouncement) ContainerID() *cid.ID {
|
||||
return cid.NewFromV2(
|
||||
(*container.UsedSpaceAnnouncement)(a).GetContainerID(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetContainerID sets announcement container value.
|
||||
func (a *UsedSpaceAnnouncement) SetContainerID(cid *cid.ID) {
|
||||
(*container.UsedSpaceAnnouncement)(a).SetContainerID(cid.ToV2())
|
||||
}
|
||||
|
||||
// UsedSpace in container.
|
||||
func (a *UsedSpaceAnnouncement) UsedSpace() uint64 {
|
||||
return (*container.UsedSpaceAnnouncement)(a).GetUsedSpace()
|
||||
}
|
||||
|
||||
// SetUsedSpace sets used space value by specified container.
|
||||
func (a *UsedSpaceAnnouncement) SetUsedSpace(value uint64) {
|
||||
(*container.UsedSpaceAnnouncement)(a).SetUsedSpace(value)
|
||||
}
|
||||
|
||||
// ToV2 returns protocol dependent version of UsedSpaceAnnouncement message.
|
||||
//
|
||||
// Nil UsedSpaceAnnouncement converts to nil.
|
||||
func (a *UsedSpaceAnnouncement) ToV2() *container.UsedSpaceAnnouncement {
|
||||
return (*container.UsedSpaceAnnouncement)(a)
|
||||
}
|
||||
|
||||
// Marshal marshals UsedSpaceAnnouncement into a protobuf binary form.
|
||||
func (a *UsedSpaceAnnouncement) Marshal() ([]byte, error) {
|
||||
return a.ToV2().StableMarshal(nil)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of UsedSpaceAnnouncement.
|
||||
func (a *UsedSpaceAnnouncement) Unmarshal(data []byte) error {
|
||||
return a.ToV2().Unmarshal(data)
|
||||
}
|
99
container/announcement_test.go
Normal file
99
container/announcement_test.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package container_test
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"testing"
|
||||
|
||||
containerv2 "github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||
containertest "github.com/nspcc-dev/neofs-sdk-go/container/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAnnouncement(t *testing.T) {
|
||||
const epoch, usedSpace uint64 = 10, 100
|
||||
|
||||
cidValue := [sha256.Size]byte{1, 2, 3}
|
||||
id := cidtest.GenerateIDWithChecksum(cidValue)
|
||||
|
||||
a := container.NewAnnouncement()
|
||||
a.SetEpoch(epoch)
|
||||
a.SetContainerID(id)
|
||||
a.SetUsedSpace(usedSpace)
|
||||
|
||||
require.Equal(t, epoch, a.Epoch())
|
||||
require.Equal(t, usedSpace, a.UsedSpace())
|
||||
require.Equal(t, id, a.ContainerID())
|
||||
|
||||
t.Run("test v2", func(t *testing.T) {
|
||||
const newEpoch, newUsedSpace uint64 = 20, 200
|
||||
|
||||
newCidValue := [32]byte{4, 5, 6}
|
||||
newCID := new(refs.ContainerID)
|
||||
newCID.SetValue(newCidValue[:])
|
||||
|
||||
v2 := a.ToV2()
|
||||
require.Equal(t, usedSpace, v2.GetUsedSpace())
|
||||
require.Equal(t, epoch, v2.GetEpoch())
|
||||
require.Equal(t, cidValue[:], v2.GetContainerID().GetValue())
|
||||
|
||||
v2.SetEpoch(newEpoch)
|
||||
v2.SetUsedSpace(newUsedSpace)
|
||||
v2.SetContainerID(newCID)
|
||||
|
||||
newA := container.NewAnnouncementFromV2(v2)
|
||||
|
||||
require.Equal(t, newEpoch, newA.Epoch())
|
||||
require.Equal(t, newUsedSpace, newA.UsedSpace())
|
||||
require.Equal(t, cid.NewFromV2(newCID), newA.ContainerID())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUsedSpaceEncoding(t *testing.T) {
|
||||
a := containertest.UsedSpaceAnnouncement()
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := a.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
a2 := container.NewAnnouncement()
|
||||
require.NoError(t, a2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, a, a2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUsedSpaceAnnouncement_ToV2(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *container.UsedSpaceAnnouncement
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
})
|
||||
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
announcement := container.NewAnnouncement()
|
||||
|
||||
// check initial values
|
||||
require.Zero(t, announcement.Epoch())
|
||||
require.Zero(t, announcement.UsedSpace())
|
||||
require.Nil(t, announcement.ContainerID())
|
||||
|
||||
// convert to v2 message
|
||||
announcementV2 := announcement.ToV2()
|
||||
|
||||
require.Zero(t, announcementV2.GetEpoch())
|
||||
require.Zero(t, announcementV2.GetUsedSpace())
|
||||
require.Nil(t, announcementV2.GetContainerID())
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewAnnouncementFromV2(t *testing.T) {
|
||||
t.Run("from nil", func(t *testing.T) {
|
||||
var x *containerv2.UsedSpaceAnnouncement
|
||||
|
||||
require.Nil(t, container.NewAnnouncementFromV2(x))
|
||||
})
|
||||
}
|
137
container/attribute.go
Normal file
137
container/attribute.go
Normal file
|
@ -0,0 +1,137 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
)
|
||||
|
||||
type (
|
||||
Attribute container.Attribute
|
||||
Attributes []*Attribute
|
||||
)
|
||||
|
||||
// NewAttribute creates and initializes blank Attribute.
|
||||
//
|
||||
// Defaults:
|
||||
// - key: "";
|
||||
// - value: "".
|
||||
func NewAttribute() *Attribute {
|
||||
return NewAttributeFromV2(new(container.Attribute))
|
||||
}
|
||||
|
||||
func (a *Attribute) SetKey(v string) {
|
||||
(*container.Attribute)(a).SetKey(v)
|
||||
}
|
||||
|
||||
func (a *Attribute) SetValue(v string) {
|
||||
(*container.Attribute)(a).SetValue(v)
|
||||
}
|
||||
|
||||
func (a *Attribute) Key() string {
|
||||
return (*container.Attribute)(a).GetKey()
|
||||
}
|
||||
|
||||
func (a *Attribute) Value() string {
|
||||
return (*container.Attribute)(a).GetValue()
|
||||
}
|
||||
|
||||
// NewAttributeFromV2 wraps protocol dependent version of
|
||||
// Attribute message.
|
||||
//
|
||||
// Nil container.Attribute converts to nil.
|
||||
func NewAttributeFromV2(v *container.Attribute) *Attribute {
|
||||
return (*Attribute)(v)
|
||||
}
|
||||
|
||||
// ToV2 converts Attribute to v2 Attribute message.
|
||||
//
|
||||
// Nil Attribute converts to nil.
|
||||
func (a *Attribute) ToV2() *container.Attribute {
|
||||
return (*container.Attribute)(a)
|
||||
}
|
||||
|
||||
func NewAttributesFromV2(v []*container.Attribute) Attributes {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
attrs := make(Attributes, 0, len(v))
|
||||
for i := range v {
|
||||
attrs = append(attrs, NewAttributeFromV2(v[i]))
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
func (a Attributes) ToV2() []*container.Attribute {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
attrs := make([]*container.Attribute, 0, len(a))
|
||||
for i := range a {
|
||||
attrs = append(attrs, a[i].ToV2())
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
// sets value of the attribute by key.
|
||||
func setAttribute(c *Container, key, value string) {
|
||||
var a *Attribute
|
||||
|
||||
iterateAttributes(c, func(a_ *Attribute) bool {
|
||||
if a_.Key() == key {
|
||||
a = a_
|
||||
}
|
||||
|
||||
return a != nil
|
||||
})
|
||||
|
||||
if a == nil {
|
||||
a = NewAttribute()
|
||||
a.SetKey(key)
|
||||
|
||||
c.SetAttributes(append(c.Attributes(), a))
|
||||
}
|
||||
|
||||
a.SetValue(value)
|
||||
}
|
||||
|
||||
// iterates over container attributes. Stops at f's true return.
|
||||
//
|
||||
// Handler must not be nil.
|
||||
func iterateAttributes(c *Container, f func(*Attribute) bool) {
|
||||
for _, a := range c.Attributes() {
|
||||
if f(a) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetNativeNameWithZone sets container native name and its zone.
|
||||
//
|
||||
// Use SetNativeName to set default zone.
|
||||
func SetNativeNameWithZone(c *Container, name, zone string) {
|
||||
setAttribute(c, container.SysAttributeName, name)
|
||||
setAttribute(c, container.SysAttributeZone, zone)
|
||||
}
|
||||
|
||||
// SetNativeName sets container native name with default zone (container).
|
||||
func SetNativeName(c *Container, name string) {
|
||||
SetNativeNameWithZone(c, name, container.SysAttributeZoneDefault)
|
||||
}
|
||||
|
||||
// GetNativeNameWithZone returns container native name and its zone.
|
||||
func GetNativeNameWithZone(c *Container) (name string, zone string) {
|
||||
iterateAttributes(c, func(a *Attribute) bool {
|
||||
if key := a.Key(); key == container.SysAttributeName {
|
||||
name = a.Value()
|
||||
} else if key == container.SysAttributeZone {
|
||||
zone = a.Value()
|
||||
}
|
||||
|
||||
return name != "" && zone != ""
|
||||
})
|
||||
|
||||
return
|
||||
}
|
155
container/attribute_test.go
Normal file
155
container/attribute_test.go
Normal file
|
@ -0,0 +1,155 @@
|
|||
package container_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
containerv2 "github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAttribute(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *container.Attribute
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
})
|
||||
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
attr := container.NewAttribute()
|
||||
|
||||
// check initial values
|
||||
require.Empty(t, attr.Key())
|
||||
require.Empty(t, attr.Value())
|
||||
|
||||
// convert to v2 message
|
||||
attrV2 := attr.ToV2()
|
||||
require.Empty(t, attrV2.GetKey())
|
||||
require.Empty(t, attrV2.GetValue())
|
||||
})
|
||||
|
||||
const (
|
||||
key = "key"
|
||||
value = "value"
|
||||
)
|
||||
|
||||
attr := container.NewAttribute()
|
||||
attr.SetKey(key)
|
||||
attr.SetValue(value)
|
||||
|
||||
require.Equal(t, key, attr.Key())
|
||||
require.Equal(t, value, attr.Value())
|
||||
|
||||
t.Run("test v2", func(t *testing.T) {
|
||||
const (
|
||||
newKey = "newKey"
|
||||
newValue = "newValue"
|
||||
)
|
||||
|
||||
v2 := attr.ToV2()
|
||||
require.Equal(t, key, v2.GetKey())
|
||||
require.Equal(t, value, v2.GetValue())
|
||||
|
||||
v2.SetKey(newKey)
|
||||
v2.SetValue(newValue)
|
||||
|
||||
newAttr := container.NewAttributeFromV2(v2)
|
||||
|
||||
require.Equal(t, newKey, newAttr.Key())
|
||||
require.Equal(t, newValue, newAttr.Value())
|
||||
})
|
||||
}
|
||||
|
||||
func TestAttributes(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x container.Attributes
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
|
||||
require.Nil(t, container.NewAttributesFromV2(nil))
|
||||
})
|
||||
|
||||
var (
|
||||
keys = []string{"key1", "key2", "key3"}
|
||||
vals = []string{"val1", "val2", "val3"}
|
||||
)
|
||||
|
||||
attrs := make(container.Attributes, 0, len(keys))
|
||||
|
||||
for i := range keys {
|
||||
attr := container.NewAttribute()
|
||||
attr.SetKey(keys[i])
|
||||
attr.SetValue(vals[i])
|
||||
|
||||
attrs = append(attrs, attr)
|
||||
}
|
||||
|
||||
t.Run("test v2", func(t *testing.T) {
|
||||
const postfix = "x"
|
||||
|
||||
v2 := attrs.ToV2()
|
||||
require.Len(t, v2, len(keys))
|
||||
|
||||
for i := range v2 {
|
||||
k := v2[i].GetKey()
|
||||
v := v2[i].GetValue()
|
||||
|
||||
require.Equal(t, keys[i], k)
|
||||
require.Equal(t, vals[i], v)
|
||||
|
||||
v2[i].SetKey(k + postfix)
|
||||
v2[i].SetValue(v + postfix)
|
||||
}
|
||||
|
||||
newAttrs := container.NewAttributesFromV2(v2)
|
||||
require.Len(t, newAttrs, len(keys))
|
||||
|
||||
for i := range newAttrs {
|
||||
require.Equal(t, keys[i]+postfix, newAttrs[i].Key())
|
||||
require.Equal(t, vals[i]+postfix, newAttrs[i].Value())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewAttributeFromV2(t *testing.T) {
|
||||
t.Run("from nil", func(t *testing.T) {
|
||||
var x *containerv2.Attribute
|
||||
|
||||
require.Nil(t, container.NewAttributeFromV2(x))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetNameWithZone(t *testing.T) {
|
||||
c := container.New()
|
||||
|
||||
for _, item := range [...]struct {
|
||||
name, zone string
|
||||
}{
|
||||
{"name1", ""},
|
||||
{"name1", "zone1"},
|
||||
{"name2", "zone1"},
|
||||
{"name2", "zone2"},
|
||||
{"", "zone2"},
|
||||
{"", ""},
|
||||
} {
|
||||
container.SetNativeNameWithZone(c, item.name, item.zone)
|
||||
|
||||
name, zone := container.GetNativeNameWithZone(c)
|
||||
|
||||
require.Equal(t, item.name, name, item.name)
|
||||
require.Equal(t, item.zone, zone, item.zone)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetNativeName(t *testing.T) {
|
||||
c := container.New()
|
||||
|
||||
const nameDefZone = "some name"
|
||||
|
||||
container.SetNativeName(c, nameDefZone)
|
||||
|
||||
name, zone := container.GetNativeNameWithZone(c)
|
||||
|
||||
require.Equal(t, nameDefZone, name)
|
||||
require.Equal(t, containerv2.SysAttributeZoneDefault, zone)
|
||||
}
|
191
container/container.go
Normal file
191
container/container.go
Normal file
|
@ -0,0 +1,191 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/signature"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/version"
|
||||
)
|
||||
|
||||
type Container struct {
|
||||
v2 container.Container
|
||||
|
||||
token *session.Token
|
||||
|
||||
sig *signature.Signature
|
||||
}
|
||||
|
||||
// New creates, initializes and returns blank Container instance.
|
||||
//
|
||||
// Defaults:
|
||||
// - token: nil;
|
||||
// - sig: nil;
|
||||
// - basicACL: acl.PrivateBasicRule;
|
||||
// - version: nil;
|
||||
// - nonce: random UUID;
|
||||
// - attr: nil;
|
||||
// - policy: nil;
|
||||
// - ownerID: nil.
|
||||
func New(opts ...NewOption) *Container {
|
||||
cnrOptions := defaultContainerOptions()
|
||||
|
||||
for i := range opts {
|
||||
opts[i].apply(&cnrOptions)
|
||||
}
|
||||
|
||||
cnr := new(Container)
|
||||
cnr.SetNonceUUID(cnrOptions.nonce)
|
||||
cnr.SetBasicACL(cnrOptions.acl)
|
||||
|
||||
if cnrOptions.owner != nil {
|
||||
cnr.SetOwnerID(cnrOptions.owner)
|
||||
}
|
||||
|
||||
if cnrOptions.policy != nil {
|
||||
cnr.SetPlacementPolicy(cnrOptions.policy)
|
||||
}
|
||||
|
||||
cnr.SetAttributes(cnrOptions.attributes)
|
||||
|
||||
return cnr
|
||||
}
|
||||
|
||||
// ToV2 returns the v2 Container message.
|
||||
//
|
||||
// Nil Container converts to nil.
|
||||
func (c *Container) ToV2() *container.Container {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &c.v2
|
||||
}
|
||||
|
||||
// NewVerifiedFromV2 constructs Container from NeoFS API V2 Container message.
|
||||
//
|
||||
// Does not perform if message meets NeoFS API V2 specification. To do this
|
||||
// use NewVerifiedFromV2 constructor.
|
||||
func NewContainerFromV2(c *container.Container) *Container {
|
||||
cnr := new(Container)
|
||||
|
||||
if c != nil {
|
||||
cnr.v2 = *c
|
||||
}
|
||||
|
||||
return cnr
|
||||
}
|
||||
|
||||
// CalculateID calculates container identifier
|
||||
// based on its structure.
|
||||
func CalculateID(c *Container) *cid.ID {
|
||||
data, err := c.ToV2().StableMarshal(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
id := cid.New()
|
||||
id.SetSHA256(sha256.Sum256(data))
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func (c *Container) Version() *version.Version {
|
||||
return version.NewFromV2(c.v2.GetVersion())
|
||||
}
|
||||
|
||||
func (c *Container) SetVersion(v *version.Version) {
|
||||
c.v2.SetVersion(v.ToV2())
|
||||
}
|
||||
|
||||
func (c *Container) OwnerID() *owner.ID {
|
||||
return owner.NewIDFromV2(c.v2.GetOwnerID())
|
||||
}
|
||||
|
||||
func (c *Container) SetOwnerID(v *owner.ID) {
|
||||
c.v2.SetOwnerID(v.ToV2())
|
||||
}
|
||||
|
||||
// Returns container nonce in UUID format.
|
||||
//
|
||||
// Returns error if container nonce is not a valid UUID.
|
||||
func (c *Container) NonceUUID() (uuid.UUID, error) {
|
||||
return uuid.FromBytes(c.v2.GetNonce())
|
||||
}
|
||||
|
||||
// SetNonceUUID sets container nonce as UUID.
|
||||
func (c *Container) SetNonceUUID(v uuid.UUID) {
|
||||
data, _ := v.MarshalBinary()
|
||||
c.v2.SetNonce(data)
|
||||
}
|
||||
|
||||
func (c *Container) BasicACL() uint32 {
|
||||
return c.v2.GetBasicACL()
|
||||
}
|
||||
|
||||
func (c *Container) SetBasicACL(v uint32) {
|
||||
c.v2.SetBasicACL(v)
|
||||
}
|
||||
|
||||
func (c *Container) Attributes() Attributes {
|
||||
return NewAttributesFromV2(c.v2.GetAttributes())
|
||||
}
|
||||
|
||||
func (c *Container) SetAttributes(v Attributes) {
|
||||
c.v2.SetAttributes(v.ToV2())
|
||||
}
|
||||
|
||||
func (c *Container) PlacementPolicy() *netmap.PlacementPolicy {
|
||||
return netmap.NewPlacementPolicyFromV2(c.v2.GetPlacementPolicy())
|
||||
}
|
||||
|
||||
func (c *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) {
|
||||
c.v2.SetPlacementPolicy(v.ToV2())
|
||||
}
|
||||
|
||||
// SessionToken returns token of the session within
|
||||
// which container was created.
|
||||
func (c Container) SessionToken() *session.Token {
|
||||
return c.token
|
||||
}
|
||||
|
||||
// SetSessionToken sets token of the session within
|
||||
// which container was created.
|
||||
func (c *Container) SetSessionToken(t *session.Token) {
|
||||
c.token = t
|
||||
}
|
||||
|
||||
// Signature returns signature of the marshaled container.
|
||||
func (c Container) Signature() *signature.Signature {
|
||||
return c.sig
|
||||
}
|
||||
|
||||
// SetSignature sets signature of the marshaled container.
|
||||
func (c *Container) SetSignature(sig *signature.Signature) {
|
||||
c.sig = sig
|
||||
}
|
||||
|
||||
// Marshal marshals Container into a protobuf binary form.
|
||||
func (c *Container) Marshal() ([]byte, error) {
|
||||
return c.v2.StableMarshal(nil)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of Container.
|
||||
func (c *Container) Unmarshal(data []byte) error {
|
||||
return c.v2.Unmarshal(data)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Container to protobuf JSON format.
|
||||
func (c *Container) MarshalJSON() ([]byte, error) {
|
||||
return c.v2.MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes Container from protobuf JSON format.
|
||||
func (c *Container) UnmarshalJSON(data []byte) error {
|
||||
return c.v2.UnmarshalJSON(data)
|
||||
}
|
135
container/container_test.go
Normal file
135
container/container_test.go
Normal file
|
@ -0,0 +1,135 @@
|
|||
package container_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/acl"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
containertest "github.com/nspcc-dev/neofs-sdk-go/container/test"
|
||||
netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test"
|
||||
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
|
||||
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
|
||||
sigtest "github.com/nspcc-dev/neofs-sdk-go/signature/test"
|
||||
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewContainer(t *testing.T) {
|
||||
c := container.New()
|
||||
|
||||
nonce := uuid.New()
|
||||
|
||||
ownerID := ownertest.GenerateID()
|
||||
policy := netmaptest.PlacementPolicy()
|
||||
|
||||
c.SetBasicACL(acl.PublicBasicRule)
|
||||
|
||||
attrs := containertest.Attributes()
|
||||
c.SetAttributes(attrs)
|
||||
|
||||
c.SetPlacementPolicy(policy)
|
||||
c.SetNonceUUID(nonce)
|
||||
c.SetOwnerID(ownerID)
|
||||
|
||||
ver := versiontest.Version()
|
||||
c.SetVersion(ver)
|
||||
|
||||
v2 := c.ToV2()
|
||||
newContainer := container.NewContainerFromV2(v2)
|
||||
|
||||
require.EqualValues(t, newContainer.PlacementPolicy(), policy)
|
||||
require.EqualValues(t, newContainer.Attributes(), attrs)
|
||||
require.EqualValues(t, newContainer.BasicACL(), acl.PublicBasicRule)
|
||||
|
||||
newNonce, err := newContainer.NonceUUID()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, newNonce, nonce)
|
||||
require.EqualValues(t, newContainer.OwnerID(), ownerID)
|
||||
require.EqualValues(t, newContainer.Version(), ver)
|
||||
}
|
||||
|
||||
func TestContainerEncoding(t *testing.T) {
|
||||
c := containertest.Container()
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := c.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
c2 := container.New()
|
||||
require.NoError(t, c2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, c, c2)
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
data, err := c.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
c2 := container.New()
|
||||
require.NoError(t, c2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, c, c2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestContainer_SessionToken(t *testing.T) {
|
||||
tok := sessiontest.Generate()
|
||||
|
||||
cnr := container.New()
|
||||
|
||||
cnr.SetSessionToken(tok)
|
||||
|
||||
require.Equal(t, tok, cnr.SessionToken())
|
||||
}
|
||||
|
||||
func TestContainer_Signature(t *testing.T) {
|
||||
sig := sigtest.Signature()
|
||||
|
||||
cnr := container.New()
|
||||
cnr.SetSignature(sig)
|
||||
|
||||
require.Equal(t, sig, cnr.Signature())
|
||||
}
|
||||
|
||||
func TestContainer_ToV2(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *container.Container
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
})
|
||||
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
cnt := container.New()
|
||||
|
||||
// check initial values
|
||||
require.Nil(t, cnt.SessionToken())
|
||||
require.Nil(t, cnt.Signature())
|
||||
require.Nil(t, cnt.Version())
|
||||
require.Nil(t, cnt.Attributes())
|
||||
require.Nil(t, cnt.PlacementPolicy())
|
||||
require.Nil(t, cnt.OwnerID())
|
||||
|
||||
require.EqualValues(t, acl.PrivateBasicRule, cnt.BasicACL())
|
||||
|
||||
nonce, err := cnt.NonceUUID()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, nonce)
|
||||
|
||||
// convert to v2 message
|
||||
cntV2 := cnt.ToV2()
|
||||
|
||||
nonceV2, err := uuid.FromBytes(cntV2.GetNonce())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, nonce.String(), nonceV2.String())
|
||||
|
||||
require.Nil(t, cntV2.GetVersion())
|
||||
require.Nil(t, cntV2.GetAttributes())
|
||||
require.Nil(t, cntV2.GetPlacementPolicy())
|
||||
require.Nil(t, cntV2.GetOwnerID())
|
||||
|
||||
require.Equal(t, uint32(acl.PrivateBasicRule), cntV2.GetBasicACL())
|
||||
})
|
||||
}
|
104
container/opts.go
Normal file
104
container/opts.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/acl"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||
)
|
||||
|
||||
type (
|
||||
NewOption interface {
|
||||
apply(*containerOptions)
|
||||
}
|
||||
|
||||
containerOptions struct {
|
||||
acl uint32
|
||||
policy *netmap.PlacementPolicy
|
||||
attributes Attributes
|
||||
owner *owner.ID
|
||||
nonce uuid.UUID
|
||||
}
|
||||
)
|
||||
|
||||
func defaultContainerOptions() containerOptions {
|
||||
rand, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
panic("can't create new random " + err.Error())
|
||||
}
|
||||
|
||||
return containerOptions{
|
||||
acl: acl.PrivateBasicRule,
|
||||
nonce: rand,
|
||||
}
|
||||
}
|
||||
|
||||
type funcContainerOption struct {
|
||||
f func(*containerOptions)
|
||||
}
|
||||
|
||||
func (fco *funcContainerOption) apply(co *containerOptions) {
|
||||
fco.f(co)
|
||||
}
|
||||
|
||||
func newFuncContainerOption(f func(option *containerOptions)) *funcContainerOption {
|
||||
return &funcContainerOption{
|
||||
f: f,
|
||||
}
|
||||
}
|
||||
|
||||
func WithPublicBasicACL() NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
option.acl = acl.PublicBasicRule
|
||||
})
|
||||
}
|
||||
|
||||
func WithReadOnlyBasicACL() NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
option.acl = acl.ReadOnlyBasicRule
|
||||
})
|
||||
}
|
||||
|
||||
func WithCustomBasicACL(acl uint32) NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
option.acl = acl
|
||||
})
|
||||
}
|
||||
|
||||
func WithNonce(nonce uuid.UUID) NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
option.nonce = nonce
|
||||
})
|
||||
}
|
||||
|
||||
func WithOwnerID(id *owner.ID) NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
option.owner = id
|
||||
})
|
||||
}
|
||||
|
||||
func WithNEO3Wallet(w *owner.NEO3Wallet) NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
if option.owner == nil {
|
||||
option.owner = new(owner.ID)
|
||||
}
|
||||
|
||||
option.owner.SetNeo3Wallet(w)
|
||||
})
|
||||
}
|
||||
|
||||
func WithPolicy(policy *netmap.PlacementPolicy) NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
option.policy = policy
|
||||
})
|
||||
}
|
||||
|
||||
func WithAttribute(key, value string) NewOption {
|
||||
return newFuncContainerOption(func(option *containerOptions) {
|
||||
attr := NewAttribute()
|
||||
attr.SetKey(key)
|
||||
attr.SetValue(value)
|
||||
|
||||
option.attributes = append(option.attributes, attr)
|
||||
})
|
||||
}
|
48
container/test/generate.go
Normal file
48
container/test/generate.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package containertest
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||
netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test"
|
||||
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
|
||||
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
|
||||
)
|
||||
|
||||
// Attribute returns random container.Attribute.
|
||||
func Attribute() *container.Attribute {
|
||||
x := container.NewAttribute()
|
||||
|
||||
x.SetKey("key")
|
||||
x.SetValue("value")
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// Attributes returns random container.Attributes.
|
||||
func Attributes() container.Attributes {
|
||||
return container.Attributes{Attribute(), Attribute()}
|
||||
}
|
||||
|
||||
// Container returns random container.Container.
|
||||
func Container() *container.Container {
|
||||
x := container.New()
|
||||
|
||||
x.SetVersion(versiontest.Version())
|
||||
x.SetAttributes(Attributes())
|
||||
x.SetOwnerID(ownertest.GenerateID())
|
||||
x.SetBasicACL(123)
|
||||
x.SetPlacementPolicy(netmaptest.PlacementPolicy())
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// UsedSpaceAnnouncement returns random container.UsedSpaceAnnouncement.
|
||||
func UsedSpaceAnnouncement() *container.UsedSpaceAnnouncement {
|
||||
x := container.NewAnnouncement()
|
||||
|
||||
x.SetContainerID(cidtest.GenerateID())
|
||||
x.SetEpoch(55)
|
||||
x.SetUsedSpace(999)
|
||||
|
||||
return x
|
||||
}
|
11
container/wellknown_attributes.go
Normal file
11
container/wellknown_attributes.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package container
|
||||
|
||||
const (
|
||||
// AttributeName is an attribute key that is commonly used to denote
|
||||
// human-friendly name.
|
||||
AttributeName = "Name"
|
||||
|
||||
// AttributeTimestamp is an attribute key that is commonly used to denote
|
||||
// user-defined local time of container creation in Unix Timestamp format.
|
||||
AttributeTimestamp = "Timestamp"
|
||||
)
|
|
@ -2,6 +2,61 @@ package test
|
|||
|
||||
import "github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
|
||||
func filter(withInner bool) *netmap.Filter {
|
||||
x := netmap.NewFilter()
|
||||
|
||||
x.SetName("name")
|
||||
x.SetKey("key")
|
||||
x.SetValue("value")
|
||||
x.SetOperation(netmap.OpAND)
|
||||
|
||||
if withInner {
|
||||
x.SetInnerFilters(filter(false), filter(false))
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// Filter returns random netmap.Filter.
|
||||
func Filter() *netmap.Filter {
|
||||
return filter(true)
|
||||
}
|
||||
|
||||
// Replica returns random netmap.Replica.
|
||||
func Replica() *netmap.Replica {
|
||||
x := netmap.NewReplica()
|
||||
|
||||
x.SetCount(666)
|
||||
x.SetSelector("selector")
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// Selector returns random netmap.Selector.
|
||||
func Selector() *netmap.Selector {
|
||||
x := netmap.NewSelector()
|
||||
|
||||
x.SetCount(11)
|
||||
x.SetName("name")
|
||||
x.SetFilter("filter")
|
||||
x.SetAttribute("attribute")
|
||||
x.SetClause(netmap.ClauseDistinct)
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// PlacementPolicy returns random netmap.PlacementPolicy.
|
||||
func PlacementPolicy() *netmap.PlacementPolicy {
|
||||
x := netmap.NewPlacementPolicy()
|
||||
|
||||
x.SetContainerBackupFactor(9)
|
||||
x.SetFilters(Filter(), Filter())
|
||||
x.SetReplicas(Replica(), Replica())
|
||||
x.SetSelectors(Selector(), Selector())
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// NetworkParameter returns random netmap.NetworkParameter.
|
||||
func NetworkParameter() *netmap.NetworkParameter {
|
||||
x := netmap.NewNetworkParameter()
|
||||
|
|
Loading…
Reference in a new issue