-
Notifications
You must be signed in to change notification settings - Fork 19
Add CLI and env var config support, split bitcoind_rpc_addr
into host/port
#69
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
base: main
Are you sure you want to change the base?
Conversation
👋 Thanks for assigning @jkczyz as a reviewer! |
Thank you for your work on this! I'm still going through the changes, but I have an early high-level question. Is there a reason or trade-off why the My initial thought was that a crate like Just want to make sure I understand the design decision. |
I chose to use I hadn’t considered using a separate configuration crate like |
🔔 1st Reminder Hey @jkczyz! This PR has been waiting for your review. |
🔔 2nd Reminder Hey @jkczyz! This PR has been waiting for your review. |
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.
Thanks for tackling these issues! Looks like CI is failing, though.
ldk-server/src/util/config.rs
Outdated
None | ||
}; | ||
|
||
macro_rules! pick { |
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.
TBH, the call sites may be more readable if everything was explicitly written out. There isn't much happening here, so I don't think it would be too verbose.
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.
Got it, I removed the picks macro and wrote the calls explicitly.
rpc_address: String, | ||
rpc_user: String, | ||
rpc_password: String, | ||
rpc_host: Option<String>, | ||
rpc_port: Option<u16>, | ||
rpc_user: Option<String>, | ||
rpc_password: Option<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.
Could you make a separate commit for splitting the RPC address?
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.
Yes, sorry, I forgot to split it into two commits.
ldk-server/src/util/config.rs
Outdated
|
||
macro_rules! pick { | ||
($cli:expr, $toml:expr, $err_msg:expr) => { | ||
$cli.or($toml).ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, $err_msg)) |
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.
or_else
?
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.
done!
ldk-server/src/util/config.rs
Outdated
}; | ||
} | ||
|
||
fn missing_field_msg(field: &str) -> 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.
Could this return the io::Error
instead? Then the unrolled macro would be less verbose.
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.
Yes, I removed the macro and made the code explicit. The function now directly returns io::Error
d05dec0
to
96a5676
Compare
CI was failing because tests used the same file names. I fixed it by giving each test a unique file name. |
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.
Thanks again for your work on this! The changes look good overall, but I left a few comments for consideration.
ldk-server/src/util/config.rs
Outdated
format!("Failed to read config file '{}': {}", config_path.as_ref().display(), e), | ||
) | ||
#[derive(Parser, Debug)] | ||
#[command(version, about = "LDK Node Configuration", long_about = None)] |
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.
nit: would it be appropriate to use 'LDK Server Configuration' here instead of ‘LDK Node Configuration’?
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.
Done!
ldk-server/src/util/config.rs
Outdated
format!("Config file contains invalid TOML format: {}", e), | ||
) | ||
})?) | ||
} else { |
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.
Do we really need the else {}
block here? Since we're primarily interested in the Some()
case, and considering the events-rabbitmq
and experimental-lsps2-support
features are already being handled in load_config_feature()
, this block might be redundant.
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 else {}
is needed to handle the None case and also manage features when they're passed. I replaced if
with match
to make the options clearer.
storage_dir_path: Option<String>, | ||
} | ||
|
||
pub fn load_config(args_config: &ArgsConfig) -> io::Result<Config> { |
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 load_config()
function seems to be doing quite a lot at the moment. It might be beneficial to implement TryFrom<TomlConfig> for Config
and move all the logic after the if let Some()
block into the try_from()
method, similar to how it was structured before.
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.
I see your point.TryFrom<TomlConfig>
made sense when the goal was a direct conversion from TOML to Config. Now that load_config()
merges values from both TomlConfig
and ArgsConfig
, the logic is more about combining sources than just converting one type. In this case, keeping it in load_config()
seems more consistent.
96a5676
to
7cf7e98
Compare
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.
Sorry about the delay. Some travel got the best of my time.
ldk-server/src/main.rs
Outdated
let bitcoind_rpc_addr = config_file.bitcoind_rpc_addr; | ||
|
||
builder.set_chain_source_bitcoind_rpc( | ||
bitcoind_rpc_addr.ip().to_string(), | ||
bitcoind_rpc_addr.port(), | ||
config_file.bitcoind_rpc_addr.ip().to_string(), | ||
config_file.bitcoind_rpc_addr.port(), |
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.
Does this belong in the second commit?
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.
Yeah, done!
node: NodeConfig, | ||
storage: StorageConfig, | ||
bitcoind: BitcoindConfig, | ||
node: Option<NodeConfig>, | ||
storage: Option<StorageConfig>, | ||
bitcoind: Option<BitcoindConfig>, |
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.
I don't have a good enough grasp of this change to understand why these need to be Option
s now. Same elsewhere. Could you explain?
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.
Previously these configs were only provided via file. I made them Option so they’re not required in the file anymore, since they can now also be passed via CLI or env. This way, the user can decide to provide some settings only through CLI/env or file, while they’re still required at node startup.
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.
Ah, I see. So long Config
isn't using Option
s then this should be ok. (cc: @tnull in case he has any opinons on the matter).
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.
I think it might make sense to rename these structs, since they’re only used for the TOML file. Adding a suffix or prefix to make that explicit could make the code clearer.
ldk-server/src/util/config.rs
Outdated
let network = match args_config.node_network.or(node.and_then(|n| n.network)) { | ||
Some(n) => n, | ||
None => return Err(missing_field_err("network")), | ||
}; |
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 match
ing like this, let's use ok_or_else()?
and map
when needed. Likewise elsewhere.
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.
Done!
ldk-server/src/util/config.rs
Outdated
let listening_addr_str = match args_config | ||
.node_listening_address | ||
.as_deref() | ||
.or(node.and_then(|n| n.listening_address.as_deref())) | ||
{ | ||
Some(addr) => addr, | ||
None => return Err(missing_field_err("node_listening_address")), | ||
}; | ||
let listening_addr = SocketAddress::from_str(listening_addr_str).map_err(|e| { | ||
io::Error::new(io::ErrorKind::InvalidInput, format!("Invalid listening address: {}", e)) | ||
})?; |
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.
I think we can combine these using and_then
?
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.
Done!
7cf7e98
to
a93ee9f
Compare
node: NodeConfig, | ||
storage: StorageConfig, | ||
bitcoind: BitcoindConfig, | ||
node: Option<NodeConfig>, | ||
storage: Option<StorageConfig>, | ||
bitcoind: Option<BitcoindConfig>, |
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.
Ah, I see. So long Config
isn't using Option
s then this should be ok. (cc: @tnull in case he has any opinons on the matter).
ldk-server/src/util/config.rs
Outdated
toml_config = remove_config_line(&toml_config, &format!("{} =", $field)); | ||
fs::write(storage_path.join(config_file_name), &toml_config).unwrap(); | ||
let result = load_config(&args_config); | ||
println!("Rsult: {:?}", result); |
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.
s/Rsult/Result
But why print in tests?
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're right, the print isn't needed. I had added it temporarily for debugging while checking values, but I've removed it now.
- Added `clap` dependency to `ldk-server` to support passing essential node config via CLI arguments and environment variables. - Implemented layered config loading: config file (full set of options) + environment variables + CLI arguments. Env vars and CLI args override values from the config file when present. - Added tests for the new config loading logic. - Updated README with usage instructions and explanation of config precedence. Close lightningdevkit#42
…pc_port` This change replaces the single RPC address field with separate host and port fields, allowing hostname support and improving compatibility with containerized environments. Closes lightningdevkit#66 juntar com o segundo commit
a93ee9f
to
43d1a52
Compare
Added support for configuring the node via CLI arguments and environment variables, using
clap
(as already done inldk-server-cli
).Configuration is now loaded from three sources:
Environment variables and CLI arguments override values defined in the config file when provided.
In addition, the
bitcoind_rpc_addr
field was split into two variables for better clarity:bitcoind_rpc_host
bitcoind_rpc_port
Tests were added for the new configuration loading logic, and the README was updated with usage instructions.
close #42 and #66