Compare commits
8 commits
Author | SHA1 | Date | |
---|---|---|---|
02d191e9a6 | |||
cecb3f7867 | |||
f53d30fa95 | |||
1b92817bd3 | |||
32ec421ac7 | |||
4d102b05e5 | |||
308da7cb01 | |||
37b83c0856 |
25 changed files with 95 additions and 506 deletions
|
@ -38,6 +38,12 @@ var (
|
||||||
func parseTarget(cmd *cobra.Command) policyengine.Target {
|
func parseTarget(cmd *cobra.Command) policyengine.Target {
|
||||||
name, _ := cmd.Flags().GetString(targetNameFlag)
|
name, _ := cmd.Flags().GetString(targetNameFlag)
|
||||||
typ, err := parseTargetType(cmd)
|
typ, err := parseTargetType(cmd)
|
||||||
|
|
||||||
|
// interpret "root" namespace as empty
|
||||||
|
if typ == policyengine.Namespace && name == "root" {
|
||||||
|
name = ""
|
||||||
|
}
|
||||||
|
|
||||||
commonCmd.ExitOnErr(cmd, "read target type error: %w", err)
|
commonCmd.ExitOnErr(cmd, "read target type error: %w", err)
|
||||||
|
|
||||||
return policyengine.Target{
|
return policyengine.Target{
|
||||||
|
|
|
@ -214,29 +214,6 @@ func EACL(ctx context.Context, prm EACLPrm) (res EACLRes, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEACLPrm groups parameters of SetEACL operation.
|
|
||||||
type SetEACLPrm struct {
|
|
||||||
Client *client.Client
|
|
||||||
ClientParams client.PrmContainerSetEACL
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetEACLRes groups the resulting values of SetEACL operation.
|
|
||||||
type SetEACLRes struct{}
|
|
||||||
|
|
||||||
// SetEACL requests to save an eACL table in FrostFS.
|
|
||||||
//
|
|
||||||
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
|
||||||
// The required time is also not predictable.
|
|
||||||
//
|
|
||||||
// Success can be verified by reading by container identifier.
|
|
||||||
//
|
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
|
||||||
func SetEACL(ctx context.Context, prm SetEACLPrm) (res SetEACLRes, err error) {
|
|
||||||
_, err = prm.Client.ContainerSetEACL(ctx, prm.ClientParams)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkInfoPrm groups parameters of NetworkInfo operation.
|
// NetworkInfoPrm groups parameters of NetworkInfo operation.
|
||||||
type NetworkInfoPrm struct {
|
type NetworkInfoPrm struct {
|
||||||
Client *client.Client
|
Client *client.Client
|
||||||
|
|
|
@ -26,7 +26,6 @@ func init() {
|
||||||
listContainerObjectsCmd,
|
listContainerObjectsCmd,
|
||||||
getContainerInfoCmd,
|
getContainerInfoCmd,
|
||||||
getExtendedACLCmd,
|
getExtendedACLCmd,
|
||||||
setExtendedACLCmd,
|
|
||||||
containerNodesCmd,
|
containerNodesCmd,
|
||||||
policyPlaygroundCmd,
|
policyPlaygroundCmd,
|
||||||
}
|
}
|
||||||
|
@ -39,7 +38,6 @@ func init() {
|
||||||
initContainerListObjectsCmd()
|
initContainerListObjectsCmd()
|
||||||
initContainerInfoCmd()
|
initContainerInfoCmd()
|
||||||
initContainerGetEACLCmd()
|
initContainerGetEACLCmd()
|
||||||
initContainerSetEACLCmd()
|
|
||||||
initContainerNodesCmd()
|
initContainerNodesCmd()
|
||||||
initContainerPolicyPlaygroundCmd()
|
initContainerPolicyPlaygroundCmd()
|
||||||
|
|
||||||
|
@ -53,7 +51,6 @@ func init() {
|
||||||
}{
|
}{
|
||||||
{createContainerCmd, "PUT"},
|
{createContainerCmd, "PUT"},
|
||||||
{deleteContainerCmd, "DELETE"},
|
{deleteContainerCmd, "DELETE"},
|
||||||
{setExtendedACLCmd, "SETEACL"},
|
|
||||||
} {
|
} {
|
||||||
commonflags.InitSession(el.cmd, "container "+el.verb)
|
commonflags.InitSession(el.cmd, "container "+el.verb)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var flagVarsSetEACL struct {
|
|
||||||
noPreCheck bool
|
|
||||||
|
|
||||||
srcPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
var setExtendedACLCmd = &cobra.Command{
|
|
||||||
Use: "set-eacl",
|
|
||||||
Short: "Set new extended ACL table for container",
|
|
||||||
Long: `Set new extended ACL table for container.
|
|
||||||
Container ID in EACL table will be substituted with ID from the CLI.`,
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
id := parseContainerID(cmd)
|
|
||||||
eaclTable := common.ReadEACL(cmd, flagVarsSetEACL.srcPath)
|
|
||||||
|
|
||||||
tok := getSession(cmd)
|
|
||||||
|
|
||||||
eaclTable.SetCID(id)
|
|
||||||
|
|
||||||
pk := key.GetOrGenerate(cmd)
|
|
||||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
|
||||||
|
|
||||||
if !flagVarsSetEACL.noPreCheck {
|
|
||||||
cmd.Println("Checking the ability to modify access rights in the container...")
|
|
||||||
|
|
||||||
extendable, err := internalclient.IsACLExtendable(cmd.Context(), cli, id)
|
|
||||||
commonCmd.ExitOnErr(cmd, "Extensibility check failure: %w", err)
|
|
||||||
|
|
||||||
if !extendable {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", errors.New("container ACL is immutable"))
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Println("ACL extension is enabled in the container, continue processing.")
|
|
||||||
}
|
|
||||||
|
|
||||||
setEACLPrm := internalclient.SetEACLPrm{
|
|
||||||
Client: cli,
|
|
||||||
ClientParams: client.PrmContainerSetEACL{
|
|
||||||
Table: eaclTable,
|
|
||||||
Session: tok,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := internalclient.SetEACL(cmd.Context(), setEACLPrm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
if containerAwait {
|
|
||||||
exp, err := eaclTable.Marshal()
|
|
||||||
commonCmd.ExitOnErr(cmd, "broken EACL table: %w", err)
|
|
||||||
|
|
||||||
cmd.Println("awaiting...")
|
|
||||||
|
|
||||||
getEACLPrm := internalclient.EACLPrm{
|
|
||||||
Client: cli,
|
|
||||||
ClientParams: client.PrmContainerEACL{
|
|
||||||
ContainerID: &id,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < awaitTimeout; i++ {
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
res, err := internalclient.EACL(cmd.Context(), getEACLPrm)
|
|
||||||
if err == nil {
|
|
||||||
// compare binary values because EACL could have been set already
|
|
||||||
table := res.EACL()
|
|
||||||
got, err := table.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Equal(exp, got) {
|
|
||||||
cmd.Println("EACL has been persisted on sidechain")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commonCmd.ExitOnErr(cmd, "", errSetEACLTimeout)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func initContainerSetEACLCmd() {
|
|
||||||
commonflags.Init(setExtendedACLCmd)
|
|
||||||
|
|
||||||
flags := setExtendedACLCmd.Flags()
|
|
||||||
flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
|
|
||||||
flags.StringVar(&flagVarsSetEACL.srcPath, "table", "", "path to file with JSON or binary encoded EACL table")
|
|
||||||
flags.BoolVar(&containerAwait, "await", false, "block execution until EACL is persisted")
|
|
||||||
flags.BoolVar(&flagVarsSetEACL.noPreCheck, "no-precheck", false, "do not pre-check the extensibility of the container ACL")
|
|
||||||
}
|
|
|
@ -20,7 +20,6 @@ const (
|
||||||
var (
|
var (
|
||||||
errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain")
|
errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain")
|
||||||
errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain")
|
errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain")
|
||||||
errSetEACLTimeout = errors.New("timeout: EACL has not been persisted on sidechain")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseContainerID(cmd *cobra.Command) cid.ID {
|
func parseContainerID(cmd *cobra.Command) cid.ID {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
verifyPresenceAllFlag = "verify-presence-all"
|
verifyPresenceAllFlag = "verify-presence-all"
|
||||||
|
preferInternalAddressesFlag = "prefer-internal-addresses"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -97,6 +98,7 @@ func initObjectNodesCmd() {
|
||||||
|
|
||||||
flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes.")
|
flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes.")
|
||||||
flags.Bool(commonflags.JSON, false, "Print information about the object placement as json.")
|
flags.Bool(commonflags.JSON, false, "Print information about the object placement as json.")
|
||||||
|
flags.Bool(preferInternalAddressesFlag, false, "Use internal addresses first to get object info.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectNodes(cmd *cobra.Command, _ []string) {
|
func objectNodes(cmd *cobra.Command, _ []string) {
|
||||||
|
@ -449,11 +451,20 @@ func getNodesToCheckObjectExistance(cmd *cobra.Command, netmap *netmapSDK.NetMap
|
||||||
func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.NodeInfo, pk *ecdsa.PrivateKey) (*client.Client, error) {
|
func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.NodeInfo, pk *ecdsa.PrivateKey) (*client.Client, error) {
|
||||||
var cli *client.Client
|
var cli *client.Client
|
||||||
var addresses []string
|
var addresses []string
|
||||||
|
if preferInternal, _ := cmd.Flags().GetBool(preferInternalAddressesFlag); preferInternal {
|
||||||
candidate.IterateNetworkEndpoints(func(s string) bool {
|
candidate.IterateNetworkEndpoints(func(s string) bool {
|
||||||
addresses = append(addresses, s)
|
addresses = append(addresses, s)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
addresses = append(addresses, candidate.ExternalAddresses()...)
|
addresses = append(addresses, candidate.ExternalAddresses()...)
|
||||||
|
} else {
|
||||||
|
addresses = append(addresses, candidate.ExternalAddresses()...)
|
||||||
|
candidate.IterateNetworkEndpoints(func(s string) bool {
|
||||||
|
addresses = append(addresses, s)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var lastErr error
|
var lastErr error
|
||||||
for _, address := range addresses {
|
for _, address := range addresses {
|
||||||
var networkAddr network.Address
|
var networkAddr network.Address
|
||||||
|
|
10
go.mod
10
go.mod
|
@ -4,11 +4,11 @@ go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.17.1
|
code.gitea.io/sdk/gitea v0.17.1
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3
|
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
|
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
||||||
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-20240617140730-1a5886e776de
|
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec
|
||||||
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-20240712081403-2628f6184984
|
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984
|
||||||
git.frostfs.info/TrueCloudLab/tzhash v1.8.0
|
git.frostfs.info/TrueCloudLab/tzhash v1.8.0
|
||||||
|
@ -23,7 +23,7 @@ require (
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/mr-tron/base58 v1.2.0
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/multiformats/go-multiaddr v0.12.1
|
github.com/multiformats/go-multiaddr v0.12.1
|
||||||
github.com/nspcc-dev/neo-go v0.106.0
|
github.com/nspcc-dev/neo-go v0.106.2
|
||||||
github.com/olekukonko/tablewriter v0.0.5
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/panjf2000/ants/v2 v2.9.0
|
github.com/panjf2000/ants/v2 v2.9.0
|
||||||
github.com/paulmach/orb v0.11.0
|
github.com/paulmach/orb v0.11.0
|
||||||
|
@ -38,7 +38,7 @@ require (
|
||||||
go.opentelemetry.io/otel v1.22.0
|
go.opentelemetry.io/otel v1.22.0
|
||||||
go.opentelemetry.io/otel/trace v1.22.0
|
go.opentelemetry.io/otel/trace v1.22.0
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||||
golang.org/x/sync v0.6.0
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/sys v0.18.0
|
golang.org/x/sys v0.18.0
|
||||||
golang.org/x/term v0.18.0
|
golang.org/x/term v0.18.0
|
||||||
|
@ -128,4 +128,4 @@ require (
|
||||||
rsc.io/tmplfunc v0.0.3 // indirect
|
rsc.io/tmplfunc v0.0.3 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18
|
replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928
|
||||||
|
|
16
go.sum
16
go.sum
|
@ -1,19 +1,19 @@
|
||||||
code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
|
code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
|
||||||
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg=
|
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e h1:gEWT+70E/RvGkxtSv+PlyUN2vtJVymhQa1mypvrXukM=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
|
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4=
|
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
|
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=
|
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU=
|
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI=
|
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw=
|
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de h1:OjsWY0jpGJV1t87XgwL/3PsDx7fJ6lfNMXtY8UhoUbM=
|
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec h1:A09Swh7yogmmiABUf7Ht6MTQXJ07MyGx4+ziUQNelec=
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU=
|
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec/go.mod h1:DlJmgV4/qkFkx2ab+YWznlMijiF2yZHnrJswJOB7XGs=
|
||||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc=
|
git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc=
|
||||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM=
|
git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM=
|
||||||
git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 h1:JRjwcHaQajTbSCBCK3yZnqvyHvgWBaoThDGuT4kvIIc=
|
git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM=
|
||||||
git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg=
|
git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg=
|
||||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 h1:O3F2Grz07RWZ68mRz1xsYsNPNvZLwY00BM+xoYb1kNk=
|
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 h1:O3F2Grz07RWZ68mRz1xsYsNPNvZLwY00BM+xoYb1kNk=
|
||||||
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA=
|
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA=
|
||||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA=
|
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA=
|
||||||
|
@ -321,8 +321,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
// Client is an interface of FrostFS storage
|
// Client is an interface of FrostFS storage
|
||||||
// node's client.
|
// node's client.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
ContainerAnnounceUsedSpace(context.Context, client.PrmAnnounceSpace) (*client.ResAnnounceSpace, error)
|
|
||||||
ObjectPutInit(context.Context, client.PrmObjectPutInit) (client.ObjectWriter, error)
|
ObjectPutInit(context.Context, client.PrmObjectPutInit) (client.ObjectWriter, error)
|
||||||
ObjectPutSingle(context.Context, client.PrmObjectPutSingle) (*client.ResObjectPutSingle, error)
|
ObjectPutSingle(context.Context, client.PrmObjectPutSingle) (*client.ResObjectPutSingle, error)
|
||||||
ObjectDelete(context.Context, client.PrmObjectDelete) (*client.ResObjectDelete, error)
|
ObjectDelete(context.Context, client.PrmObjectDelete) (*client.ResObjectDelete, error)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package container
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -238,5 +237,5 @@ func (c *testMorphClient) NotarySignAndInvokeTX(mainTx *transaction.Transaction)
|
||||||
type testFrostFSIDClient struct{}
|
type testFrostFSIDClient struct{}
|
||||||
|
|
||||||
func (c *testFrostFSIDClient) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) {
|
func (c *testFrostFSIDClient) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) {
|
||||||
return nil, fmt.Errorf("subject not found")
|
return &frostfsidclient.Subject{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,11 +180,6 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, hasNamespace := strings.CutSuffix(ctx.d.Zone(), ".ns")
|
|
||||||
if !hasNamespace {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
addr, err := util.Uint160DecodeBytesBE(cnr.Owner().WalletBytes()[1 : 1+util.Uint160Size])
|
addr, err := util.Uint160DecodeBytesBE(cnr.Owner().WalletBytes()[1 : 1+util.Uint160Size])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get container owner address: %w", err)
|
return fmt.Errorf("could not get container owner address: %w", err)
|
||||||
|
@ -195,6 +190,11 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain
|
||||||
return fmt.Errorf("could not get subject from FrostfsID contract: %w", err)
|
return fmt.Errorf("could not get subject from FrostfsID contract: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace, hasNamespace := strings.CutSuffix(ctx.d.Zone(), ".ns")
|
||||||
|
if !hasNamespace {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if subject.Namespace != namespace {
|
if subject.Namespace != namespace {
|
||||||
return errContainerAndOwnerNamespaceDontMatch
|
return errContainerAndOwnerNamespaceDontMatch
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +1,13 @@
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AnnounceLoadPrm groups parameters of AnnounceLoad operation.
|
|
||||||
type AnnounceLoadPrm struct {
|
|
||||||
a container.SizeEstimation
|
|
||||||
key []byte
|
|
||||||
|
|
||||||
client.InvokePrmOptional
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAnnouncement sets announcement.
|
|
||||||
func (a2 *AnnounceLoadPrm) SetAnnouncement(a container.SizeEstimation) {
|
|
||||||
a2.a = a
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetReporter sets public key of the reporter.
|
|
||||||
func (a2 *AnnounceLoadPrm) SetReporter(key []byte) {
|
|
||||||
a2.key = key
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceLoad saves container size estimation calculated by storage node
|
|
||||||
// with key in FrostFS system through Container contract call.
|
|
||||||
//
|
|
||||||
// Returns any error encountered that caused the saving to interrupt.
|
|
||||||
func (c *Client) AnnounceLoad(p AnnounceLoadPrm) error {
|
|
||||||
binCnr := make([]byte, sha256.Size)
|
|
||||||
p.a.Container().Encode(binCnr)
|
|
||||||
|
|
||||||
prm := client.InvokePrm{}
|
|
||||||
prm.SetMethod(putSizeMethod)
|
|
||||||
prm.SetArgs(p.a.Epoch(), binCnr, p.a.Value(), p.key)
|
|
||||||
prm.InvokePrmOptional = p.InvokePrmOptional
|
|
||||||
|
|
||||||
_, err := c.client.Invoke(prm)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not invoke method (%s): %w", putSizeMethod, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EstimationID is an identity of container load estimation inside Container contract.
|
// EstimationID is an identity of container load estimation inside Container contract.
|
||||||
type EstimationID []byte
|
type EstimationID []byte
|
||||||
|
|
||||||
|
|
9
pkg/network/cache/multi.go
vendored
9
pkg/network/cache/multi.go
vendored
|
@ -239,15 +239,6 @@ func (x *multiClient) ObjectPutSingle(ctx context.Context, p client.PrmObjectPut
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *multiClient) ContainerAnnounceUsedSpace(ctx context.Context, prm client.PrmAnnounceSpace) (res *client.ResAnnounceSpace, err error) {
|
|
||||||
err = x.iterateClients(ctx, func(c clientcore.Client) error {
|
|
||||||
res, err = c.ContainerAnnounceUsedSpace(ctx, prm)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *multiClient) ObjectDelete(ctx context.Context, p client.PrmObjectDelete) (res *client.ResObjectDelete, err error) {
|
func (x *multiClient) ObjectDelete(ctx context.Context, p client.PrmObjectDelete) (res *client.ResObjectDelete, err error) {
|
||||||
err = x.iterateClients(ctx, func(c clientcore.Client) error {
|
err = x.iterateClients(ctx, func(c clientcore.Client) error {
|
||||||
res, err = c.ObjectDelete(ctx, p)
|
res, err = c.ObjectDelete(ctx, p)
|
||||||
|
|
|
@ -81,21 +81,6 @@ func (s *Server) List(ctx context.Context, req *containerGRPC.ListRequest) (*con
|
||||||
return resp.ToGRPCMessage().(*containerGRPC.ListResponse), nil
|
return resp.ToGRPCMessage().(*containerGRPC.ListResponse), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetExtendedACL converts gRPC SetExtendedACLRequest message and passes it to internal Container service.
|
|
||||||
func (s *Server) SetExtendedACL(ctx context.Context, req *containerGRPC.SetExtendedACLRequest) (*containerGRPC.SetExtendedACLResponse, error) {
|
|
||||||
setEACLReq := new(container.SetExtendedACLRequest)
|
|
||||||
if err := setEACLReq.FromGRPCMessage(req); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.srv.SetExtendedACL(ctx, setEACLReq)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.ToGRPCMessage().(*containerGRPC.SetExtendedACLResponse), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetExtendedACL converts gRPC GetExtendedACLRequest message and passes it to internal Container service.
|
// GetExtendedACL converts gRPC GetExtendedACLRequest message and passes it to internal Container service.
|
||||||
func (s *Server) GetExtendedACL(ctx context.Context, req *containerGRPC.GetExtendedACLRequest) (*containerGRPC.GetExtendedACLResponse, error) {
|
func (s *Server) GetExtendedACL(ctx context.Context, req *containerGRPC.GetExtendedACLRequest) (*containerGRPC.GetExtendedACLResponse, error) {
|
||||||
getEACLReq := new(container.GetExtendedACLRequest)
|
getEACLReq := new(container.GetExtendedACLRequest)
|
||||||
|
@ -110,18 +95,3 @@ func (s *Server) GetExtendedACL(ctx context.Context, req *containerGRPC.GetExten
|
||||||
|
|
||||||
return resp.ToGRPCMessage().(*containerGRPC.GetExtendedACLResponse), nil
|
return resp.ToGRPCMessage().(*containerGRPC.GetExtendedACLResponse), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnnounceUsedSpace converts gRPC AnnounceUsedSpaceRequest message and passes it to internal Container service.
|
|
||||||
func (s *Server) AnnounceUsedSpace(ctx context.Context, req *containerGRPC.AnnounceUsedSpaceRequest) (*containerGRPC.AnnounceUsedSpaceResponse, error) {
|
|
||||||
announceReq := new(container.AnnounceUsedSpaceRequest)
|
|
||||||
if err := announceReq.FromGRPCMessage(req); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.srv.AnnounceUsedSpace(ctx, announceReq)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.ToGRPCMessage().(*containerGRPC.AnnounceUsedSpaceResponse), nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -78,15 +78,6 @@ func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ac *apeChecker) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) {
|
|
||||||
ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.AnnounceUsedSpace")
|
|
||||||
defer span.End()
|
|
||||||
|
|
||||||
// this method is not used, so not checked
|
|
||||||
|
|
||||||
return ac.next.AnnounceUsedSpace(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ac *apeChecker) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) {
|
func (ac *apeChecker) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) {
|
||||||
ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Delete")
|
ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Delete")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
@ -220,7 +211,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := ac.namespaceByOwner(req.GetBody().GetContainer().GetOwnerID())
|
namespace, err := ac.namespaceByKnownOwner(req.GetBody().GetContainer().GetOwnerID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get namespace error: %w", err)
|
return nil, fmt.Errorf("get namespace error: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -303,18 +294,6 @@ func (ac *apeChecker) getRoleWithoutContainerID(oID *refs.OwnerID, mh *session.R
|
||||||
return nativeschema.PropertyValueContainerRoleOthers, pk, nil
|
return nativeschema.PropertyValueContainerRoleOthers, pk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ac *apeChecker) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) {
|
|
||||||
ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.SetExtendedACL")
|
|
||||||
defer span.End()
|
|
||||||
|
|
||||||
if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetEACL().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(),
|
|
||||||
nativeschema.MethodSetContainerEACL); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ac.next.SetExtendedACL(ctx, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, containerID *refs.ContainerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, op string) error {
|
func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, containerID *refs.ContainerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, op string) error {
|
||||||
if vh == nil {
|
if vh == nil {
|
||||||
return errMissingVerificationHeader
|
return errMissingVerificationHeader
|
||||||
|
@ -629,6 +608,25 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) {
|
||||||
return namespace, nil
|
return namespace, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ac *apeChecker) namespaceByKnownOwner(owner *refs.OwnerID) (string, error) {
|
||||||
|
var ownerSDK user.ID
|
||||||
|
if owner == nil {
|
||||||
|
return "", errOwnerIDIsNotSet
|
||||||
|
}
|
||||||
|
if err := ownerSDK.ReadFromV2(*owner); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
addr, err := ownerSDK.ScriptHash()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
subject, err := ac.frostFSIDClient.GetSubject(addr)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("get subject error: %w", err)
|
||||||
|
}
|
||||||
|
return subject.Namespace, nil
|
||||||
|
}
|
||||||
|
|
||||||
// validateNamespace validates a namespace set in a container.
|
// validateNamespace validates a namespace set in a container.
|
||||||
// If frostfs-id contract stores a namespace N1 for an owner ID and a container within a request
|
// If frostfs-id contract stores a namespace N1 for an owner ID and a container within a request
|
||||||
// is set with namespace N2 (via Zone() property), then N2 is invalid and the request is denied.
|
// is set with namespace N2 (via Zone() property), then N2 is invalid and the request is denied.
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
|
@ -50,7 +49,6 @@ func TestAPE(t *testing.T) {
|
||||||
t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag)
|
t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag)
|
||||||
t.Run("deny get container by IP", testDenyGetContainerByIP)
|
t.Run("deny get container by IP", testDenyGetContainerByIP)
|
||||||
t.Run("deny get container by group id", testDenyGetContainerByGroupID)
|
t.Run("deny get container by group id", testDenyGetContainerByGroupID)
|
||||||
t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR)
|
|
||||||
t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken)
|
t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken)
|
||||||
t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken)
|
t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken)
|
||||||
t.Run("deny put container, read namespace from frostfsID", testDenyPutContainerReadNamespaceFromFrostfsID)
|
t.Run("deny put container, read namespace from frostfsID", testDenyPutContainerReadNamespaceFromFrostfsID)
|
||||||
|
@ -665,84 +663,6 @@ func testDenyGetContainerByGroupID(t *testing.T) {
|
||||||
require.ErrorAs(t, err, &errAccessDenied)
|
require.ErrorAs(t, err, &errAccessDenied)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDenySetContainerEACLForIR(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
srv := &srvStub{
|
|
||||||
calls: map[string]int{},
|
|
||||||
}
|
|
||||||
router := inmemory.NewInMemory()
|
|
||||||
contRdr := &containerStub{
|
|
||||||
c: map[cid.ID]*containercore.Container{},
|
|
||||||
}
|
|
||||||
ir := &irStub{
|
|
||||||
keys: [][]byte{},
|
|
||||||
}
|
|
||||||
nm := &netmapStub{}
|
|
||||||
frostfsIDSubjectReader := &frostfsidStub{
|
|
||||||
subjects: map[util.Uint160]*client.Subject{},
|
|
||||||
}
|
|
||||||
apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv)
|
|
||||||
|
|
||||||
contID := cidtest.ID()
|
|
||||||
testContainer := containertest.Container()
|
|
||||||
pp := netmap.PlacementPolicy{}
|
|
||||||
require.NoError(t, pp.DecodeString("REP 1"))
|
|
||||||
testContainer.SetPlacementPolicy(pp)
|
|
||||||
contRdr.c[contID] = &containercore.Container{Value: testContainer}
|
|
||||||
|
|
||||||
nm.currentEpoch = 100
|
|
||||||
nm.netmaps = map[uint64]*netmap.NetMap{}
|
|
||||||
var testNetmap netmap.NetMap
|
|
||||||
testNetmap.SetEpoch(nm.currentEpoch)
|
|
||||||
testNetmap.SetNodes([]netmap.NodeInfo{{}})
|
|
||||||
nm.netmaps[nm.currentEpoch] = &testNetmap
|
|
||||||
nm.netmaps[nm.currentEpoch-1] = &testNetmap
|
|
||||||
|
|
||||||
_, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{
|
|
||||||
Rules: []chain.Rule{
|
|
||||||
{
|
|
||||||
Status: chain.AccessDenied,
|
|
||||||
Actions: chain.Actions{
|
|
||||||
Names: []string{
|
|
||||||
nativeschema.MethodSetContainerEACL,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Resources: chain.Resources{
|
|
||||||
Names: []string{
|
|
||||||
fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Condition: []chain.Condition{
|
|
||||||
{
|
|
||||||
Kind: chain.KindRequest,
|
|
||||||
Key: nativeschema.PropertyKeyActorRole,
|
|
||||||
Value: nativeschema.PropertyValueContainerRoleIR,
|
|
||||||
Op: chain.CondStringEquals,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
req := &container.SetExtendedACLRequest{}
|
|
||||||
req.SetBody(&container.SetExtendedACLRequestBody{})
|
|
||||||
var refContID refs.ContainerID
|
|
||||||
contID.WriteToV2(&refContID)
|
|
||||||
req.GetBody().SetEACL(&acl.Table{})
|
|
||||||
req.GetBody().GetEACL().SetContainerID(&refContID)
|
|
||||||
|
|
||||||
pk, err := keys.NewPrivateKey()
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req))
|
|
||||||
ir.keys = append(ir.keys, pk.PublicKey().Bytes())
|
|
||||||
|
|
||||||
resp, err := apeSrv.SetExtendedACL(context.Background(), req)
|
|
||||||
require.Nil(t, resp)
|
|
||||||
var errAccessDenied *apistatus.ObjectAccessDenied
|
|
||||||
require.ErrorAs(t, err, &errAccessDenied)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDenyGetContainerEACLForIRSessionToken(t *testing.T) {
|
func testDenyGetContainerEACLForIRSessionToken(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
srv := &srvStub{
|
srv := &srvStub{
|
||||||
|
@ -845,17 +765,22 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) {
|
||||||
keys: [][]byte{},
|
keys: [][]byte{},
|
||||||
}
|
}
|
||||||
nm := &netmapStub{}
|
nm := &netmapStub{}
|
||||||
frostfsIDSubjectReader := &frostfsidStub{
|
|
||||||
subjects: map[util.Uint160]*client.Subject{},
|
|
||||||
}
|
|
||||||
apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv)
|
|
||||||
|
|
||||||
testContainer := containertest.Container()
|
testContainer := containertest.Container()
|
||||||
|
owner := testContainer.Owner()
|
||||||
|
ownerAddr, err := owner.ScriptHash()
|
||||||
|
require.NoError(t, err)
|
||||||
|
frostfsIDSubjectReader := &frostfsidStub{
|
||||||
|
subjects: map[util.Uint160]*client.Subject{
|
||||||
|
ownerAddr: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv)
|
||||||
|
|
||||||
nm.currentEpoch = 100
|
nm.currentEpoch = 100
|
||||||
nm.netmaps = map[uint64]*netmap.NetMap{}
|
nm.netmaps = map[uint64]*netmap.NetMap{}
|
||||||
|
|
||||||
_, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{
|
_, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{
|
||||||
Rules: []chain.Rule{
|
Rules: []chain.Rule{
|
||||||
{
|
{
|
||||||
Status: chain.AccessDenied,
|
Status: chain.AccessDenied,
|
||||||
|
@ -1229,11 +1154,6 @@ type srvStub struct {
|
||||||
calls map[string]int
|
calls map[string]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srvStub) AnnounceUsedSpace(context.Context, *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) {
|
|
||||||
s.calls["AnnounceUsedSpace"]++
|
|
||||||
return &container.AnnounceUsedSpaceResponse{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *srvStub) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) {
|
func (s *srvStub) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) {
|
||||||
s.calls["Delete"]++
|
s.calls["Delete"]++
|
||||||
return &container.DeleteResponse{}, nil
|
return &container.DeleteResponse{}, nil
|
||||||
|
@ -1259,11 +1179,6 @@ func (s *srvStub) Put(context.Context, *container.PutRequest) (*container.PutRes
|
||||||
return &container.PutResponse{}, nil
|
return &container.PutResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srvStub) SetExtendedACL(context.Context, *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) {
|
|
||||||
s.calls["SetExtendedACL"]++
|
|
||||||
return &container.SetExtendedACLResponse{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type irStub struct {
|
type irStub struct {
|
||||||
keys [][]byte
|
keys [][]byte
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||||
container_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
container_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
@ -29,24 +28,6 @@ func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Serv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnnounceUsedSpace implements Server.
|
|
||||||
func (a *auditService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) {
|
|
||||||
res, err := a.next.AnnounceUsedSpace(ctx, req)
|
|
||||||
if !a.enabled.Load() {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var ids []*refs.ContainerID
|
|
||||||
for _, v := range req.GetBody().GetAnnouncements() {
|
|
||||||
ids = append(ids, v.GetContainerID())
|
|
||||||
}
|
|
||||||
|
|
||||||
audit.LogRequest(a.log, container_grpc.ContainerService_AnnounceUsedSpace_FullMethodName, req,
|
|
||||||
audit.TargetFromRefs(ids, &cid.ID{}), err == nil)
|
|
||||||
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete implements Server.
|
// Delete implements Server.
|
||||||
func (a *auditService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) {
|
func (a *auditService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) {
|
||||||
res, err := a.next.Delete(ctx, req)
|
res, err := a.next.Delete(ctx, req)
|
||||||
|
@ -103,14 +84,3 @@ func (a *auditService) Put(ctx context.Context, req *container.PutRequest) (*con
|
||||||
audit.TargetFromRef(res.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
audit.TargetFromRef(res.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetExtendedACL implements Server.
|
|
||||||
func (a *auditService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) {
|
|
||||||
res, err := a.next.SetExtendedACL(ctx, req)
|
|
||||||
if !a.enabled.Load() {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
audit.LogRequest(a.log, container_grpc.ContainerService_SetExtendedACL_FullMethodName, req,
|
|
||||||
audit.TargetFromRef(req.GetBody().GetEACL().GetContainerID(), &cid.ID{}), err == nil)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ type ServiceExecutor interface {
|
||||||
Delete(context.Context, *session.Token, *container.DeleteRequestBody) (*container.DeleteResponseBody, error)
|
Delete(context.Context, *session.Token, *container.DeleteRequestBody) (*container.DeleteResponseBody, error)
|
||||||
Get(context.Context, *container.GetRequestBody) (*container.GetResponseBody, error)
|
Get(context.Context, *container.GetRequestBody) (*container.GetResponseBody, error)
|
||||||
List(context.Context, *container.ListRequestBody) (*container.ListResponseBody, error)
|
List(context.Context, *container.ListRequestBody) (*container.ListResponseBody, error)
|
||||||
SetExtendedACL(context.Context, *session.Token, *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error)
|
|
||||||
GetExtendedACL(context.Context, *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error)
|
GetExtendedACL(context.Context, *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,24 +95,6 @@ func (s *executorSvc) List(ctx context.Context, req *container.ListRequest) (*co
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *executorSvc) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) {
|
|
||||||
meta := req.GetMetaHeader()
|
|
||||||
for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() {
|
|
||||||
meta = origin
|
|
||||||
}
|
|
||||||
|
|
||||||
respBody, err := s.exec.SetExtendedACL(ctx, meta.GetSessionToken(), req.GetBody())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not execute SetEACL request: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := new(container.SetExtendedACLResponse)
|
|
||||||
resp.SetBody(respBody)
|
|
||||||
|
|
||||||
s.respSvc.SetMeta(resp)
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *executorSvc) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) {
|
func (s *executorSvc) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) {
|
||||||
respBody, err := s.exec.GetExtendedACL(ctx, req.GetBody())
|
respBody, err := s.exec.GetExtendedACL(ctx, req.GetBody())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,8 +13,6 @@ import (
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var errMissingUserID = errors.New("missing user ID")
|
var errMissingUserID = errors.New("missing user ID")
|
||||||
|
@ -204,10 +202,6 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *morphExecutor) SetExtendedACL(_ context.Context, _ *sessionV2.Token, _ *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method SetExtendedACL not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {
|
func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {
|
||||||
idV2 := body.GetContainerID()
|
idV2 := body.GetContainerID()
|
||||||
if idV2 == nil {
|
if idV2 == nil {
|
||||||
|
|
|
@ -12,7 +12,5 @@ type Server interface {
|
||||||
Get(context.Context, *container.GetRequest) (*container.GetResponse, error)
|
Get(context.Context, *container.GetRequest) (*container.GetResponse, error)
|
||||||
Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error)
|
Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error)
|
||||||
List(context.Context, *container.ListRequest) (*container.ListResponse, error)
|
List(context.Context, *container.ListRequest) (*container.ListResponse, error)
|
||||||
SetExtendedACL(context.Context, *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error)
|
|
||||||
GetExtendedACL(context.Context, *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error)
|
GetExtendedACL(context.Context, *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error)
|
||||||
AnnounceUsedSpace(context.Context, *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,15 +57,6 @@ func (s *signService) List(ctx context.Context, req *container.ListRequest) (*co
|
||||||
return resp, s.sigSvc.SignResponse(resp, err)
|
return resp, s.sigSvc.SignResponse(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *signService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) {
|
|
||||||
if err := s.sigSvc.VerifyRequest(req); err != nil {
|
|
||||||
resp := new(container.SetExtendedACLResponse)
|
|
||||||
return resp, s.sigSvc.SignResponse(resp, err)
|
|
||||||
}
|
|
||||||
resp, err := util.EnsureNonNilResponse(s.svc.SetExtendedACL(ctx, req))
|
|
||||||
return resp, s.sigSvc.SignResponse(resp, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) {
|
func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) {
|
||||||
if err := s.sigSvc.VerifyRequest(req); err != nil {
|
if err := s.sigSvc.VerifyRequest(req); err != nil {
|
||||||
resp := new(container.GetExtendedACLResponse)
|
resp := new(container.GetExtendedACLResponse)
|
||||||
|
@ -74,12 +65,3 @@ func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExte
|
||||||
resp, err := util.EnsureNonNilResponse(s.svc.GetExtendedACL(ctx, req))
|
resp, err := util.EnsureNonNilResponse(s.svc.GetExtendedACL(ctx, req))
|
||||||
return resp, s.sigSvc.SignResponse(resp, err)
|
return resp, s.sigSvc.SignResponse(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *signService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) {
|
|
||||||
if err := s.sigSvc.VerifyRequest(req); err != nil {
|
|
||||||
resp := new(container.AnnounceUsedSpaceResponse)
|
|
||||||
return resp, s.sigSvc.SignResponse(resp, err)
|
|
||||||
}
|
|
||||||
resp, err := util.EnsureNonNilResponse(s.svc.AnnounceUsedSpace(ctx, req))
|
|
||||||
return resp, s.sigSvc.SignResponse(resp, err)
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *request) assembleEC(ctx context.Context) {
|
func (r *request) assembleEC(ctx context.Context) {
|
||||||
if r.isRaw() && r.isLocal() {
|
if r.isRaw() {
|
||||||
r.log.Debug(logs.GetCanNotAssembleTheObject)
|
r.log.Debug(logs.GetCanNotAssembleTheObject)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func (r *request) assembleEC(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
r.prm.common = r.prm.common.WithLocalOnly(false)
|
r.prm.common = r.prm.common.WithLocalOnly(false)
|
||||||
assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.containerSource, r.log, r.headOnly(), r.isRaw(), r.traverserGenerator, r.curProcEpoch)
|
assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.containerSource, r.log, r.headOnly(), r.traverserGenerator, r.curProcEpoch)
|
||||||
|
|
||||||
r.log.Debug(logs.GetAssemblingECObject,
|
r.log.Debug(logs.GetAssemblingECObject,
|
||||||
zap.Uint64("range_offset", r.ctxRange().GetOffset()),
|
zap.Uint64("range_offset", r.ctxRange().GetOffset()),
|
||||||
|
|
|
@ -37,7 +37,6 @@ type assemblerec struct {
|
||||||
cs container.Source
|
cs container.Source
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
head bool
|
head bool
|
||||||
raw bool
|
|
||||||
traverserGenerator traverserGenerator
|
traverserGenerator traverserGenerator
|
||||||
epoch uint64
|
epoch uint64
|
||||||
}
|
}
|
||||||
|
@ -51,7 +50,6 @@ func newAssemblerEC(
|
||||||
cs container.Source,
|
cs container.Source,
|
||||||
log *logger.Logger,
|
log *logger.Logger,
|
||||||
head bool,
|
head bool,
|
||||||
raw bool,
|
|
||||||
tg traverserGenerator,
|
tg traverserGenerator,
|
||||||
epoch uint64,
|
epoch uint64,
|
||||||
) *assemblerec {
|
) *assemblerec {
|
||||||
|
@ -64,7 +62,6 @@ func newAssemblerEC(
|
||||||
cs: cs,
|
cs: cs,
|
||||||
log: log,
|
log: log,
|
||||||
head: head,
|
head: head,
|
||||||
raw: raw,
|
|
||||||
traverserGenerator: tg,
|
traverserGenerator: tg,
|
||||||
epoch: epoch,
|
epoch: epoch,
|
||||||
}
|
}
|
||||||
|
@ -74,9 +71,6 @@ func newAssemblerEC(
|
||||||
// It returns parent object.
|
// It returns parent object.
|
||||||
func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) {
|
func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) {
|
||||||
switch {
|
switch {
|
||||||
case a.raw:
|
|
||||||
err := a.reconstructRawError(ctx)
|
|
||||||
return nil, err
|
|
||||||
case a.head:
|
case a.head:
|
||||||
return a.reconstructHeader(ctx, writer)
|
return a.reconstructHeader(ctx, writer)
|
||||||
case a.rng != nil:
|
case a.rng != nil:
|
||||||
|
@ -149,56 +143,6 @@ func (a *assemblerec) reconstructObjectFromParts(ctx context.Context, headers bo
|
||||||
return c.Reconstruct(parts)
|
return c.Reconstruct(parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *assemblerec) reconstructRawError(ctx context.Context) error {
|
|
||||||
chunks := make(map[string]objectSDK.ECChunk)
|
|
||||||
var chunksGuard sync.Mutex
|
|
||||||
for _, ch := range a.ecInfo.localChunks {
|
|
||||||
chunks[string(ch.ID.GetValue())] = ch
|
|
||||||
}
|
|
||||||
|
|
||||||
objID := a.addr.Object()
|
|
||||||
trav, _, err := a.traverserGenerator.GenerateTraverser(a.addr.Container(), &objID, a.epoch)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
|
||||||
for {
|
|
||||||
batch := trav.Next()
|
|
||||||
if len(batch) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for _, node := range batch {
|
|
||||||
var info client.NodeInfo
|
|
||||||
client.NodeInfoFromNetmapElement(&info, node)
|
|
||||||
eg.Go(func() error {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, found := a.ecInfo.remoteChunks[string(info.PublicKey())]; found {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeChunks := a.tryGetChunkListFromNode(ctx, info)
|
|
||||||
|
|
||||||
chunksGuard.Lock()
|
|
||||||
defer chunksGuard.Unlock()
|
|
||||||
for _, ch := range nodeChunks {
|
|
||||||
chunks[string(ch.ID.GetValue())] = ch
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err = eg.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return createECInfoErr(chunks)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *assemblerec) retrieveParts(ctx context.Context, trav *placement.Traverser, cnr *container.Container) []*objectSDK.Object {
|
func (a *assemblerec) retrieveParts(ctx context.Context, trav *placement.Traverser, cnr *container.Container) []*objectSDK.Object {
|
||||||
dataCount := policy.ECDataCount(cnr.Value.PlacementPolicy())
|
dataCount := policy.ECDataCount(cnr.Value.PlacementPolicy())
|
||||||
parityCount := policy.ECParityCount(cnr.Value.PlacementPolicy())
|
parityCount := policy.ECParityCount(cnr.Value.PlacementPolicy())
|
||||||
|
@ -293,7 +237,7 @@ func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch object
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var addr oid.Address
|
var addr oid.Address
|
||||||
addr.SetContainer(addr.Container())
|
addr.SetContainer(a.addr.Container())
|
||||||
addr.SetObject(objID)
|
addr.SetObject(objID)
|
||||||
var object *objectSDK.Object
|
var object *objectSDK.Object
|
||||||
if a.head {
|
if a.head {
|
||||||
|
@ -359,11 +303,3 @@ func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node cli
|
||||||
}
|
}
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
|
|
||||||
func createECInfoErr(chunks map[string]objectSDK.ECChunk) *objectSDK.ECInfoError {
|
|
||||||
info := objectSDK.NewECInfo()
|
|
||||||
for _, ch := range chunks {
|
|
||||||
info.AddChunk(ch)
|
|
||||||
}
|
|
||||||
return objectSDK.NewECInfoError(info)
|
|
||||||
}
|
|
||||||
|
|
|
@ -111,6 +111,10 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) {
|
||||||
exec.log.Debug(logs.GetRequestedRangeIsOutOfObjectBounds)
|
exec.log.Debug(logs.GetRequestedRangeIsOutOfObjectBounds)
|
||||||
case statusEC:
|
case statusEC:
|
||||||
exec.log.Debug(logs.GetRequestedObjectIsEC)
|
exec.log.Debug(logs.GetRequestedObjectIsEC)
|
||||||
|
if exec.isRaw() && execCnr {
|
||||||
|
exec.executeOnContainer(ctx)
|
||||||
|
exec.analyzeStatus(ctx, false)
|
||||||
|
}
|
||||||
exec.assembleEC(ctx)
|
exec.assembleEC(ctx)
|
||||||
default:
|
default:
|
||||||
exec.log.Debug(logs.OperationFinishedWithError,
|
exec.log.Debug(logs.OperationFinishedWithError,
|
||||||
|
|
|
@ -35,8 +35,12 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool {
|
||||||
switch {
|
switch {
|
||||||
default:
|
default:
|
||||||
r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err))
|
r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err))
|
||||||
|
if r.status != statusEC {
|
||||||
|
// for raw requests, continue to collect other parts
|
||||||
r.status = statusUndefined
|
r.status = statusUndefined
|
||||||
r.err = new(apistatus.ObjectNotFound)
|
r.err = new(apistatus.ObjectNotFound)
|
||||||
|
}
|
||||||
|
return false
|
||||||
case err == nil:
|
case err == nil:
|
||||||
r.status = statusOK
|
r.status = statusOK
|
||||||
r.err = nil
|
r.err = nil
|
||||||
|
@ -48,22 +52,28 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool {
|
||||||
r.collectedObject = obj
|
r.collectedObject = obj
|
||||||
r.writeCollectedObject(ctx)
|
r.writeCollectedObject(ctx)
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
case errors.As(err, &errRemoved):
|
case errors.As(err, &errRemoved):
|
||||||
r.status = statusINHUMED
|
r.status = statusINHUMED
|
||||||
r.err = errRemoved
|
r.err = errRemoved
|
||||||
|
return true
|
||||||
case errors.As(err, &errOutOfRange):
|
case errors.As(err, &errOutOfRange):
|
||||||
r.status = statusOutOfRange
|
r.status = statusOutOfRange
|
||||||
r.err = errOutOfRange
|
r.err = errOutOfRange
|
||||||
|
return true
|
||||||
case errors.As(err, &errSplitInfo):
|
case errors.As(err, &errSplitInfo):
|
||||||
r.status = statusVIRTUAL
|
r.status = statusVIRTUAL
|
||||||
mergeSplitInfo(r.splitInfo(), errSplitInfo.SplitInfo())
|
mergeSplitInfo(r.splitInfo(), errSplitInfo.SplitInfo())
|
||||||
r.err = objectSDK.NewSplitInfoError(r.infoSplit)
|
r.err = objectSDK.NewSplitInfoError(r.infoSplit)
|
||||||
|
return true
|
||||||
case errors.As(err, &errECInfo):
|
case errors.As(err, &errECInfo):
|
||||||
r.status = statusEC
|
r.status = statusEC
|
||||||
r.err = r.infoEC.addRemote(string(info.PublicKey()), errECInfo.ECInfo())
|
r.err = r.infoEC.addRemote(string(info.PublicKey()), errECInfo.ECInfo())
|
||||||
|
if r.isRaw() {
|
||||||
|
return false // continue to collect all parts
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.status != statusUndefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *request) getRemote(ctx context.Context, rs remoteStorage, info client.NodeInfo) (*objectSDK.Object, error) {
|
func (r *request) getRemote(ctx context.Context, rs remoteStorage, info client.NodeInfo) (*objectSDK.Object, error) {
|
||||||
|
|
Loading…
Reference in a new issue