[#XX] client: apemanager
DCO / DCO (pull_request) Failing after 6m2s Details
Tests and linters / Tests (1.21) (pull_request) Successful in 6m4s Details
Tests and linters / Tests (1.20) (pull_request) Successful in 6m10s Details
Tests and linters / Lint (pull_request) Successful in 7m12s Details

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
Airat Arifullin 2024-04-25 21:34:15 +03:00
parent 20ab57bf7e
commit 93c8923d33
13 changed files with 482 additions and 3 deletions

View File

@ -0,0 +1,37 @@
package apemanager
import (
"fmt"
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
)
type ChainID []byte
type Chain struct {
// Raw is the encoded chain representation.
Raw *[]byte
}
func (c *Chain) ToV2() *apemanager_v2.Chain {
v2ct := new(apemanager_v2.Chain)
if c.Raw != nil {
v2Raw := new(apemanager_v2.ChainRaw)
v2Raw.SetRaw(*c.Raw)
v2ct.SetKind(v2Raw)
}
return v2ct
}
func (c *Chain) ReadFromV2(v2ct *apemanager_v2.Chain) error {
switch v := v2ct.GetKind().(type) {
default:
return fmt.Errorf("unsupported chain kind: %T", v)
case *apemanager_v2.ChainRaw:
raw := v.GetRaw()
c.Raw = &raw
}
return nil
}

View File

@ -0,0 +1,43 @@
package apemanager
import (
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
)
type TargetType apemanager_v2.TargetType
const (
TargetTypeUndefined TargetType = iota
TargetTypeNamespace
TargetTypeContainer
TargetTypeUser
TargetTypeGroup
)
func (targetType TargetType) ToV2() apemanager_v2.TargetType {
return apemanager_v2.TargetType(targetType)
}
func (targetType *TargetType) FromV2(v2targetType apemanager_v2.TargetType) {
*targetType = TargetType(v2targetType)
}
type ChainTarget struct {
TargetType TargetType
Name string
}
func (ct *ChainTarget) ToV2() *apemanager_v2.ChainTarget {
v2ct := new(apemanager_v2.ChainTarget)
v2ct.SetTargetType(ct.TargetType.ToV2())
v2ct.SetName(ct.Name)
return v2ct
}
func (ct *ChainTarget) FromV2(v2ct *apemanager_v2.ChainTarget) {
ct.TargetType.FromV2(v2ct.GetTargetType())
ct.Name = v2ct.GetName()
}

View File

@ -0,0 +1,65 @@
package apemanager_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
"github.com/stretchr/testify/require"
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
)
var (
m = map[apemanager.TargetType]apemanager_v2.TargetType{
apemanager.TargetTypeUndefined: apemanager_v2.TargetTypeUndefined,
apemanager.TargetTypeNamespace: apemanager_v2.TargetTypeNamespace,
apemanager.TargetTypeContainer: apemanager_v2.TargetTypeContainer,
apemanager.TargetTypeUser: apemanager_v2.TargetTypeUser,
apemanager.TargetTypeGroup: apemanager_v2.TargetTypeGroup,
}
)
func TestTargetType(t *testing.T) {
for typesdk, typev2 := range m {
t.Run("from sdk to v2 "+typev2.String(), func(t *testing.T) {
v2 := typesdk.ToV2()
require.Equal(t, v2, typev2)
})
t.Run("from v2 to sdk "+typev2.String(), func(t *testing.T) {
var typ apemanager.TargetType
typ.FromV2(typev2)
require.Equal(t, typesdk, typ)
})
}
}
func TestChainTarget(t *testing.T) {
var (
typ = apemanager.TargetTypeNamespace
name = "namespaceXXYYZZ"
)
t.Run("from sdk to v2", func(t *testing.T) {
ct := apemanager.ChainTarget{
TargetType: typ,
Name: name,
}
v2 := ct.ToV2()
require.Equal(t, m[typ], v2.GetTargetType())
require.Equal(t, name, v2.GetName())
})
t.Run("from v2 to sdk", func(t *testing.T) {
v2 := &apemanager_v2.ChainTarget{}
v2.SetTargetType(m[typ])
v2.SetName(name)
var ct apemanager.ChainTarget
ct.FromV2(v2)
require.Equal(t, typ, ct.TargetType)
require.Equal(t, name, ct.Name)
})
}

View File

@ -0,0 +1,41 @@
package apemanager_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
"github.com/stretchr/testify/require"
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
)
const (
encoded = `{"ID":"","Rules":[{"Status":"Allow","Actions":{"Inverted":false,"Names":["GetObject"]},"Resources":{"Inverted":false,"Names":["native:object/*"]},"Any":false,"Condition":[{"Op":"StringEquals","Object":"Resource","Key":"Department","Value":"HR"}]}],"MatchType":"DenyPriority"}`
)
func TestChainData(t *testing.T) {
var c apemanager.Chain
b := []byte(encoded)
c.Raw = &b
v2, ok := c.ToV2().GetKind().(*apemanager_v2.ChainRaw)
require.True(t, ok)
require.Equal(t, b, v2.Raw)
}
func TestChainMessageV2(t *testing.T) {
b := []byte(encoded)
v2Raw := &apemanager_v2.ChainRaw{}
v2Raw.SetRaw(b)
v2 := &apemanager_v2.Chain{}
v2.SetKind(v2Raw)
var c apemanager.Chain
c.ReadFromV2(v2)
require.NotNil(t, c.Raw)
require.Equal(t, b, *c.Raw)
}

