1
0
Fork 0
mirror of https://github.com/eosswedenorg/thalos synced 2026-06-16 04:24:56 +02:00

tools: cleanup and refactor to make code more readable.

This commit is contained in:
Henrik Hautakoski 2024-06-19 21:45:45 +02:00
parent ea5b2b8fc2
commit 8b8867394f
6 changed files with 341 additions and 328 deletions

View file

@ -18,101 +18,108 @@ import (
log "github.com/sirupsen/logrus"
)
var benchCmd = &cobra.Command{
Use: "bench",
Short: "Run a benchmark against a thalos node",
Run: func(cmd *cobra.Command, args []string) {
counter := 0
interval, _ := cmd.Flags().GetDuration("interval")
func CreateBenchCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "bench",
Short: "Run a benchmark against a thalos node",
Run: func(cmd *cobra.Command, args []string) {
counter := 0
interval, _ := cmd.Flags().GetDuration("interval")
url, _ := cmd.Flags().GetString("redis-url")
user, _ := cmd.Flags().GetString("redis-user")
pw, _ := cmd.Flags().GetString("redis-pw")
prefix, _ := cmd.Flags().GetString("prefix")
chain_id, _ := cmd.Flags().GetString("chain_id")
db, _ := cmd.Flags().GetInt("redis-db")
url, _ := cmd.Flags().GetString("redis-url")
user, _ := cmd.Flags().GetString("redis-user")
pw, _ := cmd.Flags().GetString("redis-pw")
prefix, _ := cmd.Flags().GetString("prefix")
chain_id, _ := cmd.Flags().GetString("chain_id")
db, _ := cmd.Flags().GetInt("redis-db")
log.WithFields(log.Fields{
"url": url,
"prefix": prefix,
"chain_id": chain_id,
"database": db,
}).Info("Connecting to redis")
log.WithFields(log.Fields{
"url": url,
"prefix": prefix,
"chain_id": chain_id,
"database": db,
}).Info("Connecting to redis")
// Create redis client
rdb := redis.NewClient(&redis.Options{
Addr: url,
Username: user,
Password: pw,
DB: db,
})
// Create redis client
rdb := redis.NewClient(&redis.Options{
Addr: url,
Username: user,
Password: pw,
DB: db,
})
if err := rdb.Ping(context.Background()).Err(); err != nil {
log.WithError(err).Fatal("Failed to connect to redis")
return
}
if err := rdb.Ping(context.Background()).Err(); err != nil {
log.WithError(err).Fatal("Failed to connect to redis")
return
}
log.Println("Connected to redis")
log.Println("Connected to redis")
log.WithFields(log.Fields{
"interval": interval,
}).Info("Starting benchmark")
log.WithFields(log.Fields{
"interval": interval,
}).Info("Starting benchmark")
sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{
Prefix: prefix,
ChainID: chain_id,
})
sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{
Prefix: prefix,
ChainID: chain_id,
})
codec, err := message.GetCodec("json")
if err != nil {
log.WithError(err).Fatal("Failed to get codec")
return
}
codec, err := message.GetCodec("json")
if err != nil {
log.WithError(err).Fatal("Failed to get codec")
return
}
client := api.NewClient(sub, codec.Decoder)
client := api.NewClient(sub, codec.Decoder)
// Subscribe to all actions
if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil {
log.WithError(err).Fatal("Failed to subscribe to channels")
return
}
// Subscribe to all actions
if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil {
log.WithError(err).Fatal("Failed to subscribe to channels")
return
}
go func() {
for t := range client.Channel() {
switch err := t.(type) {
case message.ActionTrace:
counter++
case error:
log.WithError(err).Error("Error when reading stream")
go func() {
for t := range client.Channel() {
switch err := t.(type) {
case message.ActionTrace:
counter++
case error:
log.WithError(err).Error("Error when reading stream")
}
}
}()
t := time.Now()
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
// Read stuff.
for {
select {
case <-sig:
fmt.Println("Got interrupt")
client.Close()
return
case now := <-time.After(interval):
elapsed := now.Sub(t)
t = now
log.WithFields(log.Fields{
"num_messages": counter,
"elapsed": elapsed,
"msg_per_sec": float64(counter) / elapsed.Seconds(),
"msg_per_ms": float64(counter) / float64(elapsed.Milliseconds()),
"msg_per_min": float64(counter) / elapsed.Minutes(),
}).Info("Benchmark results")
counter = 0
}
}
}()
},
}
t := time.Now()
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
cmd.Flags().AddFlagSet(RedisFlags())
cmd.Flags().DurationP("interval", "i", time.Minute, "How often the benchmark results should be displayed.")
// Read stuff.
for {
select {
case <-sig:
fmt.Println("Got interrupt")
client.Close()
return
case now := <-time.After(interval):
elapsed := now.Sub(t)
t = now
log.WithFields(log.Fields{
"num_messages": counter,
"elapsed": elapsed,
"msg_per_sec": float64(counter) / elapsed.Seconds(),
"msg_per_ms": float64(counter) / float64(elapsed.Milliseconds()),
"msg_per_min": float64(counter) / elapsed.Minutes(),
}).Info("Benchmark results")
counter = 0
}
}
},
return cmd
}

