control: Recieve target in gRPC methods for APE managing #842

Merged
fyrchik merged 2 commits from aarifullin/frostfs-node:feature/chain_control_api into master 2023-12-07 14:22:00 +00:00
14 changed files with 121 additions and 31 deletions

View file

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/json" "encoding/json"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
@ -13,6 +14,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -60,9 +62,14 @@ func addRule(cmd *cobra.Command, _ []string) {
cmd.Println("Container ID: " + cidStr) cmd.Println("Container ID: " + cidStr)
cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain))
name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr)
req := &control.AddChainLocalOverrideRequest{ req := &control.AddChainLocalOverrideRequest{
Body: &control.AddChainLocalOverrideRequest_Body{ Body: &control.AddChainLocalOverrideRequest_Body{
ContainerId: rawCID, Target: &control.ChainTarget{
Type: control.ChainTarget_CONTAINER,
Name: name,
},
Chain: serializedChain, Chain: serializedChain,
}, },
} }

View file

@ -2,6 +2,7 @@ package control
import ( import (
"crypto/sha256" "crypto/sha256"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
@ -10,6 +11,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -32,9 +34,14 @@ func getRule(cmd *cobra.Command, _ []string) {
chainID, _ := cmd.Flags().GetString(chainIDFlag) chainID, _ := cmd.Flags().GetString(chainIDFlag)
name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr)
req := &control.GetChainLocalOverrideRequest{ req := &control.GetChainLocalOverrideRequest{
Body: &control.GetChainLocalOverrideRequest_Body{ Body: &control.GetChainLocalOverrideRequest_Body{
ContainerId: rawCID, Target: &control.ChainTarget{
Name: name,
Type: control.ChainTarget_CONTAINER,
},
ChainId: chainID, ChainId: chainID,
}, },
} }

View file

@ -2,6 +2,7 @@ package control
import ( import (
"crypto/sha256" "crypto/sha256"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
@ -10,6 +11,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -30,9 +32,14 @@ func listRules(cmd *cobra.Command, _ []string) {
rawCID := make([]byte, sha256.Size) rawCID := make([]byte, sha256.Size)
cnr.Encode(rawCID) cnr.Encode(rawCID)
name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr)
req := &control.ListChainLocalOverridesRequest{ req := &control.ListChainLocalOverridesRequest{
Body: &control.ListChainLocalOverridesRequest_Body{ Body: &control.ListChainLocalOverridesRequest_Body{
ContainerId: rawCID, Target: &control.ChainTarget{
Name: name,
Type: control.ChainTarget_CONTAINER,
},
}, },
} }

View file

@ -2,6 +2,7 @@ package control
import ( import (
"crypto/sha256" "crypto/sha256"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
@ -9,6 +10,7 @@ import (
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -35,9 +37,14 @@ func removeRule(cmd *cobra.Command, _ []string) {
chainID, _ := cmd.Flags().GetString(chainIDFlag) chainID, _ := cmd.Flags().GetString(chainIDFlag)
name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr)
req := &control.RemoveChainLocalOverrideRequest{ req := &control.RemoveChainLocalOverrideRequest{
Body: &control.RemoveChainLocalOverrideRequest_Body{ Body: &control.RemoveChainLocalOverrideRequest_Body{
ContainerId: rawCID, Target: &control.ChainTarget{
Name: name,
Type: control.ChainTarget_CONTAINER,
},
ChainId: chainID, ChainId: chainID,
}, },
} }

2
go.mod
View file

@ -8,7 +8,7 @@ require (
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e
git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/hrw v1.2.1
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3
git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/tzhash v1.8.0
github.com/cheggaaa/pb v1.0.29 github.com/cheggaaa/pb v1.0.29
github.com/chzyer/readline v1.5.1 github.com/chzyer/readline v1.5.1

BIN
go.sum

Binary file not shown.

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"strings"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
@ -14,13 +15,36 @@ import (
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
// extractCID extracts CID from the schema's pattern.
// TODO (aarifullin): This is temporary solution should be replaced by
fyrchik marked this conversation as resolved Outdated

Do we have a task for this? Refs #847 @dstepanov-yadro

Do we have a task for this? Refs #847 @dstepanov-yadro

I am going to erase this method and TODO here. So, as soon as this PR will be merged!

This method is needed because frostfs-node still uses deprecated APE version

I am going to erase this method and `TODO` [here](https://git.frostfs.info/TrueCloudLab/frostfs-node/pulls/820). So, as soon as this PR will be merged! This method is needed because frostfs-node still uses deprecated APE version
// resource name validation.
func extractCID(resource string) (cid.ID, error) {
var cidStr string
// Sscanf requires to make tokens delimited by spaces.
pattern := strings.Replace(nativeschema.ResourceFormatRootContainerObjects, "/", " ", -1)
resource = strings.Replace(resource, "/", " ", -1)
if _, err := fmt.Sscanf(resource, pattern, &cidStr); err != nil {
err = fmt.Errorf("could not parse the target name '%s' to CID: %w", resource, err)
return cid.ID{}, err
}
var cid cid.ID
err := cid.DecodeString(cidStr)
return cid, err
}
func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) { func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) {
if err := s.isValidRequest(req); err != nil { if err := s.isValidRequest(req); err != nil {
return nil, status.Error(codes.PermissionDenied, err.Error()) return nil, status.Error(codes.PermissionDenied, err.Error())
} }
var cid cid.ID target := req.GetBody().GetTarget()
err := cid.Decode(req.GetBody().GetContainerId()) if target.Type != control.ChainTarget_CONTAINER {

Why do we require exactly container target (what about namespace)?

Why do we require exactly container target (what about namespace)?

As you can see here is deprecated prototype of APE used. This check will be fixe here but we need this PR #842 first.

Briefly: the current implementation works with containers only but this will become unactual in #820

As you can see here is deprecated prototype of APE used. This check will be fixe [here](https://git.frostfs.info/TrueCloudLab/frostfs-node/pulls/820) but we need this PR #842 first. Briefly: the current implementation works with containers only but this will become unactual in #820
return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error())
}
cid, err := extractCID(target.GetName())
if err != nil { if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error()) return nil, status.Error(codes.InvalidArgument, err.Error())
} }
@ -37,10 +61,12 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL
s.apeChainCounter.Add(1) s.apeChainCounter.Add(1)
// TODO (aarifullin): the such chain id is not well-designed yet. // TODO (aarifullin): the such chain id is not well-designed yet.
if chain.ID == "" {
chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load()))
}
resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString())
if _, err = src.LocalStorage().AddOverride(apechain.Ingress, resource, &chain); err != nil { if _, err = src.LocalStorage().AddOverride(apechain.Ingress, engine.ContainerTarget(resource), &chain); err != nil {
return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) return nil, status.Error(getCodeByLocalStorageErr(err), err.Error())
} }
@ -61,8 +87,12 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL
return nil, status.Error(codes.PermissionDenied, err.Error()) return nil, status.Error(codes.PermissionDenied, err.Error())
} }
var cid cid.ID target := req.GetBody().GetTarget()
err := cid.Decode(req.GetBody().GetContainerId()) if target.Type != control.ChainTarget_CONTAINER {
return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error())
}
cid, err := extractCID(target.GetName())
if err != nil { if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error()) return nil, status.Error(codes.InvalidArgument, err.Error())
} }
@ -73,7 +103,7 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL
} }
resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString())
chain, err := src.LocalStorage().GetOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())) chain, err := src.LocalStorage().GetOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId()))
if err != nil { if err != nil {
return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) return nil, status.Error(getCodeByLocalStorageErr(err), err.Error())
} }
@ -95,8 +125,12 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha
return nil, status.Error(codes.PermissionDenied, err.Error()) return nil, status.Error(codes.PermissionDenied, err.Error())
} }
var cid cid.ID target := req.GetBody().GetTarget()
err := cid.Decode(req.GetBody().GetContainerId()) if target.Type != control.ChainTarget_CONTAINER {
return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error())
}
cid, err := extractCID(target.GetName())
if err != nil { if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error()) return nil, status.Error(codes.InvalidArgument, err.Error())
} }
@ -107,7 +141,7 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha
} }
resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString())
chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, resource) chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, engine.ContainerTarget(resource))
if err != nil { if err != nil {
return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) return nil, status.Error(getCodeByLocalStorageErr(err), err.Error())
} }
@ -133,8 +167,12 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove
return nil, status.Error(codes.PermissionDenied, err.Error()) return nil, status.Error(codes.PermissionDenied, err.Error())
} }
var cid cid.ID target := req.GetBody().GetTarget()
err := cid.Decode(req.GetBody().GetContainerId()) if target.Type != control.ChainTarget_CONTAINER {
return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error())
}
cid, err := extractCID(target.GetName())
if err != nil { if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error()) return nil, status.Error(codes.InvalidArgument, err.Error())
} }
@ -145,7 +183,7 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove
} }
resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString())
if err = src.LocalStorage().RemoveOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())); err != nil { if err = src.LocalStorage().RemoveOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())); err != nil {
return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) return nil, status.Error(getCodeByLocalStorageErr(err), err.Error())
} }
resp := &control.RemoveChainLocalOverrideResponse{ resp := &control.RemoveChainLocalOverrideResponse{

Binary file not shown.

View file

@ -421,10 +421,12 @@ message StopShardEvacuationResponse {
// AddChainLocalOverride request. // AddChainLocalOverride request.
message AddChainLocalOverrideRequest { message AddChainLocalOverrideRequest {
message Body { message Body {
// Container id for which the overrides are applied. // Target for which the overrides are applied.
bytes container_id = 1; ChainTarget target = 1;
// Serialized rule chain. // Serialized rule chain. If chain ID is left empty
// in the chain, then it will be generated and returned
// in the response.
bytes chain = 2; bytes chain = 2;
} }
@ -437,6 +439,8 @@ message AddChainLocalOverrideRequest {
message AddChainLocalOverrideResponse { message AddChainLocalOverrideResponse {
message Body { message Body {
// Chain ID assigned for the added rule chain. // Chain ID assigned for the added rule chain.
// If chain ID is left empty in the request, then
// it will be generated.
string chain_id = 1; string chain_id = 1;
} }
@ -448,8 +452,8 @@ message AddChainLocalOverrideResponse {
// GetChainLocalOverride request. // GetChainLocalOverride request.
message GetChainLocalOverrideRequest { message GetChainLocalOverrideRequest {
message Body { message Body {
// Container id for which the overrides are defined. // Target for which the overrides are applied.
bytes container_id = 1; ChainTarget target = 1;
// Chain ID assigned for the added rule chain. // Chain ID assigned for the added rule chain.
string chain_id = 2; string chain_id = 2;
@ -475,8 +479,8 @@ message GetChainLocalOverrideResponse {
// ListChainLocalOverrides request. // ListChainLocalOverrides request.
message ListChainLocalOverridesRequest { message ListChainLocalOverridesRequest {
message Body { message Body {
// Container id for which the overrides are defined. // Target for which the overrides are applied.
bytes container_id = 1; ChainTarget target = 1;
} }
Body body = 1; Body body = 1;
@ -498,8 +502,8 @@ message ListChainLocalOverridesResponse {
message RemoveChainLocalOverrideRequest { message RemoveChainLocalOverrideRequest {
message Body { message Body {
// Container id for which the overrides are defined. // Target for which the overrides are applied.
bytes container_id = 1; ChainTarget target = 1;
// Chain ID assigned for the added rule chain. // Chain ID assigned for the added rule chain.
string chain_id = 2; string chain_id = 2;

Binary file not shown.

Binary file not shown.

View file

@ -169,3 +169,20 @@ enum ShardMode {
// DegradedReadOnly. // DegradedReadOnly.
DEGRADED_READ_ONLY = 4; DEGRADED_READ_ONLY = 4;
} }
// ChainTarget is an object to which local overrides
// are applied.
message ChainTarget {
enum TargetType {
UNDEFINED = 0;
fyrchik marked this conversation as resolved Outdated

Maybe use some undefined as default = 0? The parameter is mandatory

Maybe use some `undefined` as default `= 0`? The parameter is mandatory

Introduced Undefined number

Introduced `Undefined` number
NAMESPACE = 1;
CONTAINER = 2;
}
TargetType type = 1;
string Name = 2;
}

Binary file not shown.

View file

@ -9,6 +9,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
) )
var errAPEChainNoSource = errors.New("could not get ape chain source for the container") var errAPEChainNoSource = errors.New("could not get ape chain source for the container")
@ -36,7 +37,9 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error {
request := new(Request) request := new(Request)
request.FromRequestInfo(reqInfo) request.FromRequestInfo(reqInfo)
status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, "", request) cnrTarget := getResource(reqInfo).Name()
status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request)
if err != nil { if err != nil {
return err return err
} }