-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
detect if dcrcli.conf is not configured #64
detect if dcrcli.conf is not configured #64
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've done good work here. Let's tie up loose edges so we can merge this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting this auto-config thing to work smoothly is not proving as straightforward as we'd like but we'll get it. Some more thoughts on what could be done better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're close! Minor changes left...
config.go
Outdated
defaultRpcAddress = "localhost:19111" | ||
defaultRpcUsername = "rpcuser" | ||
defaultRpcPassword = "rpcpass" | ||
ServerAddress = "127.0.0.1:7778" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use defaultHTTPServerAddress
instead, btw, ServerAddress
doesn't need to be public. We can/should make defaultHTTPServerAddress
= 127.0.0.1:7778
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we don't need to automatically save a value for serveraddress
to dcrcli.conf
. The program is designed such that if there is no value set in config, the default value would be used.
If we must save a value for this option to dcrcli.conf
, we should request it from the user. But I don't think that is relevant, we probably should just stick to having a default value to use if user doesn't manually supply one.
config.go
Outdated
@@ -129,18 +137,45 @@ func loadConfig(appName string) (*config, []string, error) { | |||
os.Exit(0) | |||
} | |||
|
|||
//config | |||
if preCfg.Init { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the file already exists and user passes the --init
flag? I think a warning is in order before the existing config file is overwritten.
config.go
Outdated
parser.WriteHelp(os.Stderr) | ||
return nil, nil, err | ||
} | ||
|
||
if preCfg.WalletRPCServer == "" || preCfg.RPCUser == "" || preCfg.RPCPassword == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I run dcrcli -c="localhost:19111" -u="rpcuser" -p="rpcpass"
, I still get the error about missing config fie (true) and not passing dcrwallet RPC credentials in command line options (false)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ademuanthony That happens because the command line options have not been parsed at this point. Parse the command line arguments first (parser.Parse
), before parsing the configuration file.
config.go
Outdated
if err == nil { | ||
return loadConfig(appName) | ||
} | ||
fmt.Println(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should behave as though --init
flag was passed, exit after running configure
.
Currently, if I get to this point and say yes, it creates the config, prints out The config file has been set successfully
but also proceeds to print out the following message which is a little confusing:
available cmds: balance, send, receive, history
experimental: send-custom
config.go
Outdated
if err != nil { | ||
return inputErr(err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we maintain the pattern below and remove this empty line space?
config.go
Outdated
RpcAddress string | ||
RpcUsername string | ||
RpcPassword string | ||
ServerAddress string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in an earlier comment, saving this to dcrcli.conf
is unnecessary - the app will not break if this value is not set in config.
There are a couple of other config options that are needed but have default values like RPCCert
and NoDaemonTLS
. Their absence in dcrcli.conf
or in the command-line options won't cause the app to break. Don't see a need to ask the user to supply such information when initialising a conf file.
If we want to ask the user to supply them, then let's make them behave like WalletRPCServer
, RPCUser
and RPCPassword
config options (no default values). They must be provided either in command-line options or saved in dcrcli.conf
. if none of the above is done, then the user should be prompted to create a config file or pass those values.
If we're using default values, let's keep using default values until a user on his own goes to set a different value in dcrcli.conf
or passes a different value in command-line options
main.go
Outdated
@@ -42,8 +39,7 @@ func (v *Version) String() string { | |||
} | |||
|
|||
func main() { | |||
appName := filepath.Base(os.Args[0]) | |||
appName = strings.TrimSuffix(appName, filepath.Ext(appName)) | |||
appName := cli.AppName() | |||
|
|||
config, args, err := loadConfig(appName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only use of appName
in this function. We can do without it. loadConfig
is able to access cli.AppName()
directly where needed. It currently does so in line 167 of config.go
We'll need to update readme, the part about configuring dcrcli using the sample config file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the configuration directory (~/.dcrcli) does not exist, the program should create it before writing the configuration file. Currently, it does not check whether the directory exists.
$ ./dcrcli --init
Wallet RPC server (default = localhost:19111):
RPC username (default = rpcuser):
RPC password (default = rpcpass): error in creating config file: open /home/barisere/.dcrcli/dcrcli.conf: no such file or directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the program does not offer a default when asking the user whether to create the configuration file immediately.
$ ./dcrcli
The config file (/home/barisere/.dcrcli/dcrcli.conf) is missing, and you did not pass dcrwallet RPC credentials in command line options.
Please run 'dcrcli --init' to create the config file or pass RPC credentials by following the instructions set in 'dcrcli -h'
Do you want to create the config file now? (y/n):
The output of the last line of the prompt should be
Do you want to create the config file now? (Y/n):
That indicates that "Y" is the default, so the user can simply hit enter and have the process continue. With the current implementation, the process aborts if the user does not provide an input.
Also check for wrong input. Validate that the input is either "Y" or "N", and it should be case-insensitive.
config.go
Outdated
parser.WriteHelp(os.Stderr) | ||
return nil, nil, err | ||
} | ||
|
||
if preCfg.WalletRPCServer == "" || preCfg.RPCUser == "" || preCfg.RPCPassword == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The absence of those properties does not mean that the configuration file is missing. As @itswisdomagain noted, those properties can be provided via command line options.
I have an idea what the solution may be. First, parse the command line options as I suggested in my previous comment. Then add an else
branch to the if
block on line 155. The else
branch should run only if there was an *os.PathError
and the properties you check for on line 161 are empty; i.e., the configuration file is missing, and the associated options were not provided on the command line.
I just came into a shocking revelation. RPC username ( The only exception to this is when the user specifies This means that the only info we need to run It gets even exciting. The behaviour for dcrwallet is such that if a user does not set a gRPC address to use for incoming connections, The only potential problem with using this default value is - what if the value isn't correct? What if the user set a different dcrwallet listen address? That problem wouldn't really solved by asking the user to specify an address instead of using the default address. The user may still specify an incorrect address. This is a whole other problem that gave birth to issue #77. This PR does not confirm if an rpc server address is valid or not. That's for a different PR in response to #77. This PR is slowly becoming unnecessary work. I'll create a different PR very soon to remove the unused rpc username and password options from config.go; and also use a default rpc address if none is provided. When that PR gets merged, one is left asking, is there ever a scenario where we'll need to ask a user to create a My recommendation at this point is, we change this PR's direction. The goal should now be to create a conf file whenever necessary by running |
README.md
Outdated
``` | ||
|
||
Then edit dcrcli.conf and input your RPC settings. After you are finished, move dcrcli.conf to the `appdata` folder (default is `~/.dcrcli` on Linux, `%localappdata%\Dcrcli` on Windows). See the output of `dcrcli -h` for a list of all options | ||
Follow the command prompt and input your RPC settings. | ||
The configuration file, dcrcli.conf will be created in your `appdata` folder (default is `~/.dcrcli` on Linux, `%localappdata%\Dcrcli` on Windows). See the output of `dcrcli -h` for a list of all options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the default appdata
folder on Mac?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question. That's one of the changes that the readme needs.
For Mac: ~/Library/Application Support/Dcrcli/dcrcli.conf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of saying
See the output of
dcrcli -h
for a list of all options"
I think a more relevant information to display here is
To use a different app data folder, use
dcrcli --init -C="path/to/desired/app/data/folder"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Using dcrcli section below should come above this Configuration section. That section (Using dcrcli) should mention using
dcrcli [options] <command> [args...]
to run a commanddcrcli -h
to view general program help, application options and available commandsdcrcli <command> -h
to view help information for a particular command
README.md
Outdated
|
||
```bash | ||
cp sample-dcrcli.conf dcrcli.conf | ||
dcrcli --init |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can prepend this with a "$" to indicate that it's a command to run at the terminal.
$ dcrcli --init
config.go
Outdated
@@ -39,6 +46,7 @@ type config struct { | |||
HTTPServerAddress string `short:"s" long:"serveraddress" description:"Address and port of the HTTP server."` | |||
HTTPMode bool `long:"http" description:"Run in HTTP mode."` | |||
NoDaemonTLS bool `long:"nodaemontls" description:"Disable TLS"` | |||
Init bool `long:"init" description:"Create the config file"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR #60 introduces a new flag (--createwallet
) for creating wallet (if it doesn't exist already) before using dcrcli. I initially used --init
for that use case but decided init
was a little ambiguous and not very descriptive.
I want to suggest using a more descriptive flag here, say --createconfig
or --config
. --config
might not work since it could be confused with --configfile
used for specifying a config file path.
@itswisdomagain
But that's just me being familiar with other tools that use this style. |
@barisere I think in those cases, |
@ademuanthony Please address #64 (review).
Also move the error message to its own line. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the creation of the configuration file succeeds, the output is as follows.
$ ./dcrcli --init -C ./dcrcli.conf.new
Wallet RPC server (default = localhost:19111):
RPC username (default = rpcuser):
RPC password (default = rpcpass):
The config file has been set successfully
The blank lines are not necessary, and the absolute path to the file written is displayed to the user.
An output like the following looks fine to me. What do you think about it?
$ ./dcrcli --init -C ./dcrcli.conf.new
Wallet RPC server (default = localhost:19111):
RPC username (default = rpcuser):
RPC password (default = rpcpass):
The config file has been written to /home/barisere/code/go/src/github.com/raedahgroup/dcrcli/dcrcli.conf.new
I notice we're simply logging errors to the console. I suggest we log them to a file as well, and let the users know about the file. That way, the history of errors does not get lost, and we can get easily introduce telemetry if we want to. The main benefit is being able to go look at detailed error output (including stack traces if necessary) in the log file, and knowing where to start looking for problems. If a user reports an error, we can request the log file for richer context. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the configuration file is created, the default rpccert
field should be an actual path on the user's filesystem. Currently it is hard-coded.
Compare
; Specify dcrwallet's RPC certificate, or disable TLS for the
; rpccert=/home/me/.dcrwallet/rpc.cert
vs
; Specify dcrwallet's RPC certificate, or disable TLS for the
; rpccert=/home/barisere/.dcrwallet/rpc.cert
Yes! Yes! A new issue should be created for this and addressed in a separate PR. Will need permission from @raedah first though |
README.md
Outdated
``` | ||
|
||
Then edit dcrcli.conf and input your RPC settings. After you are finished, move dcrcli.conf to the `appdata` folder (default is `~/.dcrcli` on Linux, `%localappdata%\Dcrcli` on Windows). See the output of `dcrcli -h` for a list of all options | ||
Follow the command prompt and input your RPC settings. | ||
The configuration file, dcrcli.conf will be created in your `appdata` folder (default is `~/.dcrcli` on Linux, `%localappdata%\Dcrcli` on Windows). See the output of `dcrcli -h` for a list of all options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of saying
See the output of
dcrcli -h
for a list of all options"
I think a more relevant information to display here is
To use a different app data folder, use
dcrcli --init -C="path/to/desired/app/data/folder"
README.md
Outdated
``` | ||
|
||
Then edit dcrcli.conf and input your RPC settings. After you are finished, move dcrcli.conf to the `appdata` folder (default is `~/.dcrcli` on Linux, `%localappdata%\Dcrcli` on Windows). See the output of `dcrcli -h` for a list of all options | ||
Follow the command prompt and input your RPC settings. | ||
The configuration file, dcrcli.conf will be created in your `appdata` folder (default is `~/.dcrcli` on Linux, `%localappdata%\Dcrcli` on Windows). See the output of `dcrcli -h` for a list of all options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Using dcrcli section below should come above this Configuration section. That section (Using dcrcli) should mention using
dcrcli [options] <command> [args...]
to run a commanddcrcli -h
to view general program help, application options and available commandsdcrcli <command> -h
to view help information for a particular command
defaultRpcAddress = "localhost:19111" | ||
defaultRpcUsername = "rpcuser" | ||
defaultRpcPassword = "rpcpass" | ||
ServerAddress = "127.0.0.1:7778" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't relevant, we already have defaultHTTPServerAddress
@@ -36,6 +44,7 @@ type Config struct { | |||
HTTPServerAddress string `short:"s" long:"serveraddress" description:"Address and port of the HTTP server."` | |||
HTTPMode bool `long:"http" description:"Run in HTTP mode."` | |||
NoDaemonTLS bool `long:"nodaemontls" description:"Disable TLS"` | |||
Init bool `long:"init" description:"Create the config file"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In line with this comment and this reply, I want to re-recommend this flag be renamed.
It's okay if git and npm uses init
, you can't use those programs without first issuing that command, "init" makes sense.
In our case, "init" isn't a pre-requirement to use the program, so it's quite misleading... What this does isn't setting up the program for use, but instead creating a config file on-demand - at any time the user says he wants to create one. I think --config
is appropriate
return fmt.Errorf("error receiving input: %s", err.Error()) | ||
} | ||
|
||
var rpcAddress, rpcUsername, rpcPassword string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rpcUsername
and rpcPassword
values are not used in the dcrcli program. They should be completely removed from the list of config options and this function should not request values for them from the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since those 2 options are no longer required, it doesn't make sense for a user to run dcrcli --init
or dcrcli --config
just to set rpcAddress
. I think it'd be appropriate to prompt user to provide values for all or most of the application options. One exception would be the ConfigFile
option (only makes sense in command-line options).
Then use the values provided to create the config file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we remove the config flag entirely and just request the address from the user at the point of loading the config options in the program?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the config/init flag? No. We've done too much work here already to throw it away.
We also should not request the address from the user. To connect to dcrwallet, the dcrwallet cert file path is also needed but we don't request that from the user either. If the user doesn't set a value in config or in command-line options, we use the default. That's currently what we're doing for the wallet rpc server address as well.
ServerAddress string | ||
}{ | ||
RpcAddress: rpcAddress, RpcUsername: rpcUsername, RpcPassword: rpcPassword, | ||
ServerAddress: ServerAddress, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not directly save a default/static value to config file. Before doing so, the user should be prompted for a value to use with the option of retaining the default value
|
||
; Turn HTTP mode on (http=true or http=1) or off (http=false or http=0). | ||
; HTTP mode is off by default. | ||
; http=true | ||
; http=true` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to remember to update this file as more application options/flags are added. For example, we now have UseTestNet (; testnet=1
)
If the config file is not found and the user did not pass Dcrwallet credentials in command line options, propose to guide the user in creating a new config file and do same if the user accepts, else quit the application use text/template for the conf parsing Clean up Default value for RPC credentails Suggest and use default value for the RPC credentials Refactored the code to use the already existing RequestInput Modified the terminalpromt.RequestInput func to eccept nil validation func Cleaning up remove empty validator define default values as constants configure handler moved the config setup to a handler and inform the user of the appropriate configuration command at startup if config not found. removed the sample-dcrcli.conf to leave the template string in the handler as the single source of truth for the config file Requested changes Renamed 'configure' command to 'config'. removed appName from cli struct and use AppName fn in its place. detached invalidCommandReceived from cli struct. removed unnecessary create config dialog. point out the default values. Created a config flag and call the call configure Moved the configure func to config.go and also call the func on start if the config file is not found Created a config flag and call the call configure Moved the configure func to config.go and also call the func on start if the config file is not found Merge remote-tracking branch 'origin/iss-50-conf-detection' into iss-50-conf-detection configuration instruction in readMe
I'm gonna close this PR @ademuanthony and @barisere. The issue this PR took to solve is outdated and irrelevant. But the work done so far, isn't completely unusable. We'll channel it into a more relevant issue. I'll create the new issue and reference this PR. However, this PR should not be re-opened for the new issue. A new PR should be created. Most of the code changes here can and should be retained though. I've updated the issue being fixed by this PR (#50) with a reason for closing both the issue and this PR. You can find the reason here planetdecred/godcr#50 (comment) |
fixes #50
![detect-conf](https://user-images.githubusercontent.com/11990092/50062817-77a65100-01a9-11e9-8449-50c588b4e54d.png)
If the config file is not found and the user did not pass Dcrwallet credentials in command line options, propose to guide the user in creating a new config file and do same if the user accepts, else quit the application
The app will suggest default values and use them if none is provided for the RPC credential
![iss-50-use-default-values](https://user-images.githubusercontent.com/11990092/50063668-b807ce00-01ad-11e9-8efa-da5a40874f3e.png)