Skip to content

Commit

Permalink
cli: unify usage of expired-at flag and lifetime flag
Browse files Browse the repository at this point in the history
Refactor CLI usage to standardize the expired-at flag and lifetime flag.
 This change is aimed at preventing confusion during flag interpretation
  and empowering users.

Closes #1574.

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
  • Loading branch information
AliceInHunterland committed Aug 25, 2023
1 parent f5d80b0 commit 3b463c0
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 32 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ minor release, the component will be purged, so be prepared (see `Updating` sect
- `peapod` command for `neofs-lens` (#2507)
- New CLI exit code for awaiting timeout (#2380)
- Validation of excessive positional arguments to `neofs-cli` commands (#1941)
- `--lifetime` flag to `bearer create` and `object put` CLI commands (#1574)
- `--expired-at` flag to `session create` and `storagegroup put` CLI commands (#1574)

### Fixed
- `neo-go` RPC connection loss handling (#1337)
Expand Down
13 changes: 11 additions & 2 deletions cmd/neofs-cli/modules/bearer/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package bearer
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"time"
Expand Down Expand Up @@ -47,27 +48,32 @@ func init() {
createCmd.Flags().String(outFlag, "", "File to write token to")
createCmd.Flags().Bool(jsonFlag, false, "Output token in JSON")
createCmd.Flags().StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage)
createCmd.Flags().Uint64P(commonflags.Lifetime, "l", 0, "Number of epochs for token to stay valid")

_ = cobra.MarkFlagFilename(createCmd.Flags(), eaclFlag)

_ = cobra.MarkFlagRequired(createCmd.Flags(), issuedAtFlag)
_ = cobra.MarkFlagRequired(createCmd.Flags(), notValidBeforeFlag)
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.ExpireAt)
_ = cobra.MarkFlagRequired(createCmd.Flags(), ownerFlag)
_ = cobra.MarkFlagRequired(createCmd.Flags(), outFlag)
createCmd.MarkFlagsMutuallyExclusive(commonflags.ExpireAt, commonflags.Lifetime)
}

func createToken(cmd *cobra.Command, _ []string) {
iat, iatRelative, err := common.ParseEpoch(cmd, issuedAtFlag)
common.ExitOnErr(cmd, "can't parse --"+issuedAtFlag+" flag: %w", err)

lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
exp, expRelative, err := common.ParseEpoch(cmd, commonflags.ExpireAt)
common.ExitOnErr(cmd, "can't parse --"+commonflags.ExpireAt+" flag: %w", err)
if exp == 0 && lifetime == 0 {
common.ExitOnErr(cmd, "", errors.New("expiration epoch or lifetime period is required"))
}

nvb, nvbRelative, err := common.ParseEpoch(cmd, notValidBeforeFlag)
common.ExitOnErr(cmd, "can't parse --"+notValidBeforeFlag+" flag: %w", err)

if iatRelative || expRelative || nvbRelative {
if iatRelative || expRelative || nvbRelative || lifetime != 0 {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()

Expand All @@ -84,6 +90,9 @@ func createToken(cmd *cobra.Command, _ []string) {
if nvbRelative {
nvb += currEpoch
}
if lifetime != 0 {
exp = currEpoch + lifetime
}
}
if exp < nvb {
common.ExitOnErr(cmd, "",
Expand Down
2 changes: 1 addition & 1 deletion cmd/neofs-cli/modules/object/lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var objectLockCmd = &cobra.Command{
exp, _ := cmd.Flags().GetUint64(commonflags.ExpireAt)
lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
if exp == 0 && lifetime == 0 { // mutual exclusion is ensured by cobra
common.ExitOnErr(cmd, "", errors.New("either expiration epoch of a lifetime is required"))
common.ExitOnErr(cmd, "", errors.New("expiration epoch or lifetime period is required"))
}

if lifetime != 0 {
Expand Down
11 changes: 11 additions & 0 deletions cmd/neofs-cli/modules/object/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ func initObjectPutCmd() {
flags.Bool("disable-filename", false, "Do not set well-known filename attribute")
flags.Bool("disable-timestamp", false, "Do not set well-known timestamp attribute")
flags.Uint64VarP(&putExpiredOn, commonflags.ExpireAt, "e", 0, "The last active epoch in the life of the object")
flags.Uint64P(commonflags.Lifetime, "l", 0, "Number of epochs for object to stay valid")
flags.Bool(noProgressFlag, false, "Do not show progress bar")

flags.String(notificationFlag, "", "Object notification in the form of *epoch*:*topic*; '-' topic means using default")
flags.Bool(binaryFlag, false, "Deserialize object structure from given file.")
objectPutCmd.MarkFlagsMutuallyExclusive(commonflags.ExpireAt, commonflags.Lifetime)
}

func putObject(cmd *cobra.Command, _ []string) {
Expand Down Expand Up @@ -100,6 +102,15 @@ func putObject(cmd *cobra.Command, _ []string) {
common.ExitOnErr(cmd, "can't parse object attributes: %w", err)

expiresOn, _ := cmd.Flags().GetUint64(commonflags.ExpireAt)
lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
if lifetime > 0 {
endpoint, _ := cmd.Flags().GetString(commonflags.RPC)
currEpoch, err := internalclient.GetCurrentEpoch(ctx, endpoint)
common.ExitOnErr(cmd, "Request current epoch: %w", err)

expiresOn = currEpoch + lifetime
}

if expiresOn > 0 {
var expAttrFound bool
expAttrValue := strconv.FormatUint(expiresOn, 10)
Expand Down
7 changes: 5 additions & 2 deletions cmd/neofs-cli/modules/object/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,11 @@ func OpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPr
const sessionLifetime = 10 // in NeoFS epochs

common.PrintVerbose(cmd, "Opening remote session with the node...")

err := sessionCli.CreateSession(ctx, &tok, cli, *key, sessionLifetime)
endpoint, _ := cmd.Flags().GetString(commonflags.RPC)
currEpoch, err := internal.GetCurrentEpoch(ctx, endpoint)
common.ExitOnErr(cmd, "can't fetch current epoch: %w", err)
exp := currEpoch + sessionLifetime
err = sessionCli.CreateSession(ctx, &tok, cli, *key, exp, currEpoch)
common.ExitOnErr(cmd, "open remote session: %w", err)

common.PrintVerbose(cmd, "Session successfully opened.")
Expand Down
41 changes: 21 additions & 20 deletions cmd/neofs-cli/modules/session/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package session
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"os"

Expand Down Expand Up @@ -44,10 +45,12 @@ func init() {
createCmd.Flags().String(outFlag, "", "File to write session token to")
createCmd.Flags().Bool(jsonFlag, false, "Output token in JSON")
createCmd.Flags().StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage)
createCmd.Flags().Uint64P(commonflags.ExpireAt, "e", 0, "The last active epoch for token to stay valid")

_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.WalletPath)
_ = cobra.MarkFlagRequired(createCmd.Flags(), outFlag)
_ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.RPC)
createCmd.MarkFlagsMutuallyExclusive(commonflags.ExpireAt, commonflags.Lifetime)
}

func createSession(cmd *cobra.Command, _ []string) {
Expand All @@ -62,14 +65,23 @@ func createSession(cmd *cobra.Command, _ []string) {
c, err := internalclient.GetSDKClient(ctx, netAddr)
common.ExitOnErr(cmd, "can't create client: %w", err)

endpoint, _ := cmd.Flags().GetString(commonflags.RPC)
currEpoch, err := internalclient.GetCurrentEpoch(ctx, endpoint)
common.ExitOnErr(cmd, "can't get current epoch: %w", err)

exp, _ := cmd.Flags().GetUint64(commonflags.ExpireAt)
lifetime := uint64(defaultLifetime)
if lfArg, _ := cmd.Flags().GetUint64(commonflags.Lifetime); lfArg != 0 {
lifetime = lfArg
exp = currEpoch + lfArg
}
if exp == 0 {
exp = currEpoch + lifetime
}
if exp <= currEpoch {
common.ExitOnErr(cmd, "", errors.New("expiration epoch must be greater than current epoch"))
}

var tok session.Object

err = CreateSession(ctx, &tok, c, *privKey, lifetime)
err = CreateSession(ctx, &tok, c, *privKey, exp, currEpoch)
common.ExitOnErr(cmd, "can't create session: %w", err)

var data []byte
Expand All @@ -91,21 +103,10 @@ func createSession(cmd *cobra.Command, _ []string) {
// number of epochs.
//
// Fills ID, lifetime and session key.
func CreateSession(ctx context.Context, dst *session.Object, c *client.Client, key ecdsa.PrivateKey, lifetime uint64) error {
var netInfoPrm internalclient.NetworkInfoPrm
netInfoPrm.SetClient(c)

ni, err := internalclient.NetworkInfo(ctx, netInfoPrm)
if err != nil {
return fmt.Errorf("can't fetch network info: %w", err)
}

cur := ni.NetworkInfo().CurrentEpoch()
exp := cur + lifetime

func CreateSession(ctx context.Context, dst *session.Object, c *client.Client, key ecdsa.PrivateKey, expireAt uint64, currEpoch uint64) error {
var sessionPrm internalclient.CreateSessionPrm
sessionPrm.SetClient(c)
sessionPrm.SetExp(exp)
sessionPrm.SetExp(expireAt)
sessionPrm.SetPrivateKey(key)

sessionRes, err := internalclient.CreateSession(ctx, sessionPrm)
Expand All @@ -130,9 +131,9 @@ func CreateSession(ctx context.Context, dst *session.Object, c *client.Client, k
}

dst.SetID(idSession)
dst.SetNbf(cur)
dst.SetIat(cur)
dst.SetExp(exp)
dst.SetNbf(currEpoch)
dst.SetIat(currEpoch)
dst.SetExp(expireAt)
dst.SetAuthKey(&keySession)

return nil
Expand Down
25 changes: 18 additions & 7 deletions cmd/neofs-cli/modules/storagegroup/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,18 @@ func initSGPutCmd() {
_ = sgPutCmd.MarkFlagRequired(sgMembersFlag)

flags.Uint64(commonflags.Lifetime, 0, "Storage group lifetime in epochs")
_ = sgPutCmd.MarkFlagRequired(commonflags.Lifetime)
flags.Uint64P(commonflags.ExpireAt, "e", 0, "The last active epoch of the storage group")
sgPutCmd.MarkFlagsMutuallyExclusive(commonflags.ExpireAt, commonflags.Lifetime)
}

func putSG(cmd *cobra.Command, _ []string) {
// with 1.8.0 cobra release we can use this instead of below
// sgPutCmd.MarkFlagsOneRequired("expire-at", "lifetime")
exp, _ := cmd.Flags().GetUint64(commonflags.ExpireAt)
lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
if exp == 0 && lifetime == 0 { // mutual exclusion is ensured by cobra
common.ExitOnErr(cmd, "", errors.New("expiration epoch or lifetime period is required"))
}
ctx, cancel := commonflags.GetCommandContext(cmd)
defer cancel()

Expand Down Expand Up @@ -101,14 +109,17 @@ func putSG(cmd *cobra.Command, _ []string) {
}, cnr, members, !resGetCnr.Container().IsHomomorphicHashingDisabled())
common.ExitOnErr(cmd, "could not collect storage group members: %w", err)

var netInfoPrm internalclient.NetworkInfoPrm
netInfoPrm.SetClient(cli)
if lifetime != 0 {
var netInfoPrm internalclient.NetworkInfoPrm
netInfoPrm.SetClient(cli)

ni, err := internalclient.NetworkInfo(ctx, netInfoPrm)
common.ExitOnErr(cmd, "can't fetch network info: %w", err)
ni, err := internalclient.NetworkInfo(ctx, netInfoPrm)
common.ExitOnErr(cmd, "can't fetch network info: %w", err)
currEpoch := ni.NetworkInfo().CurrentEpoch()
exp = currEpoch + lifetime
}

lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime)
sg.SetExpirationEpoch(ni.NetworkInfo().CurrentEpoch() + lifetime)
sg.SetExpirationEpoch(exp)

obj := object.New()
obj.SetContainerID(cnr)
Expand Down

0 comments on commit 3b463c0

Please sign in to comment.