diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d0a26e8cd..2bcd98f60f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,19 @@ Changelog for NeoFS Node ### Removed +### Changed +- CLI `--timeout` flag configures whole execution timeout from now (#2124) +- CLI default timeout for commands with `--await` flag increased to 1m (#2124) + ### Updated ### Updating from v0.37.0 +CLI command timeouts (flag `--timeout`) now limit the total command execution +time and not single network operation. If any commands suddenly start to fail +on timeout, try increasing the value, for example, twice. Also note that the +execution of commands with the `--await` flag and without an explicitly +specified time period is now limited to 1 minute. This value can be changed with +`--timeout` flag. ## [0.37.0] - 2023-06-15 - Sogado diff --git a/cmd/neofs-cli/internal/client/client.go b/cmd/neofs-cli/internal/client/client.go index 5daf72a710..ad48d300c0 100644 --- a/cmd/neofs-cli/internal/client/client.go +++ b/cmd/neofs-cli/internal/client/client.go @@ -37,8 +37,8 @@ func (x BalanceOfRes) Balance() accounting.Decimal { // BalanceOf requests the current balance of a NeoFS user. // // Returns any error which prevented the operation from completing correctly in error return. -func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) { - res.cliRes, err = prm.cli.BalanceGet(context.Background(), prm.PrmBalanceGet) +func BalanceOf(ctx context.Context, prm BalanceOfPrm) (res BalanceOfRes, err error) { + res.cliRes, err = prm.cli.BalanceGet(ctx, prm.PrmBalanceGet) return } @@ -62,8 +62,8 @@ func (x ListContainersRes) IDList() []cid.ID { // ListContainers requests a list of NeoFS user's containers. // // Returns any error which prevented the operation from completing correctly in error return. -func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) { - res.cliRes, err = prm.cli.ContainerList(context.Background(), prm.PrmContainerList) +func ListContainers(ctx context.Context, prm ListContainersPrm) (res ListContainersRes, err error) { + res.cliRes, err = prm.cli.ContainerList(ctx, prm.PrmContainerList) return } @@ -92,8 +92,8 @@ func (x PutContainerRes) ID() cid.ID { // Success can be verified by reading by identifier. // // Returns any error which prevented the operation from completing correctly in error return. -func PutContainer(prm PutContainerPrm) (res PutContainerRes, err error) { - cliRes, err := prm.cli.ContainerPut(context.Background(), prm.PrmContainerPut) +func PutContainer(ctx context.Context, prm PutContainerPrm) (res PutContainerRes, err error) { + cliRes, err := prm.cli.ContainerPut(ctx, prm.PrmContainerPut) if err == nil { res.cnr = cliRes.ID() } @@ -125,20 +125,20 @@ func (x GetContainerRes) Container() containerSDK.Container { // GetContainer reads a container from NeoFS by ID. // // Returns any error which prevented the operation from completing correctly in error return. -func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) { - res.cliRes, err = prm.cli.ContainerGet(context.Background(), prm.cliPrm) +func GetContainer(ctx context.Context, prm GetContainerPrm) (res GetContainerRes, err error) { + res.cliRes, err = prm.cli.ContainerGet(ctx, prm.cliPrm) return } // IsACLExtendable checks if ACL of the container referenced by the given identifier // can be extended. Client connection MUST BE correctly established in advance. -func IsACLExtendable(c *client.Client, cnr cid.ID) (bool, error) { +func IsACLExtendable(ctx context.Context, c *client.Client, cnr cid.ID) (bool, error) { var prm GetContainerPrm prm.SetClient(c) prm.SetContainer(cnr) - res, err := GetContainer(prm) + res, err := GetContainer(ctx, prm) if err != nil { return false, fmt.Errorf("get container from the NeoFS: %w", err) } @@ -163,8 +163,8 @@ type DeleteContainerRes struct{} // Success can be verified by reading by identifier. // // Returns any error which prevented the operation from completing correctly in error return. -func DeleteContainer(prm DeleteContainerPrm) (res DeleteContainerRes, err error) { - _, err = prm.cli.ContainerDelete(context.Background(), prm.PrmContainerDelete) +func DeleteContainer(ctx context.Context, prm DeleteContainerPrm) (res DeleteContainerRes, err error) { + _, err = prm.cli.ContainerDelete(ctx, prm.PrmContainerDelete) return } @@ -188,8 +188,8 @@ func (x EACLRes) EACL() eacl.Table { // EACL reads eACL table from NeoFS by container ID. // // Returns any error which prevented the operation from completing correctly in error return. -func EACL(prm EACLPrm) (res EACLRes, err error) { - res.cliRes, err = prm.cli.ContainerEACL(context.Background(), prm.PrmContainerEACL) +func EACL(ctx context.Context, prm EACLPrm) (res EACLRes, err error) { + res.cliRes, err = prm.cli.ContainerEACL(ctx, prm.PrmContainerEACL) return } @@ -211,8 +211,8 @@ type SetEACLRes struct{} // Success can be verified by reading by container identifier. // // Returns any error which prevented the operation from completing correctly in error return. -func SetEACL(prm SetEACLPrm) (res SetEACLRes, err error) { - _, err = prm.cli.ContainerSetEACL(context.Background(), prm.PrmContainerSetEACL) +func SetEACL(ctx context.Context, prm SetEACLPrm) (res SetEACLRes, err error) { + _, err = prm.cli.ContainerSetEACL(ctx, prm.PrmContainerSetEACL) return } @@ -236,8 +236,8 @@ func (x NetworkInfoRes) NetworkInfo() netmap.NetworkInfo { // NetworkInfo reads information about the NeoFS network. // // Returns any error which prevented the operation from completing correctly in error return. -func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) { - res.cliRes, err = prm.cli.NetworkInfo(context.Background(), prm.PrmNetworkInfo) +func NetworkInfo(ctx context.Context, prm NetworkInfoPrm) (res NetworkInfoRes, err error) { + res.cliRes, err = prm.cli.NetworkInfo(ctx, prm.PrmNetworkInfo) return } @@ -266,8 +266,8 @@ func (x NodeInfoRes) LatestVersion() version.Version { // NodeInfo requests information about the remote server from NeoFS netmap. // // Returns any error which prevented the operation from completing correctly in error return. -func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) { - res.cliRes, err = prm.cli.EndpointInfo(context.Background(), prm.PrmEndpointInfo) +func NodeInfo(ctx context.Context, prm NodeInfoPrm) (res NodeInfoRes, err error) { + res.cliRes, err = prm.cli.EndpointInfo(ctx, prm.PrmEndpointInfo) return } @@ -290,8 +290,8 @@ func (x NetMapSnapshotRes) NetMap() netmap.NetMap { // NetMapSnapshot requests current network view of the remote server. // // Returns any error which prevented the operation from completing correctly in error return. -func NetMapSnapshot(prm NetMapSnapshotPrm) (res NetMapSnapshotRes, err error) { - res.cliRes, err = prm.cli.NetMapSnapshot(context.Background(), client.PrmNetMapSnapshot{}) +func NetMapSnapshot(ctx context.Context, prm NetMapSnapshotPrm) (res NetMapSnapshotRes, err error) { + res.cliRes, err = prm.cli.NetMapSnapshot(ctx, client.PrmNetMapSnapshot{}) return } @@ -319,8 +319,8 @@ func (x CreateSessionRes) SessionKey() []byte { // CreateSession opens a new unlimited session with the remote node. // // Returns any error which prevented the operation from completing correctly in error return. -func CreateSession(prm CreateSessionPrm) (res CreateSessionRes, err error) { - res.cliRes, err = prm.cli.SessionCreate(context.Background(), prm.PrmSessionCreate) +func CreateSession(ctx context.Context, prm CreateSessionPrm) (res CreateSessionRes, err error) { + res.cliRes, err = prm.cli.SessionCreate(ctx, prm.PrmSessionCreate) return } @@ -365,7 +365,7 @@ func (x PutObjectRes) ID() oid.ID { // PutObject saves the object in NeoFS network. // // Returns any error which prevented the operation from completing correctly in error return. -func PutObject(prm PutObjectPrm) (*PutObjectRes, error) { +func PutObject(ctx context.Context, prm PutObjectPrm) (*PutObjectRes, error) { var putPrm client.PrmObjectPutInit if prm.sessionToken != nil { @@ -382,7 +382,7 @@ func PutObject(prm PutObjectPrm) (*PutObjectRes, error) { putPrm.WithXHeaders(prm.xHeaders...) - wrt, err := prm.cli.ObjectPutInit(context.Background(), putPrm) + wrt, err := prm.cli.ObjectPutInit(ctx, putPrm) if err != nil { return nil, fmt.Errorf("init object writing: %w", err) } @@ -462,7 +462,7 @@ func (x DeleteObjectRes) Tombstone() oid.ID { // DeleteObject marks an object to be removed from NeoFS through tombstone placement. // // Returns any error which prevented the operation from completing correctly in error return. -func DeleteObject(prm DeleteObjectPrm) (*DeleteObjectRes, error) { +func DeleteObject(ctx context.Context, prm DeleteObjectPrm) (*DeleteObjectRes, error) { var delPrm client.PrmObjectDelete delPrm.FromContainer(prm.objAddr.Container()) delPrm.ByID(prm.objAddr.Object()) @@ -477,7 +477,7 @@ func DeleteObject(prm DeleteObjectPrm) (*DeleteObjectRes, error) { delPrm.WithXHeaders(prm.xHeaders...) - cliRes, err := prm.cli.ObjectDelete(context.Background(), delPrm) + cliRes, err := prm.cli.ObjectDelete(ctx, delPrm) if err != nil { return nil, fmt.Errorf("remove object via client: %w", err) } @@ -518,7 +518,7 @@ func (x GetObjectRes) Header() *object.Object { // // Returns any error which prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. -func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { +func GetObject(ctx context.Context, prm GetObjectPrm) (*GetObjectRes, error) { var getPrm client.PrmObjectGet getPrm.FromContainer(prm.objAddr.Container()) getPrm.ByID(prm.objAddr.Object()) @@ -541,7 +541,7 @@ func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { getPrm.WithXHeaders(prm.xHeaders...) - rdr, err := prm.cli.ObjectGetInit(context.Background(), getPrm) + rdr, err := prm.cli.ObjectGetInit(ctx, getPrm) if err != nil { return nil, fmt.Errorf("init object reading on client: %w", err) } @@ -594,7 +594,7 @@ func (x HeadObjectRes) Header() *object.Object { // // Returns any error which prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. -func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { +func HeadObject(ctx context.Context, prm HeadObjectPrm) (*HeadObjectRes, error) { var cliPrm client.PrmObjectHead cliPrm.FromContainer(prm.objAddr.Container()) cliPrm.ByID(prm.objAddr.Object()) @@ -617,7 +617,7 @@ func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { cliPrm.WithXHeaders(prm.xHeaders...) - res, err := prm.cli.ObjectHead(context.Background(), cliPrm) + res, err := prm.cli.ObjectHead(ctx, cliPrm) if err != nil { return nil, fmt.Errorf("read object header via client: %w", err) } @@ -659,7 +659,7 @@ func (x SearchObjectsRes) IDList() []oid.ID { // SearchObjects selects objects from the container which match the filters. // // Returns any error which prevented the operation from completing correctly in error return. -func SearchObjects(prm SearchObjectsPrm) (*SearchObjectsRes, error) { +func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes, error) { var cliPrm client.PrmObjectSearch cliPrm.InContainer(prm.cnrID) cliPrm.SetFilters(prm.filters) @@ -678,7 +678,7 @@ func SearchObjects(prm SearchObjectsPrm) (*SearchObjectsRes, error) { cliPrm.WithXHeaders(prm.xHeaders...) - rdr, err := prm.cli.ObjectSearchInit(context.Background(), cliPrm) + rdr, err := prm.cli.ObjectSearchInit(ctx, cliPrm) if err != nil { return nil, fmt.Errorf("init object search: %w", err) } @@ -749,7 +749,7 @@ func (x HashPayloadRangesRes) HashList() [][]byte { // // Returns any error which prevented the operation from completing correctly in error return. // Returns an error if number of received hashes differs with the number of requested ranges. -func HashPayloadRanges(prm HashPayloadRangesPrm) (*HashPayloadRangesRes, error) { +func HashPayloadRanges(ctx context.Context, prm HashPayloadRangesPrm) (*HashPayloadRangesRes, error) { var cliPrm client.PrmObjectHash cliPrm.FromContainer(prm.objAddr.Container()) cliPrm.ByID(prm.objAddr.Object()) @@ -783,7 +783,7 @@ func HashPayloadRanges(prm HashPayloadRangesPrm) (*HashPayloadRangesRes, error) cliPrm.WithXHeaders(prm.xHeaders...) - res, err := prm.cli.ObjectHash(context.Background(), cliPrm) + res, err := prm.cli.ObjectHash(ctx, cliPrm) if err != nil { return nil, fmt.Errorf("read payload hashes via client: %w", err) } @@ -817,7 +817,7 @@ type PayloadRangeRes struct{} // // Returns any error which prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. -func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { +func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, error) { var cliPrm client.PrmObjectRange cliPrm.FromContainer(prm.objAddr.Container()) cliPrm.ByID(prm.objAddr.Object()) @@ -843,7 +843,7 @@ func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { cliPrm.WithXHeaders(prm.xHeaders...) - rdr, err := prm.cli.ObjectRangeInit(context.Background(), cliPrm) + rdr, err := prm.cli.ObjectRangeInit(ctx, cliPrm) if err != nil { return nil, fmt.Errorf("init payload reading: %w", err) } @@ -877,12 +877,12 @@ type SyncContainerRes struct{} // Interrupts on any writer error. // // Panics if a container passed as a parameter is nil. -func SyncContainerSettings(prm SyncContainerPrm) (*SyncContainerRes, error) { +func SyncContainerSettings(ctx context.Context, prm SyncContainerPrm) (*SyncContainerRes, error) { if prm.c == nil { panic("sync container settings with the network: nil container") } - err := client.SyncContainerWithNetwork(context.Background(), prm.c, prm.cli) + err := client.SyncContainerWithNetwork(ctx, prm.c, prm.cli) if err != nil { return nil, err } diff --git a/cmd/neofs-cli/internal/client/sdk.go b/cmd/neofs-cli/internal/client/sdk.go index a2399fd27a..0258d48141 100644 --- a/cmd/neofs-cli/internal/client/sdk.go +++ b/cmd/neofs-cli/internal/client/sdk.go @@ -7,9 +7,9 @@ import ( "crypto/rand" "errors" "fmt" + "time" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" - "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-sdk-go/client" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" @@ -21,22 +21,22 @@ var errInvalidEndpoint = errors.New("provided RPC endpoint is incorrect") // GetSDKClientByFlag returns default neofs-sdk-go client using the specified flag for the address. // On error, outputs to stderr of cmd and exits with non-zero code. -func GetSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) *client.Client { - cli, err := getSDKClientByFlag(cmd, key, endpointFlag) +func GetSDKClientByFlag(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) *client.Client { + cli, err := getSDKClientByFlag(ctx, cmd, key, endpointFlag) if err != nil { common.ExitOnErr(cmd, "can't create API client: %w", err) } return cli } -func getSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) (*client.Client, error) { +func getSDKClientByFlag(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) (*client.Client, error) { var addr network.Address err := addr.FromString(viper.GetString(endpointFlag)) if err != nil { return nil, fmt.Errorf("%v: %w", errInvalidEndpoint, err) } - return GetSDKClient(context.TODO(), cmd, key, addr) + return GetSDKClient(ctx, cmd, key, addr) } // GetSDKClient returns default neofs-sdk-go client. @@ -51,14 +51,16 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey prmInit.ResolveNeoFSFailures() prmDial.SetServerURI(addr.URIAddr()) prmDial.SetContext(ctx) - if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 { - // In CLI we can only set a timeout for the whole operation. - // By also setting stream timeout we ensure that no operation hands - // for too long. - prmDial.SetTimeout(timeout) - prmDial.SetStreamTimeout(timeout) - - common.PrintVerbose(cmd, "Set request timeout to %s.", timeout) + + deadline, ok := ctx.Deadline() + if ok { + if timeout := time.Until(deadline); timeout > 0 { + // In CLI we can only set a timeout for the whole operation. + // By also setting stream timeout we ensure that no operation hands + // for too long. + prmDial.SetTimeout(timeout) + prmDial.SetStreamTimeout(timeout) + } } c.Init(prmInit) diff --git a/cmd/neofs-cli/internal/commonflags/flags.go b/cmd/neofs-cli/internal/commonflags/flags.go index 7ed0e7d28e..c1e7d75c7e 100644 --- a/cmd/neofs-cli/internal/commonflags/flags.go +++ b/cmd/neofs-cli/internal/commonflags/flags.go @@ -1,6 +1,7 @@ package commonflags import ( + "context" "time" "github.com/spf13/cobra" @@ -82,3 +83,35 @@ func Bind(cmd *cobra.Command) { _ = viper.BindPFlag(RPC, ff.Lookup(RPC)) _ = viper.BindPFlag(Timeout, ff.Lookup(Timeout)) } + +// GetCommandContextWithAwait works like GetCommandContext but uses specified +// await timeout if 'timeout' flag is omitted and given boolean await flag is +// set. +func GetCommandContextWithAwait(cmd *cobra.Command, awaitFlag string, awaitTimeout time.Duration) (context.Context, context.CancelFunc) { + if !viper.IsSet(Timeout) { + if await, _ := cmd.Flags().GetBool(awaitFlag); await { + return getCommandContext(cmd, awaitTimeout) + } + } + + return GetCommandContext(cmd) +} + +// GetCommandContext returns cmd context with timeout specified in 'timeout' flag +// if the flag is set. +func GetCommandContext(cmd *cobra.Command) (context.Context, context.CancelFunc) { + return getCommandContext(cmd, viper.GetDuration(Timeout)) +} + +func getCommandContext(cmd *cobra.Command, timeout time.Duration) (context.Context, context.CancelFunc) { + parentCtx := cmd.Context() + if parentCtx == nil { + parentCtx = context.Background() + } + + if timeout <= 0 { + return parentCtx, func() {} + } + + return context.WithTimeout(parentCtx, timeout) +} diff --git a/cmd/neofs-cli/modules/accounting/balance.go b/cmd/neofs-cli/modules/accounting/balance.go index ffccafc6a7..20bd6b0d61 100644 --- a/cmd/neofs-cli/modules/accounting/balance.go +++ b/cmd/neofs-cli/modules/accounting/balance.go @@ -1,6 +1,7 @@ package accounting import ( + "context" "math/big" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" @@ -25,6 +26,8 @@ var accountingBalanceCmd = &cobra.Command{ Short: "Get internal balance of NeoFS account", Long: `Get internal balance of NeoFS account`, Run: func(cmd *cobra.Command, args []string) { + ctx := context.Background() + var idUser user.ID pk := key.GetOrGenerate(cmd) @@ -37,13 +40,13 @@ var accountingBalanceCmd = &cobra.Command{ common.ExitOnErr(cmd, "can't decode owner ID wallet address: %w", idUser.DecodeString(balanceOwner)) } - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.BalanceOfPrm prm.SetClient(cli) prm.SetAccount(idUser) - res, err := internalclient.BalanceOf(prm) + res, err := internalclient.BalanceOf(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) // print to stdout diff --git a/cmd/neofs-cli/modules/container/create.go b/cmd/neofs-cli/modules/container/create.go index feb17a2ff0..a3eea1d0b5 100644 --- a/cmd/neofs-cli/modules/container/create.go +++ b/cmd/neofs-cli/modules/container/create.go @@ -38,17 +38,20 @@ var createContainerCmd = &cobra.Command{ Long: `Create new container and register it in the NeoFS. It will be stored in sidechain when inner ring will accepts it.`, Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := getAwaitContext(cmd) + defer cancel() + placementPolicy, err := parseContainerPolicy(cmd, containerPolicy) common.ExitOnErr(cmd, "", err) key := key.Get(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, key, commonflags.RPC) if !force { var prm internalclient.NetMapSnapshotPrm prm.SetClient(cli) - resmap, err := internalclient.NetMapSnapshot(prm) + resmap, err := internalclient.NetMapSnapshot(ctx, prm) common.ExitOnErr(cmd, "unable to get netmap snapshot to validate container placement, "+ "use --force option to skip this check: %w", err) @@ -106,7 +109,7 @@ It will be stored in sidechain when inner ring will accepts it.`, syncContainerPrm.SetClient(cli) syncContainerPrm.SetContainer(&cnr) - _, err = internalclient.SyncContainerSettings(syncContainerPrm) + _, err = internalclient.SyncContainerSettings(ctx, syncContainerPrm) common.ExitOnErr(cmd, "syncing container's settings rpc error: %w", err) var putPrm internalclient.PutContainerPrm @@ -117,11 +120,12 @@ It will be stored in sidechain when inner ring will accepts it.`, putPrm.WithinSession(*tok) } - res, err := internalclient.PutContainer(putPrm) + res, err := internalclient.PutContainer(ctx, putPrm) common.ExitOnErr(cmd, "put container rpc error: %w", err) id := res.ID() + cmd.Println("container creation request accepted for processing (the operation may not be completed yet)") cmd.Println("container ID:", id) if containerAwait { @@ -131,17 +135,24 @@ It will be stored in sidechain when inner ring will accepts it.`, getPrm.SetClient(cli) getPrm.SetContainer(id) - for i := 0; i < awaitTimeout; i++ { - time.Sleep(1 * time.Second) + const waitInterval = time.Second + + t := time.NewTimer(waitInterval) + defer t.Stop() - _, err := internalclient.GetContainer(getPrm) + for ; ; t.Reset(waitInterval) { + select { + case <-ctx.Done(): + common.ExitOnErr(cmd, "", errCreateTimeout) + case <-t.C: + } + + _, err := internalclient.GetContainer(ctx, getPrm) if err == nil { cmd.Println("container has been persisted on sidechain") return } } - - common.ExitOnErr(cmd, "", errCreateTimeout) } }, } @@ -160,7 +171,8 @@ func initContainerCreateCmd() { )) flags.StringVarP(&containerPolicy, "policy", "p", "", "QL-encoded or JSON-encoded placement policy or path to file with it") flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2") - flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted") + flags.BoolVar(&containerAwait, "await", false, fmt.Sprintf("Block execution until container is persisted. "+ + "Increases default execution timeout to %.0fs", awaitTimeout.Seconds())) // simple %s notation prints 1m0s https://github.com/golang/go/issues/39064 flags.StringVar(&containerName, "name", "", "Container name attribute") flags.BoolVar(&containerNoTimestamp, "disable-timestamp", false, "Disable timestamp container attribute") flags.StringVar(&containerSubnet, "subnet", "", "String representation of container subnetwork") diff --git a/cmd/neofs-cli/modules/container/delete.go b/cmd/neofs-cli/modules/container/delete.go index 4096ede503..1e05737193 100644 --- a/cmd/neofs-cli/modules/container/delete.go +++ b/cmd/neofs-cli/modules/container/delete.go @@ -20,12 +20,15 @@ var deleteContainerCmd = &cobra.Command{ Long: `Delete existing container. Only owner of the container has a permission to remove container.`, Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := getAwaitContext(cmd) + defer cancel() + id := parseContainerID(cmd) tok := getSession(cmd) pk := key.Get(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) if force, _ := cmd.Flags().GetBool(commonflags.ForceFlag); !force { common.PrintVerbose(cmd, "Reading the container to check ownership...") @@ -34,7 +37,7 @@ Only owner of the container has a permission to remove container.`, getPrm.SetClient(cli) getPrm.SetContainer(id) - resGet, err := internalclient.GetContainer(getPrm) + resGet, err := internalclient.GetContainer(ctx, getPrm) common.ExitOnErr(cmd, "can't get the container: %w", err) owner := resGet.Container().Owner() @@ -73,7 +76,7 @@ Only owner of the container has a permission to remove container.`, common.PrintVerbose(cmd, "Searching for LOCK objects...") - res, err := internalclient.SearchObjects(searchPrm) + res, err := internalclient.SearchObjects(ctx, searchPrm) common.ExitOnErr(cmd, "can't search for LOCK objects: %w", err) if len(res.IDList()) != 0 { @@ -92,10 +95,10 @@ Only owner of the container has a permission to remove container.`, delPrm.WithinSession(*tok) } - _, err := internalclient.DeleteContainer(delPrm) + _, err := internalclient.DeleteContainer(ctx, delPrm) common.ExitOnErr(cmd, "rpc error: %w", err) - cmd.Println("container delete method invoked") + cmd.Println("container removal request accepted for processing (the operation may not be completed yet)") if containerAwait { cmd.Println("awaiting...") @@ -104,17 +107,24 @@ Only owner of the container has a permission to remove container.`, getPrm.SetClient(cli) getPrm.SetContainer(id) - for i := 0; i < awaitTimeout; i++ { - time.Sleep(1 * time.Second) + const waitInterval = time.Second + + t := time.NewTimer(waitInterval) + defer t.Stop() - _, err := internalclient.GetContainer(getPrm) + for ; ; t.Reset(waitInterval) { + select { + case <-ctx.Done(): + common.ExitOnErr(cmd, "", errDeleteTimeout) + case <-t.C: + } + + _, err := internalclient.GetContainer(ctx, getPrm) if err != nil { cmd.Println("container has been removed:", containerID) return } } - - common.ExitOnErr(cmd, "", errDeleteTimeout) } }, } @@ -127,6 +137,7 @@ func initContainerDeleteCmd() { flags.StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage) - flags.BoolVar(&containerAwait, "await", false, "Block execution until container is removed") + flags.BoolVar(&containerAwait, "await", false, fmt.Sprintf("Block execution until container is removed. "+ + "Increases default execution timeout to %.0fs", awaitTimeout.Seconds())) // simple %s notation prints 1m0s https://github.com/golang/go/issues/39064 flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Skip validation checks (ownership, presence of LOCK objects)") } diff --git a/cmd/neofs-cli/modules/container/get.go b/cmd/neofs-cli/modules/container/get.go index 1085dc4145..9ea081844c 100644 --- a/cmd/neofs-cli/modules/container/get.go +++ b/cmd/neofs-cli/modules/container/get.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/ecdsa" "os" @@ -32,7 +33,10 @@ var getContainerInfoCmd = &cobra.Command{ Short: "Get container field info", Long: `Get container field info`, Run: func(cmd *cobra.Command, args []string) { - cnr, _ := getContainer(cmd) + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + + cnr, _ := getContainer(ctx, cmd) prettyPrintContainer(cmd, cnr, containerJSON) @@ -132,7 +136,7 @@ func prettyPrintBasicACL(cmd *cobra.Command, basicACL acl.Basic) { util.PrettyPrintTableBACL(cmd, &basicACL) } -func getContainer(cmd *cobra.Command) (container.Container, *ecdsa.PrivateKey) { +func getContainer(ctx context.Context, cmd *cobra.Command) (container.Container, *ecdsa.PrivateKey) { var cnr container.Container var pk *ecdsa.PrivateKey if containerPathFrom != "" { @@ -144,13 +148,13 @@ func getContainer(cmd *cobra.Command) (container.Container, *ecdsa.PrivateKey) { } else { id := parseContainerID(cmd) pk = key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.GetContainerPrm prm.SetClient(cli) prm.SetContainer(id) - res, err := internalclient.GetContainer(prm) + res, err := internalclient.GetContainer(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) cnr = res.Container() diff --git a/cmd/neofs-cli/modules/container/get_eacl.go b/cmd/neofs-cli/modules/container/get_eacl.go index 482977b17f..e3c4d19473 100644 --- a/cmd/neofs-cli/modules/container/get_eacl.go +++ b/cmd/neofs-cli/modules/container/get_eacl.go @@ -15,15 +15,18 @@ var getExtendedACLCmd = &cobra.Command{ Short: "Get extended ACL table of container", Long: `Get extended ACL table of container`, Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + id := parseContainerID(cmd) pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var eaclPrm internalclient.EACLPrm eaclPrm.SetClient(cli) eaclPrm.SetContainer(id) - res, err := internalclient.EACL(eaclPrm) + res, err := internalclient.EACL(ctx, eaclPrm) common.ExitOnErr(cmd, "rpc error: %w", err) eaclTable := res.EACL() diff --git a/cmd/neofs-cli/modules/container/list.go b/cmd/neofs-cli/modules/container/list.go index d3d4d61e72..5cd55c081e 100644 --- a/cmd/neofs-cli/modules/container/list.go +++ b/cmd/neofs-cli/modules/container/list.go @@ -30,6 +30,9 @@ var listContainersCmd = &cobra.Command{ Short: "List all created containers", Long: "List all created containers", Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var idUser user.ID key := key.GetOrGenerate(cmd) @@ -42,13 +45,13 @@ var listContainersCmd = &cobra.Command{ common.ExitOnErr(cmd, "invalid user ID: %w", err) } - cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, key, commonflags.RPC) var prm internalclient.ListContainersPrm prm.SetClient(cli) prm.SetAccount(idUser) - res, err := internalclient.ListContainers(prm) + res, err := internalclient.ListContainers(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) var prmGet internalclient.GetContainerPrm @@ -61,7 +64,7 @@ var listContainersCmd = &cobra.Command{ if flagVarListPrintAttr { prmGet.SetContainer(list[i]) - res, err := internalclient.GetContainer(prmGet) + res, err := internalclient.GetContainer(ctx, prmGet) if err == nil { res.Container().IterateAttributes(func(key, val string) { if !strings.HasPrefix(key, container.SysAttributePrefix) { diff --git a/cmd/neofs-cli/modules/container/list_objects.go b/cmd/neofs-cli/modules/container/list_objects.go index 74c1f955f8..7dd0683208 100644 --- a/cmd/neofs-cli/modules/container/list_objects.go +++ b/cmd/neofs-cli/modules/container/list_objects.go @@ -29,12 +29,15 @@ var listContainerObjectsCmd = &cobra.Command{ Short: "List existing objects in container", Long: `List existing objects in container`, Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + id := parseContainerID(cmd) filters := new(object.SearchFilters) filters.AddRootFilter() // search only user created objects - cli := internalclient.GetSDKClientByFlag(cmd, key.GetOrGenerate(cmd), commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, key.GetOrGenerate(cmd), commonflags.RPC) var prmSearch internalclient.SearchObjectsPrm var prmHead internalclient.HeadObjectPrm @@ -51,7 +54,7 @@ var listContainerObjectsCmd = &cobra.Command{ prmSearch.SetContainerID(id) prmSearch.SetFilters(*filters) - res, err := internalclient.SearchObjects(prmSearch) + res, err := internalclient.SearchObjects(ctx, prmSearch) common.ExitOnErr(cmd, "rpc error: %w", err) objectIDs := res.IDList() @@ -65,7 +68,7 @@ var listContainerObjectsCmd = &cobra.Command{ addr.SetObject(objectIDs[i]) prmHead.SetAddress(addr) - resHead, err := internalclient.HeadObject(prmHead) + resHead, err := internalclient.HeadObject(ctx, prmHead) if err == nil { attrs := resHead.Header().Attributes() for i := range attrs { diff --git a/cmd/neofs-cli/modules/container/nodes.go b/cmd/neofs-cli/modules/container/nodes.go index 5df5e934cd..08c3b4232b 100644 --- a/cmd/neofs-cli/modules/container/nodes.go +++ b/cmd/neofs-cli/modules/container/nodes.go @@ -18,18 +18,21 @@ var containerNodesCmd = &cobra.Command{ Short: "Show nodes for container", Long: "Show nodes taking part in a container at the current epoch.", Run: func(cmd *cobra.Command, args []string) { - var cnr, pkey = getContainer(cmd) + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + + var cnr, pkey = getContainer(ctx, cmd) if pkey == nil { pkey = key.GetOrGenerate(cmd) } - cli := internalclient.GetSDKClientByFlag(cmd, pkey, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pkey, commonflags.RPC) var prm internalclient.NetMapSnapshotPrm prm.SetClient(cli) - resmap, err := internalclient.NetMapSnapshot(prm) + resmap, err := internalclient.NetMapSnapshot(ctx, prm) common.ExitOnErr(cmd, "unable to get netmap snapshot", err) var id cid.ID diff --git a/cmd/neofs-cli/modules/container/set_eacl.go b/cmd/neofs-cli/modules/container/set_eacl.go index fb5f39e695..446ce39f97 100644 --- a/cmd/neofs-cli/modules/container/set_eacl.go +++ b/cmd/neofs-cli/modules/container/set_eacl.go @@ -3,6 +3,7 @@ package container import ( "bytes" "errors" + "fmt" "time" internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" @@ -24,6 +25,9 @@ var setExtendedACLCmd = &cobra.Command{ 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, args []string) { + ctx, cancel := getAwaitContext(cmd) + defer cancel() + id := parseContainerID(cmd) eaclTable := common.ReadEACL(cmd, flagVarsSetEACL.srcPath) @@ -32,12 +36,12 @@ Container ID in EACL table will be substituted with ID from the CLI.`, eaclTable.SetCID(id) pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) if !flagVarsSetEACL.noPreCheck { cmd.Println("Checking the ability to modify access rights in the container...") - extendable, err := internalclient.IsACLExtendable(cli, id) + extendable, err := internalclient.IsACLExtendable(ctx, cli, id) common.ExitOnErr(cmd, "Extensibility check failure: %w", err) if !extendable { @@ -55,9 +59,11 @@ Container ID in EACL table will be substituted with ID from the CLI.`, setEACLPrm.WithinSession(*tok) } - _, err := internalclient.SetEACL(setEACLPrm) + _, err := internalclient.SetEACL(ctx, setEACLPrm) common.ExitOnErr(cmd, "rpc error: %w", err) + cmd.Println("eACL modification request accepted for processing (the operation may not be completed yet)") + if containerAwait { exp, err := eaclTable.Marshal() common.ExitOnErr(cmd, "broken EACL table: %w", err) @@ -68,10 +74,19 @@ Container ID in EACL table will be substituted with ID from the CLI.`, getEACLPrm.SetClient(cli) getEACLPrm.SetContainer(id) - for i := 0; i < awaitTimeout; i++ { - time.Sleep(1 * time.Second) + const waitInterval = time.Second + + t := time.NewTimer(waitInterval) + defer t.Stop() + + for ; ; t.Reset(waitInterval) { + select { + case <-ctx.Done(): + common.ExitOnErr(cmd, "", errSetEACLTimeout) + case <-t.C: + } - res, err := internalclient.EACL(getEACLPrm) + res, err := internalclient.EACL(ctx, getEACLPrm) if err == nil { // compare binary values because EACL could have been set already table := res.EACL() @@ -87,7 +102,6 @@ Container ID in EACL table will be substituted with ID from the CLI.`, } } - common.ExitOnErr(cmd, "", errSetEACLTimeout) } }, } @@ -98,6 +112,7 @@ func initContainerSetEACLCmd() { 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(&containerAwait, "await", false, fmt.Sprintf("block execution until EACL is persisted. "+ + "Increases default execution timeout to %.0fs", awaitTimeout.Seconds())) // simple %s notation prints 1m0s https://github.com/golang/go/issues/39064 flags.BoolVar(&flagVarsSetEACL.noPreCheck, "no-precheck", false, "do not pre-check the extensibility of the container ACL") } diff --git a/cmd/neofs-cli/modules/container/util.go b/cmd/neofs-cli/modules/container/util.go index 97d5bb5f3b..fcbb8d3849 100644 --- a/cmd/neofs-cli/modules/container/util.go +++ b/cmd/neofs-cli/modules/container/util.go @@ -1,7 +1,9 @@ package container import ( + "context" "errors" + "time" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" @@ -13,13 +15,13 @@ import ( const ( attributeDelimiter = "=" - awaitTimeout = 120 // in seconds + awaitTimeout = time.Minute ) var ( - errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain") - errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain") - errSetEACLTimeout = errors.New("timeout: EACL has not been persisted on sidechain") + errCreateTimeout = errors.New("container creation was requested, but timeout has happened while waiting for the outcome") + errDeleteTimeout = errors.New("container removal was requested, but timeout has happened while waiting for the outcome") + errSetEACLTimeout = errors.New("eACL modification was requested, but timeout has happened while waiting for the outcome") ) func parseContainerID(cmd *cobra.Command) cid.ID { @@ -55,3 +57,7 @@ func getSession(cmd *cobra.Command) *session.Container { return &res } + +func getAwaitContext(cmd *cobra.Command) (context.Context, context.CancelFunc) { + return commonflags.GetCommandContextWithAwait(cmd, "await", awaitTimeout) +} diff --git a/cmd/neofs-cli/modules/control/drop_objects.go b/cmd/neofs-cli/modules/control/drop_objects.go index 61d58d50b4..b91c56d3bd 100644 --- a/cmd/neofs-cli/modules/control/drop_objects.go +++ b/cmd/neofs-cli/modules/control/drop_objects.go @@ -3,6 +3,7 @@ package control import ( rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/spf13/cobra" @@ -15,6 +16,9 @@ var dropObjectsCmd = &cobra.Command{ Short: "Drop objects from the node's local storage", Long: "Drop objects from the node's local storage", Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) dropObjectsList, _ := cmd.Flags().GetStringSlice(dropObjectsFlag) @@ -32,7 +36,7 @@ var dropObjectsCmd = &cobra.Command{ signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.DropObjectsResponse var err error diff --git a/cmd/neofs-cli/modules/control/evacuate_shard.go b/cmd/neofs-cli/modules/control/evacuate_shard.go index dd82cefd42..974f961421 100644 --- a/cmd/neofs-cli/modules/control/evacuate_shard.go +++ b/cmd/neofs-cli/modules/control/evacuate_shard.go @@ -3,6 +3,7 @@ package control import ( "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/spf13/cobra" @@ -16,6 +17,9 @@ var evacuateShardCmd = &cobra.Command{ } func evacuateShard(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) req := &control.EvacuateShardRequest{Body: new(control.EvacuateShardRequest_Body)} @@ -24,7 +28,7 @@ func evacuateShard(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.EvacuateShardResponse var err error diff --git a/cmd/neofs-cli/modules/control/flush_cache.go b/cmd/neofs-cli/modules/control/flush_cache.go index 31ef9c9783..73aeeb6f1a 100644 --- a/cmd/neofs-cli/modules/control/flush_cache.go +++ b/cmd/neofs-cli/modules/control/flush_cache.go @@ -3,6 +3,7 @@ package control import ( "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/spf13/cobra" @@ -16,6 +17,9 @@ var flushCacheCmd = &cobra.Command{ } func flushCache(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) req := &control.FlushCacheRequest{Body: new(control.FlushCacheRequest_Body)} @@ -23,7 +27,7 @@ func flushCache(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.FlushCacheResponse var err error diff --git a/cmd/neofs-cli/modules/control/healthcheck.go b/cmd/neofs-cli/modules/control/healthcheck.go index 7d5f50b8fa..be2fa8f2bc 100644 --- a/cmd/neofs-cli/modules/control/healthcheck.go +++ b/cmd/neofs-cli/modules/control/healthcheck.go @@ -5,6 +5,7 @@ import ( rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" ircontrol "github.com/nspcc-dev/neofs-node/pkg/services/control/ir" @@ -32,9 +33,12 @@ func initControlHealthCheckCmd() { } func healthCheck(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) if isIR, _ := cmd.Flags().GetBool(healthcheckIRFlag); isIR { healthCheckIR(cmd, pk, cli) diff --git a/cmd/neofs-cli/modules/control/set_netmap_status.go b/cmd/neofs-cli/modules/control/set_netmap_status.go index 2781543223..61eba58ef2 100644 --- a/cmd/neofs-cli/modules/control/set_netmap_status.go +++ b/cmd/neofs-cli/modules/control/set_netmap_status.go @@ -45,6 +45,9 @@ func initControlSetNetmapStatusCmd() { } func setNetmapStatus(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) body := new(control.SetNetmapStatusRequest_Body) force, _ := cmd.Flags().GetBool(commonflags.ForceFlag) @@ -78,7 +81,7 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.SetNetmapStatusResponse var err error diff --git a/cmd/neofs-cli/modules/control/shards_dump.go b/cmd/neofs-cli/modules/control/shards_dump.go index 4b04a323da..4c32a1fff9 100644 --- a/cmd/neofs-cli/modules/control/shards_dump.go +++ b/cmd/neofs-cli/modules/control/shards_dump.go @@ -3,6 +3,7 @@ package control import ( "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/spf13/cobra" @@ -21,6 +22,9 @@ var dumpShardCmd = &cobra.Command{ } func dumpShard(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) body := new(control.DumpShardRequest_Body) @@ -37,7 +41,7 @@ func dumpShard(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.DumpShardResponse var err error diff --git a/cmd/neofs-cli/modules/control/shards_list.go b/cmd/neofs-cli/modules/control/shards_list.go index d8711d69a2..af5473fa94 100644 --- a/cmd/neofs-cli/modules/control/shards_list.go +++ b/cmd/neofs-cli/modules/control/shards_list.go @@ -30,6 +30,9 @@ func initControlShardsListCmd() { } func listShards(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) req := new(control.ListShardsRequest) @@ -37,7 +40,7 @@ func listShards(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.ListShardsResponse var err error diff --git a/cmd/neofs-cli/modules/control/shards_restore.go b/cmd/neofs-cli/modules/control/shards_restore.go index b61ccee97a..ff2870f706 100644 --- a/cmd/neofs-cli/modules/control/shards_restore.go +++ b/cmd/neofs-cli/modules/control/shards_restore.go @@ -3,6 +3,7 @@ package control import ( "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/spf13/cobra" @@ -21,6 +22,9 @@ var restoreShardCmd = &cobra.Command{ } func restoreShard(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) body := new(control.RestoreShardRequest_Body) @@ -37,7 +41,7 @@ func restoreShard(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.RestoreShardResponse var err error diff --git a/cmd/neofs-cli/modules/control/shards_set_mode.go b/cmd/neofs-cli/modules/control/shards_set_mode.go index 0b63ca30ba..951bfc6249 100644 --- a/cmd/neofs-cli/modules/control/shards_set_mode.go +++ b/cmd/neofs-cli/modules/control/shards_set_mode.go @@ -7,6 +7,7 @@ import ( "github.com/mr-tron/base58" rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/spf13/cobra" @@ -99,6 +100,9 @@ func initControlSetShardModeCmd() { } func setShardMode(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) strMode, _ := cmd.Flags().GetString(shardModeFlag) @@ -121,7 +125,7 @@ func setShardMode(cmd *cobra.Command, _ []string) { signRequest(cmd, pk, req) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.SetShardModeResponse var err error diff --git a/cmd/neofs-cli/modules/control/synchronize_tree.go b/cmd/neofs-cli/modules/control/synchronize_tree.go index 2bf4515196..a83525cb61 100644 --- a/cmd/neofs-cli/modules/control/synchronize_tree.go +++ b/cmd/neofs-cli/modules/control/synchronize_tree.go @@ -36,6 +36,9 @@ func initControlSynchronizeTreeCmd() { } func synchronizeTree(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.Get(cmd) var cnr cid.ID @@ -63,7 +66,7 @@ func synchronizeTree(cmd *cobra.Command, _ []string) { err := controlSvc.SignMessage(pk, req) common.ExitOnErr(cmd, "could not sign request: %w", err) - cli := getClient(cmd, pk) + cli := getClient(ctx, cmd, pk) var resp *control.SynchronizeTreeResponse err = cli.ExecRaw(func(client *rawclient.Client) error { diff --git a/cmd/neofs-cli/modules/control/util.go b/cmd/neofs-cli/modules/control/util.go index 59bae90e6f..b1c29daf9f 100644 --- a/cmd/neofs-cli/modules/control/util.go +++ b/cmd/neofs-cli/modules/control/util.go @@ -1,6 +1,7 @@ package control import ( + "context" "crypto/ecdsa" "errors" @@ -54,6 +55,6 @@ func verifyResponse(cmd *cobra.Command, } } -func getClient(cmd *cobra.Command, pk *ecdsa.PrivateKey) *client.Client { - return internalclient.GetSDKClientByFlag(cmd, pk, controlRPC) +func getClient(ctx context.Context, cmd *cobra.Command, pk *ecdsa.PrivateKey) *client.Client { + return internalclient.GetSDKClientByFlag(ctx, cmd, pk, controlRPC) } diff --git a/cmd/neofs-cli/modules/netmap/get_epoch.go b/cmd/neofs-cli/modules/netmap/get_epoch.go index 9ac6e64d3b..eaf0091634 100644 --- a/cmd/neofs-cli/modules/netmap/get_epoch.go +++ b/cmd/neofs-cli/modules/netmap/get_epoch.go @@ -13,13 +13,16 @@ var getEpochCmd = &cobra.Command{ Short: "Get current epoch number", Long: "Get current epoch number", Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + p := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, p, commonflags.RPC) var prm internalclient.NetworkInfoPrm prm.SetClient(cli) - res, err := internalclient.NetworkInfo(prm) + res, err := internalclient.NetworkInfo(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) netInfo := res.NetworkInfo() diff --git a/cmd/neofs-cli/modules/netmap/netinfo.go b/cmd/neofs-cli/modules/netmap/netinfo.go index 6999aa3dfb..aea9077ed3 100644 --- a/cmd/neofs-cli/modules/netmap/netinfo.go +++ b/cmd/neofs-cli/modules/netmap/netinfo.go @@ -17,13 +17,16 @@ var netInfoCmd = &cobra.Command{ Short: "Get information about NeoFS network", Long: "Get information about NeoFS network", Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + p := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, p, commonflags.RPC) var prm internalclient.NetworkInfoPrm prm.SetClient(cli) - res, err := internalclient.NetworkInfo(prm) + res, err := internalclient.NetworkInfo(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) netInfo := res.NetworkInfo() diff --git a/cmd/neofs-cli/modules/netmap/nodeinfo.go b/cmd/neofs-cli/modules/netmap/nodeinfo.go index 9c14a1b73c..d2233e9862 100644 --- a/cmd/neofs-cli/modules/netmap/nodeinfo.go +++ b/cmd/neofs-cli/modules/netmap/nodeinfo.go @@ -18,13 +18,16 @@ var nodeInfoCmd = &cobra.Command{ Short: "Get target node info", Long: `Get target node info`, Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + p := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, p, commonflags.RPC) var prm internalclient.NodeInfoPrm prm.SetClient(cli) - res, err := internalclient.NodeInfo(prm) + res, err := internalclient.NodeInfo(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) prettyPrintNodeInfo(cmd, res.NodeInfo()) diff --git a/cmd/neofs-cli/modules/netmap/snapshot.go b/cmd/neofs-cli/modules/netmap/snapshot.go index 0e9bf2b7bf..92b26b8f4f 100644 --- a/cmd/neofs-cli/modules/netmap/snapshot.go +++ b/cmd/neofs-cli/modules/netmap/snapshot.go @@ -13,13 +13,16 @@ var snapshotCmd = &cobra.Command{ Short: "Request current local snapshot of the network map", Long: `Request current local snapshot of the network map`, Run: func(cmd *cobra.Command, args []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + p := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, p, commonflags.RPC) var prm internalclient.NetMapSnapshotPrm prm.SetClient(cli) - res, err := internalclient.NetMapSnapshot(prm) + res, err := internalclient.NetMapSnapshot(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) common.PrettyPrintNetMap(cmd, res.NetMap()) diff --git a/cmd/neofs-cli/modules/object/delete.go b/cmd/neofs-cli/modules/object/delete.go index 6bf06c662b..f5b8128d0e 100644 --- a/cmd/neofs-cli/modules/object/delete.go +++ b/cmd/neofs-cli/modules/object/delete.go @@ -33,6 +33,9 @@ func initObjectDeleteCmd() { } func deleteObject(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID var obj oid.ID var objAddr oid.Address @@ -61,11 +64,11 @@ func deleteObject(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) var prm internalclient.DeleteObjectPrm - ReadOrOpenSession(cmd, &prm, pk, cnr, &obj) + ReadOrOpenSession(ctx, cmd, &prm, pk, cnr, &obj) Prepare(cmd, &prm) prm.SetAddress(objAddr) - res, err := internalclient.DeleteObject(prm) + res, err := internalclient.DeleteObject(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) tomb := res.Tombstone() diff --git a/cmd/neofs-cli/modules/object/get.go b/cmd/neofs-cli/modules/object/get.go index 69bbd644aa..97a97de334 100644 --- a/cmd/neofs-cli/modules/object/get.go +++ b/cmd/neofs-cli/modules/object/get.go @@ -43,6 +43,9 @@ func initObjectGetCmd() { } func getObject(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID var obj oid.ID @@ -65,7 +68,7 @@ func getObject(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.GetObjectPrm prm.SetClient(cli) @@ -101,7 +104,7 @@ func getObject(cmd *cobra.Command, _ []string) { }) } - res, err := internalclient.GetObject(prm) + res, err := internalclient.GetObject(ctx, prm) if p != nil { p.Finish() } @@ -115,7 +118,7 @@ func getObject(cmd *cobra.Command, _ []string) { if binary { objToStore := res.Header() - //TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload + // TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload objToStore.SetPayload(payloadBuffer.Bytes()) objBytes, err := objToStore.Marshal() common.ExitOnErr(cmd, "", err) diff --git a/cmd/neofs-cli/modules/object/hash.go b/cmd/neofs-cli/modules/object/hash.go index 2430443c70..f45a79bc44 100644 --- a/cmd/neofs-cli/modules/object/hash.go +++ b/cmd/neofs-cli/modules/object/hash.go @@ -48,6 +48,9 @@ func initObjectHashCmd() { } func getObjectHash(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID var obj oid.ID @@ -64,7 +67,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) { common.ExitOnErr(cmd, "could not decode salt: %w", err) pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) tz := typ == hashTz fullHash := len(ranges) == 0 @@ -75,7 +78,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) { headPrm.SetAddress(objAddr) // get hash of full payload through HEAD (may be user can do it through dedicated command?) - res, err := internalclient.HeadObject(headPrm) + res, err := internalclient.HeadObject(ctx, headPrm) common.ExitOnErr(cmd, "rpc error: %w", err) var cs checksum.Checksum @@ -108,7 +111,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) { hashPrm.TZ() } - res, err := internalclient.HashPayloadRanges(hashPrm) + res, err := internalclient.HashPayloadRanges(ctx, hashPrm) common.ExitOnErr(cmd, "rpc error: %w", err) hs := res.HashList() diff --git a/cmd/neofs-cli/modules/object/head.go b/cmd/neofs-cli/modules/object/head.go index 81ac42cdce..f4bc607fd0 100644 --- a/cmd/neofs-cli/modules/object/head.go +++ b/cmd/neofs-cli/modules/object/head.go @@ -45,6 +45,9 @@ func initObjectHeadCmd() { } func getObjectHeader(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID var obj oid.ID @@ -52,7 +55,7 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { mainOnly, _ := cmd.Flags().GetBool("main-only") pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.HeadObjectPrm prm.SetClient(cli) @@ -64,7 +67,7 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { prm.SetAddress(objAddr) prm.SetMainOnlyFlag(mainOnly) - res, err := internalclient.HeadObject(prm) + res, err := internalclient.HeadObject(ctx, prm) if err != nil { if ok := printSplitInfoErr(cmd, err); ok { return diff --git a/cmd/neofs-cli/modules/object/lock.go b/cmd/neofs-cli/modules/object/lock.go index dd639784b3..34652af7d1 100644 --- a/cmd/neofs-cli/modules/object/lock.go +++ b/cmd/neofs-cli/modules/object/lock.go @@ -26,6 +26,9 @@ var objectLockCmd = &cobra.Command{ Short: "Lock object in container", Long: "Lock object in container", Run: func(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID @@ -82,11 +85,11 @@ var objectLockCmd = &cobra.Command{ obj.SetPayload(lock.Marshal()) var prm internalclient.PutObjectPrm - ReadOrOpenSession(cmd, &prm, key, cnr, nil) + ReadOrOpenSession(ctx, cmd, &prm, key, cnr, nil) Prepare(cmd, &prm) prm.SetHeader(obj) - res, err := internalclient.PutObject(prm) + res, err := internalclient.PutObject(ctx, prm) common.ExitOnErr(cmd, "Store lock object in NeoFS: %w", err) cmd.Printf("Lock object ID: %s\n", res.ID()) diff --git a/cmd/neofs-cli/modules/object/put.go b/cmd/neofs-cli/modules/object/put.go index ca28d31c2f..29ed6dc48e 100644 --- a/cmd/neofs-cli/modules/object/put.go +++ b/cmd/neofs-cli/modules/object/put.go @@ -60,6 +60,9 @@ func initObjectPutCmd() { } func putObject(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + binary, _ := cmd.Flags().GetBool(binaryFlag) cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag) @@ -130,7 +133,7 @@ func putObject(cmd *cobra.Command, _ []string) { } var prm internalclient.PutObjectPrm - ReadOrOpenSession(cmd, &prm, pk, cnr, nil) + ReadOrOpenSession(ctx, cmd, &prm, pk, cnr, nil) Prepare(cmd, &prm) prm.SetHeader(obj) @@ -161,7 +164,7 @@ func putObject(cmd *cobra.Command, _ []string) { } } - res, err := internalclient.PutObject(prm) + res, err := internalclient.PutObject(ctx, prm) if p != nil { p.Finish() } diff --git a/cmd/neofs-cli/modules/object/range.go b/cmd/neofs-cli/modules/object/range.go index bf85f75a34..e51f35f45b 100644 --- a/cmd/neofs-cli/modules/object/range.go +++ b/cmd/neofs-cli/modules/object/range.go @@ -44,6 +44,9 @@ func initObjectRangeCmd() { } func getObjectRange(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID var obj oid.ID @@ -74,7 +77,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.PayloadRangePrm prm.SetClient(cli) @@ -87,7 +90,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) { prm.SetRange(ranges[0]) prm.SetPayloadWriter(out) - _, err = internalclient.PayloadRange(prm) + _, err = internalclient.PayloadRange(ctx, prm) if err != nil { if ok := printSplitInfoErr(cmd, err); ok { return diff --git a/cmd/neofs-cli/modules/object/search.go b/cmd/neofs-cli/modules/object/search.go index a6c0990573..30cfb93de4 100644 --- a/cmd/neofs-cli/modules/object/search.go +++ b/cmd/neofs-cli/modules/object/search.go @@ -44,6 +44,9 @@ func initObjectSearchCmd() { } func searchObject(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID readCID(cmd, &cnr) @@ -52,7 +55,7 @@ func searchObject(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.SearchObjectsPrm prm.SetClient(cli) @@ -61,7 +64,7 @@ func searchObject(cmd *cobra.Command, _ []string) { prm.SetContainerID(cnr) prm.SetFilters(sf) - res, err := internalclient.SearchObjects(prm) + res, err := internalclient.SearchObjects(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) ids := res.IDList() diff --git a/cmd/neofs-cli/modules/object/util.go b/cmd/neofs-cli/modules/object/util.go index 3366485f59..96a9475b26 100644 --- a/cmd/neofs-cli/modules/object/util.go +++ b/cmd/neofs-cli/modules/object/util.go @@ -1,6 +1,7 @@ package object import ( + "context" "crypto/ecdsa" "errors" "fmt" @@ -206,19 +207,19 @@ func _readVerifiedSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.Private } // ReadOrOpenSession opens client connection and calls ReadOrOpenSessionViaClient with it. -func ReadOrOpenSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { - cli := internal.GetSDKClientByFlag(cmd, key, commonflags.RPC) - ReadOrOpenSessionViaClient(cmd, dst, cli, key, cnr, obj) +func ReadOrOpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { + cli := internal.GetSDKClientByFlag(ctx, cmd, key, commonflags.RPC) + ReadOrOpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, obj) } // ReadOrOpenSessionViaClient tries to read session from the file specified in // commonflags.SessionToken flag, finalizes structures of the decoded token // and write the result into provided SessionPrm. If file is missing, // ReadOrOpenSessionViaClient calls OpenSessionViaClient. -func ReadOrOpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { +func ReadOrOpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { tok := getSession(cmd) if tok == nil { - OpenSessionViaClient(cmd, dst, cli, key, cnr, obj) + OpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, obj) return } @@ -229,7 +230,7 @@ func ReadOrOpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client. if _, ok := dst.(*internal.DeleteObjectPrm); ok { common.PrintVerbose(cmd, "Collecting relatives of the removal object...") - objs = append(objs, collectObjectRelatives(cmd, cli, cnr, *obj)...) + objs = append(objs, collectObjectRelatives(ctx, cmd, cli, cnr, *obj)...) } } @@ -238,9 +239,9 @@ func ReadOrOpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client. } // OpenSession opens client connection and calls OpenSessionViaClient with it. -func OpenSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { - cli := internal.GetSDKClientByFlag(cmd, key, commonflags.RPC) - OpenSessionViaClient(cmd, dst, cli, key, cnr, obj) +func OpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { + cli := internal.GetSDKClientByFlag(ctx, cmd, key, commonflags.RPC) + OpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, obj) } // OpenSessionViaClient opens object session with the remote node, finalizes @@ -254,14 +255,14 @@ func OpenSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr // // If provided SessionPrm is of type internal.DeleteObjectPrm, OpenSessionViaClient // spreads the session to all object's relatives. -func OpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { +func OpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { var objs []oid.ID if obj != nil { if _, ok := dst.(*internal.DeleteObjectPrm); ok { common.PrintVerbose(cmd, "Collecting relatives of the removal object...") - rels := collectObjectRelatives(cmd, cli, cnr, *obj) + rels := collectObjectRelatives(ctx, cmd, cli, cnr, *obj) if len(rels) == 0 { objs = []oid.ID{*obj} @@ -277,7 +278,7 @@ func OpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client common.PrintVerbose(cmd, "Opening remote session with the node...") - err := sessionCli.CreateSession(&tok, cli, neofsecdsa.SignerRFC6979(*key), sessionLifetime) + err := sessionCli.CreateSession(ctx, &tok, cli, neofsecdsa.SignerRFC6979(*key), sessionLifetime) common.ExitOnErr(cmd, "open remote session: %w", err) common.PrintVerbose(cmd, "Session successfully opened.") @@ -338,7 +339,7 @@ func initFlagSession(cmd *cobra.Command, verb string) { // container. // // The object itself is not included in the result. -func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, obj oid.ID) []oid.ID { +func collectObjectRelatives(ctx context.Context, cmd *cobra.Command, cli *client.Client, cnr cid.ID, obj oid.ID) []oid.ID { common.PrintVerbose(cmd, "Fetching raw object header...") // request raw header first @@ -353,7 +354,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, Prepare(cmd, &prmHead) - _, err := internal.HeadObject(prmHead) + _, err := internal.HeadObject(ctx, prmHead) var errSplit *object.SplitInfoError @@ -380,7 +381,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, prmHead.SetRawFlag(false) // client is already set - res, err := internal.HeadObject(prmHead) + res, err := internal.HeadObject(ctx, prmHead) if err == nil { children := res.Header().Children() @@ -406,7 +407,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, prm.SetClient(cli) prm.SetFilters(query) - res, err := internal.SearchObjects(prm) + res, err := internal.SearchObjects(ctx, prm) common.ExitOnErr(cmd, "failed to search objects by split ID: %w", err) members := res.IDList() @@ -435,7 +436,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, addrObj.SetObject(idMember) - res, err = internal.HeadObject(prmHead) + res, err = internal.HeadObject(ctx, prmHead) common.ExitOnErr(cmd, "failed to read split chain member's header: %w", err) idMember, ok = res.Header().PreviousID() @@ -462,7 +463,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, prmSearch.SetContainerID(cnr) prmSearch.SetFilters(query) - resSearch, err := internal.SearchObjects(prmSearch) + resSearch, err := internal.SearchObjects(ctx, prmSearch) common.ExitOnErr(cmd, "failed to find object children: %w", err) list := resSearch.IDList() diff --git a/cmd/neofs-cli/modules/session/create.go b/cmd/neofs-cli/modules/session/create.go index ee604ff839..f4414fd5be 100644 --- a/cmd/neofs-cli/modules/session/create.go +++ b/cmd/neofs-cli/modules/session/create.go @@ -50,13 +50,15 @@ func init() { } func createSession(cmd *cobra.Command, _ []string) { + ctx := context.Background() + privKey := key.Get(cmd) var netAddr network.Address addrStr, _ := cmd.Flags().GetString(commonflags.RPC) common.ExitOnErr(cmd, "can't parse endpoint: %w", netAddr.FromString(addrStr)) - c, err := internalclient.GetSDKClient(context.TODO(), cmd, privKey, netAddr) + c, err := internalclient.GetSDKClient(ctx, cmd, privKey, netAddr) common.ExitOnErr(cmd, "can't create client: %w", err) lifetime := uint64(defaultLifetime) @@ -66,7 +68,7 @@ func createSession(cmd *cobra.Command, _ []string) { var tok session.Object - err = CreateSession(&tok, c, neofsecdsa.SignerRFC6979(*privKey), lifetime) + err = CreateSession(ctx, &tok, c, neofsecdsa.SignerRFC6979(*privKey), lifetime) common.ExitOnErr(cmd, "can't create session: %w", err) var data []byte @@ -88,11 +90,11 @@ func createSession(cmd *cobra.Command, _ []string) { // number of epochs. // // Fills ID, lifetime and session key. -func CreateSession(dst *session.Object, c *client.Client, _signer neofscrypto.Signer, lifetime uint64) error { +func CreateSession(ctx context.Context, dst *session.Object, c *client.Client, _signer neofscrypto.Signer, lifetime uint64) error { var netInfoPrm internalclient.NetworkInfoPrm netInfoPrm.SetClient(c) - ni, err := internalclient.NetworkInfo(netInfoPrm) + ni, err := internalclient.NetworkInfo(ctx, netInfoPrm) if err != nil { return fmt.Errorf("can't fetch network info: %w", err) } @@ -105,7 +107,7 @@ func CreateSession(dst *session.Object, c *client.Client, _signer neofscrypto.Si sessionPrm.SetExp(exp) sessionPrm.UseSigner(_signer) - sessionRes, err := internalclient.CreateSession(sessionPrm) + sessionRes, err := internalclient.CreateSession(ctx, sessionPrm) if err != nil { return fmt.Errorf("can't open session: %w", err) } diff --git a/cmd/neofs-cli/modules/storagegroup/delete.go b/cmd/neofs-cli/modules/storagegroup/delete.go index 10f7bde7b9..6c971ddfd9 100644 --- a/cmd/neofs-cli/modules/storagegroup/delete.go +++ b/cmd/neofs-cli/modules/storagegroup/delete.go @@ -31,6 +31,9 @@ func initSGDeleteCmd() { } func delSG(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.GetOrGenerate(cmd) var cnr cid.ID @@ -39,11 +42,11 @@ func delSG(cmd *cobra.Command, _ []string) { addr := readObjectAddress(cmd, &cnr, &obj) var prm internalclient.DeleteObjectPrm - objectCli.OpenSession(cmd, &prm, pk, cnr, &obj) + objectCli.OpenSession(ctx, cmd, &prm, pk, cnr, &obj) objectCli.Prepare(cmd, &prm) prm.SetAddress(addr) - res, err := internalclient.DeleteObject(prm) + res, err := internalclient.DeleteObject(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) tombstone := res.Tombstone() diff --git a/cmd/neofs-cli/modules/storagegroup/get.go b/cmd/neofs-cli/modules/storagegroup/get.go index f7511b3575..5bc02e4125 100644 --- a/cmd/neofs-cli/modules/storagegroup/get.go +++ b/cmd/neofs-cli/modules/storagegroup/get.go @@ -38,6 +38,9 @@ func initSGGetCmd() { } func getSG(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID var obj oid.ID @@ -45,7 +48,7 @@ func getSG(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) buf := bytes.NewBuffer(nil) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.GetObjectPrm objectCli.Prepare(cmd, &prm) @@ -56,7 +59,7 @@ func getSG(cmd *cobra.Command, _ []string) { prm.SetAddress(addr) prm.SetPayloadWriter(buf) - res, err := internalclient.GetObject(prm) + res, err := internalclient.GetObject(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) rawObj := res.Header() diff --git a/cmd/neofs-cli/modules/storagegroup/list.go b/cmd/neofs-cli/modules/storagegroup/list.go index 0d5be94d66..c1a71a47bb 100644 --- a/cmd/neofs-cli/modules/storagegroup/list.go +++ b/cmd/neofs-cli/modules/storagegroup/list.go @@ -26,12 +26,15 @@ func initSGListCmd() { } func listSG(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + var cnr cid.ID readCID(cmd, &cnr) pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) var prm internalclient.SearchObjectsPrm objectCli.Prepare(cmd, &prm) @@ -39,7 +42,7 @@ func listSG(cmd *cobra.Command, _ []string) { prm.SetContainerID(cnr) prm.SetFilters(storagegroup.SearchQuery()) - res, err := internalclient.SearchObjects(prm) + res, err := internalclient.SearchObjects(ctx, prm) common.ExitOnErr(cmd, "rpc error: %w", err) ids := res.IDList() diff --git a/cmd/neofs-cli/modules/storagegroup/put.go b/cmd/neofs-cli/modules/storagegroup/put.go index 13a81f8728..57a91afd1e 100644 --- a/cmd/neofs-cli/modules/storagegroup/put.go +++ b/cmd/neofs-cli/modules/storagegroup/put.go @@ -1,6 +1,7 @@ package storagegroup import ( + "context" "crypto/ecdsa" "errors" "fmt" @@ -48,6 +49,9 @@ func initSGPutCmd() { } func putSG(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.GetOrGenerate(cmd) var ownerID user.ID @@ -77,14 +81,14 @@ func putSG(cmd *cobra.Command, _ []string) { getCnrPrm internalclient.GetContainerPrm ) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + cli := internalclient.GetSDKClientByFlag(ctx, cmd, pk, commonflags.RPC) getCnrPrm.SetClient(cli) getCnrPrm.SetContainer(cnr) - resGetCnr, err := internalclient.GetContainer(getCnrPrm) + resGetCnr, err := internalclient.GetContainer(ctx, getCnrPrm) common.ExitOnErr(cmd, "get container RPC call: %w", err) - objectCli.OpenSessionViaClient(cmd, &putPrm, cli, pk, cnr, nil) + objectCli.OpenSessionViaClient(ctx, cmd, &putPrm, cli, pk, cnr, nil) objectCli.Prepare(cmd, &headPrm, &putPrm) headPrm.SetRawFlag(true) @@ -101,7 +105,7 @@ func putSG(cmd *cobra.Command, _ []string) { var netInfoPrm internalclient.NetworkInfoPrm netInfoPrm.SetClient(cli) - ni, err := internalclient.NetworkInfo(netInfoPrm) + ni, err := internalclient.NetworkInfo(ctx, netInfoPrm) common.ExitOnErr(cmd, "can't fetch network info: %w", err) lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime) @@ -115,7 +119,7 @@ func putSG(cmd *cobra.Command, _ []string) { putPrm.SetHeader(obj) - res, err := internalclient.PutObject(putPrm) + res, err := internalclient.PutObject(ctx, putPrm) common.ExitOnErr(cmd, "rpc error: %w", err) cmd.Println("Storage group successfully stored") @@ -123,6 +127,7 @@ func putSG(cmd *cobra.Command, _ []string) { } type sgHeadReceiver struct { + ctx context.Context cmd *cobra.Command key *ecdsa.PrivateKey ownerID *user.ID @@ -132,7 +137,7 @@ type sgHeadReceiver struct { func (c sgHeadReceiver) Head(addr oid.Address) (interface{}, error) { c.prm.SetAddress(addr) - res, err := internalclient.HeadObject(c.prm) + res, err := internalclient.HeadObject(c.ctx, c.prm) var errSplitInfo *object.SplitInfoError diff --git a/cmd/neofs-cli/modules/tree/add.go b/cmd/neofs-cli/modules/tree/add.go index 2230733346..79b873631c 100644 --- a/cmd/neofs-cli/modules/tree/add.go +++ b/cmd/neofs-cli/modules/tree/add.go @@ -34,6 +34,9 @@ func initAddCmd() { } func add(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.GetOrGenerate(cmd) var cnr cid.ID @@ -46,8 +49,6 @@ func add(cmd *cobra.Command, _ []string) { meta, err := parseMeta(cmd) common.ExitOnErr(cmd, "meta data parsing: %w", err) - ctx := cmd.Context() - cli, err := _client(ctx) common.ExitOnErr(cmd, "client: %w", err) diff --git a/cmd/neofs-cli/modules/tree/add_by_path.go b/cmd/neofs-cli/modules/tree/add_by_path.go index 17e413194a..2e7578b98f 100644 --- a/cmd/neofs-cli/modules/tree/add_by_path.go +++ b/cmd/neofs-cli/modules/tree/add_by_path.go @@ -40,6 +40,9 @@ func initAddByPathCmd() { } func addByPath(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.GetOrGenerate(cmd) cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) @@ -49,7 +52,6 @@ func addByPath(cmd *cobra.Command, _ []string) { common.ExitOnErr(cmd, "decode container ID string: %w", err) tid, _ := cmd.Flags().GetString(treeIDFlagKey) - ctx := cmd.Context() cli, err := _client(ctx) common.ExitOnErr(cmd, "client: %w", err) diff --git a/cmd/neofs-cli/modules/tree/get_by_path.go b/cmd/neofs-cli/modules/tree/get_by_path.go index eb7af4446f..074f16c289 100644 --- a/cmd/neofs-cli/modules/tree/get_by_path.go +++ b/cmd/neofs-cli/modules/tree/get_by_path.go @@ -40,6 +40,9 @@ func initGetByPathCmd() { } func getByPath(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.GetOrGenerate(cmd) cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) @@ -49,7 +52,6 @@ func getByPath(cmd *cobra.Command, _ []string) { common.ExitOnErr(cmd, "decode container ID string: %w", err) tid, _ := cmd.Flags().GetString(treeIDFlagKey) - ctx := cmd.Context() cli, err := _client(ctx) common.ExitOnErr(cmd, "client: %w", err) diff --git a/cmd/neofs-cli/modules/tree/list.go b/cmd/neofs-cli/modules/tree/list.go index 076cf1f1dd..bfef9c3e25 100644 --- a/cmd/neofs-cli/modules/tree/list.go +++ b/cmd/neofs-cli/modules/tree/list.go @@ -31,6 +31,9 @@ func initListCmd() { } func list(cmd *cobra.Command, _ []string) { + ctx, cancel := commonflags.GetCommandContext(cmd) + defer cancel() + pk := key.GetOrGenerate(cmd) cidString, _ := cmd.Flags().GetString(commonflags.CIDFlag) @@ -38,8 +41,6 @@ func list(cmd *cobra.Command, _ []string) { err := cnr.DecodeString(cidString) common.ExitOnErr(cmd, "decode container ID string: %w", err) - ctx := cmd.Context() - cli, err := _client(ctx) common.ExitOnErr(cmd, "client: %w", err)