Compare commits

...

5 commits

Author SHA1 Message Date
fe6f3471f9 Reuse PrintChains function
Replace non-printable symbols by dot (.) when printing chain id

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-09-03 16:35:36 +03:00
39f8d20cfa Print resolved container id in list-container
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-09-03 15:41:05 +03:00
f9ac7b7f53 Use stdout as command output
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-09-03 15:39:03 +03:00
9cb198d411 Add printing user info
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-08-29 09:49:56 +03:00
c40ad3627d Add listing user/container chains by name
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-08-29 09:42:39 +03:00
10 changed files with 399 additions and 36 deletions

View file

@ -5,7 +5,7 @@ To build:
$ make
```
to list all container targets:
To list all container targets:
```
$ ./bin/policy-reader contract -r http://morph-chain.frostfs.devenv:30333 list-targets --type container
@ -15,10 +15,9 @@ Ei2Fz988ZUFEHUEXxTadouysebPGAW7vsxn1hSiYYzT (base64: 'RWkyRno5ODhaVUZFSFVFWH
Ew23XpQadxG5iyujTg2xPajaQXnN17tWSjgFk7Bv5ADj (base64: 'RXcyM1hwUWFkeEc1aXl1alRnMnhQYWphUVhuTjE3dFdTamdGazdCdjVBRGo=')
```
see additional params:
See additional params:
```
./bin/policy-reader -h
Helps reading policy information from contact in FrostFS network
Usage:
@ -29,6 +28,7 @@ Examples:
policy-reader --version
Available Commands:
chains Chain related policy operations
completion Generate the autocompletion script for the specified shell
contract Operations with policy contract
help Help about any command
@ -40,3 +40,8 @@ Flags:
Use "policy-reader [command] --help" for more information about a command.
```
Use:
* `policy-reader contract` to invoke contract functions
* `policy-reader chains` to list chains related to some entities (user/container) by name

3
go.mod
View file

@ -17,6 +17,7 @@ require (
git.frostfs.info/TrueCloudLab/hrw v1.2.1 // indirect
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
@ -35,6 +36,7 @@ require (
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect
github.com/nspcc-dev/rfc6979 v0.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
@ -44,6 +46,7 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
github.com/urfave/cli v1.22.5 // indirect
go.etcd.io/bbolt v1.3.9 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect

5
go.sum
View file

@ -12,6 +12,7 @@ git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b h
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A=
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA=
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -24,6 +25,7 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc=
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -117,12 +119,14 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
@ -225,6 +229,7 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

56
internal/output/chains.go Normal file
View file

@ -0,0 +1,56 @@
package output
import (
"encoding/base64"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/spf13/cobra"
)
const (
minPrintable = 32
maxPrintable = 127
)
func PrintChains(cmd *cobra.Command, list []stackitem.Item, decodeChain, decodeID bool) error {
for _, item := range list {
bytes, err := item.TryBytes()
if err != nil {
return err
}
if !decodeChain {
cmd.Println(string(bytes))
continue
}
var chain apechain.Chain
if err = chain.DecodeBytes(bytes); err != nil {
cmd.PrintErrf("invalid chain format: %s\n", base64.StdEncoding.EncodeToString(bytes))
continue
}
raw, err := chain.MarshalJSON()
if err != nil {
return err
}
if decodeID {
var printableID string
for _, r := range string(chain.ID) {
if minPrintable <= r && r <= maxPrintable {
printableID += string(r)
} else {
printableID += "."
}
}
cmd.Println(printableID, string(raw))
} else {
cmd.Println(string(raw))
}
}
return nil
}

View file

@ -5,6 +5,7 @@ import (
"strings"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ns"
"github.com/nspcc-dev/neo-go/pkg/util"
)
@ -32,3 +33,25 @@ func ResolveContractHash(endpoint, contractHash string) (util.Uint160, error) {
return nns.ResolveContractHash(domain)
}
// ResolveContainerID determine container id by resolving NNS name.
func ResolveContainerID(endpoint, namespace, containerName string) (cid.ID, error) {
var cnrID cid.ID
if err := cnrID.DecodeString(containerName); err == nil {
return cnrID, nil
}
var domain container.Domain
domain.SetName(containerName)
if namespace != "" {
domain.SetZone(namespace + ".ns")
}
var nns ns.NNS
if err := nns.Dial(endpoint); err != nil {
return cid.ID{}, fmt.Errorf("dial nns %s: %w", endpoint, err)
}
defer nns.Close()
return nns.ResolveContainerDomain(domain)
}

View file

@ -0,0 +1,83 @@
package chains
import (
"math/big"
"git.frostfs.info/TrueCloudLab/frostfs-contract/commonclient"
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
"git.frostfs.info/dkirillov/policy-reader/internal/output"
"git.frostfs.info/dkirillov/policy-reader/internal/resolver"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var listContainerCmd = &cobra.Command{
Use: "list-container",
Short: "List container related policies",
Long: "List container related policies along with filtering by service (s3/storage)",
Example: `policy-reader container -r http://localhost:40332 list --container 7h7NcXcF6k6b1yidqEHc1jkyXUm1MfUDrrTuHAefhiDe
policy-reader container -r http://localhost:40332 --policy-hash 81c1a41d09e08087a4b679418b12be5d3ab15742 list --container 7h7NcXcF6k6b1yidqEHc1jkyXUm1MfUDrrTuHAefhiDe --namespace test`,
RunE: runListContainerCmd,
}
const (
containerFlag = "container"
)
func initListContainerCmd() {
listContainerCmd.Flags().String(containerFlag, "", "Container id or bucket name in nns (if name is provided than 'namespace' should be set too)")
listContainerCmd.Flags().String(namespaceFlag, "", "Namespace where container name will be looked up")
listContainerCmd.Flags().String(serviceFlag, "none", "Service (none/s3/storage) to filter chains")
listContainerCmd.Flags().Bool(decodeIDFlag, false, "Use this flag to additionally decode chain id")
_ = listContainerCmd.MarkFlagRequired(containerFlag)
}
func runListContainerCmd(cmd *cobra.Command, _ []string) error {
service, err := parseService(viper.GetString(serviceFlag))
if err != nil {
return err
}
endpoint := viper.GetString(rpcEndpointFlag)
ns := viper.GetString(namespaceFlag)
cnrID, err := resolver.ResolveContainerID(endpoint, ns, viper.GetString(containerFlag))
if err != nil {
return err
}
policyHash, err := resolver.ResolveContractHash(endpoint, viper.GetString(policyHashFlag))
if err != nil {
return err
}
rpcCli, err := rpcclient.New(cmd.Context(), endpoint, rpcclient.Options{})
if err != nil {
return err
}
res, err := commonclient.ReadIteratorItems(invoker.New(rpcCli, nil), 100, policyHash, "iteratorChainsByPrefix", big.NewInt(int64(policycontract.Namespace)), ns, string(service))
if err != nil {
return err
}
const decodeChain = true
decodeID := viper.GetBool(decodeIDFlag)
cmd.Println("cid:", cnrID)
cmd.Printf("namespace '%s' policies: %d\n", ns, len(res))
if err = output.PrintChains(cmd, res, decodeChain, decodeID); err != nil {
return err
}
res, err = commonclient.ReadIteratorItems(invoker.New(rpcCli, nil), 100, policyHash, "iteratorChainsByPrefix", big.NewInt(int64(policycontract.Container)), cnrID.String(), string(service))
if err != nil {
return err
}
cmd.Printf("container policies: %d\n", len(res))
return output.PrintChains(cmd, res, decodeChain, decodeID)
}

