From 02059ee3f8120651c44a70182c2fd8b633505720 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Thu, 21 Nov 2019 14:51:18 +0100 Subject: [PATCH] feat: restructure plugin and options in listconfigs This will change the command `listconfigs` output in several ways: - Deprecated the duplicated "plugin" JSON output by replacing it with - a "plugins" array with substructures for each plugin with: - path, name and their options Changelog-Changed: JSON-RPC: `listconfigs` now structures plugins and include their options Changelog-Deprecated: JSON-RPC: `listconfigs` duplicated "plugin" paths --- lightningd/plugin.c | 42 +++++++++++++++++++++++++++++++++++++++++- tests/test_misc.py | 15 ++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 55fc5f538f17..493780b96a9b 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -1086,9 +1086,49 @@ void json_add_opt_plugins(struct json_stream *response, const struct plugins *plugins) { struct plugin *p; + struct plugin_opt *opt; + const char *plugin_name; + const char *opt_name; + + /* DEPRECATED: duplicated JSON "plugin" entries */ + if (deprecated_apis) { + list_for_each(&plugins->plugins, p, list) { + json_add_string(response, "plugin", p->cmd); + } + } + + /* we output 'plugins' and their options as an array of substructures */ + json_array_start(response, "plugins"); list_for_each(&plugins->plugins, p, list) { - json_add_string(response, "plugin", p->cmd); + json_object_start(response, NULL); + json_add_string(response, "path", p->cmd); + + /* FIXME: use executables basename until plugins can define their names */ + plugin_name = path_basename(NULL, p->cmd); + json_add_string(response, "name", plugin_name); // basename(p->cmd)); + tal_free(plugin_name); + + if (!list_empty(&p->plugin_opts)) { + json_object_start(response, "options"); + list_for_each(&p->plugin_opts, opt, list) + { + /* Trim the `--` that we added before */ + opt_name = opt->name + 2; + if (opt->value->as_bool) { + json_add_bool(response, opt_name, opt->value->as_bool); + } else if (opt->value->as_int) { + json_add_bool(response, opt_name, opt->value->as_int); + } else if (opt->value->as_str) { + json_add_string(response, opt_name, opt->value->as_str); + } else { + json_add_null(response, opt_name); + } + } + json_object_end(response); + } + json_object_end(response); } + json_array_end(response); } /** diff --git a/tests/test_misc.py b/tests/test_misc.py index e1f01d4794c3..142341b3e58c 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -742,12 +742,25 @@ def test_listconfigs(node_factory, bitcoind, chainparams): # Test one at a time. for c in configs.keys(): - if c.startswith('#'): + if c.startswith('#') or c.startswith('plugins'): continue oneconfig = l1.rpc.listconfigs(config=c) assert(oneconfig[c] == configs[c]) +def test_listconfigs_plugins(node_factory, bitcoind, chainparams): + l1 = node_factory.get_node() + + # assert that we have pay plugin and that plugins have a name and path + configs = l1.rpc.listconfigs() + assert configs['plugins'] + assert len([p for p in configs['plugins'] if p['name'] == "pay"]) == 1 + for p in configs['plugins']: + assert p['name'] and len(p['name']) > 0 + assert p['path'] and len(p['path']) > 0 + assert os.path.isfile(p['path']) and os.access(p['path'], os.X_OK) + + def test_multirpc(node_factory): """Test that we can do multiple RPC without waiting for response""" l1 = node_factory.get_node()