frostfs-s3-gw/pkg/service/control/client/client.go
Alex Vanin 13d00dd7ce [#362] Expand control service
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-04-12 16:52:08 +03:00

184 lines
4.3 KiB
Go

package client
import (
"context"
"fmt"
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
"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 {
Kind policycontract.Kind
Name string
Chain *chain.Chain
}
type PolicyInfo struct {
Kind policycontract.Kind
Name string
ChainID chain.ID
}
func kindToTarget(k policycontract.Kind) control.PolicyTarget {
switch k {
case policycontract.Container:
return control.PolicyTarget_CONTAINER
case policycontract.Namespace:
return control.PolicyTarget_NAMESPACE
case 'u':
return control.PolicyTarget_USER
case 'g':
return control.PolicyTarget_GROUP
default:
return control.PolicyTarget_TARGET_UNDEFINED
}
}
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{
Target: kindToTarget(policies[i].Kind),
Name: policies[i].Name,
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{
Target: kindToTarget(policies[i].Kind),
Name: policies[i].Name,
ChainID: []byte(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, kind policycontract.Kind, name string, chainID chain.ID) (*chain.Chain, error) {
req := &control.GetPolicyRequest{
Body: &control.GetPolicyRequest_Body{
Target: kindToTarget(kind),
Name: name,
ChainID: []byte(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, kind policycontract.Kind, name string) ([]chain.ID, error) {
req := &control.ListPoliciesRequest{
Body: &control.ListPoliciesRequest_Body{
Target: kindToTarget(kind),
Name: name,
},
}
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
}