parent
11283c1c79
commit
2b780c1772
8 changed files with 76 additions and 61 deletions
|
@ -19,12 +19,12 @@ import (
|
|||
"github.com/nspcc-dev/neofs-http-gw/response"
|
||||
"github.com/nspcc-dev/neofs-http-gw/tokens"
|
||||
"github.com/nspcc-dev/neofs-http-gw/utils"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object/address"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -105,7 +105,9 @@ func (r request) receiveFile(clnt *pool.Pool, objectAddress *address.Address) {
|
|||
|
||||
var prm pool.PrmObjectGet
|
||||
prm.SetAddress(*objectAddress)
|
||||
prm.UseBearer(bearerToken(r.RequestCtx))
|
||||
if btoken := bearerToken(r.RequestCtx); btoken != nil {
|
||||
prm.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
rObj, err := clnt.GetObject(r.appCtx, prm)
|
||||
if err != nil {
|
||||
|
@ -215,7 +217,7 @@ func title(str string) string {
|
|||
return string(r0) + str[size:]
|
||||
}
|
||||
|
||||
func bearerToken(ctx context.Context) *token.BearerToken {
|
||||
func bearerToken(ctx context.Context) *bearer.Token {
|
||||
if tkn, err := tokens.LoadBearerToken(ctx); err == nil {
|
||||
return tkn
|
||||
}
|
||||
|
@ -309,8 +311,8 @@ func (d *Downloader) byAttribute(c *fasthttp.RequestCtx, f func(request, *pool.P
|
|||
val, _ = url.QueryUnescape(c.UserValue("attr_val").(string))
|
||||
log = d.log.With(zap.String("cid", scid), zap.String("attr_key", key), zap.String("attr_val", val))
|
||||
)
|
||||
containerID := cid.New()
|
||||
if err := containerID.Parse(scid); err != nil {
|
||||
containerID := new(cid.ID)
|
||||
if err := containerID.DecodeString(scid); err != nil {
|
||||
log.Error("wrong container id", zap.Error(err))
|
||||
response.Error(c, "wrong container id", httpStatus)
|
||||
return
|
||||
|
@ -341,8 +343,8 @@ func (d *Downloader) byAttribute(c *fasthttp.RequestCtx, f func(request, *pool.P
|
|||
}
|
||||
|
||||
var addrObj address.Address
|
||||
addrObj.SetContainerID(containerID)
|
||||
addrObj.SetObjectID(&buf[0])
|
||||
addrObj.SetContainerID(*containerID)
|
||||
addrObj.SetObjectID(buf[0])
|
||||
|
||||
f(*d.newRequest(c, log), d.pool, &addrObj)
|
||||
}
|
||||
|
@ -355,7 +357,9 @@ func (d *Downloader) search(c *fasthttp.RequestCtx, cid *cid.ID, key, val string
|
|||
var prm pool.PrmObjectSearch
|
||||
prm.SetContainerID(*cid)
|
||||
prm.SetFilters(filters)
|
||||
prm.UseBearer(bearerToken(c))
|
||||
if btoken := bearerToken(c); btoken != nil {
|
||||
prm.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
return d.pool.SearchObjects(d.appCtx, prm)
|
||||
}
|
||||
|
@ -366,8 +370,8 @@ func (d *Downloader) DownloadZipped(c *fasthttp.RequestCtx) {
|
|||
prefix, _ := url.QueryUnescape(c.UserValue("prefix").(string))
|
||||
log := d.log.With(zap.String("cid", scid), zap.String("prefix", prefix))
|
||||
|
||||
containerID := cid.New()
|
||||
if err := containerID.Parse(scid); err != nil {
|
||||
containerID := new(cid.ID)
|
||||
if err := containerID.DecodeString(scid); err != nil {
|
||||
log.Error("wrong container id", zap.Error(err))
|
||||
response.Error(c, "wrong container id", fasthttp.StatusBadRequest)
|
||||
return
|
||||
|
@ -405,7 +409,7 @@ func (d *Downloader) DownloadZipped(c *fasthttp.RequestCtx) {
|
|||
bufZip []byte
|
||||
)
|
||||
|
||||
addr.SetContainerID(containerID)
|
||||
addr.SetContainerID(*containerID)
|
||||
|
||||
btoken := bearerToken(c)
|
||||
empty := true
|
||||
|
@ -420,11 +424,13 @@ func (d *Downloader) DownloadZipped(c *fasthttp.RequestCtx) {
|
|||
|
||||
empty = false
|
||||
|
||||
addr.SetObjectID(&id)
|
||||
addr.SetObjectID(id)
|
||||
|
||||
var prm pool.PrmObjectGet
|
||||
prm.SetAddress(addr)
|
||||
prm.UseBearer(btoken)
|
||||
if btoken != nil {
|
||||
prm.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
resGet, err = d.pool.GetObject(d.appCtx, prm)
|
||||
if err != nil {
|
||||
|
|
|
@ -37,7 +37,9 @@ func (r request) headObject(clnt *pool.Pool, objectAddress *address.Address) {
|
|||
|
||||
var prm pool.PrmObjectHead
|
||||
prm.SetAddress(*objectAddress)
|
||||
prm.UseBearer(btoken)
|
||||
if btoken != nil {
|
||||
prm.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
obj, err := clnt.HeadObject(r.appCtx, prm)
|
||||
if err != nil {
|
||||
|
@ -77,7 +79,9 @@ func (r request) headObject(clnt *pool.Pool, objectAddress *address.Address) {
|
|||
var prmRange pool.PrmObjectRange
|
||||
prmRange.SetAddress(*objectAddress)
|
||||
prmRange.SetLength(sz)
|
||||
prmRange.UseBearer(btoken)
|
||||
if btoken != nil {
|
||||
prmRange.UseBearer(*btoken)
|
||||
}
|
||||
|
||||
return clnt.ObjectRange(r.appCtx, prmRange)
|
||||
})
|
||||
|
@ -90,9 +94,11 @@ func (r request) headObject(clnt *pool.Pool, objectAddress *address.Address) {
|
|||
}
|
||||
|
||||
func idsToResponse(resp *fasthttp.Response, obj *object.Object) {
|
||||
resp.Header.Set(hdrObjectID, obj.ID().String())
|
||||
objID, _ := obj.ID()
|
||||
cnrID, _ := obj.ContainerID()
|
||||
resp.Header.Set(hdrObjectID, objID.String())
|
||||
resp.Header.Set(hdrOwnerID, obj.OwnerID().String())
|
||||
resp.Header.Set(hdrContainerID, obj.ContainerID().String())
|
||||
resp.Header.Set(hdrContainerID, cnrID.String())
|
||||
}
|
||||
|
||||
// HeadByAddress handles head requests using simple cid/oid format.
|
||||
|
|
3
go.mod
3
go.mod
|
@ -6,7 +6,7 @@ require (
|
|||
github.com/fasthttp/router v1.4.1
|
||||
github.com/nspcc-dev/neo-go v0.98.0
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.12.1
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.3.0.20220407103316-e50e6d28280d
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.3.0.20220421125737-6e81e13e1bff
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/common v0.30.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
|
@ -56,6 +56,7 @@ require (
|
|||
github.com/nspcc-dev/hrw v1.0.9 // indirect
|
||||
github.com/nspcc-dev/neofs-crypto v0.3.0 // indirect
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0 // indirect
|
||||
github.com/nspcc-dev/tzhash v1.5.2 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/onsi/gomega v1.15.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
|
|
7
go.sum
7
go.sum
|
@ -745,11 +745,13 @@ github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BE
|
|||
github.com/nspcc-dev/neofs-crypto v0.3.0 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM=
|
||||
github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
|
||||
github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4=
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.3.0.20220407103316-e50e6d28280d h1:OHyq8+zyQtARFWj3quRPabcfQWJZEiU7HYp6QGCSjaM=
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.3.0.20220407103316-e50e6d28280d/go.mod h1:Hl7a1l0ntZ4b1ZABpGX6fuAuFS3c6+hyMCUNVvZv/w4=
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.3.0.20220421125737-6e81e13e1bff h1:rnkApn6vXUDcN9e/AsS/gaQZSe24VulI5IYrOkkvutM=
|
||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.3.0.20220421125737-6e81e13e1bff/go.mod h1:cQKdlr9Gmp5jxbOJ78S714i1AycfYUzpVddxVUD48WM=
|
||||
github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE=
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
|
||||
github.com/nspcc-dev/tzhash v1.5.2 h1:GuIQPOY2xpl5ZE1pbUbz+QdKXVOTyzbbxSVv0nBfa98=
|
||||
github.com/nspcc-dev/tzhash v1.5.2/go.mod h1:gwAx6mcsbkfY+JVp+PovoP2Gvw6y57W8dj7zDHKOhzI=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
|
@ -1316,6 +1318,7 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
|
@ -108,16 +108,16 @@ func simplePut(ctx context.Context, t *testing.T, clientPool *pool.Pool, CID *ci
|
|||
err = json.NewDecoder(resp.Body).Decode(addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = CID.Parse(addr.CID)
|
||||
err = CID.DecodeString(addr.CID)
|
||||
require.NoError(t, err)
|
||||
|
||||
id := oid.NewID()
|
||||
err = id.Parse(addr.OID)
|
||||
id := new(oid.ID)
|
||||
err = id.DecodeString(addr.OID)
|
||||
require.NoError(t, err)
|
||||
|
||||
objectAddress := address.NewAddress()
|
||||
objectAddress.SetContainerID(CID)
|
||||
objectAddress.SetObjectID(id)
|
||||
objectAddress.SetContainerID(*CID)
|
||||
objectAddress.SetObjectID(*id)
|
||||
|
||||
payload := bytes.NewBuffer(nil)
|
||||
|
||||
|
@ -320,7 +320,7 @@ func createContainer(ctx context.Context, t *testing.T, clientPool *pool.Pool) (
|
|||
|
||||
func putObject(ctx context.Context, t *testing.T, clientPool *pool.Pool, CID *cid.ID, content string, attributes map[string]string) *oid.ID {
|
||||
obj := object.New()
|
||||
obj.SetContainerID(CID)
|
||||
obj.SetContainerID(*CID)
|
||||
obj.SetOwnerID(clientPool.OwnerID())
|
||||
|
||||
var attrs []object.Attribute
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
|
@ -62,14 +62,14 @@ func StoreBearerToken(ctx *fasthttp.RequestCtx) error {
|
|||
|
||||
// LoadBearerToken returns a bearer token stored in the context given (if it's
|
||||
// present there).
|
||||
func LoadBearerToken(ctx context.Context) (*token.BearerToken, error) {
|
||||
if tkn, ok := ctx.Value(bearerTokenKey).(*token.BearerToken); ok && tkn != nil {
|
||||
func LoadBearerToken(ctx context.Context) (*bearer.Token, error) {
|
||||
if tkn, ok := ctx.Value(bearerTokenKey).(*bearer.Token); ok && tkn != nil {
|
||||
return tkn, nil
|
||||
}
|
||||
return nil, errors.New("found empty bearer token")
|
||||
}
|
||||
|
||||
func fetchBearerToken(ctx *fasthttp.RequestCtx) (*token.BearerToken, error) {
|
||||
func fetchBearerToken(ctx *fasthttp.RequestCtx) (*bearer.Token, error) {
|
||||
// ignore empty value
|
||||
if ctx == nil {
|
||||
return nil, nil
|
||||
|
@ -78,7 +78,7 @@ func fetchBearerToken(ctx *fasthttp.RequestCtx) (*token.BearerToken, error) {
|
|||
lastErr error
|
||||
|
||||
buf []byte
|
||||
tkn = new(token.BearerToken)
|
||||
tkn = new(bearer.Token)
|
||||
)
|
||||
for _, parse := range []fromHandler{BearerTokenFromHeader, BearerTokenFromCookie} {
|
||||
if buf = parse(&ctx.Request.Header); buf == nil {
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
@ -59,16 +59,12 @@ func Test_fromHeader(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_fetchBearerToken(t *testing.T) {
|
||||
uid := owner.NewID()
|
||||
var uid user.ID
|
||||
|
||||
tkn := new(token.BearerToken)
|
||||
tkn.SetOwner(uid)
|
||||
tkn := new(bearer.Token)
|
||||
tkn.SetOwnerID(uid)
|
||||
|
||||
data, err := tkn.Marshal()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
t64 := base64.StdEncoding.EncodeToString(data)
|
||||
t64 := base64.StdEncoding.EncodeToString(tkn.Marshal())
|
||||
require.NotEmpty(t, t64)
|
||||
|
||||
cases := []struct {
|
||||
|
@ -78,7 +74,7 @@ func Test_fetchBearerToken(t *testing.T) {
|
|||
header string
|
||||
|
||||
error string
|
||||
expect *token.BearerToken
|
||||
expect *bearer.Token
|
||||
}{
|
||||
{name: "empty"},
|
||||
|
||||
|
@ -137,15 +133,12 @@ func makeTestRequest(cookie, header string) *fasthttp.RequestCtx {
|
|||
}
|
||||
|
||||
func Test_checkAndPropagateBearerToken(t *testing.T) {
|
||||
uid := owner.NewID()
|
||||
var uid user.ID
|
||||
|
||||
tkn := new(token.BearerToken)
|
||||
tkn.SetOwner(uid)
|
||||
tkn := new(bearer.Token)
|
||||
tkn.SetOwnerID(uid)
|
||||
|
||||
data, err := tkn.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
t64 := base64.StdEncoding.EncodeToString(data)
|
||||
t64 := base64.StdEncoding.EncodeToString(tkn.Marshal())
|
||||
require.NotEmpty(t, t64)
|
||||
|
||||
ctx := makeTestRequest(t64, "")
|
||||
|
|
|
@ -12,14 +12,14 @@ import (
|
|||
"github.com/nspcc-dev/neofs-http-gw/response"
|
||||
"github.com/nspcc-dev/neofs-http-gw/tokens"
|
||||
"github.com/nspcc-dev/neofs-http-gw/utils"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
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/object"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/object/address"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -56,7 +56,7 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) {
|
|||
file MultipartFile
|
||||
idObj *oid.ID
|
||||
addr = address.NewAddress()
|
||||
idCnr = cid.New()
|
||||
idCnr = new(cid.ID)
|
||||
scid, _ = c.UserValue("cid").(string)
|
||||
log = u.log.With(zap.String("cid", scid))
|
||||
bodyStream = c.RequestBodyStream()
|
||||
|
@ -67,7 +67,7 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) {
|
|||
response.Error(c, "could not fetch bearer token", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err = idCnr.Parse(scid); err != nil {
|
||||
if err = idCnr.DecodeString(scid); err != nil {
|
||||
log.Error("wrong container id", zap.Error(err))
|
||||
response.Error(c, "wrong container id", fasthttp.StatusBadRequest)
|
||||
return
|
||||
|
@ -131,14 +131,17 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) {
|
|||
id, bt := u.fetchOwnerAndBearerToken(c)
|
||||
|
||||
obj := object.New()
|
||||
obj.SetContainerID(idCnr)
|
||||
obj.SetContainerID(*idCnr)
|
||||
obj.SetOwnerID(id)
|
||||
obj.SetAttributes(attributes...)
|
||||
|
||||
var prm pool.PrmObjectPut
|
||||
prm.SetHeader(*obj)
|
||||
prm.SetPayload(file)
|
||||
prm.UseBearer(bt)
|
||||
|
||||
if bt != nil {
|
||||
prm.UseBearer(*bt)
|
||||
}
|
||||
|
||||
if idObj, err = u.pool.PutObject(u.appCtx, prm); err != nil {
|
||||
log.Error("could not store file in neofs", zap.Error(err))
|
||||
|
@ -146,8 +149,8 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) {
|
|||
return
|
||||
}
|
||||
|
||||
addr.SetObjectID(idObj)
|
||||
addr.SetContainerID(idCnr)
|
||||
addr.SetObjectID(*idObj)
|
||||
addr.SetContainerID(*idCnr)
|
||||
|
||||
// Try to return the response, otherwise, if something went wrong, throw an error.
|
||||
if err = newPutResponse(addr).encode(c); err != nil {
|
||||
|
@ -173,9 +176,10 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) {
|
|||
c.Response.Header.SetContentType(jsonHeader)
|
||||
}
|
||||
|
||||
func (u *Uploader) fetchOwnerAndBearerToken(ctx context.Context) (*owner.ID, *token.BearerToken) {
|
||||
func (u *Uploader) fetchOwnerAndBearerToken(ctx context.Context) (*user.ID, *bearer.Token) {
|
||||
if tkn, err := tokens.LoadBearerToken(ctx); err == nil && tkn != nil {
|
||||
return tkn.Issuer(), tkn
|
||||
issuer, _ := tkn.Issuer()
|
||||
return &issuer, tkn
|
||||
}
|
||||
return u.pool.OwnerID(), nil
|
||||
}
|
||||
|
@ -186,9 +190,11 @@ type putResponse struct {
|
|||
}
|
||||
|
||||
func newPutResponse(addr *address.Address) *putResponse {
|
||||
objID, _ := addr.ObjectID()
|
||||
cnrID, _ := addr.ContainerID()
|
||||
return &putResponse{
|
||||
ObjectID: addr.ObjectID().String(),
|
||||
ContainerID: addr.ContainerID().String(),
|
||||
ObjectID: objID.String(),
|
||||
ContainerID: cnrID.String(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue