frostfs-s3-gw/pkg/service/control/client/client.go
Denis Kirillov 42862fd69e [#258] Support policy management in control svc
Add PutPolicies, RemovePolicies, GetPolicy, ListPolicies methods

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-12-01 15:47:12 +03:00

162 lines
3.7 KiB
Go

package client
import (
"context"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control"
controlSvc "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/control/server"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type Client struct {
svc control.ControlServiceClient
key *keys.PrivateKey
}
type Config struct {
Logger *zap.Logger
}
type PolicyData struct {
Namespace string
Chain *chain.Chain
}
type PolicyInfo struct {
Namespace string
ChainID chain.ID
}
func New(ctx context.Context, addr string, key *keys.PrivateKey) (*Client, error) {
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, fmt.Errorf("failed to dial s3 gw control api: %w", err)
}
svc := control.NewControlServiceClient(conn)
cli := &Client{
svc: svc,
key: key,
}
return cli, cli.Healthcheck(ctx)
}
func (c *Client) Healthcheck(ctx context.Context) error {
req := &control.HealthCheckRequest{}
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
return err
}
res, err := c.svc.HealthCheck(ctx, req)
if err != nil {
return err
}
if res.Body.HealthStatus != control.HealthStatus_READY {
return fmt.Errorf("service isn't ready, status: %s", res.Body.HealthStatus)
}
return nil
}
func (c *Client) PutPolicies(ctx context.Context, policies []PolicyData) error {
chainDatas := make([]*control.PutPoliciesRequest_ChainData, len(policies))
for i := range policies {
chainDatas[i] = &control.PutPoliciesRequest_ChainData{
Namespace: policies[i].Namespace,
Chain: policies[i].Chain.Bytes(),
}
}
req := &control.PutPoliciesRequest{
Body: &control.PutPoliciesRequest_Body{
ChainDatas: chainDatas,
},
}
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
return err
}
_, err := c.svc.PutPolicies(ctx, req)
return err
}
func (c *Client) RemovePolicies(ctx context.Context, policies []PolicyInfo) error {
chainInfos := make([]*control.RemovePoliciesRequest_ChainInfo, len(policies))
for i := range policies {
chainInfos[i] = &control.RemovePoliciesRequest_ChainInfo{
Namespace: policies[i].Namespace,
ChainID: string(policies[i].ChainID),
}
}
req := &control.RemovePoliciesRequest{
Body: &control.RemovePoliciesRequest_Body{
ChainInfos: chainInfos,
},
}
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
return err
}
_, err := c.svc.RemovePolicies(ctx, req)
return err
}
func (c *Client) GetPolicy(ctx context.Context, namespace string, chainID chain.ID) (*chain.Chain, error) {
req := &control.GetPolicyRequest{
Body: &control.GetPolicyRequest_Body{
Namespace: namespace,
ChainID: string(chainID),
},
}
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
return nil, err
}
resp, err := c.svc.GetPolicy(ctx, req)
if err != nil {
return nil, err
}
var policyChain chain.Chain
if err = policyChain.DecodeBytes(resp.GetBody().GetChain()); err != nil {
return nil, err
}
return &policyChain, nil
}
func (c *Client) ListPolicies(ctx context.Context, namespace string) ([]chain.ID, error) {
req := &control.ListPoliciesRequest{
Body: &control.ListPoliciesRequest_Body{
Namespace: namespace,
},
}
if err := controlSvc.SignMessage(&c.key.PrivateKey, req); err != nil {
return nil, err
}
resp, err := c.svc.ListPolicies(ctx, req)
if err != nil {
return nil, err
}
res := make([]chain.ID, len(resp.GetBody().GetChainIDs()))
for i, chainID := range resp.GetBody().GetChainIDs() {
res[i] = chain.ID(chainID)
}
return res, nil
}