175
modules/chains/list_user.go Normal file
View file

@ -0,0 +1,175 @@
package chains
import (
"encoding/hex"
"errors"
"fmt"
"math/big"
"git.frostfs.info/TrueCloudLab/frostfs-contract/commonclient"
ffsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/dkirillov/policy-reader/internal/output"
"git.frostfs.info/dkirillov/policy-reader/internal/resolver"
neoflags "github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var listUserCmd = &cobra.Command{
Use: "list-user",
Short: "List user related policies",
Long: "List user related policies along with filtering by service (s3/storage)",
Example: `policy-reader user -r http://localhost:40332 list --user NiGqBpUdMvAC68SxUeyYwVPyBCsqzNuof
policy-reader user -r http://localhost:40332 --policy-hash 81c1a41d09e08087a4b679418b12be5d3ab15742 list --user NiGqBpUdMvAC68SxUeyYwVPyBCsqzNuofL --service s3`,
RunE: runListCmd,
}
var errUnknownServiceType = errors.New("unknown service type")
const (
userFlag = "user"
namespaceFlag = "namespace"
serviceFlag = "service"
decodeIDFlag = "decode-id"
)
func initListUserCmd() {
listUserCmd.Flags().String(userFlag, "", "User address or name in frostfsid contract (if name is provided than 'namespace' should be set too)")
listUserCmd.Flags().String(namespaceFlag, "", "Namespace where user name will be looked up")
listUserCmd.Flags().String(serviceFlag, "none", "Service (none/s3/storage) to filter chains")
listUserCmd.Flags().Bool(decodeIDFlag, false, "Use this flag to additionally decode chain id")
_ = listUserCmd.MarkFlagRequired(userFlag)
}
func runListCmd(cmd *cobra.Command, _ []string) error {
service, err := parseService(viper.GetString(serviceFlag))
if err != nil {
return err
}
endpoint := viper.GetString(rpcEndpointFlag)
policyHash, err := resolver.ResolveContractHash(endpoint, viper.GetString(policyHashFlag))
if err != nil {
return err
}
frostfsidHash, err := resolver.ResolveContractHash(endpoint, viper.GetString(frostfsidHashFlag))
if err != nil {
return err
}
rpcCli, err := rpcclient.New(cmd.Context(), endpoint, rpcclient.Options{})
if err != nil {
return err
}
acc, err := wallet.NewAccount()
if err != nil {
return err
}
ffsidCli, err := ffsidclient.New(rpcCli, acc, frostfsidHash, ffsidclient.Options{})
if err != nil {
return err
}
subj, err := resolveSubject(ffsidCli, viper.GetString(namespaceFlag), viper.GetString(userFlag))
if err != nil {
return err
}
printSubject(cmd, subj)
res, err := commonclient.ReadIteratorItems(invoker.New(rpcCli, nil), 100, policyHash, "iteratorChainsByPrefix", big.NewInt(int64(policycontract.Namespace)), subj.Namespace, string(service))
if err != nil {
return err
}
const decodeChain = true
decodeID := viper.GetBool(decodeIDFlag)
cmd.Printf("user namespace '%s' policies: %d\n", subj.Namespace, len(res))
if err = output.PrintChains(cmd, res, decodeID, decodeID); err != nil {
return err
}
userEntity := big.NewInt(int64(policycontract.User))
userEntityName := fmt.Sprintf("%s:%s", subj.Namespace, subj.PrimaryKey.Address())
res, err = commonclient.ReadIteratorItems(invoker.New(rpcCli, nil), 100, policyHash, "iteratorChainsByPrefix", userEntity, userEntityName, string(service))
if err != nil {
return err
}
cmd.Printf("user policies: %d\n", len(res))
if err = output.PrintChains(cmd, res, decodeChain, decodeID); err != nil {
return err
}
cmd.Printf("user group policies: %d\n", len(subj.Groups))
groupEntity := big.NewInt(int64(policycontract.Group))
for _, group := range subj.Groups {
groupEntityName := fmt.Sprintf("%s:%d", group.Namespace, group.ID)
res, err = commonclient.ReadIteratorItems(invoker.New(rpcCli, nil), 100, policyHash, "iteratorChainsByPrefix", groupEntity, groupEntityName, string(service))
if err != nil {
return err
}
cmd.Printf("user group '%s' (id: %d) policies: %d\n", group.Name, group.ID, len(res))
if err = output.PrintChains(cmd, res, decodeChain, decodeID); err != nil {
return err
}
}
return nil
}
func resolveSubject(ffsid *ffsidclient.Client, namespace, userName string) (*ffsidclient.SubjectExtended, error) {
if userHash, err := neoflags.ParseAddress(userName); err == nil {
subj, err := ffsid.GetSubject(userHash)
if err != nil {
return nil, err
}
return ffsid.GetSubjectExtended(subj.PrimaryKey.GetScriptHash())
}
subj, err := ffsid.GetSubjectByName(namespace, userName)
if err != nil {
return nil, err
}
return ffsid.GetSubjectExtended(subj.PrimaryKey.GetScriptHash())
}
func parseService(service string) (apechain.Name, error) {
switch service {
case "none":
return "", nil
case "s3":
return apechain.S3, nil
case "storage":
return apechain.Ingress, nil
}
return "", errUnknownServiceType
}
func printSubject(cmd *cobra.Command, subj *ffsidclient.SubjectExtended) {
cmd.Println("ns:", subj.Namespace)
cmd.Println("name:", subj.Name)
cmd.Println("key:", hex.EncodeToString(subj.PrimaryKey.Bytes()))
cmd.Println("claims:")
for k, v := range subj.KV {
cmd.Println(k, v)
}
}

