From 27bc9488e646e35df0d3f9411bea78d9797601a2 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Wed, 11 Jan 2023 11:58:49 -0400 Subject: [PATCH] feat: load config from toml file --- cmd/waku/flags.go | 283 ++++++++++++++++++++-------------------- cmd/waku/main.go | 5 +- cmd/waku/no_rln.go | 2 +- cmd/waku/rln.go | 2 +- go.mod | 4 +- go.sum | 6 +- waku/cliutils/altsrc.go | 96 ++++++++++++++ 7 files changed, 251 insertions(+), 147 deletions(-) create mode 100644 waku/cliutils/altsrc.go diff --git a/cmd/waku/flags.go b/cmd/waku/flags.go index d690d928..ea21d991 100644 --- a/cmd/waku/flags.go +++ b/cmd/waku/flags.go @@ -3,161 +3,162 @@ package main import ( "time" - "github.com/urfave/cli/v2" + cli "github.com/urfave/cli/v2" + "github.com/urfave/cli/v2/altsrc" "github.com/waku-org/go-waku/waku/cliutils" ) var ( - TcpPort = &cli.IntFlag{ + TcpPort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "tcp-port", Aliases: []string{"port", "p"}, Value: 60000, Usage: "Libp2p TCP listening port (0 for random)", Destination: &options.Port, EnvVars: []string{"WAKUNODE2_TCP_PORT"}, - } - Address = &cli.StringFlag{ + }) + Address = altsrc.NewStringFlag(&cli.StringFlag{ Name: "address", Aliases: []string{"host", "listen-address"}, Value: "0.0.0.0", Usage: "Listening address", Destination: &options.Address, EnvVars: []string{"WAKUNODE2_ADDRESS"}, - } - WebsocketSupport = &cli.BoolFlag{ + }) + WebsocketSupport = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "websocket-support", Aliases: []string{"ws"}, Usage: "Enable websockets support", Destination: &options.Websocket.Enable, EnvVars: []string{"WAKUNODE2_WEBSOCKET_SUPPORT"}, - } - WebsocketPort = &cli.IntFlag{ + }) + WebsocketPort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "websocket-port", Aliases: []string{"ws-port"}, Value: 60001, Usage: "Libp2p TCP listening port for websocket connection (0 for random)", Destination: &options.Websocket.WSPort, EnvVars: []string{"WAKUNODE2_WEBSOCKET_PORT"}, - } - WebsocketSecurePort = &cli.IntFlag{ + }) + WebsocketSecurePort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "websocket-secure-port", Aliases: []string{"wss-port"}, Value: 6443, Usage: "Libp2p TCP listening port for secure websocket connection (0 for random, binding to 443 requires root access)", Destination: &options.Websocket.WSSPort, EnvVars: []string{"WAKUNODE2_WEBSOCKET_SECURE_PORT"}, - } - WebsocketAddress = &cli.StringFlag{ + }) + WebsocketAddress = altsrc.NewStringFlag(&cli.StringFlag{ Name: "websocket-address", Aliases: []string{"ws-address"}, Value: "0.0.0.0", Usage: "Listening address for websocket connections", Destination: &options.Websocket.Address, EnvVars: []string{"WAKUNODE2_WEBSOCKET_ADDRESS"}, - } - WebsocketSecureSupport = &cli.BoolFlag{ + }) + WebsocketSecureSupport = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "websocket-secure-support", Aliases: []string{"wss"}, Usage: "Enable secure websockets support", Destination: &options.Websocket.Secure, EnvVars: []string{"WAKUNODE2_WEBSOCKET_SECURE_SUPPORT"}, - } - WebsocketSecureKeyPath = &cli.PathFlag{ + }) + WebsocketSecureKeyPath = altsrc.NewPathFlag(&cli.PathFlag{ Name: "websocket-secure-key-path", Aliases: []string{"wss-key"}, Value: "/path/to/key.txt", Usage: "Secure websocket key path", Destination: &options.Websocket.KeyPath, EnvVars: []string{"WAKUNODE2_WEBSOCKET_SECURE_KEY_PATH"}, - } - WebsocketSecureCertPath = &cli.PathFlag{ + }) + WebsocketSecureCertPath = altsrc.NewPathFlag(&cli.PathFlag{ Name: "websocket-secure-cert-path", Aliases: []string{"wss-cert"}, Value: "/path/to/cert.txt", Usage: "Secure websocket certificate path", Destination: &options.Websocket.CertPath, EnvVars: []string{"WAKUNODE2_WEBSOCKET_SECURE_CERT_PATH"}, - } - Dns4DomainName = &cli.StringFlag{ + }) + Dns4DomainName = altsrc.NewStringFlag(&cli.StringFlag{ Name: "dns4-domain-name", Value: "", Usage: "The domain name resolving to the node's public IPv4 address", Destination: &options.Dns4DomainName, EnvVars: []string{"WAKUNODE2_WEBSOCKET_DNS4_DOMAIN_NAME"}, - } - NodeKey = &cli.GenericFlag{ + }) + NodeKey = cliutils.NewGenericFlagSingleValue(&cli.GenericFlag{ Name: "nodekey", Usage: "P2P node private key as hex. Can also be set with GOWAKU-NODEKEY env variable (default random)", Value: &cliutils.PrivateKeyValue{ Value: &options.NodeKey, }, EnvVars: []string{"WAKUNODE2_NODEKEY"}, - } - KeyFile = &cli.PathFlag{ + }) + KeyFile = altsrc.NewPathFlag(&cli.PathFlag{ Name: "key-file", Value: "./nodekey", Usage: "Path to a file containing the private key for the P2P node", Destination: &options.KeyFile, EnvVars: []string{"WAKUNODE2_KEY_FILE"}, - } - KeyPassword = &cli.StringFlag{ + }) + KeyPassword = altsrc.NewStringFlag(&cli.StringFlag{ Name: "key-password", Value: "secret", Usage: "Password used for the private key file", Destination: &options.KeyPasswd, EnvVars: []string{"WAKUNODE2_KEY_PASSWORD"}, - } - GenerateKey = &cli.BoolFlag{ + }) + GenerateKey = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "generate-key", Usage: "Generate private key file at path specified in --key-file with the password defined by --key-password", Destination: &options.GenerateKey, - } - Overwrite = &cli.BoolFlag{ + }) + Overwrite = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "overwrite", Usage: "When generating a keyfile, overwrite the nodekey file if it already exists", Destination: &options.Overwrite, - } - StaticNode = &cli.GenericFlag{ + }) + StaticNode = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{ Name: "staticnode", Usage: "Multiaddr of peer to directly connect with. Option may be repeated", Value: &cliutils.MultiaddrSlice{ Values: &options.StaticNodes, }, EnvVars: []string{"WAKUNODE2_STATICNODE"}, - } - KeepAlive = &cli.DurationFlag{ + }) + KeepAlive = altsrc.NewDurationFlag(&cli.DurationFlag{ Name: "keep-alive", Value: 5 * time.Minute, Usage: "Interval of time for pinging peers to keep the connection alive.", Destination: &options.KeepAlive, EnvVars: []string{"WAKUNODE2_KEEP_ALIVE"}, - } - PersistPeers = &cli.BoolFlag{ + }) + PersistPeers = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "persist-peers", Usage: "Enable peer persistence", Destination: &options.PersistPeers, Value: false, EnvVars: []string{"WAKUNODE2_PERSIST_PEERS"}, - } - NAT = &cli.StringFlag{ + }) + NAT = altsrc.NewStringFlag(&cli.StringFlag{ Name: "nat", // This was added so js-waku test don't fail Usage: "TODO: Not implemented yet. Specify method to use for determining public address: any, none ('any' will attempt upnp/pmp)", Value: "any", Destination: &options.NAT, // TODO: accept none,any,upnp,extaddr EnvVars: []string{"WAKUNODE2_NAT"}, - } - AdvertiseAddress = &cli.StringFlag{ + }) + AdvertiseAddress = altsrc.NewStringFlag(&cli.StringFlag{ Name: "advertise-address", Usage: "External address to advertise to other nodes (overrides --address and --ws-address flags)", Destination: &options.AdvertiseAddress, EnvVars: []string{"WAKUNODE2_ADVERTISE_ADDRESS"}, - } - ShowAddresses = &cli.BoolFlag{ + }) + ShowAddresses = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "show-addresses", Usage: "Display listening addresses according to current configuration", Destination: &options.ShowAddresses, - } - LogLevel = &cli.GenericFlag{ + }) + LogLevel = cliutils.NewGenericFlagSingleValue(&cli.GenericFlag{ Name: "log-level", Aliases: []string{"l"}, Value: &cliutils.ChoiceValue{ @@ -166,8 +167,8 @@ var ( }, Usage: "Define the logging level (allowed values: DEBUG, INFO, WARN, ERROR, DPANIC, PANIC, FATAL)", EnvVars: []string{"WAKUNODE2_LOG_LEVEL"}, - } - LogEncoding = &cli.GenericFlag{ + }) + LogEncoding = cliutils.NewGenericFlagSingleValue(&cli.GenericFlag{ Name: "log-encoding", Usage: "Define the encoding used for the logs (allowed values: console, nocolor, json)", Value: &cliutils.ChoiceValue{ @@ -175,327 +176,327 @@ var ( Value: &options.LogEncoding, }, EnvVars: []string{"WAKUNODE2_LOG_ENCODING"}, - } - LogOutput = &cli.StringFlag{ + }) + LogOutput = altsrc.NewStringFlag(&cli.StringFlag{ Name: "log-output", Value: "stdout", Usage: "specifies where logging output should be written (stdout, file, file:./filename.log)", Destination: &options.LogOutput, EnvVars: []string{"WAKUNODE2_LOG_OUTPUT"}, - } - AgentString = &cli.StringFlag{ + }) + AgentString = altsrc.NewStringFlag(&cli.StringFlag{ Name: "agent-string", Value: "go-waku", Usage: "client id to advertise", Destination: &options.UserAgent, EnvVars: []string{"WAKUNODE2_AGENT_STRING"}, - } - Relay = &cli.BoolFlag{ + }) + Relay = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "relay", Value: true, Usage: "Enable relay protocol", Destination: &options.Relay.Enable, EnvVars: []string{"WAKUNODE2_RELAY"}, - } - Topics = &cli.StringSliceFlag{ + }) + Topics = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{ Name: "topics", Usage: "List of topics to listen", Destination: &options.Relay.Topics, EnvVars: []string{"WAKUNODE2_TOPICS"}, - } - RelayPeerExchange = &cli.BoolFlag{ + }) + RelayPeerExchange = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "relay-peer-exchange", Value: false, Usage: "Enable GossipSub Peer Exchange", Destination: &options.Relay.PeerExchange, EnvVars: []string{"WAKUNODE2_RELAY_PEER_EXCHANGE"}, - } - MinRelayPeersToPublish = &cli.IntFlag{ + }) + MinRelayPeersToPublish = altsrc.NewIntFlag(&cli.IntFlag{ Name: "min-relay-peers-to-publish", Value: 1, Usage: "Minimum number of peers to publish to Relay", Destination: &options.Relay.MinRelayPeersToPublish, EnvVars: []string{"WAKUNODE2_MIN_RELAY_PEERS_TO_PUBLISH"}, - } - StoreNodeFlag = &cli.GenericFlag{ + }) + StoreNodeFlag = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{ Name: "storenode", Usage: "Multiaddr of a peer that supports store protocol. Option may be repeated", Value: &cliutils.MultiaddrSlice{ Values: &options.Store.Nodes, }, EnvVars: []string{"WAKUNODE2_STORENODE"}, - } - StoreFlag = &cli.BoolFlag{ + }) + StoreFlag = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "store", Usage: "Enable store protocol to persist messages", Destination: &options.Store.Enable, EnvVars: []string{"WAKUNODE2_STORE"}, - } - StoreMessageRetentionTime = &cli.DurationFlag{ + }) + StoreMessageRetentionTime = altsrc.NewDurationFlag(&cli.DurationFlag{ Name: "store-message-retention-time", Value: time.Hour * 24 * 2, Usage: "maximum number of seconds before a message is removed from the store. Set to 0 to disable it", Destination: &options.Store.RetentionTime, EnvVars: []string{"WAKUNODE2_STORE_MESSAGE_RETENTION_TIME"}, - } - StoreMessageRetentionCapacity = &cli.IntFlag{ + }) + StoreMessageRetentionCapacity = altsrc.NewIntFlag(&cli.IntFlag{ Name: "store-message-retention-capacity", Value: 0, Usage: "maximum number of messages to store. Set to 0 to disable it", Destination: &options.Store.RetentionMaxMessages, EnvVars: []string{"WAKUNODE2_STORE_MESSAGE_RETENTION_CAPACITY"}, - } - StoreMessageDBURL = &cli.StringFlag{ + }) + StoreMessageDBURL = altsrc.NewStringFlag(&cli.StringFlag{ Name: "store-message-db-url", Usage: "The database connection URL for persistent storage.", Value: "sqlite3://store.db", Destination: &options.Store.DatabaseURL, EnvVars: []string{"WAKUNODE2_STORE_MESSAGE_DB_URL"}, - } - StoreResumePeer = &cli.GenericFlag{ + }) + StoreResumePeer = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{ Name: "store-resume-peer", Usage: "Peer multiaddress to resume the message store at boot. Option may be repeated", Value: &cliutils.MultiaddrSlice{ Values: &options.Store.ResumeNodes, }, EnvVars: []string{"WAKUNODE2_STORE_RESUME_PEER"}, - } - SwapFlag = &cli.BoolFlag{ + }) + SwapFlag = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "swap", Usage: "Enable swap protocol", Value: false, Destination: &options.Swap.Enable, EnvVars: []string{"WAKUNODE2_SWAP"}, - } - SwapMode = &cli.IntFlag{ + }) + SwapMode = altsrc.NewIntFlag(&cli.IntFlag{ Name: "swap-mode", Value: 0, Usage: "Swap mode: 0=soft, 1=mock, 2=hard", Destination: &options.Swap.Mode, EnvVars: []string{"WAKUNODE2_SWAP_MODE"}, - } - SwapPaymentThreshold = &cli.IntFlag{ + }) + SwapPaymentThreshold = altsrc.NewIntFlag(&cli.IntFlag{ Name: "swap-payment-threshold", Value: 100, Usage: "Threshold for payment", Destination: &options.Swap.PaymentThreshold, EnvVars: []string{"WAKUNODE2_SWAP_PAYMENT_THRESHOLD"}, - } - SwapDisconnectThreshold = &cli.IntFlag{ + }) + SwapDisconnectThreshold = altsrc.NewIntFlag(&cli.IntFlag{ Name: "swap-disconnect-threshold", Value: -100, Usage: "Threshold for disconnecting", Destination: &options.Swap.DisconnectThreshold, EnvVars: []string{"WAKUNODE2_SWAP_DISCONNECT_THRESHOLD"}, - } - FilterFlag = &cli.BoolFlag{ + }) + FilterFlag = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "filter", Usage: "Enable filter protocol", Destination: &options.Filter.Enable, EnvVars: []string{"WAKUNODE2_FILTER"}, - } - LightClient = &cli.BoolFlag{ + }) + LightClient = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "light-client", Usage: "Don't accept filter subscribers", Destination: &options.Filter.DisableFullNode, EnvVars: []string{"WAKUNODE2_LIGHT_CLIENT"}, - } - FilterNode = &cli.GenericFlag{ + }) + FilterNode = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{ Name: "filternode", Usage: "Multiaddr of a peer that supports filter protocol. Option may be repeated", Value: &cliutils.MultiaddrSlice{ Values: &options.Filter.Nodes, }, EnvVars: []string{"WAKUNODE2_FILTERNODE"}, - } - FilterTimeout = &cli.DurationFlag{ + }) + FilterTimeout = altsrc.NewDurationFlag(&cli.DurationFlag{ Name: "filter-timeout", Value: 14400 * time.Second, Usage: "Timeout for filter node in seconds", Destination: &options.Filter.Timeout, EnvVars: []string{"WAKUNODE2_FILTER_TIMEOUT"}, - } - LightPush = &cli.BoolFlag{ + }) + LightPush = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "lightpush", Usage: "Enable lightpush protocol", Destination: &options.LightPush.Enable, EnvVars: []string{"WAKUNODE2_LIGHTPUSH"}, - } - LightPushNode = &cli.GenericFlag{ + }) + LightPushNode = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{ Name: "lightpushnode", Usage: "Multiaddr of a peer that supports lightpush protocol. Option may be repeated", Value: &cliutils.MultiaddrSlice{ Values: &options.LightPush.Nodes, }, EnvVars: []string{"WAKUNODE2_LIGHTPUSHNODE"}, - } - Discv5Discovery = &cli.BoolFlag{ + }) + Discv5Discovery = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "discv5-discovery", Usage: "Enable discovering nodes via Node Discovery v5", Destination: &options.DiscV5.Enable, EnvVars: []string{"WAKUNODE2_DISCV5_DISCOVERY"}, - } - Discv5BootstrapNode = &cli.StringSliceFlag{ + }) + Discv5BootstrapNode = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{ Name: "discv5-bootstrap-node", Usage: "Text-encoded ENR for bootstrap node. Used when connecting to the network. Option may be repeated", Destination: &options.DiscV5.Nodes, EnvVars: []string{"WAKUNODE2_DISCV5_BOOTSTRAP_NODE"}, - } - Discv5UDPPort = &cli.IntFlag{ + }) + Discv5UDPPort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "discv5-udp-port", Value: 9000, Usage: "Listening UDP port for Node Discovery v5.", Destination: &options.DiscV5.Port, EnvVars: []string{"WAKUNODE2_DISCV5_UDP_PORT"}, - } - Discv5ENRAutoUpdate = &cli.BoolFlag{ + }) + Discv5ENRAutoUpdate = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "discv5-enr-auto-update", Usage: "Discovery can automatically update its ENR with the IP address as seen by other nodes it communicates with.", Destination: &options.DiscV5.AutoUpdate, EnvVars: []string{"WAKUNODE2_DISCV5_ENR_AUTO_UPDATE"}, - } - PeerExchange = &cli.BoolFlag{ + }) + PeerExchange = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "peer-exchange", Usage: "Enable waku peer exchange protocol (responder side)", Destination: &options.PeerExchange.Enable, EnvVars: []string{"WAKUNODE2_PEER_EXCHANGE"}, - } - PeerExchangeNode = &cli.GenericFlag{ + }) + PeerExchangeNode = cliutils.NewGenericFlagSingleValue(&cli.GenericFlag{ Name: "peer-exchange-node", Usage: "Peer multiaddr to send peer exchange requests to. (enables peer exchange protocol requester side)", Value: &cliutils.MultiaddrValue{ Value: &options.PeerExchange.Node, }, EnvVars: []string{"WAKUNODE2_PEER_EXCHANGE_NODE"}, - } - DNSDiscovery = &cli.BoolFlag{ + }) + DNSDiscovery = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "dns-discovery", Usage: "Enable DNS discovery", Destination: &options.DNSDiscovery.Enable, EnvVars: []string{"WAKUNODE2_DNS_DISCOVERY"}, - } - DNSDiscoveryUrl = &cli.StringSliceFlag{ + }) + DNSDiscoveryUrl = altsrc.NewStringSliceFlag(&cli.StringSliceFlag{ Name: "dns-discovery-url", Usage: "URL for DNS node list in format 'enrtree://@'", Destination: &options.DNSDiscovery.URLs, EnvVars: []string{"WAKUNODE2_DNS_DISCOVERY_URL"}, - } - DNSDiscoveryNameServer = &cli.StringFlag{ + }) + DNSDiscoveryNameServer = altsrc.NewStringFlag(&cli.StringFlag{ Name: "dns-discovery-name-server", Aliases: []string{"dns-discovery-nameserver"}, Usage: "DNS nameserver IP to query (empty to use system's default)", Destination: &options.DNSDiscovery.Nameserver, EnvVars: []string{"WAKUNODE2_DNS_DISCOVERY_NAME_SERVER"}, - } - MetricsServer = &cli.BoolFlag{ + }) + MetricsServer = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "metrics-server", Aliases: []string{"metrics"}, Usage: "Enable the metrics server", Destination: &options.Metrics.Enable, EnvVars: []string{"WAKUNODE2_METRICS_SERVER"}, - } - MetricsServerAddress = &cli.StringFlag{ + }) + MetricsServerAddress = altsrc.NewStringFlag(&cli.StringFlag{ Name: "metrics-server-address", Aliases: []string{"metrics-address"}, Value: "127.0.0.1", Usage: "Listening address of the metrics server", Destination: &options.Metrics.Address, EnvVars: []string{"WAKUNODE2_METRICS_SERVER_ADDRESS"}, - } - MetricsServerPort = &cli.IntFlag{ + }) + MetricsServerPort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "metrics-server-port", Aliases: []string{"metrics-port"}, Value: 8008, Usage: "Listening HTTP port of the metrics server", Destination: &options.Metrics.Port, EnvVars: []string{"WAKUNODE2_METRICS_SERVER_PORT"}, - } - RPCFlag = &cli.BoolFlag{ + }) + RPCFlag = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "rpc", Usage: "Enable the rpc server", Destination: &options.RPCServer.Enable, EnvVars: []string{"WAKUNODE2_RPC"}, - } - RPCPort = &cli.IntFlag{ + }) + RPCPort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "rpc-port", Value: 8545, Usage: "Listening port of the rpc server", Destination: &options.RPCServer.Port, EnvVars: []string{"WAKUNODE2_RPC_PORT"}, - } - RPCAddress = &cli.StringFlag{ + }) + RPCAddress = altsrc.NewStringFlag(&cli.StringFlag{ Name: "rpc-address", Value: "127.0.0.1", Usage: "Listening address of the rpc server", Destination: &options.RPCServer.Address, EnvVars: []string{"WAKUNODE2_RPC_ADDRESS"}, - } - RPCRelayCacheCapacity = &cli.IntFlag{ + }) + RPCRelayCacheCapacity = altsrc.NewIntFlag(&cli.IntFlag{ Name: "rpc-relay-cache-capacity", Value: 30, Usage: "Capacity of the Relay REST API message cache", Destination: &options.RPCServer.RelayCacheCapacity, EnvVars: []string{"WAKUNODE2_RPC_RELAY_CACHE_CAPACITY"}, - } - RPCAdmin = &cli.BoolFlag{ + }) + RPCAdmin = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "rpc-admin", Value: false, Usage: "Enable access to JSON-RPC Admin API", Destination: &options.RPCServer.Admin, EnvVars: []string{"WAKUNODE2_RPC_ADMIN"}, - } - RPCPrivate = &cli.BoolFlag{ + }) + RPCPrivate = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "rpc-private", Value: false, Usage: "Enable access to JSON-RPC Private API", Destination: &options.RPCServer.Private, EnvVars: []string{"WAKUNODE2_RPC_PRIVATE"}, - } - RESTFlag = &cli.BoolFlag{ + }) + RESTFlag = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "rest", Usage: "Enable Waku REST HTTP server", Destination: &options.RESTServer.Enable, EnvVars: []string{"WAKUNODE2_REST"}, - } - RESTAddress = &cli.StringFlag{ + }) + RESTAddress = altsrc.NewStringFlag(&cli.StringFlag{ Name: "rest-address", Value: "127.0.0.1", Usage: "Listening address of the REST HTTP server", Destination: &options.RESTServer.Address, EnvVars: []string{"WAKUNODE2_REST_ADDRESS"}, - } - RESTPort = &cli.IntFlag{ + }) + RESTPort = altsrc.NewIntFlag(&cli.IntFlag{ Name: "rest-port", Value: 8645, Usage: "Listening port of the REST HTTP server", Destination: &options.RESTServer.Port, EnvVars: []string{"WAKUNODE2_REST_PORT"}, - } - RESTRelayCacheCapacity = &cli.IntFlag{ + }) + RESTRelayCacheCapacity = altsrc.NewIntFlag(&cli.IntFlag{ Name: "rest-relay-cache-capacity", Value: 30, Usage: "Capacity of the Relay REST API message cache", Destination: &options.RESTServer.RelayCacheCapacity, EnvVars: []string{"WAKUNODE2_REST_RELAY_CACHE_CAPACITY"}, - } - RESTAdmin = &cli.BoolFlag{ + }) + RESTAdmin = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "rest-admin", Value: false, Usage: "Enable access to REST HTTP Admin API", Destination: &options.RESTServer.Admin, EnvVars: []string{"WAKUNODE2_REST_ADMIN"}, - } - RESTPrivate = &cli.BoolFlag{ + }) + RESTPrivate = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "rest-private", Value: false, Usage: "Enable access to REST HTTP Private API", Destination: &options.RESTServer.Private, EnvVars: []string{"WAKUNODE2_REST_PRIVATE"}, - } - PProf = &cli.BoolFlag{ + }) + PProf = altsrc.NewBoolFlag(&cli.BoolFlag{ Name: "pprof", Usage: "provides runtime profiling data at /debug/pprof in both REST and RPC servers if they're enabled", Destination: &options.PProf, EnvVars: []string{"WAKUNODE2_PPROF"}, - } + }) ) diff --git a/cmd/waku/main.go b/cmd/waku/main.go index f5675e01..35e12343 100644 --- a/cmd/waku/main.go +++ b/cmd/waku/main.go @@ -4,7 +4,8 @@ import ( "os" logging "github.com/ipfs/go-log/v2" - "github.com/urfave/cli/v2" + cli "github.com/urfave/cli/v2" + "github.com/urfave/cli/v2/altsrc" "github.com/waku-org/go-waku/waku" "github.com/waku-org/go-waku/waku/v2/node" "github.com/waku-org/go-waku/waku/v2/utils" @@ -18,6 +19,7 @@ func main() { options.LogEncoding = "console" cliFlags := []cli.Flag{ + &cli.StringFlag{Name: "config-file", Usage: "loads configuration from a TOML file (cmd-line parameters take precedence)"}, TcpPort, Address, WebsocketSupport, @@ -101,6 +103,7 @@ func main() { app := &cli.App{ Name: "gowaku", Version: node.GetVersionInfo().String(), + Before: altsrc.InitInputSourceWithContext(cliFlags, altsrc.NewTomlSourceFromFlagFunc("config-file")), Flags: cliFlags, Action: func(c *cli.Context) error { utils.InitLogger(options.LogEncoding, options.LogOutput) diff --git a/cmd/waku/no_rln.go b/cmd/waku/no_rln.go index 1fa9f58a..7bbb48a8 100644 --- a/cmd/waku/no_rln.go +++ b/cmd/waku/no_rln.go @@ -3,7 +3,7 @@ package main -import "github.com/urfave/cli/v2" +import cli "github.com/urfave/cli/v2" func rlnFlags() []cli.Flag { return nil diff --git a/cmd/waku/rln.go b/cmd/waku/rln.go index 50855ac5..e1ef58f7 100644 --- a/cmd/waku/rln.go +++ b/cmd/waku/rln.go @@ -4,7 +4,7 @@ package main import ( - "github.com/urfave/cli/v2" + cli "github.com/urfave/cli/v2" wcli "github.com/waku-org/go-waku/waku/cliutils" ) diff --git a/go.mod b/go.mod index a5d84ae7..7fd6cf0f 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/onsi/ginkgo v1.16.5 // indirect github.com/stretchr/testify v1.8.1 github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect - github.com/urfave/cli/v2 v2.20.2 + github.com/urfave/cli/v2 v2.23.7 go.opencensus.io v0.23.0 go.uber.org/zap v1.23.0 golang.org/x/sync v0.1.0 @@ -41,6 +41,8 @@ require ( github.com/waku-org/go-noise v0.0.4 ) +require github.com/BurntSushi/toml v1.2.1 // indirect + require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect diff --git a/go.sum b/go.sum index 9fbace23..072a8441 100644 --- a/go.sum +++ b/go.sum @@ -100,6 +100,8 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -1517,8 +1519,8 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/urfave/cli/v2 v2.20.2 h1:dKA0LUjznZpwmmbrc0pOgcLTEilnHeM8Av9Yng77gHM= -github.com/urfave/cli/v2 v2.20.2/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= +github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= diff --git a/waku/cliutils/altsrc.go b/waku/cliutils/altsrc.go new file mode 100644 index 00000000..1a2a12a6 --- /dev/null +++ b/waku/cliutils/altsrc.go @@ -0,0 +1,96 @@ +package cliutils + +import ( + "flag" + "strings" + "syscall" + + cli "github.com/urfave/cli/v2" + "github.com/urfave/cli/v2/altsrc" +) + +type GenericFlagSingleValue struct { + *cli.GenericFlag + set *flag.FlagSet +} + +type GenericFlagMultiValue struct { + *cli.GenericFlag + set *flag.FlagSet +} + +func NewGenericFlagSingleValue(fl *cli.GenericFlag) *GenericFlagSingleValue { + return &GenericFlagSingleValue{GenericFlag: fl, set: nil} +} + +func NewGenericFlagMultiValue(fl *cli.GenericFlag) *GenericFlagMultiValue { + return &GenericFlagMultiValue{GenericFlag: fl, set: nil} +} + +func (f *GenericFlagSingleValue) Apply(set *flag.FlagSet) error { + f.set = set + return f.GenericFlag.Apply(set) +} + +func (f *GenericFlagMultiValue) Apply(set *flag.FlagSet) error { + f.set = set + return f.GenericFlag.Apply(set) +} + +func isEnvVarSet(envVars []string) bool { + for _, envVar := range envVars { + if _, ok := syscall.Getenv(envVar); ok { + // TODO: Can't use this for bools as + // set means that it was true or false based on + // Bool flag type, should work for other types + return true + } + } + + return false +} + +func (f *GenericFlagSingleValue) ApplyInputSourceValue(cCtx *cli.Context, isc altsrc.InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + + for _, name := range f.GenericFlag.Names() { + value, err := isc.String(name) + if err != nil { + return err + } + if value == "" { + continue + } + + for _, n := range f.Names() { + _ = f.set.Set(n, value) + } + } + + return nil +} + +func (f *GenericFlagMultiValue) ApplyInputSourceValue(cCtx *cli.Context, isc altsrc.InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + + for _, name := range f.GenericFlag.Names() { + value, err := isc.StringSlice(name) + if err != nil { + return err + } + if len(value) == 0 { + continue + } + + for _, n := range f.Names() { + _ = f.set.Set(n, strings.Join(value, ",")) + } + + } + + return nil +}