mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
config: Add include directive support.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Added: Config: configuration files now support `include`.
This commit is contained in:
parent
6defc69482
commit
34c89cb226
@ -18,6 +18,10 @@ options: later options override earlier ones except \fIaddr\fR options
|
|||||||
and \fIlog-level\fR with subsystems, which accumulate\.
|
and \fIlog-level\fR with subsystems, which accumulate\.
|
||||||
|
|
||||||
|
|
||||||
|
\fIinclude \fR followed by a filename includes another configuration file at that
|
||||||
|
point, relative to the current configuration file\.
|
||||||
|
|
||||||
|
|
||||||
All these options are mirrored as commandline arguments to
|
All these options are mirrored as commandline arguments to
|
||||||
\fBlightningd\fR(8), so \fI--foo\fR becomes simply \fIfoo\fR in the configuration
|
\fBlightningd\fR(8), so \fI--foo\fR becomes simply \fIfoo\fR in the configuration
|
||||||
file, and \fI--foo=bar\fR becomes \fIfoo=bar\fR in the configuration file\.
|
file, and \fI--foo=bar\fR becomes \fIfoo=bar\fR in the configuration file\.
|
||||||
|
@ -18,6 +18,9 @@ Configuration file options are processed first, then command line
|
|||||||
options: later options override earlier ones except *addr* options
|
options: later options override earlier ones except *addr* options
|
||||||
and *log-level* with subsystems, which accumulate.
|
and *log-level* with subsystems, which accumulate.
|
||||||
|
|
||||||
|
*include * followed by a filename includes another configuration file at that
|
||||||
|
point, relative to the current configuration file.
|
||||||
|
|
||||||
All these options are mirrored as commandline arguments to
|
All these options are mirrored as commandline arguments to
|
||||||
lightningd(8), so *--foo* becomes simply *foo* in the configuration
|
lightningd(8), so *--foo* becomes simply *foo* in the configuration
|
||||||
file, and *--foo=bar* becomes *foo=bar* in the configuration file.
|
file, and *--foo=bar* becomes *foo=bar* in the configuration file.
|
||||||
|
@ -700,9 +700,7 @@ static void setup_default_config(struct lightningd *ld)
|
|||||||
ld->pidfile = tal_fmt(ld, "lightningd-%s.pid", chainparams->network_name);
|
ld->pidfile = tal_fmt(ld, "lightningd-%s.pid", chainparams->network_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int config_parse_line_number;
|
||||||
/* FIXME: make this nicer! */
|
|
||||||
static int config_parse_line_number = 0;
|
|
||||||
|
|
||||||
static void config_log_stderr_exit(const char *fmt, ...)
|
static void config_log_stderr_exit(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -723,7 +721,8 @@ static void config_log_stderr_exit(const char *fmt, ...)
|
|||||||
assert(problem != NULL);
|
assert(problem != NULL);
|
||||||
/*mangle it to remove '--' and add the line number.*/
|
/*mangle it to remove '--' and add the line number.*/
|
||||||
msg = tal_fmt(NULL, "%s line %d: %.*s: %s",
|
msg = tal_fmt(NULL, "%s line %d: %.*s: %s",
|
||||||
argv0, config_parse_line_number, len-2, arg+2, problem);
|
argv0,
|
||||||
|
config_parse_line_number, len-2, arg+2, problem);
|
||||||
} else {
|
} else {
|
||||||
msg = tal_vfmt(NULL, fmt, ap);
|
msg = tal_vfmt(NULL, fmt, ap);
|
||||||
}
|
}
|
||||||
@ -732,30 +731,22 @@ static void config_log_stderr_exit(const char *fmt, ...)
|
|||||||
fatal("%s", msg);
|
fatal("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void parse_include(struct lightningd *ld,
|
||||||
* We turn the config file into cmdline arguments. @early tells us
|
const char *filename,
|
||||||
* whether to parse early options only (and ignore any unknown ones),
|
bool must_exist,
|
||||||
* or the non-early options.
|
bool early)
|
||||||
*/
|
|
||||||
static void opt_parse_from_config(struct lightningd *ld, bool early)
|
|
||||||
{
|
{
|
||||||
char *contents, **lines;
|
char *contents, **lines;
|
||||||
char **all_args; /*For each line: either argument string or NULL*/
|
char **all_args; /*For each line: either `--`argument, include file, or NULL*/
|
||||||
char *argv[3];
|
char *argv[3];
|
||||||
int i, argc;
|
int i, argc;
|
||||||
char *filename;
|
|
||||||
|
|
||||||
if (ld->config_filename != NULL)
|
|
||||||
filename = ld->config_filename;
|
|
||||||
else
|
|
||||||
filename = path_join(tmpctx, ld->config_dir, "config");
|
|
||||||
|
|
||||||
contents = grab_file(ld, filename);
|
contents = grab_file(ld, filename);
|
||||||
|
|
||||||
/* The default config doesn't have to exist, but if the config was
|
/* The default config doesn't have to exist, but if the config was
|
||||||
* specified on the command line it has to exist. */
|
* specified on the command line it has to exist. */
|
||||||
if (!contents) {
|
if (!contents) {
|
||||||
if ((errno != ENOENT) || (ld->config_filename != NULL))
|
if (must_exist)
|
||||||
fatal("Opening and reading %s: %s",
|
fatal("Opening and reading %s: %s",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
@ -769,8 +760,13 @@ static void opt_parse_from_config(struct lightningd *ld, bool early)
|
|||||||
for (i = 0; i < tal_count(lines) - 1; i++) {
|
for (i = 0; i < tal_count(lines) - 1; i++) {
|
||||||
if (strstarts(lines[i], "#")) {
|
if (strstarts(lines[i], "#")) {
|
||||||
all_args[i] = NULL;
|
all_args[i] = NULL;
|
||||||
}
|
} else if (strstarts(lines[i], "include ")) {
|
||||||
else {
|
/* If relative, it's relative to current config file */
|
||||||
|
all_args[i] = path_join(all_args,
|
||||||
|
take(path_dirname(NULL,
|
||||||
|
filename)),
|
||||||
|
lines[i] + strlen("include "));
|
||||||
|
} else {
|
||||||
/* Only valid forms are "foo" and "foo=bar" */
|
/* Only valid forms are "foo" and "foo=bar" */
|
||||||
all_args[i] = tal_fmt(all_args, "--%s", lines[i]);
|
all_args[i] = tal_fmt(all_args, "--%s", lines[i]);
|
||||||
}
|
}
|
||||||
@ -781,32 +777,51 @@ static void opt_parse_from_config(struct lightningd *ld, bool early)
|
|||||||
argv[1] is the only element that changes between iterations.
|
argv[1] is the only element that changes between iterations.
|
||||||
*/
|
*/
|
||||||
argc = 2;
|
argc = 2;
|
||||||
argv[0] = "lightning config file";
|
argv[0] = cast_const(char *, filename);
|
||||||
argv[argc] = NULL;
|
argv[argc] = NULL;
|
||||||
|
|
||||||
if (early) {
|
for (i = 0; i < tal_count(all_args); i++) {
|
||||||
for (i = 0; i < tal_count(all_args); i++) {
|
if (all_args[i] == NULL)
|
||||||
if (all_args[i] != NULL) {
|
continue;
|
||||||
config_parse_line_number = i + 1;
|
|
||||||
argv[1] = all_args[i];
|
if (!strstarts(all_args[i], "--")) {
|
||||||
opt_early_parse_incomplete(argc, argv,
|
parse_include(ld, all_args[i], true, early);
|
||||||
config_log_stderr_exit);
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (i = 0; i < tal_count(all_args); i++) {
|
config_parse_line_number = i + 1;
|
||||||
if (all_args[i] != NULL) {
|
argv[1] = all_args[i];
|
||||||
config_parse_line_number = i + 1;
|
if (early) {
|
||||||
argv[1] = all_args[i];
|
opt_early_parse_incomplete(argc, argv,
|
||||||
opt_parse(&argc, argv, config_log_stderr_exit);
|
config_log_stderr_exit);
|
||||||
argc = 2; /* opt_parse might have changed it */
|
} else {
|
||||||
}
|
opt_parse(&argc, argv, config_log_stderr_exit);
|
||||||
|
argc = 2; /* opt_parse might have changed it */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tal_free(contents);
|
tal_free(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We turn the config file into cmdline arguments. @early tells us
|
||||||
|
* whether to parse early options only (and ignore any unknown ones),
|
||||||
|
* or the non-early options.
|
||||||
|
*/
|
||||||
|
static void opt_parse_from_config(struct lightningd *ld, bool early)
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
/* The default config doesn't have to exist, but if the config was
|
||||||
|
* specified on the command line it has to exist. */
|
||||||
|
if (ld->config_filename != NULL)
|
||||||
|
filename = ld->config_filename;
|
||||||
|
else
|
||||||
|
filename = path_join(tmpctx, ld->config_dir, "config");
|
||||||
|
|
||||||
|
parse_include(ld, filename, ld->config_filename != NULL, early);
|
||||||
|
}
|
||||||
|
|
||||||
static char *test_subdaemons_and_exit(struct lightningd *ld)
|
static char *test_subdaemons_and_exit(struct lightningd *ld)
|
||||||
{
|
{
|
||||||
test_subdaemons(ld);
|
test_subdaemons(ld);
|
||||||
|
@ -1767,3 +1767,18 @@ def test_signmessage(node_factory):
|
|||||||
checknokey = l2.rpc.checkmessage(message="message for you", zbase=zm)
|
checknokey = l2.rpc.checkmessage(message="message for you", zbase=zm)
|
||||||
assert checknokey['pubkey'] == l1.info['id']
|
assert checknokey['pubkey'] == l1.info['id']
|
||||||
assert checknokey['verified']
|
assert checknokey['verified']
|
||||||
|
|
||||||
|
|
||||||
|
def test_include(node_factory):
|
||||||
|
l1 = node_factory.get_node(start=False)
|
||||||
|
|
||||||
|
subdir = os.path.join(l1.daemon.opts.get("lightning-dir"), "subdir")
|
||||||
|
os.makedirs(subdir)
|
||||||
|
with open(os.path.join(subdir, "conf1"), 'w') as f:
|
||||||
|
f.write('include conf2')
|
||||||
|
with open(os.path.join(subdir, "conf2"), 'w') as f:
|
||||||
|
f.write('alias=conf2')
|
||||||
|
l1.daemon.opts['conf'] = os.path.join(subdir, "conf1")
|
||||||
|
l1.start()
|
||||||
|
|
||||||
|
assert l1.rpc.listconfigs('alias')['alias'] == 'conf2'
|
||||||
|
Loading…
Reference in New Issue
Block a user