38
modules/chains/root.go Normal file
View file

@ -0,0 +1,38 @@
package chains
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var Cmd = &cobra.Command{
Use: "chains",
Short: "Chain related policy operations",
Long: "Chain related policy operations",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
if viper.IsSet(rpcEndpointFlag) {
return cmd.Parent().PersistentFlags().Set(rpcEndpointFlag, viper.GetString(rpcEndpointFlag))
}
return nil
},
}
const (
rpcEndpointFlag = "rpc-endpoint"
policyHashFlag = "policy-hash"
frostfsidHashFlag = "frostfsid-hash"
)
func init() {
Cmd.PersistentFlags().StringP(rpcEndpointFlag, "r", "", "Neo-go endpoint")
Cmd.PersistentFlags().String(policyHashFlag, "policy.frostfs", "NNS name or script hash of policy contract")
Cmd.PersistentFlags().String(frostfsidHashFlag, "frostfsid.frostfs", "NNS name or script hash of frostfsid contract")
_ = Cmd.MarkPersistentFlagRequired(rpcEndpointFlag)
Cmd.AddCommand(listUserCmd)
initListUserCmd()
Cmd.AddCommand(listContainerCmd)
initListContainerCmd()
}

View file

@ -4,7 +4,7 @@ import (
"encoding/base64"
"git.frostfs.info/TrueCloudLab/frostfs-contract/commonclient"
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/dkirillov/policy-reader/internal/output"
"git.frostfs.info/dkirillov/policy-reader/internal/resolver"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
@ -90,36 +90,6 @@ func runListChainsByPrefixCmd(cmd *cobra.Command, _ []string) error {
cmd.Printf("%s target chains names: %d\n", typ, len(res))
decodeID := viper.GetBool(decodeIDFlag)
for _, re := range res {
bytes, err := re.TryBytes()
if err != nil {
return err
}
if typ == "iam" {
cmd.Println(string(bytes))
continue
}
var chain apechain.Chain
if err = chain.DecodeBytes(bytes); err != nil {
cmd.Printf("invalid chain format: %s\n", base64.StdEncoding.EncodeToString(bytes))
continue
}
raw, err := chain.MarshalJSON()
if err != nil {
return err
}
if decodeID {
cmd.Println(string(chain.ID), string(raw))
} else {
cmd.Println(string(raw))
}
}
return nil
decodeChain := typ != "iam"
return output.PrintChains(cmd, res, decodeChain, viper.GetBool(decodeIDFlag))
}

View file

@ -7,6 +7,7 @@ import (
"strings"
"git.frostfs.info/dkirillov/policy-reader/internal/version"
"git.frostfs.info/dkirillov/policy-reader/modules/chains"
"git.frostfs.info/dkirillov/policy-reader/modules/contract"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -51,6 +52,9 @@ const configFlag = "config"
func init() {
cobra.EnableTraverseRunHooks = true
rootCmd.SetOut(os.Stdout)
rootCmd.PersistentFlags().StringP(configFlag, "c", "", "Path to config file")
cobra.AddTemplateFunc("runtimeVersion", runtime.Version)
@ -60,6 +64,7 @@ GoVersion: {{ runtimeVersion }}
`)
rootCmd.AddCommand(contract.Cmd)
rootCmd.AddCommand(chains.Cmd)
}
func readConfig(v *viper.Viper, fileName string) error {