diff --git a/doc/PLUGINS.md b/doc/PLUGINS.md index 9c80101ba..e03b13894 100644 --- a/doc/PLUGINS.md +++ b/doc/PLUGINS.md @@ -58,9 +58,10 @@ interface. ### The `getmanifest` method The `getmanifest` method is required for all plugins and will be -called on startup with optionsl parameters (in particular, it may have -`allow-deprecated-apis: false`, but you should accept others). It -MUST return a JSON object similar to this example: +called on startup with optional parameters (in particular, it may have +`allow-deprecated-apis: false`, but you should accept, and ignore, +other parameters). It MUST return a JSON object similar to this +example: ```json { @@ -69,7 +70,8 @@ MUST return a JSON object similar to this example: "name": "greeting", "type": "string", "default": "World", - "description": "What name should I call you?" + "description": "What name should I call you?", + "deprecated": false } ], "rpcmethods": [ @@ -82,7 +84,8 @@ MUST return a JSON object similar to this example: "name": "gettime", "usage": "", "description": "Returns the current time in {timezone}", - "long_description": "Returns the current time in the timezone that is given as the only parameter.\nThis description may be quite long and is allowed to span multiple lines." + "long_description": "Returns the current time in the timezone that is given as the only parameter.\nThis description may be quite long and is allowed to span multiple lines.", + "deprecated": false } ], "subscriptions": [ @@ -116,6 +119,11 @@ are mandatory, while the `long_description` can be omitted (it'll be set to `description` if it was not provided). `usage` should surround optional parameter names in `[]`. +`options` and `rpcmethods` can mark themselves `deprecated: true` if +you plan on removing them: this will disable them if the user sets +`allow-deprecated-apis` to false (which every developer should do, +right?). + The `dynamic` indicates if the plugin can be managed after `lightningd` has been started. Critical plugins that should not be stopped should set it to false. diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 7b8ae9225..a6e51766a 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -587,6 +587,10 @@ char *plugin_opt_set(const char *arg, struct plugin_opt *popt) char *endp; long long l; + /* Warn them that this is deprecated */ + if (popt->deprecated && !deprecated_apis) + return tal_fmt(tmpctx, "deprecated option (will be removed!)"); + tal_free(popt->value->as_str); popt->value->as_str = tal_strdup(popt, arg); @@ -630,12 +634,13 @@ static void destroy_plugin_opt(struct plugin_opt *opt) static const char *plugin_opt_add(struct plugin *plugin, const char *buffer, const jsmntok_t *opt) { - const jsmntok_t *nametok, *typetok, *defaulttok, *desctok; + const jsmntok_t *nametok, *typetok, *defaulttok, *desctok, *deptok; struct plugin_opt *popt; nametok = json_get_member(buffer, opt, "name"); typetok = json_get_member(buffer, opt, "type"); desctok = json_get_member(buffer, opt, "description"); defaulttok = json_get_member(buffer, opt, "default"); + deptok = json_get_member(buffer, opt, "deprecated"); if (!typetok || !nametok || !desctok) { return tal_fmt(plugin, @@ -648,6 +653,15 @@ static const char *plugin_opt_add(struct plugin *plugin, const char *buffer, popt->name = tal_fmt(popt, "--%.*s", nametok->end - nametok->start, buffer + nametok->start); popt->description = NULL; + if (deptok) { + if (!json_to_bool(buffer, deptok, &popt->deprecated)) + return tal_fmt(plugin, + "%s: invalid \"deprecated\" field %.*s", + popt->name, + deptok->end - deptok->start, + buffer + deptok->start); + } else + popt->deprecated = false; if (json_tok_streq(buffer, typetok, "string")) { popt->type = "string"; @@ -837,7 +851,8 @@ static const char *plugin_rpcmethod_add(struct plugin *plugin, const char *buffer, const jsmntok_t *meth) { - const jsmntok_t *nametok, *categorytok, *desctok, *longdesctok, *usagetok; + const jsmntok_t *nametok, *categorytok, *desctok, *longdesctok, + *usagetok, *deptok; struct json_command *cmd; const char *usage; @@ -846,6 +861,7 @@ static const char *plugin_rpcmethod_add(struct plugin *plugin, desctok = json_get_member(buffer, meth, "description"); longdesctok = json_get_member(buffer, meth, "long_description"); usagetok = json_get_member(buffer, meth, "usage"); + deptok = json_get_member(buffer, meth, "deprecated"); if (!nametok || nametok->type != JSMN_STRING) { return tal_fmt(plugin, @@ -891,7 +907,16 @@ static const char *plugin_rpcmethod_add(struct plugin *plugin, } else usage = "[params]"; - cmd->deprecated = false; + if (deptok) { + if (!json_to_bool(buffer, deptok, &cmd->deprecated)) + return tal_fmt(plugin, + "%s: invalid \"deprecated\" field %.*s", + cmd->name, + deptok->end - deptok->start, + buffer + deptok->start); + } else + cmd->deprecated = false; + cmd->dispatch = plugin_rpcmethod_dispatch; if (!jsonrpc_command_add(plugin->plugins->ld->jsonrpc, cmd, usage)) { return tal_fmt(plugin, @@ -1491,6 +1516,9 @@ void json_add_opt_plugins_array(struct json_stream *response, if (!list_empty(&p->plugin_opts)) { json_object_start(response, "options"); list_for_each(&p->plugin_opts, opt, list) { + if (!deprecated_apis && opt->deprecated) + continue; + /* Trim the `--` that we added before */ opt_name = opt->name + 2; if (opt->value->as_bool) { diff --git a/lightningd/plugin.h b/lightningd/plugin.h index 1e4338f84..60e5fc505 100644 --- a/lightningd/plugin.h +++ b/lightningd/plugin.h @@ -137,6 +137,7 @@ struct plugin_opt { const char *type; const char *description; struct plugin_opt_value *value; + bool deprecated; }; /**