From 51b85b0a73a2ba58e3ce321a3d51c8f585c50f2d Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 24 Dec 2020 14:25:36 +0300 Subject: [PATCH] [#278] cli: Support request X-Headers Signed-off-by: Leonard Lyubich --- cmd/neofs-cli/modules/accounting.go | 5 +- cmd/neofs-cli/modules/container.go | 26 ++++++----- cmd/neofs-cli/modules/netmap.go | 5 +- cmd/neofs-cli/modules/object.go | 72 ++++++++++++++++++----------- cmd/neofs-cli/modules/root.go | 42 +++++++++++++++++ 5 files changed, 105 insertions(+), 45 deletions(-) diff --git a/cmd/neofs-cli/modules/accounting.go b/cmd/neofs-cli/modules/accounting.go index b5e03e18..a74b2d65 100644 --- a/cmd/neofs-cli/modules/accounting.go +++ b/cmd/neofs-cli/modules/accounting.go @@ -6,7 +6,6 @@ import ( "math" "github.com/nspcc-dev/neofs-api-go/pkg/accounting" - "github.com/nspcc-dev/neofs-api-go/pkg/client" "github.com/nspcc-dev/neofs-api-go/pkg/owner" "github.com/spf13/cobra" ) @@ -42,14 +41,14 @@ var accountingBalanceCmd = &cobra.Command{ switch balanceOwner { case "": - response, err = cli.GetSelfBalance(ctx, client.WithTTL(getTTL())) + response, err = cli.GetSelfBalance(ctx, globalCallOptions()...) default: oid, err = ownerFromString(balanceOwner) if err != nil { return err } - response, err = cli.GetBalance(ctx, oid, client.WithTTL(getTTL())) + response, err = cli.GetBalance(ctx, oid, globalCallOptions()...) } if err != nil { diff --git a/cmd/neofs-cli/modules/container.go b/cmd/neofs-cli/modules/container.go index b86e27e9..6ae5480d 100644 --- a/cmd/neofs-cli/modules/container.go +++ b/cmd/neofs-cli/modules/container.go @@ -80,14 +80,14 @@ var listContainersCmd = &cobra.Command{ switch containerOwner { case "": - response, err = cli.ListSelfContainers(ctx, client.WithTTL(getTTL())) + response, err = cli.ListSelfContainers(ctx, globalCallOptions()...) default: oid, err = ownerFromString(containerOwner) if err != nil { return err } - response, err = cli.ListContainers(ctx, oid, client.WithTTL(getTTL())) + response, err = cli.ListContainers(ctx, oid, globalCallOptions()...) } if err != nil { @@ -140,7 +140,7 @@ It will be stored in sidechain when inner ring will accepts it.`, cnr.SetAttributes(attributes) cnr.SetNonceUUID(nonce) - id, err := cli.PutContainer(ctx, cnr, client.WithTTL(getTTL())) + id, err := cli.PutContainer(ctx, cnr, globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -153,7 +153,7 @@ It will be stored in sidechain when inner ring will accepts it.`, for i := 0; i < awaitTimeout; i++ { time.Sleep(1 * time.Second) - _, err := cli.GetContainer(ctx, id, client.WithTTL(getTTL())) + _, err := cli.GetContainer(ctx, id, globalCallOptions()...) if err == nil { fmt.Println("container has been persisted on sidechain") return nil @@ -185,7 +185,7 @@ Only owner of the container has a permission to remove container.`, return err } - err = cli.DeleteContainer(ctx, id, client.WithTTL(getTTL())) + err = cli.DeleteContainer(ctx, id, globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -198,7 +198,7 @@ Only owner of the container has a permission to remove container.`, for i := 0; i < awaitTimeout; i++ { time.Sleep(1 * time.Second) - _, err := cli.GetContainer(ctx, id, client.WithTTL(getTTL())) + _, err := cli.GetContainer(ctx, id, globalCallOptions()...) if err != nil { fmt.Println("container has been removed:", containerID) return nil @@ -242,8 +242,10 @@ var listContainerObjectsCmd = &cobra.Command{ searchQuery.WithSearchFilters(*filters) objectIDs, err := cli.SearchObject(ctx, searchQuery, - client.WithTTL(getTTL()), - client.WithSession(sessionToken)) + append(globalCallOptions(), + client.WithSession(sessionToken), + )..., + ) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -288,7 +290,7 @@ var getContainerInfoCmd = &cobra.Command{ return err } - cnr, err = cli.GetContainer(ctx, id, client.WithTTL(getTTL())) + cnr, err = cli.GetContainer(ctx, id, globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -341,7 +343,7 @@ var getExtendedACLCmd = &cobra.Command{ return err } - res, err := cli.GetEACLWithSignature(ctx, id, client.WithTTL(getTTL())) + res, err := cli.GetEACLWithSignature(ctx, id, globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -407,7 +409,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`, eaclTable.SetCID(id) - err = cli.SetEACL(ctx, eaclTable, client.WithTTL(getTTL())) + err = cli.SetEACL(ctx, eaclTable, globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -423,7 +425,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`, for i := 0; i < awaitTimeout; i++ { time.Sleep(1 * time.Second) - eaclSig, err := cli.GetEACLWithSignature(ctx, id, client.WithTTL(getTTL())) + eaclSig, err := cli.GetEACLWithSignature(ctx, id, globalCallOptions()...) if err == nil { // compare binary values because EACL could have been set already got, err := eaclSig.EACL().Marshal() diff --git a/cmd/neofs-cli/modules/netmap.go b/cmd/neofs-cli/modules/netmap.go index 3b67ef35..e0949ebc 100644 --- a/cmd/neofs-cli/modules/netmap.go +++ b/cmd/neofs-cli/modules/netmap.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" - "github.com/nspcc-dev/neofs-api-go/pkg/client" "github.com/nspcc-dev/neofs-api-go/pkg/netmap" "github.com/spf13/cobra" ) @@ -47,7 +46,7 @@ var getEpochCmd = &cobra.Command{ return err } - e, err := cli.Epoch(context.Background(), client.WithTTL(getTTL())) + e, err := cli.Epoch(context.Background(), globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } @@ -68,7 +67,7 @@ var localNodeInfoCmd = &cobra.Command{ return err } - nodeInfo, err := cli.EndpointInfo(context.Background(), client.WithTTL(getTTL())) + nodeInfo, err := cli.EndpointInfo(context.Background(), globalCallOptions()...) if err != nil { return fmt.Errorf("rpc error: %w", err) } diff --git a/cmd/neofs-cli/modules/object.go b/cmd/neofs-cli/modules/object.go index 546b5536..bdb9cec9 100644 --- a/cmd/neofs-cli/modules/object.go +++ b/cmd/neofs-cli/modules/object.go @@ -229,9 +229,11 @@ func putObject(cmd *cobra.Command, _ []string) error { new(client.PutObjectParams). WithObject(obj.Object()). WithPayloadReader(f), - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { return fmt.Errorf("can't put object: %w", err) } @@ -259,9 +261,11 @@ func deleteObject(cmd *cobra.Command, _ []string) error { tombstoneAddr, err := client.DeleteObject(cli, ctx, new(client.DeleteObjectParams).WithAddress(objAddr), - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { return err } @@ -307,9 +311,11 @@ func getObject(cmd *cobra.Command, _ []string) error { WithAddress(objAddr). WithPayloadWriter(out). WithRawFlag(raw), - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { if ok := printSplitInfoErr(cmd, err); ok { return nil @@ -354,9 +360,11 @@ func getObjectHeader(cmd *cobra.Command, _ []string) error { ps.WithRawFlag(raw) obj, err := cli.GetObjectHeader(ctx, ps, - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { if ok := printSplitInfoErr(cmd, err); ok { return nil @@ -390,9 +398,11 @@ func searchObject(cmd *cobra.Command, _ []string) error { } ps := new(client.SearchObjectParams).WithContainerID(cid).WithSearchFilters(sf) ids, err := cli.SearchObject(ctx, ps, - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { return fmt.Errorf("can't put object: %w", err) } @@ -429,9 +439,11 @@ func getObjectHash(cmd *cobra.Command, _ []string) error { if len(ranges) == 0 { // hash of full payload obj, err := cli.GetObjectHeader(ctx, new(client.ObjectHeaderParams).WithAddress(objAddr), - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { return fmt.Errorf("can't get object: %w", err) } @@ -448,9 +460,11 @@ func getObjectHash(cmd *cobra.Command, _ []string) error { switch typ { case hashSha256: res, err := cli.ObjectPayloadRangeSHA256(ctx, ps, - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { return err } @@ -460,9 +474,11 @@ func getObjectHash(cmd *cobra.Command, _ []string) error { } case hashTz: res, err := cli.ObjectPayloadRangeTZ(ctx, ps, - client.WithTTL(getTTL()), - client.WithSession(tok), - client.WithBearer(btok)) + append(globalCallOptions(), + client.WithSession(tok), + client.WithBearer(btok), + )..., + ) if err != nil { return err } @@ -808,9 +824,11 @@ func getObjectRange(cmd *cobra.Command, _ []string) error { WithRange(ranges[0]). WithDataWriter(out). WithRaw(raw), - client.WithTTL(getTTL()), - client.WithSession(sessionToken), - client.WithBearer(bearerToken)) + append(globalCallOptions(), + client.WithSession(sessionToken), + client.WithBearer(bearerToken), + )..., + ) if err != nil { if ok := printSplitInfoErr(cmd, err); ok { return nil diff --git a/cmd/neofs-cli/modules/root.go b/cmd/neofs-cli/modules/root.go index dbbcf622..8c725602 100644 --- a/cmd/neofs-cli/modules/root.go +++ b/cmd/neofs-cli/modules/root.go @@ -7,8 +7,10 @@ import ( "errors" "fmt" "os" + "strings" "github.com/mitchellh/go-homedir" + "github.com/nspcc-dev/neofs-api-go/pkg" "github.com/nspcc-dev/neofs-api-go/pkg/client" "github.com/nspcc-dev/neofs-api-go/pkg/owner" crypto "github.com/nspcc-dev/neofs-crypto" @@ -25,6 +27,10 @@ const ( ttlDefaultValue = 2 ) +const xHeadersFlag = "xhdr" + +var xHeaders []string + // Global scope flags. var ( cfgFile string @@ -80,6 +86,10 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output") + rootCmd.PersistentFlags().StringSliceVarP(&xHeaders, xHeadersFlag, "x", nil, + "Request X-Headers in form of Key=Value") + _ = viper.BindPFlag(xHeadersFlag, rootCmd.PersistentFlags().Lookup(xHeadersFlag)) + // Cobra also supports local flags, which will only run // when this action is called directly. // rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") @@ -194,3 +204,35 @@ func printVerbose(format string, a ...interface{}) { fmt.Printf(format+"\n", a...) } } + +func parseXHeaders() []*pkg.XHeader { + xs := make([]*pkg.XHeader, 0, len(xHeaders)) + + for i := range xHeaders { + kv := strings.SplitN(xHeaders[i], "=", 2) + if len(kv) != 2 { + panic(fmt.Errorf("invalid X-Header format: %s", xHeaders[i])) + } + + x := pkg.NewXHeader() + x.SetKey(kv[0]) + x.SetValue(kv[1]) + + xs = append(xs, x) + } + + return xs +} + +func globalCallOptions() []client.CallOption { + xHdrs := parseXHeaders() + + opts := make([]client.CallOption, 0, len(xHdrs)+1) // + TTL + opts = append(opts, client.WithTTL(getTTL())) + + for i := range xHdrs { + opts = append(opts, client.WithXHeader(xHdrs[i])) + } + + return opts +}