dc4bc/cmd/dc4bc_d/main.go

211 lines
7.3 KiB
Go
Raw Normal View History

2020-08-04 00:45:32 -07:00
package main
import (
"context"
2020-09-07 09:06:28 -07:00
"fmt"
2020-08-04 00:45:32 -07:00
"log"
"os"
"os/signal"
2020-11-05 06:25:11 -08:00
"strings"
2020-08-04 00:45:32 -07:00
"syscall"
2020-11-05 01:43:54 -08:00
"github.com/lidofinance/dc4bc/client"
"github.com/lidofinance/dc4bc/storage"
2020-08-04 00:45:32 -07:00
"github.com/spf13/cobra"
2020-11-20 05:52:16 -08:00
"github.com/spf13/viper"
2020-08-04 00:45:32 -07:00
)
const (
2020-10-15 08:55:37 -07:00
flagUserName = "username"
flagListenAddr = "listen_addr"
flagStateDBDSN = "state_dbdsn"
flagStorageDBDSN = "storage_dbdsn"
flagStorageTopic = "storage_topic"
flagKafkaProducerCredentials = "producer_credentials"
flagKafkaConsumerCredentials = "consumer_credentials"
flagKafkaTrustStorePath = "kafka_truststore_path"
flagStoreDBDSN = "key_store_dbdsn"
flagFramesDelay = "frames_delay"
flagChunkSize = "chunk_size"
2020-11-20 05:52:16 -08:00
flagConfig = "config"
)
var (
cfgFile string
2020-08-04 00:45:32 -07:00
)
func init() {
2020-11-20 05:52:16 -08:00
cobra.OnInitialize(initConfig)
2020-08-14 05:34:15 -07:00
rootCmd.PersistentFlags().String(flagUserName, "testUser", "Username")
rootCmd.PersistentFlags().String(flagListenAddr, "localhost:8080", "Listen Address")
2020-08-04 00:45:32 -07:00
rootCmd.PersistentFlags().String(flagStateDBDSN, "./dc4bc_client_state", "State DBDSN")
rootCmd.PersistentFlags().String(flagStorageDBDSN, "./dc4bc_file_storage", "Storage DBDSN")
2020-10-05 10:07:02 -07:00
rootCmd.PersistentFlags().String(flagStorageTopic, "messages", "Storage Topic (Kafka)")
2020-10-15 08:55:37 -07:00
rootCmd.PersistentFlags().String(flagKafkaProducerCredentials, "producer:producerpass", "Producer credentials for Kafka: username:password")
rootCmd.PersistentFlags().String(flagKafkaConsumerCredentials, "consumer:consumerpass", "Consumer credentials for Kafka: username:password")
2020-10-13 04:01:54 -07:00
rootCmd.PersistentFlags().String(flagKafkaTrustStorePath, "certs/ca.pem", "Path to kafka truststore")
2020-09-07 09:06:28 -07:00
rootCmd.PersistentFlags().String(flagStoreDBDSN, "./dc4bc_key_store", "Key Store DBDSN")
2020-09-29 08:16:20 -07:00
rootCmd.PersistentFlags().Int(flagFramesDelay, 10, "Delay times between frames in 100ths of a second")
rootCmd.PersistentFlags().Int(flagChunkSize, 256, "QR-code's chunk size")
2020-11-20 05:52:16 -08:00
rootCmd.PersistentFlags().StringVar(&cfgFile, flagConfig, "", "path to your config file")
exitIfError(viper.BindPFlag(flagUserName, rootCmd.PersistentFlags().Lookup(flagUserName)))
exitIfError(viper.BindPFlag(flagListenAddr, rootCmd.PersistentFlags().Lookup(flagListenAddr)))
exitIfError(viper.BindPFlag(flagStateDBDSN, rootCmd.PersistentFlags().Lookup(flagStateDBDSN)))
exitIfError(viper.BindPFlag(flagStorageDBDSN, rootCmd.PersistentFlags().Lookup(flagStorageDBDSN)))
exitIfError(viper.BindPFlag(flagStorageTopic, rootCmd.PersistentFlags().Lookup(flagStorageTopic)))
exitIfError(viper.BindPFlag(flagKafkaProducerCredentials, rootCmd.PersistentFlags().Lookup(flagKafkaProducerCredentials)))
exitIfError(viper.BindPFlag(flagKafkaConsumerCredentials, rootCmd.PersistentFlags().Lookup(flagKafkaConsumerCredentials)))
exitIfError(viper.BindPFlag(flagKafkaTrustStorePath, rootCmd.PersistentFlags().Lookup(flagKafkaTrustStorePath)))
exitIfError(viper.BindPFlag(flagStoreDBDSN, rootCmd.PersistentFlags().Lookup(flagStoreDBDSN)))
exitIfError(viper.BindPFlag(flagFramesDelay, rootCmd.PersistentFlags().Lookup(flagFramesDelay)))
exitIfError(viper.BindPFlag(flagChunkSize, rootCmd.PersistentFlags().Lookup(flagChunkSize)))
exitIfError(viper.BindPFlag(flagUserName, rootCmd.PersistentFlags().Lookup(flagUserName)))
2020-10-13 07:41:02 -07:00
}
2020-11-20 05:52:16 -08:00
func exitIfError(err error) {
2020-10-13 07:41:02 -07:00
if err != nil {
2020-11-20 05:52:16 -08:00
log.Fatalf("fatal error: %v", err)
2020-10-13 07:41:02 -07:00
}
}
2020-11-20 05:52:16 -08:00
func initConfig() {
if cfgFile == "" {
return
2020-10-15 09:35:06 -07:00
}
2020-10-13 07:41:02 -07:00
2020-11-20 05:52:16 -08:00
viper.SetConfigFile(cfgFile)
exitIfError(viper.ReadInConfig())
2020-09-07 09:06:28 -07:00
}
func genKeyPairCommand() *cobra.Command {
return &cobra.Command{
Use: "gen_keys",
Short: "generates a keypair to sign and verify messages",
2020-11-20 05:52:16 -08:00
RunE: func(cmd *cobra.Command, args []string) error {
username := viper.GetString(flagUserName)
keyStoreDBDSN := viper.GetString(flagStoreDBDSN)
2020-10-13 07:41:02 -07:00
2020-09-07 09:06:28 -07:00
keyPair := client.NewKeyPair()
2020-11-20 05:52:16 -08:00
keyStore, err := client.NewLevelDBKeyStore(username, keyStoreDBDSN)
2020-09-07 09:06:28 -07:00
if err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("failed to init key store: %w", err)
2020-09-07 09:06:28 -07:00
}
2020-11-20 05:52:16 -08:00
if err = keyStore.PutKeys(username, keyPair); err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("failed to save keypair: %w", err)
2020-09-07 09:06:28 -07:00
}
2020-11-20 05:52:16 -08:00
fmt.Printf("keypair generated for user %s and saved to %s\n", username, keyStoreDBDSN)
return nil
2020-09-07 09:06:28 -07:00
},
}
}
2020-10-12 03:17:02 -07:00
func parseKafkaAuthCredentials(creds string) (*storage.KafkaAuthCredentials, error) {
credsSplited := strings.SplitN(creds, ":", 2)
if len(credsSplited) == 1 {
return nil, fmt.Errorf("failed to parse credentials")
}
return &storage.KafkaAuthCredentials{
Username: credsSplited[0],
Password: credsSplited[1],
}, nil
}
2020-09-07 09:06:28 -07:00
func startClientCommand() *cobra.Command {
return &cobra.Command{
Use: "start",
Short: "starts dc4bc client",
2020-11-20 05:52:16 -08:00
RunE: func(cmd *cobra.Command, args []string) error {
2020-09-07 09:06:28 -07:00
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
2020-11-20 05:52:16 -08:00
stateDBDSN := viper.GetString(flagStateDBDSN)
state, err := client.NewLevelDBState(stateDBDSN)
2020-09-07 09:06:28 -07:00
if err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("failed to init state client: %w", err)
2020-09-07 09:06:28 -07:00
}
2020-11-20 05:52:16 -08:00
kafkaTrustStorePath := viper.GetString(flagKafkaTrustStorePath)
tlsConfig, err := storage.GetTLSConfig(kafkaTrustStorePath)
2020-10-15 08:55:37 -07:00
if err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("faile to create tls config: %w", err)
2020-10-15 08:55:37 -07:00
}
2020-11-20 05:52:16 -08:00
producerCredentials := viper.GetString(flagKafkaProducerCredentials)
producerCreds, err := parseKafkaAuthCredentials(producerCredentials)
2020-10-15 08:55:37 -07:00
if err != nil {
2020-11-20 05:52:16 -08:00
return fmt.Errorf("failed to parse kafka credentials: %w", err)
2020-10-15 08:55:37 -07:00
}
2020-11-20 05:52:16 -08:00
consumerCredentials := viper.GetString(flagKafkaConsumerCredentials)
consumerCreds, err := parseKafkaAuthCredentials(consumerCredentials)
2020-09-07 09:06:28 -07:00
if err != nil {
2020-11-20 05:52:16 -08:00
return fmt.Errorf("failed to parse kafka credentials: %w", err)
2020-09-07 09:06:28 -07:00
}
2020-11-20 05:52:16 -08:00
storageDBDSN := viper.GetString(flagStorageDBDSN)
storageTopic := viper.GetString(flagStorageTopic)
stg, err := storage.NewKafkaStorage(ctx, storageDBDSN, storageTopic, tlsConfig, producerCreds, consumerCreds)
2020-09-07 09:06:28 -07:00
if err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("failed to init storage client: %w", err)
2020-09-07 09:06:28 -07:00
}
2020-11-20 05:52:16 -08:00
username := viper.GetString(flagUserName)
keyStoreDBDSN := viper.GetString(flagStoreDBDSN)
keyStore, err := client.NewLevelDBKeyStore(username, keyStoreDBDSN)
2020-09-07 09:06:28 -07:00
if err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("failed to init key store: %w", err)
2020-09-07 09:06:28 -07:00
}
2020-11-25 06:50:50 -08:00
cli, err := client.NewClient(ctx, username, state, stg, keyStore)
2020-09-07 09:06:28 -07:00
if err != nil {
2020-11-20 05:58:11 -08:00
return fmt.Errorf("failed to init client: %w", err)
2020-09-07 09:06:28 -07:00
}
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigs
log.Println("Received signal, stopping client...")
cancel()
2020-10-05 08:00:54 -07:00
log.Println("BaseClient stopped, exiting")
2020-09-07 09:06:28 -07:00
os.Exit(0)
}()
2020-11-20 05:52:16 -08:00
listenAddress := viper.GetString(flagListenAddr)
2020-09-07 09:06:28 -07:00
go func() {
2020-11-20 05:52:16 -08:00
if err := cli.StartHTTPServer(listenAddress); err != nil {
2020-09-07 09:06:28 -07:00
log.Fatalf("HTTP server error: %v", err)
}
}()
2020-10-27 03:01:22 -07:00
cli.GetLogger().Log("Client started to poll messages from append-only log")
cli.GetLogger().Log("Waiting for messages from append-only log...")
2020-09-07 09:06:28 -07:00
if err = cli.Poll(); err != nil {
2020-11-20 05:55:36 -08:00
return fmt.Errorf("error while handling operations: %w", err)
2020-09-07 09:06:28 -07:00
}
cli.GetLogger().Log("polling is stopped")
2020-11-20 05:52:16 -08:00
return nil
2020-09-07 09:06:28 -07:00
},
}
2020-08-04 00:45:32 -07:00
}
var rootCmd = &cobra.Command{
2020-09-08 04:48:36 -07:00
Use: "dc4bc_d",
Short: "dc4bc client daemon implementation",
2020-08-04 00:45:32 -07:00
}
func main() {
2020-09-07 09:06:28 -07:00
rootCmd.AddCommand(
startClientCommand(),
genKeyPairCommand(),
)
2020-08-04 00:45:32 -07:00
if err := rootCmd.Execute(); err != nil {
log.Fatalf("Failed to execute root command: %v", err)
}
}