forked from TrueCloudLab/frostfs-node
[#1501] cmd: Introduce common APE-chain parser commands
* Introduce common parsing commands to use them in `frostfs-cli` and `frostfs-adm` APE-related subcommands * Introduce common flags for these parsing commands Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
parent
ffe9906266
commit
7a7ee71a4d
2 changed files with 144 additions and 0 deletions
|
@ -1,13 +1,43 @@
|
||||||
package ape
|
package ape
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
||||||
|
apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultNamespace = "root"
|
||||||
|
namespaceTarget = "namespace"
|
||||||
|
containerTarget = "container"
|
||||||
|
userTarget = "user"
|
||||||
|
groupTarget = "group"
|
||||||
|
|
||||||
|
Ingress = "ingress"
|
||||||
|
S3 = "s3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mChainName = map[string]apechain.Name{
|
||||||
|
Ingress: apechain.Ingress,
|
||||||
|
S3: apechain.S3,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errSettingDefaultValueWasDeclined = errors.New("setting default value was declined")
|
||||||
|
errUnknownTargetType = errors.New("unknown target type")
|
||||||
|
errUnsupportedChainName = errors.New("unsupported chain name")
|
||||||
|
)
|
||||||
|
|
||||||
// PrintHumanReadableAPEChain print APE chain rules.
|
// PrintHumanReadableAPEChain print APE chain rules.
|
||||||
func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
|
func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
|
||||||
cmd.Println("Chain ID: " + string(chain.ID))
|
cmd.Println("Chain ID: " + string(chain.ID))
|
||||||
|
@ -39,3 +69,98 @@ func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseTarget handles target parsing of an APE chain.
|
||||||
|
func ParseTarget(cmd *cobra.Command) engine.Target {
|
||||||
|
typ := ParseTargetType(cmd)
|
||||||
|
name, _ := cmd.Flags().GetString(TargetNameFlag)
|
||||||
|
switch typ {
|
||||||
|
case engine.Namespace:
|
||||||
|
if name == "" {
|
||||||
|
ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace))
|
||||||
|
commonCmd.ExitOnErr(cmd, "read line error: %w", err)
|
||||||
|
ln = strings.ToLower(ln)
|
||||||
|
if len(ln) > 0 && (ln[0] == 'n') {
|
||||||
|
commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined)
|
||||||
|
}
|
||||||
|
name = defaultNamespace
|
||||||
|
}
|
||||||
|
return engine.NamespaceTarget(name)
|
||||||
|
case engine.Container:
|
||||||
|
var cnr cid.ID
|
||||||
|
commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name))
|
||||||
|
return engine.ContainerTarget(name)
|
||||||
|
case engine.User:
|
||||||
|
return engine.UserTarget(name)
|
||||||
|
case engine.Group:
|
||||||
|
return engine.GroupTarget(name)
|
||||||
|
default:
|
||||||
|
commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType)
|
||||||
|
}
|
||||||
|
return engine.Target{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseTargetType handles target type parsing of an APE chain.
|
||||||
|
func ParseTargetType(cmd *cobra.Command) engine.TargetType {
|
||||||
|
typ, _ := cmd.Flags().GetString(TargetTypeFlag)
|
||||||
|
switch typ {
|
||||||
|
case namespaceTarget:
|
||||||
|
return engine.Namespace
|
||||||
|
case containerTarget:
|
||||||
|
return engine.Container
|
||||||
|
case userTarget:
|
||||||
|
return engine.User
|
||||||
|
case groupTarget:
|
||||||
|
return engine.Group
|
||||||
|
}
|
||||||
|
commonCmd.ExitOnErr(cmd, "parse target type error: %w", errUnknownTargetType)
|
||||||
|
return engine.TargetType(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseChainID handles the parsing of APE-chain identifier.
|
||||||
|
// For some subcommands, chain ID is optional as an input parameter and should be generated by
|
||||||
|
// the service instead.
|
||||||
|
func ParseChainID(cmd *cobra.Command) (id apechain.ID) {
|
||||||
|
chainID, _ := cmd.Flags().GetString(ChainIDFlag)
|
||||||
|
id = apechain.ID(chainID)
|
||||||
|
|
||||||
|
hexEncoded, _ := cmd.Flags().GetBool(ChainIDHexFlag)
|
||||||
|
if !hexEncoded {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
chainIDRaw, err := hex.DecodeString(chainID)
|
||||||
|
commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err)
|
||||||
|
id = apechain.ID(chainIDRaw)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseChain parses an APE chain which can be provided either as a rule statement
|
||||||
|
// or loaded from a binary/JSON file path.
|
||||||
|
func ParseChain(cmd *cobra.Command) *apechain.Chain {
|
||||||
|
chain := new(apechain.Chain)
|
||||||
|
chain.ID = ParseChainID(cmd)
|
||||||
|
|
||||||
|
if rules, _ := cmd.Flags().GetStringArray(RuleFlag); len(rules) > 0 {
|
||||||
|
commonCmd.ExitOnErr(cmd, "parser error: %w", apeutil.ParseAPEChain(chain, rules))
|
||||||
|
} else if encPath, _ := cmd.Flags().GetString(PathFlag); encPath != "" {
|
||||||
|
commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", apeutil.ParseAPEChainBinaryOrJSON(chain, encPath))
|
||||||
|
} else {
|
||||||
|
commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed"))
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Println("Parsed chain:")
|
||||||
|
PrintHumanReadableAPEChain(cmd, chain)
|
||||||
|
|
||||||
|
return chain
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseChainName parses chain name: the place in the request lifecycle where policy is applied.
|
||||||
|
func ParseChainName(cmd *cobra.Command) apechain.Name {
|
||||||
|
chainName, _ := cmd.Flags().GetString(ChainNameFlag)
|
||||||
|
apeChainName, ok := mChainName[strings.ToLower(chainName)]
|
||||||
|
if !ok {
|
||||||
|
commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName)
|
||||||
|
}
|
||||||
|
return apeChainName
|
||||||
|
}
|
||||||
|
|
19
cmd/internal/common/ape/flags.go
Normal file
19
cmd/internal/common/ape/flags.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package ape
|
||||||
|
|
||||||
|
const (
|
||||||
|
RuleFlag = "rule"
|
||||||
|
RuleFlagDesc = "Rule statement"
|
||||||
|
PathFlag = "path"
|
||||||
|
PathFlagDesc = "Path to encoded chain in JSON or binary format"
|
||||||
|
TargetNameFlag = "target-name"
|
||||||
|
TargetNameFlagDesc = "Resource name in APE resource name format"
|
||||||
|
TargetTypeFlag = "target-type"
|
||||||
|
TargetTypeFlagDesc = "Resource type(container/namespace)"
|
||||||
|
ChainIDFlag = "chain-id"
|
||||||
|
ChainIDFlagDesc = "Chain id"
|
||||||
|
ChainIDHexFlag = "chain-id-hex"
|
||||||
|
ChainIDHexFlagDesc = "Flag to parse chain ID as hex"
|
||||||
|
ChainNameFlag = "chain-name"
|
||||||
|
ChainNameFlagDesc = "Chain name(ingress|s3)"
|
||||||
|
AllFlag = "all"
|
||||||
|
)
|
Loading…
Reference in a new issue