View File

@ -0,0 +1,75 @@
package client
import (
"context"
"fmt"
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
session_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
)
type PrmAPEManagerAddChain struct {
XHeaders []string
ChainTarget apemanager_sdk.ChainTarget
Chain apemanager_sdk.Chain
}
func (prm *PrmAPEManagerAddChain) buildRequest(c *Client) (*apemanager_v2.AddChainRequest, error) {
if len(prm.XHeaders)%2 != 0 {
return nil, errorInvalidXHeaders
}
req := new(apemanager_v2.AddChainRequest)
reqBody := new(apemanager_v2.AddChainRequestBody)
reqBody.SetTarget(prm.ChainTarget.ToV2())
reqBody.SetChain(prm.Chain.ToV2())
req.SetBody(reqBody)
var meta session_v2.RequestMetaHeader
writeXHeadersToMeta(prm.XHeaders, &meta)
c.prepareRequest(req, &meta)
return req, nil
}
type ResAPEManagerAddChain struct {
statusRes
ChainID apemanager_sdk.ChainID
}
func (c *Client) APEManagerAddChain(ctx context.Context, prm PrmAPEManagerAddChain) (*ResAPEManagerAddChain, error) {
req, err := prm.buildRequest(c)
if err != nil {
return nil, err
}
if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil {
return nil, fmt.Errorf("sign request: %w", err)
}
resp, err := rpcapi.AddChain(&c.c, req, client.WithContext(ctx))
if err != nil {
return nil, err
}
var res ResAPEManagerAddChain
res.st, err = c.processResponse(resp)
if err != nil || !apistatus.IsSuccessful(res.st) {
return &res, err
}
res.ChainID = resp.GetBody().GetChainID()
return &res, nil
}

View File

@ -0,0 +1,78 @@
package client
import (
"context"
"fmt"
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
session_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
)
type PrmAPEManagerListChains struct {
XHeaders []string
ChainTarget apemanager_sdk.ChainTarget
}
func (prm *PrmAPEManagerListChains) buildRequest(c *Client) (*apemanager_v2.ListChainsRequest, error) {
if len(prm.XHeaders)%2 != 0 {
return nil, errorInvalidXHeaders
}
req := new(apemanager_v2.ListChainsRequest)
reqBody := new(apemanager_v2.ListChainsRequestBody)
reqBody.SetTarget(prm.ChainTarget.ToV2())
req.SetBody(reqBody)
var meta session_v2.RequestMetaHeader
writeXHeadersToMeta(prm.XHeaders, &meta)
c.prepareRequest(req, &meta)
return req, nil
}
type ResAPEManagerListChains struct {
statusRes
Chains []apemanager_sdk.Chain
}
func (c *Client) APEManagerListChains(ctx context.Context, prm PrmAPEManagerListChains) (*ResAPEManagerListChains, error) {
req, err := prm.buildRequest(c)
if err != nil {
return nil, err
}
if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil {
return nil, fmt.Errorf("sign request: %w", err)
}
resp, err := rpcapi.ListChains(&c.c, req, client.WithContext(ctx))
if err != nil {
return nil, err
}
var res ResAPEManagerListChains
res.st, err = c.processResponse(resp)
if err != nil || !apistatus.IsSuccessful(res.st) {
return nil, err
}
for _, ch := range resp.GetBody().GetChains() {
var chSDK apemanager_sdk.Chain
if err := chSDK.ReadFromV2(ch); err != nil {
return nil, err
}
res.Chains = append(res.Chains, chSDK)
}
return &res, nil
}

View File

@ -0,0 +1,71 @@
package client
import (
"context"
"fmt"
apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
session_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
)
type PrmAPEManagerRemoveChain struct {
XHeaders []string
ChainTarget apemanager_sdk.ChainTarget
ChainID apemanager_sdk.ChainID
}
func (prm *PrmAPEManagerRemoveChain) buildRequest(c *Client) (*apemanager_v2.RemoveChainRequest, error) {
if len(prm.XHeaders)%2 != 0 {
return nil, errorInvalidXHeaders
}
req := new(apemanager_v2.RemoveChainRequest)
reqBody := new(apemanager_v2.RemoveChainRequestBody)
reqBody.SetTarget(prm.ChainTarget.ToV2())
reqBody.SetChainID(prm.ChainID)
req.SetBody(reqBody)
var meta session_v2.RequestMetaHeader
writeXHeadersToMeta(prm.XHeaders, &meta)
c.prepareRequest(req, &meta)
return req, nil
}
type ResAPEManagerRemoveChain struct {
statusRes
}
func (c *Client) APEManagerRemoveChain(ctx context.Context, prm PrmAPEManagerRemoveChain) (*ResAPEManagerRemoveChain, error) {
req, err := prm.buildRequest(c)
if err != nil {
return nil, err
}
if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil {
return nil, fmt.Errorf("sign request: %w", err)
}
resp, err := rpcapi.RemoveChain(&c.c, req, client.WithContext(ctx))
if err != nil {
return nil, err
}
var res ResAPEManagerRemoveChain
res.st, err = c.processResponse(resp)
if err != nil || !apistatus.IsSuccessful(res.st) {
return &res, err
}
return &res, nil
}

