diff --git a/cmd/cosmos-proposals-checker.go b/cmd/cosmos-proposals-checker.go index 4372413..099e8d1 100644 --- a/cmd/cosmos-proposals-checker.go +++ b/cmd/cosmos-proposals-checker.go @@ -28,21 +28,49 @@ func (fs *OsFS) Create(path string) (fs.File, error) { return os.Create(path) } -func Execute(configPath string) { +func ExecuteMain(configPath string) { filesystem := &OsFS{} app := pkg.NewApp(configPath, filesystem, version) app.Start() } +func ExecuteValidateConfig(configPath string) { + filesystem := &OsFS{} + + config, err := pkg.GetConfig(filesystem, configPath) + if err != nil { + logger.GetDefaultLogger().Fatal().Err(err).Msg("Could not load config!") + } + + if err := config.Validate(); err != nil { + logger.GetDefaultLogger().Fatal().Err(err).Msg("Config is invalid!") + } + + if warnings := config.DisplayWarnings(); len(warnings) > 0 { + config.LogWarnings(logger.GetDefaultLogger(), warnings) + } else { + logger.GetDefaultLogger().Info().Msg("Provided config is valid.") + } +} + func main() { var ConfigPath string rootCmd := &cobra.Command{ - Use: "cosmos-proposals-checker", + Use: "cosmos-proposals-checker --config [config path]", Long: "Checks the specific wallets on different chains for proposal votes.", Version: version, Run: func(cmd *cobra.Command, args []string) { - Execute(ConfigPath) + ExecuteMain(ConfigPath) + }, + } + + validateConfigCmd := &cobra.Command{ + Use: "validate-config --config [config path]", + Long: "Checks the specific wallets on different chains for proposal votes.", + Version: version, + Run: func(cmd *cobra.Command, args []string) { + ExecuteValidateConfig(ConfigPath) }, } @@ -51,6 +79,13 @@ func main() { logger.GetDefaultLogger().Fatal().Err(err).Msg("Could not set flag as required") } + validateConfigCmd.PersistentFlags().StringVar(&ConfigPath, "config", "", "Config file path") + if err := validateConfigCmd.MarkPersistentFlagRequired("config"); err != nil { + logger.GetDefaultLogger().Fatal().Err(err).Msg("Could not set flag as required") + } + + rootCmd.AddCommand(validateConfigCmd) + if err := rootCmd.Execute(); err != nil { logger.GetDefaultLogger().Fatal().Err(err).Msg("Could not start application") } diff --git a/config.example.toml b/config.example.toml index 0a2c231..f0d909c 100644 --- a/config.example.toml +++ b/config.example.toml @@ -71,7 +71,7 @@ keplr-name = "sentinel" mintscan-prefix = "sentinel" lcd-endpoints = ["https://lcd-sentinel-app.cosmostation.io", "https://lcd-sentinel.whispernode.com"] wallets = [ - "sent1rw9wtyhsus7jvx55v3qv5nzun054ma6kas4u3l" + { address = "sent1rw9wtyhsus7jvx55v3qv5nzun054ma6kas4u3l" } ] # PagerDuty notifier config. diff --git a/pkg/app.go b/pkg/app.go index 87a31d7..11172d6 100644 --- a/pkg/app.go +++ b/pkg/app.go @@ -36,6 +36,12 @@ func NewApp(configPath string, filesystem fs.FS, version string) *App { logger.GetDefaultLogger().Fatal().Err(err).Msg("Provided config is invalid!") } + if warnings := config.DisplayWarnings(); len(warnings) > 0 { + config.LogWarnings(logger.GetDefaultLogger(), warnings) + } else { + logger.GetDefaultLogger().Info().Msg("Provided config is valid.") + } + log := logger.GetLogger(config.LogConfig) stateManager := state.NewStateManager(config.StatePath, filesystem, log) diff --git a/pkg/types/chain.go b/pkg/types/chain.go index c383751..ee18bca 100644 --- a/pkg/types/chain.go +++ b/pkg/types/chain.go @@ -133,3 +133,25 @@ func (c *Chain) GetExplorer() *Explorer { return c.Explorer } + +func (c *Chain) DisplayWarnings() []Warning { + warnings := make([]Warning, 0) + + if c.Explorer == nil { + warnings = append(warnings, Warning{ + Labels: map[string]string{"chain": c.Name}, + Message: "explorer is not set, cannot generate links", + }) + } else { + warnings = append(warnings, c.Explorer.DisplayWarnings(c.Name)...) + } + + if c.KeplrName == "" { + warnings = append(warnings, Warning{ + Labels: map[string]string{"chain": c.Name}, + Message: "keplr-name is not set, cannot generate Keplr link to proposal", + }) + } + + return warnings +} diff --git a/pkg/types/chain_test.go b/pkg/types/chain_test.go index 89e91b6..2e312f5 100644 --- a/pkg/types/chain_test.go +++ b/pkg/types/chain_test.go @@ -131,3 +131,30 @@ func TestSetExplorerEmpty(t *testing.T) { explorer := chain.GetExplorer() assert.Nil(t, explorer) } + +func TestChainDisplayWarningsEmptyExplorer(t *testing.T) { + t.Parallel() + + chain := Chain{KeplrName: "test"} + warnings := chain.DisplayWarnings() + assert.Len(t, warnings, 1) +} + +func TestChainDisplayWarningsEmptyKeplrName(t *testing.T) { + t.Parallel() + + chain := Chain{Explorer: &Explorer{ProposalLinkPattern: "test", WalletLinkPattern: "test"}} + warnings := chain.DisplayWarnings() + assert.Len(t, warnings, 1) +} + +func TestChainDisplayWarningsOk(t *testing.T) { + t.Parallel() + + chain := Chain{ + Explorer: &Explorer{ProposalLinkPattern: "test", WalletLinkPattern: "test"}, + KeplrName: "test", + } + warnings := chain.DisplayWarnings() + assert.Empty(t, warnings) +} diff --git a/pkg/types/config.go b/pkg/types/config.go index 4e55d52..548b317 100644 --- a/pkg/types/config.go +++ b/pkg/types/config.go @@ -3,6 +3,8 @@ package types import ( "fmt" "time" + + "github.com/rs/zerolog" ) type Config struct { @@ -43,3 +45,39 @@ func (c *Config) Validate() error { return nil } + +func (c *Config) DisplayWarnings() []Warning { + warnings := make([]Warning, 0) + + for _, chain := range c.Chains { + warnings = append(warnings, chain.DisplayWarnings()...) + } + + if c.MutesPath == "" { + warnings = append(warnings, Warning{ + Labels: map[string]string{}, + Message: "mutes-path is not set, cannot persist proposals mutes on disk.", + }) + } + + if c.StatePath == "" { + warnings = append(warnings, Warning{ + Labels: map[string]string{}, + Message: "state-path is not set, cannot persist proposals state on disk.", + }) + } + + return warnings +} + +func (c *Config) LogWarnings(logger *zerolog.Logger, warnings []Warning) { + for _, warning := range warnings { + entry := logger.Warn() + + for key, label := range warning.Labels { + entry = entry.Str(key, label) + } + + entry.Msg(warning.Message) + } +} diff --git a/pkg/types/config_test.go b/pkg/types/config_test.go index e3f534e..8ee3eaa 100644 --- a/pkg/types/config_test.go +++ b/pkg/types/config_test.go @@ -3,6 +3,8 @@ package types import ( "testing" + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" @@ -202,3 +204,86 @@ func TestValidateConfigValidChain(t *testing.T) { err := config.Validate() require.NoError(t, err, "Error should not be presented!") } + +func TestConfigDisplayWarningInvalidChain(t *testing.T) { + t.Parallel() + + config := Config{ + Timezone: "Europe/Moscow", + StatePath: "test", + MutesPath: "test", + Chains: []*Chain{ + { + KeplrName: "test", + }, + }, + } + warnings := config.DisplayWarnings() + assert.Len(t, warnings, 1) +} + +func TestConfigDisplayWarningNoStatePath(t *testing.T) { + t.Parallel() + + config := Config{ + Timezone: "Europe/Moscow", + MutesPath: "test", + Chains: []*Chain{ + { + KeplrName: "test", + Explorer: &Explorer{WalletLinkPattern: "test", ProposalLinkPattern: "test"}, + }, + }, + } + warnings := config.DisplayWarnings() + assert.Len(t, warnings, 1) +} + +func TestConfigDisplayWarningNoMutesPath(t *testing.T) { + t.Parallel() + + config := Config{ + Timezone: "Europe/Moscow", + StatePath: "test", + Chains: []*Chain{ + { + KeplrName: "test", + Explorer: &Explorer{WalletLinkPattern: "test", ProposalLinkPattern: "test"}, + }, + }, + } + warnings := config.DisplayWarnings() + assert.Len(t, warnings, 1) +} + +func TestConfigDisplayWarningOk(t *testing.T) { + t.Parallel() + + config := Config{ + Timezone: "Europe/Moscow", + StatePath: "test", + MutesPath: "test", + Chains: []*Chain{ + { + KeplrName: "test", + Explorer: &Explorer{WalletLinkPattern: "test", ProposalLinkPattern: "test"}, + }, + }, + } + warnings := config.DisplayWarnings() + assert.Empty(t, warnings) +} + +func TestConfigLogWarnings(t *testing.T) { + t.Parallel() + + config := Config{ + Timezone: "Europe/Moscow", + Chains: []*Chain{ + {}, + }, + } + warnings := config.DisplayWarnings() + logger := zerolog.Nop() + config.LogWarnings(&logger, warnings) +} diff --git a/pkg/types/explorer.go b/pkg/types/explorer.go index 0e3f8e6..b0f6084 100644 --- a/pkg/types/explorer.go +++ b/pkg/types/explorer.go @@ -4,3 +4,23 @@ type Explorer struct { ProposalLinkPattern string `toml:"proposal-link-pattern"` WalletLinkPattern string `toml:"wallet-link-pattern"` } + +func (e *Explorer) DisplayWarnings(chainName string) []Warning { + warnings := make([]Warning, 0) + + if e.WalletLinkPattern == "" { + warnings = append(warnings, Warning{ + Labels: map[string]string{"chain": chainName}, + Message: "wallet-link-pattern for explorer is not set, cannot generate wallet links", + }) + } + + if e.ProposalLinkPattern == "" { + warnings = append(warnings, Warning{ + Labels: map[string]string{"chain": chainName}, + Message: "proposal-link-pattern for explorer is not set, cannot generate proposal links", + }) + } + + return warnings +} diff --git a/pkg/types/explorer_test.go b/pkg/types/explorer_test.go new file mode 100644 index 0000000..e81cb30 --- /dev/null +++ b/pkg/types/explorer_test.go @@ -0,0 +1,31 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestExplorerDisplayWarningsNoProposalsLinkPattern(t *testing.T) { + t.Parallel() + + explorer := &Explorer{WalletLinkPattern: "test"} + warnings := explorer.DisplayWarnings("test") + assert.Len(t, warnings, 1) +} + +func TestExplorerDisplayWarningsNoWalletLinkPattern(t *testing.T) { + t.Parallel() + + explorer := &Explorer{ProposalLinkPattern: "test"} + warnings := explorer.DisplayWarnings("test") + assert.Len(t, warnings, 1) +} + +func TestExplorerDisplayWarningsOk(t *testing.T) { + t.Parallel() + + explorer := &Explorer{ProposalLinkPattern: "test", WalletLinkPattern: "test"} + warnings := explorer.DisplayWarnings("test") + assert.Empty(t, warnings) +} diff --git a/pkg/types/warning.go b/pkg/types/warning.go new file mode 100644 index 0000000..76c3fe3 --- /dev/null +++ b/pkg/types/warning.go @@ -0,0 +1,6 @@ +package types + +type Warning struct { + Message string + Labels map[string]string +}