Skip to content

Commit eae0d1d

Browse files
rustyrussellnepet
authored andcommitted
lightningd: fix up deprecated rest-port, rest-protocol, rest-host and rest-certs option if we would otherwise fail.
Since these worked in v23.08, we can't just rename them. So if they are used and unclaimed, we should rename them internally (if they're claimed, it's probably clightning-rest, and we should *NOT* touch them!). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Deprecated: Plugins: `clnrest` parameters `rest-port`, `rest-protocol`, `rest-host` and `rest-certs`: prefix `cln` to them
1 parent 8f8202d commit eae0d1d

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

lightningd/options.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,8 +1811,43 @@ void handle_early_opts(struct lightningd *ld, int argc, char *argv[])
18111811
logging_options_parsed(ld->log_book);
18121812
}
18131813

1814+
/* Free *str, set *str to copy with `cln` prepended */
1815+
static void prefix_cln(const char **str STEALS)
1816+
{
1817+
const char *newstr = tal_fmt(tal_parent(*str), "cln%s", *str);
1818+
tal_free(*str);
1819+
*str = newstr;
1820+
}
1821+
1822+
/* Due to a conflict between the widely-deployed clightning-rest plugin and
1823+
* our own clnrest plugin, and people wanting to run both, in v23.11 we
1824+
* renamed some options. This breaks perfectly working v23.08 deployments who
1825+
* don't care about clightning-rest, so we work around it here. */
1826+
static void fixup_clnrest_options(struct lightningd *ld)
1827+
{
1828+
for (size_t i = 0; i < tal_count(ld->configvars); i++) {
1829+
struct configvar *cv = ld->configvars[i];
1830+
1831+
/* These worked for v23.08 */
1832+
if (!strstarts(cv->configline, "rest-port=")
1833+
&& !strstarts(cv->configline, "rest-protocol=")
1834+
&& !strstarts(cv->configline, "rest-host=")
1835+
&& !strstarts(cv->configline, "rest-certs="))
1836+
continue;
1837+
/* Did some (plugin) claim it? */
1838+
if (opt_find_long(cv->configline, &cv->optarg))
1839+
continue;
1840+
log_unusual(ld->log, "Option %s deprecated in v23.11, renaming to cln%s",
1841+
cv->configline, cv->configline);
1842+
prefix_cln(&cv->configline);
1843+
}
1844+
}
1845+
18141846
void handle_opts(struct lightningd *ld)
18151847
{
1848+
if (ld->deprecated_apis)
1849+
fixup_clnrest_options(ld);
1850+
18161851
/* Now we know all the options, finish parsing and finish
18171852
* populating ld->configvars with cmdline. */
18181853
parse_configvars_final(ld->configvars, true, ld->developer);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env python3
2+
"""Register rest-port to test that we don't "fix" it."""
3+
4+
from pyln.client import Plugin
5+
6+
7+
plugin = Plugin()
8+
9+
10+
@plugin.init()
11+
def init(configuration, options, plugin):
12+
print(f"rest-port is {plugin.get_option('rest-port')}")
13+
14+
15+
plugin.add_option('rest-port', None, "Parameter to clash with clnrest.py deprecated one")
16+
17+
18+
plugin.run()

tests/test_clnrest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pyln.testing.utils import env, TEST_NETWORK
44
from pyln.client import Millisatoshi
55
import unittest
6+
import os
67
import requests
78
from pathlib import Path
89
from requests.adapters import HTTPAdapter
@@ -433,3 +434,35 @@ def test_clnrest_http_headers(node_factory):
433434
headers={'Origin': 'http://192.168.1.10:1010'},
434435
verify=ca_cert)
435436
assert response.headers['Access-Control-Allow-Origin'] == 'http://192.168.1.10:1010'
437+
438+
439+
def test_clnrest_old_params(node_factory):
440+
"""Test that we handle the v23.08-style parameters"""
441+
rest_port = str(reserve())
442+
rest_host = '127.0.0.1'
443+
base_url = f'https://{rest_host}:{rest_port}'
444+
l1 = node_factory.get_node(options={'rest-port': rest_port,
445+
'rest-host': rest_host,
446+
'allow-deprecated-apis': True})
447+
# This might happen really early!
448+
l1.daemon.logsearch_start = 0
449+
l1.daemon.wait_for_logs([r'UNUSUAL lightningd: Option rest-port=.* deprecated in v23\.11, renaming to clnrest-port',
450+
r'UNUSUAL lightningd: Option rest-host=.* deprecated in v23\.11, renaming to clnrest-host'])
451+
l1.daemon.wait_for_log(r'plugin-clnrest.py: REST server running at ' + base_url)
452+
453+
# Now try one where a plugin (e.g. clightning-rest) registers the option.
454+
plugin = os.path.join(os.path.dirname(__file__), 'plugins/clnrest-use-options.py')
455+
l2 = node_factory.get_node(options={'rest-port': rest_port,
456+
'rest-host': rest_host,
457+
'plugin': plugin,
458+
'allow-deprecated-apis': True})
459+
460+
l2.daemon.logsearch_start = 0
461+
# We still rename this one, since it's for clnrest.
462+
assert l2.daemon.is_in_log(r'UNUSUAL lightningd: Option rest-host=.* deprecated in v23\.11, renaming to clnrest-host')
463+
464+
# This one does not get renamed!
465+
assert not l2.daemon.is_in_log(r'UNUSUAL lightningd: Option rest-port=.* deprecated in v23\.11, renaming to clnrest-host')
466+
assert [p for p in l2.rpc.plugin('list')['plugins'] if 'clnrest.py' in p['name']] == []
467+
assert l2.daemon.is_in_log(r'plugin-clnrest.py: Killing plugin: disabled itself at init: `clnrest-port` option is not configured')
468+
assert l2.daemon.is_in_log(rf'clnrest-use-options.py: rest-port is {rest_port}')

0 commit comments

Comments
 (0)