View File

@ -61,6 +61,12 @@ func IsErrSessionNotFound(err error) bool {
return wrapsErrType[*apistatus.SessionTokenNotFound](err)
}
// IsErrAPEManagerAccessDenied checks if err corresponds to FrostFS status return
// corresponding to apemanager access deny. Supports wrapped errors.
func IsErrAPEManagerAccessDenied(err error) bool {
return wrapsErrType[*apistatus.APEManagerAccessDenied](err)
}
// returns error describing missing field with the given name.
func newErrMissingResponseField(name string) error {
return fmt.Errorf("missing %s field in the response", name)

View File

@ -0,0 +1,42 @@
package apistatus
import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
)
type APEManagerAccessDenied struct {
v2 status.Status
}
const defaultAPEManagerAccessDeniedMsg = "apemanager access denied"
func (x *APEManagerAccessDenied) Error() string {
msg := x.v2.Message()
if msg == "" {
msg = defaultAPEManagerAccessDeniedMsg
}
return errMessageStatusV2(
globalizeCodeV2(apemanager.StatusAPEManagerAccessDenied, apemanager.GlobalizeFail),
msg,
)
}
func (x *APEManagerAccessDenied) fromStatusV2(st *status.Status) {
x.v2 = *st
}
func (x APEManagerAccessDenied) ToStatusV2() *status.Status {
x.v2.SetCode(globalizeCodeV2(apemanager.StatusAPEManagerAccessDenied, apemanager.GlobalizeFail))
x.v2.SetMessage(defaultContainerNotFoundMsg)
return &x.v2
}
func (x *APEManagerAccessDenied) WriteReason(reason string) {
apemanager.WriteAccessDeniedDesc(&x.v2, reason)
}
func (x APEManagerAccessDenied) Reason() string {
return apemanager.ReadAccessDeniedDesc(x.v2)
}

View File

@ -3,6 +3,7 @@ package apistatus
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
"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"
@ -92,6 +93,12 @@ func FromStatusV2(st *status.Status) Status {
case session.StatusTokenExpired:
decoder = new(SessionTokenExpired)
}
case apemanager.LocalizeFailStatus(&code):
//nolint:exhaustive
switch code {
case apemanager.StatusAPEManagerAccessDenied:
decoder = new(APEManagerAccessDenied)
}
}
if decoder == nil {

View File

@ -125,6 +125,12 @@ func TestToStatusV2(t *testing.T) {
}),
codeV2: 4097,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.APEManagerAccessDenied)
}),
codeV2: 5120,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.NodeUnderMaintenance)
@ -278,6 +284,12 @@ func TestFromStatusV2(t *testing.T) {
}),
codeV2: 4097,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.APEManagerAccessDenied)
}),
codeV2: 5120,
},
{
status: (statusConstructor)(func() apistatus.Status {
return new(apistatus.NodeUnderMaintenance)

4
go.mod
View File

@ -2,8 +2,10 @@ module git.frostfs.info/TrueCloudLab/frostfs-sdk-go
go 1.20
replace git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240503055204-0fe6b9adbb72 => git.frostfs.info/aarifullin/frostfs-api-go/v2 v2.15.1-0.20240506112849-e6a1622c1682
require (
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240503055204-0fe6b9adbb72
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
git.frostfs.info/TrueCloudLab/hrw v1.2.1

4
go.sum
View File

@ -31,8 +31,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c h1:RFDrNsF2e+EJfaB8lZrRRxNjQkLfM09gnEyudvGuc10=
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb h1:S/TrbOOu9qEXZRZ9/Ddw7crnxbBUQLo68PSzQWYrc9M=
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb/go.mod h1:nkR5gaGeez3Zv2SE7aceP0YwxG2FzIB5cGKpQO2vV2o=
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=
@ -43,6 +41,8 @@ git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9m
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc=
git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA=
git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8=
git.frostfs.info/aarifullin/frostfs-api-go/v2 v2.15.1-0.20240506112849-e6a1622c1682 h1:SDf8PS+GOMXwMUlz5ZXiTG9nP9xkDlGwKDF40Ang8gA=
git.frostfs.info/aarifullin/frostfs-api-go/v2 v2.15.1-0.20240506112849-e6a1622c1682/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0=