diff --git a/modules/contract/list_chain_names.go b/modules/contract/list_chain_names.go index d2a0a04..9dd05e2 100644 --- a/modules/contract/list_chain_names.go +++ b/modules/contract/list_chain_names.go @@ -12,17 +12,29 @@ import ( ) var listChainNamesCmd = &cobra.Command{ - Use: "list-chain-names", + Use: "list-chain-names", + Short: "Invoke 'listChainNames' method", + Long: "Invoke 'listChainNames' method in policy contract and print results to stdout", + Example: `policy-reader contract -r http://localhost:40332 list-chain-names +policy-reader contract -r http://localhost:40332 --policy-hash 81c1a41d09e08087a4b679418b12be5d3ab15742 list-chain-names --type container --name 7h7NcXcF6k6b1yidqEHc1jkyXUm1MfUDrrTuHAefhiDe`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + if viper.IsSet(nameFlag) { + return cmd.Flags().Set(nameFlag, viper.GetString(nameFlag)) + } + return nil + }, RunE: runListChainNamesCmd, } const ( - nameFlag = "name" + nameFlag = "name" + nameBase64Flag = "name-base64" ) func initListChainNamesCmd() { listChainNamesCmd.Flags().String(typeFlag, "namespace", "Target type to list (namespace/container/group/user/iam)") listChainNamesCmd.Flags().String(nameFlag, "", "Target name to list") + listChainNamesCmd.Flags().Bool(nameBase64Flag, false, "Use this flag if you provide name in base64 format") _ = listChainNamesCmd.MarkFlagRequired(nameFlag) } @@ -34,7 +46,15 @@ func runListChainNamesCmd(cmd *cobra.Command, _ []string) error { return err } - entityName := viper.GetString(nameFlag) + entityNameStr := viper.GetString(nameFlag) + var entityName []byte + if viper.GetBool(nameBase64Flag) { + if entityName, err = base64.StdEncoding.DecodeString(entityNameStr); err != nil { + return err + } + } else { + entityName = []byte(entityNameStr) + } endpoint := viper.GetString(rpcEndpointFlag) diff --git a/modules/contract/list_chains_by_prefix.go b/modules/contract/list_chains_by_prefix.go index f1d93a7..4ab6cfc 100644 --- a/modules/contract/list_chains_by_prefix.go +++ b/modules/contract/list_chains_by_prefix.go @@ -13,13 +13,24 @@ import ( ) var listChainsByPrefixCmd = &cobra.Command{ - Use: "list-chains-by-prefix", + Use: "list-chains-by-prefix", + Short: "Invoke 'iteratorChainsByPrefix' method", + Long: "Invoke 'iteratorChainsByPrefix' method in policy contract and print results to stdout", + Example: `policy-reader contract -r http://localhost:40332 list-chains-by-prefix +policy-reader contract -r http://localhost:40332 --policy-hash 81c1a41d09e08087a4b679418b12be5d3ab15742 list-chains-by-prefix --type container --name 7h7NcXcF6k6b1yidqEHc1jkyXUm1MfUDrrTuHAefhiDe`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + if viper.IsSet(nameFlag) { + return cmd.Flags().Set(nameFlag, viper.GetString(nameFlag)) + } + return nil + }, RunE: runListChainsByPrefixCmd, } const ( prefixFlag = "prefix" prefixBase64Flag = "prefix-base64" + decodeIDFlag = "decode-id" ) func initListChainsByPrefixCmd() { @@ -27,6 +38,8 @@ func initListChainsByPrefixCmd() { listChainsByPrefixCmd.Flags().String(nameFlag, "", "Target name to list") listChainsByPrefixCmd.Flags().String(prefixFlag, "", "Prefix to list") listChainsByPrefixCmd.Flags().Bool(prefixBase64Flag, false, "Use this flag if you provide prefix in base64 format") + listChainsByPrefixCmd.Flags().Bool(nameBase64Flag, false, "Use this flag if you provide name in base64 format") + listChainsByPrefixCmd.Flags().Bool(decodeIDFlag, false, "Use this flag to additionally decode chain id") _ = listChainsByPrefixCmd.MarkFlagRequired(nameFlag) } @@ -38,9 +51,17 @@ func runListChainsByPrefixCmd(cmd *cobra.Command, _ []string) error { return err } - entityName := viper.GetString(nameFlag) - prefixStr := viper.GetString(prefixFlag) + entityNameStr := viper.GetString(nameFlag) + var entityName []byte + if viper.GetBool(nameBase64Flag) { + if entityName, err = base64.StdEncoding.DecodeString(entityNameStr); err != nil { + return err + } + } else { + entityName = []byte(entityNameStr) + } + prefixStr := viper.GetString(prefixFlag) var prefix []byte if viper.GetBool(prefixBase64Flag) { if prefix, err = base64.StdEncoding.DecodeString(prefixStr); err != nil { @@ -69,28 +90,35 @@ 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 } - var data []byte if typ == "iam" { - data = bytes - } else { - var chain apechain.Chain - if err = chain.DecodeBytes(bytes); err != nil { - cmd.Printf("invalid chain format: %s\n", base64.StdEncoding.EncodeToString(bytes)) - continue - } - - if data, err = chain.MarshalJSON(); err != nil { - return err - } + cmd.Println(string(bytes)) + continue } - cmd.Println(string(data)) + 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 diff --git a/modules/contract/list_targets.go b/modules/contract/list_targets.go index 356117e..cef6cbe 100644 --- a/modules/contract/list_targets.go +++ b/modules/contract/list_targets.go @@ -15,7 +15,11 @@ import ( ) var listTargetsCmd = &cobra.Command{ - Use: "list-targets", + Use: "list-targets", + Short: "Invoke 'listTargets' method", + Long: "Invoke 'listTargets' method in policy contract and print results to stdout", + Example: `policy-reader contract -r http://localhost:40332 list-targets +policy-reader contract -r http://localhost:40332 --policy-hash 81c1a41d09e08087a4b679418b12be5d3ab15742 list-targets --type container`, RunE: runListTargetsCmd, } diff --git a/modules/contract/root.go b/modules/contract/root.go index 1001428..1a50591 100644 --- a/modules/contract/root.go +++ b/modules/contract/root.go @@ -2,11 +2,19 @@ package contract import ( "github.com/spf13/cobra" + "github.com/spf13/viper" ) var Cmd = &cobra.Command{ Use: "contract", Short: "Operations with policy contract", + Long: "Operations with policy contract", + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { + if viper.IsSet(rpcEndpointFlag) { + return cmd.Parent().PersistentFlags().Set(rpcEndpointFlag, viper.GetString(rpcEndpointFlag)) + } + return nil + }, } const ( diff --git a/modules/root.go b/modules/root.go index 50121d1..d42622e 100644 --- a/modules/root.go +++ b/modules/root.go @@ -2,6 +2,7 @@ package modules import ( "context" + "os" "runtime" "strings" @@ -22,11 +23,20 @@ var rootCmd = &cobra.Command{ SilenceUsage: true, PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { viper.AutomaticEnv() - viper.SetEnvPrefix("POLICY_READER}") + viper.SetEnvPrefix("POLICY_READER") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) viper.AllowEmptyEnv(true) + viper.SetConfigType("yaml") - return viper.BindPFlags(cmd.Flags()) + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + + if viper.IsSet(configFlag) { + return readConfig(viper.GetViper(), viper.GetString(configFlag)) + } + + return nil }, RunE: func(cmd *cobra.Command, _ []string) error { return cmd.Help() @@ -40,6 +50,7 @@ func Execute(ctx context.Context) (*cobra.Command, error) { const configFlag = "config" func init() { + cobra.EnableTraverseRunHooks = true rootCmd.PersistentFlags().StringP(configFlag, "c", "", "Path to config file") cobra.AddTemplateFunc("runtimeVersion", runtime.Version) @@ -50,3 +61,18 @@ GoVersion: {{ runtimeVersion }} rootCmd.AddCommand(contract.Cmd) } + +func readConfig(v *viper.Viper, fileName string) error { + cfgFile, err := os.Open(fileName) + if err != nil { + return err + } + + defer func() { + if errClose := cfgFile.Close(); errClose != nil { + panic(errClose) + } + }() + + return v.ReadConfig(cfgFile) +}