14
cmd/tools/flags.go Normal file
View file

@ -0,0 +1,14 @@
package main
import "github.com/spf13/pflag"
func RedisFlags() *pflag.FlagSet {
set := pflag.FlagSet{}
set.String("redis-url", "127.0.0.1:6379", "host:port to the redis server")
set.String("redis-user", "", "User to use when authenticating to the server")
set.String("redis-pw", "", "Password to use when authenticating to the server")
set.Int("redis-db", 0, "What redis database we should connect to.")
set.String("prefix", "ship", "redis prefix")
set.String("chain_id", "1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4", "chain id")
return &set
}

View file

@ -1,28 +1,15 @@
package main
import (
"time"
_ "github.com/eosswedenorg/thalos/internal/log"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
var VersionString string = "dev"
var rootCmd *cobra.Command
func init() {
redisFlags := pflag.FlagSet{}
redisFlags.String("redis-url", "127.0.0.1:6379", "host:port to the redis server")
redisFlags.String("redis-user", "", "User to use when authenticating to the server")
redisFlags.String("redis-pw", "", "Password to use when authenticating to the server")
redisFlags.Int("redis-db", 0, "What redis database we should connect to.")
redisFlags.String("prefix", "ship", "redis prefix")
redisFlags.String("chain_id", "1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4", "chain id")
rootCmd = &cobra.Command{
func main() {
rootCmd := &cobra.Command{
Use: "thalos-tools",
Short: "Collection of tools for dealing with the thalos application",
FParseErrWhitelist: cobra.FParseErrWhitelist{
@ -31,33 +18,13 @@ func init() {
Version: VersionString,
}
benchCmd.Flags().AddFlagSet(&redisFlags)
benchCmd.Flags().DurationP("interval", "i", time.Minute, "How often the benchmark results should be displayed.")
validateCmd.Flags().AddFlagSet(&redisFlags)
MockPublisherCmd.Flags().AddFlagSet(&redisFlags)
MockPublisherCmd.Flags().String("codec", "json", "codec to use")
RedisACLCmd.Flags().String("default-pw", "", "Password to use for the default account, if not provided a random one will be generated")
RedisACLCmd.Flags().String("client", "thalos-client", "Thalos client account name")
RedisACLCmd.Flags().String("client-pw", "", "Password to use for the thalos client account, if not provided a random one will be generated")
RedisACLCmd.Flags().String("server", "thalos", "Thalos account name")
RedisACLCmd.Flags().String("server-pw", "", "Password to use for the thalos server account, if not provided a random one will be generated")
RedisACLCmd.Flags().String("prefix", "ship", "Redis key prefix")
RedisACLCmd.Flags().Bool("cleartext", false, "If passwords should be hashed or left in cleartext.")
RedisACLCmd.Flags().String("file", "", "Where the config should be written to (default: standard out)")
RedisACLCmd.Flags().Uint("pass-len", 32, "The length of generated passwords")
rootCmd.AddCommand(
validateCmd,
benchCmd,
RedisACLCmd,
MockPublisherCmd,
CreateValidateCmd(),
CreateBenchCmd(),
CreateRedisACLCmd(),
CreateMockPublisherCmd(),
)
}
func main() {
if err := rootCmd.Execute(); err != nil {
log.Fatal(err)
}

View file

@ -16,100 +16,106 @@ import (
log "github.com/sirupsen/logrus"
)
var MockPublisherCmd = &cobra.Command{
Use: "mock_publisher",
Short: "Run a publisher that mocks messages to a redis server. tries to send as many messages as possible",
Run: func(cmd *cobra.Command, args []string) {
url, _ := cmd.Flags().GetString("redis-url")
user, _ := cmd.Flags().GetString("redis-user")
pw, _ := cmd.Flags().GetString("redis-pw")
prefix, _ := cmd.Flags().GetString("prefix")
chain_id, _ := cmd.Flags().GetString("chain_id")
db, _ := cmd.Flags().GetInt("redis-db")
func CreateMockPublisherCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "mock_publisher",
Short: "Run a publisher that mocks messages to a redis server. tries to send as many messages as possible",
Run: func(cmd *cobra.Command, args []string) {
url, _ := cmd.Flags().GetString("redis-url")
user, _ := cmd.Flags().GetString("redis-user")
pw, _ := cmd.Flags().GetString("redis-pw")
prefix, _ := cmd.Flags().GetString("prefix")
chain_id, _ := cmd.Flags().GetString("chain_id")
db, _ := cmd.Flags().GetInt("redis-db")
// Create redis client
rdb := redis.NewClient(&redis.Options{
Addr: url,
Username: user,
Password: pw,
DB: db,
})
// Create redis client
rdb := redis.NewClient(&redis.Options{
Addr: url,
Username: user,
Password: pw,
DB: db,
})
codecArg, _ := cmd.Flags().GetString("codec")
codecArg, _ := cmd.Flags().GetString("codec")
codec, err := message.GetCodec(codecArg)
if err != nil {
log.WithError(err).Fatal("Failed to get codec")
return
}
codec, err := message.GetCodec(codecArg)
if err != nil {
log.WithError(err).Fatal("Failed to get codec")
return
}
log.WithFields(log.Fields{
"url": url,
"prefix": prefix,
"chain_id": chain_id,
"database": db,
}).Info("Starting mock publisher")
log.WithFields(log.Fields{
"url": url,
"prefix": prefix,
"chain_id": chain_id,
"database": db,
}).Info("Starting mock publisher")
ns := api_redis.Namespace{
Prefix: prefix,
ChainID: chain_id,
}
publisher := redis_driver.NewPublisher(context.Background(), rdb, ns)
ns := api_redis.Namespace{
Prefix: prefix,
ChainID: chain_id,
}
publisher := redis_driver.NewPublisher(context.Background(), rdb, ns)
msg := message.ActionTrace{
TxID: "401e8a7e5deb18a2a69fc6559f49509a155f4355c85efb69c1c1fab5b60ee532",
BlockNum: 18237917,
Timestamp: time.Date(2014, 3, 22, 11, 36, 43, 0, time.UTC),
Receipt: &message.ActionReceipt{
Receiver: "acc1",
ActDigest: "4c5c08be612e937564fc526ebb5fadf34ae8c2a571fe9d7cdb3ffcdfc53b0e8d",
GlobalSequence: 12314,
RecvSequence: 237187239,
AuthSequence: []message.AccountAuthSequence{
msg := message.ActionTrace{
TxID: "401e8a7e5deb18a2a69fc6559f49509a155f4355c85efb69c1c1fab5b60ee532",
BlockNum: 18237917,
Timestamp: time.Date(2014, 3, 22, 11, 36, 43, 0, time.UTC),
Receipt: &message.ActionReceipt{
Receiver: "acc1",
ActDigest: "4c5c08be612e937564fc526ebb5fadf34ae8c2a571fe9d7cdb3ffcdfc53b0e8d",
GlobalSequence: 12314,
RecvSequence: 237187239,
AuthSequence: []message.AccountAuthSequence{
{
Account: "acc1",
Sequence: 2732863,
},
{
Account: "acc2",
Sequence: 263762,
},
},
CodeSequence: 2327832,
ABISequence: 12376189,
},
Name: "fake",
Contract: "fake",
Receiver: "acc1",
Data: map[string]interface{}{
"one": 238771832,
"two": "str",
},
Authorization: []message.PermissionLevel{
{
Account: "acc1",
Sequence: 2732863,
Actor: "acc1",
Permission: "active",
},
{
Account: "acc2",
Sequence: 263762,
Actor: "acc2",
Permission: "owner",
},
},
CodeSequence: 2327832,
ABISequence: 12376189,
},
Name: "fake",
Contract: "fake",
Receiver: "acc1",
Data: map[string]interface{}{
"one": 238771832,
"two": "str",
},
Authorization: []message.PermissionLevel{
{
Actor: "acc1",
Permission: "active",
},
{
Actor: "acc2",
Permission: "owner",
},
},
Except: "err",
Error: 2,
Return: []byte{0xbe, 0xef},
}
Except: "err",
Error: 2,
Return: []byte{0xbe, 0xef},
}
payload, err := codec.Encoder(msg)
if err != nil {
log.WithError(err).Fatal("Failed to encode message")
return
}
channel := api.ActionChannel{}.Channel()
payload, err := codec.Encoder(msg)
if err != nil {
log.WithError(err).Fatal("Failed to encode message")
return
}
channel := api.ActionChannel{}.Channel()
for {
_ = publisher.Write(channel, payload)
publisher.Flush()
}
},
for {
_ = publisher.Write(channel, payload)
publisher.Flush()
}
},
}
cmd.Flags().AddFlagSet(RedisFlags())
cmd.Flags().String("codec", "json", "codec to use")
return cmd
}

View file

@ -43,7 +43,6 @@ func NewUser(name, password string, pass_len uint) User {
}
func (u *User) GetPassword() string {
if u.Hash {
return "#" + hash(u.Password)
}
@ -99,60 +98,74 @@ user {{.client}} on {{.clientpw}} resetchannels &{{.prefix}}::* -@all +subscribe
})
}
var RedisACLCmd = &cobra.Command{
Use: "redis-acl",
Short: "create a users.acl file",
Run: func(cmd *cobra.Command, args []string) {
var err error
out := os.Stdout
func CreateRedisACLCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "redis-acl",
Short: "create a users.acl file",
Run: func(cmd *cobra.Command, args []string) {
var err error
out := os.Stdout
rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
flagDefUserPw, _ := cmd.Flags().GetString("default-pw")
flagServer, _ := cmd.Flags().GetString("server")
flagServerPw, _ := cmd.Flags().GetString("server-pw")
flagClient, _ := cmd.Flags().GetString("client")
flagClientPw, _ := cmd.Flags().GetString("client-pw")
flagPrefix, _ := cmd.Flags().GetString("prefix")
flagPassLen, _ := cmd.Flags().GetUint("pass-len")
flagDefUserPw, _ := cmd.Flags().GetString("default-pw")
flagServer, _ := cmd.Flags().GetString("server")
flagServerPw, _ := cmd.Flags().GetString("server-pw")
flagClient, _ := cmd.Flags().GetString("client")
flagClientPw, _ := cmd.Flags().GetString("client-pw")
flagPrefix, _ := cmd.Flags().GetString("prefix")
flagPassLen, _ := cmd.Flags().GetUint("pass-len")
defaultUser := NewUser("default", flagDefUserPw, flagPassLen)
serverUser := NewUser(flagServer, flagServerPw, flagPassLen)
clientUser := NewUser(flagClient, flagClientPw, flagPassLen)
defaultUser := NewUser("default", flagDefUserPw, flagPassLen)
serverUser := NewUser(flagServer, flagServerPw, flagPassLen)
clientUser := NewUser(flagClient, flagClientPw, flagPassLen)
atleastOneGeneratedPw := defaultUser.Generated || serverUser.Generated || clientUser.Generated
atleastOneGeneratedPw := defaultUser.Generated || serverUser.Generated || clientUser.Generated
cleartext, _ := cmd.Flags().GetBool("cleartext")
if !cleartext {
if atleastOneGeneratedPw {
println("Passwords")
cleartext, _ := cmd.Flags().GetBool("cleartext")
if !cleartext {
if atleastOneGeneratedPw {
println("Passwords")
}
defaultUser.PrintIfGeneratedPW()
serverUser.PrintIfGeneratedPW()
clientUser.PrintIfGeneratedPW()
defaultUser.Hash = true
serverUser.Hash = true
clientUser.Hash = true
}
defaultUser.PrintIfGeneratedPW()
serverUser.PrintIfGeneratedPW()
clientUser.PrintIfGeneratedPW()
filename, _ := cmd.Flags().GetString("file")
if len(filename) > 0 {
out, err = os.Create(filename)
if err != nil {
log.WithError(err).Fatal("Failed to create output file")
return
}
defer out.Close()
} else if !cleartext && atleastOneGeneratedPw {
fmt.Println()
}
defaultUser.Hash = true
serverUser.Hash = true
clientUser.Hash = true
}
filename, _ := cmd.Flags().GetString("file")
if len(filename) > 0 {
out, err = os.Create(filename)
err = writeTemplate(out, defaultUser, serverUser, clientUser, flagPrefix)
if err != nil {
log.WithError(err).Fatal("Failed to create output file")
log.WithError(err).Fatal("Failed to writte config")
return
}
defer out.Close()
} else if !cleartext && atleastOneGeneratedPw {
fmt.Println()
}
},
}
err = writeTemplate(out, defaultUser, serverUser, clientUser, flagPrefix)
if err != nil {
log.WithError(err).Fatal("Failed to writte config")
return
}
},
cmd.Flags().String("default-pw", "", "Password to use for the default account, if not provided a random one will be generated")
cmd.Flags().String("client", "thalos-client", "Thalos client account name")
cmd.Flags().String("client-pw", "", "Password to use for the thalos client account, if not provided a random one will be generated")
cmd.Flags().String("server", "thalos", "Thalos account name")
cmd.Flags().String("server-pw", "", "Password to use for the thalos server account, if not provided a random one will be generated")
cmd.Flags().String("prefix", "ship", "Redis key prefix")
cmd.Flags().Bool("cleartext", false, "If passwords should be hashed or left in cleartext.")
cmd.Flags().String("file", "", "Where the config should be written to (default: standard out)")
cmd.Flags().Uint("pass-len", 32, "The length of generated passwords")
return cmd
}

View file

@ -18,101 +18,107 @@ import (
log "github.com/sirupsen/logrus"
)
var validateCmd = &cobra.Command{
Use: "validate",
Short: "Validate a thalos server by following action traces and makes sure that blocks arrive in order.",
Run: func(cmd *cobra.Command, args []string) {
status_duration := time.Second * 10
func CreateValidateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "validate",
Short: "Validate a thalos server by following action traces and makes sure that blocks arrive in order.",
Run: func(cmd *cobra.Command, args []string) {
status_duration := time.Second * 10
url, _ := cmd.Flags().GetString("redis-url")
prefix, _ := cmd.Flags().GetString("prefix")
chain_id, _ := cmd.Flags().GetString("chain_id")
db, _ := cmd.Flags().GetInt("redis-db")
url, _ := cmd.Flags().GetString("redis-url")
prefix, _ := cmd.Flags().GetString("prefix")
chain_id, _ := cmd.Flags().GetString("chain_id")
db, _ := cmd.Flags().GetInt("redis-db")
log.WithFields(log.Fields{
"url": url,
"prefix": prefix,
"chain_id": chain_id,
"database": db,
}).Info("Connecting to redis")
log.WithFields(log.Fields{
"url": url,
"prefix": prefix,
"chain_id": chain_id,
"database": db,
}).Info("Connecting to redis")
// Create redis client
rdb := redis.NewClient(&redis.Options{
Addr: url,
DB: db,
})
// Create redis client
rdb := redis.NewClient(&redis.Options{
Addr: url,
DB: db,
})
if err := rdb.Ping(context.Background()).Err(); err != nil {
log.WithError(err).Fatal("Failed to connect to redis")
return
}
if err := rdb.Ping(context.Background()).Err(); err != nil {
log.WithError(err).Fatal("Failed to connect to redis")
return
}
log.Println("Connected to redis")
log.Println("Connected to redis")
log.Info("Starting validation, following the stream")
log.Info("Starting validation, following the stream")
sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{
Prefix: prefix,
ChainID: chain_id,
})
sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{
Prefix: prefix,
ChainID: chain_id,
})
codec, err := message.GetCodec("json")
if err != nil {
log.WithError(err).Fatal("Failed to get codec")
return
}
codec, err := message.GetCodec("json")
if err != nil {
log.WithError(err).Fatal("Failed to get codec")
return
}
client := api.NewClient(sub, codec.Decoder)
client := api.NewClient(sub, codec.Decoder)
// Subscribe to all actions
if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil {
log.WithError(err).Fatal("Failed to subscribe to channels")
return
}
// Subscribe to all actions
if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil {
log.WithError(err).Fatal("Failed to subscribe to channels")
return
}
block_num := uint32(0)
timeout := time.Second * 5
timer := time.NewTicker(timeout)
block_num := uint32(0)
timeout := time.Second * 5
timer := time.NewTicker(timeout)
go func() {
for t := range client.Channel() {
switch msg := t.(type) {
case error:
log.WithError(msg).Error("Error when reading stream")
case message.ActionTrace:
if block_num > 0 {
diff := int32(msg.BlockNum - block_num)
if diff < 0 || diff > 1 {
log.WithFields(log.Fields{
"current_block": block_num,
"block": msg.BlockNum,
"diff": diff,
}).Warn("Invalid")
go func() {
for t := range client.Channel() {
switch msg := t.(type) {
case error:
log.WithError(msg).Error("Error when reading stream")
case message.ActionTrace:
if block_num > 0 {
diff := int32(msg.BlockNum - block_num)
if diff < 0 || diff > 1 {
log.WithFields(log.Fields{
"current_block": block_num,
"block": msg.BlockNum,
"diff": diff,
}).Warn("Invalid")
}
}
block_num = msg.BlockNum
timer.Reset(timeout)
}
block_num = msg.BlockNum
timer.Reset(timeout)
}
}()
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
for {
select {
case <-sig:
fmt.Println("Got interrupt")
client.Close()
return
case <-timer.C:
log.WithField("duration", timeout).
Warn("Did not get any messages during the defined duration")
case <-time.After(status_duration):
log.WithFields(log.Fields{
"current_block": block_num,
}).Info("Status")
}
}
}()
},
}
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
cmd.Flags().AddFlagSet(RedisFlags())
for {
select {
case <-sig:
fmt.Println("Got interrupt")
client.Close()
return
case <-timer.C:
log.WithField("duration", timeout).
Warn("Did not get any messages during the defined duration")
case <-time.After(status_duration):
log.WithFields(log.Fields{
"current_block": block_num,
}).Info("Status")
}
}
},
return cmd
}