mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 04:03:36 +08:00
varlinkctl: add new list-methods verb
For putting together "varlinkctl call" command lines it's useful to quickly enumerate all methods implemented by a service. Hence, let's add a new "list-methods" which uses the introspection data of a service to quickly list methods. This is implemented as a special flavour of the "introspect" logic, and just suppresses all output except for the method names.
This commit is contained in:
parent
2475b0e81a
commit
16cfe84c24
@ -119,6 +119,17 @@
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>list-methods</command> <replaceable>ADDRESS</replaceable> [<replaceable>INTERFACE…</replaceable>]</term>
|
||||
|
||||
<listitem><para>Show list of methods implemented by the specified service. Expects a service address
|
||||
in one of the formats described above as well as one or more interface names. If no interface name is
|
||||
specified, lists all methods of all interfaces implemented by the service, otherwise just the methods
|
||||
in the specified services.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>introspect</command> <replaceable>ADDRESS</replaceable> [<replaceable>INTERFACE…</replaceable>]</term>
|
||||
|
||||
|
@ -38,6 +38,9 @@ static int help(void) {
|
||||
" info ADDRESS Show service information\n"
|
||||
" list-interfaces ADDRESS\n"
|
||||
" List interfaces implemented by service\n"
|
||||
" list-methods ADDRESS [INTERFACE…]\n"
|
||||
" List methods implemented by services or specific\n"
|
||||
" interfaces\n"
|
||||
" introspect ADDRESS [INTERFACE…]\n"
|
||||
" Show interface definition\n"
|
||||
" call ADDRESS METHOD [PARAMS]\n"
|
||||
@ -293,9 +296,11 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_strv_free_ char **auto_interfaces = NULL;
|
||||
char **interfaces;
|
||||
const char *url;
|
||||
bool list_methods;
|
||||
int r;
|
||||
|
||||
assert(argc >= 2);
|
||||
list_methods = streq(argv[0], "list-methods");
|
||||
url = argv[1];
|
||||
interfaces = strv_skip(argv, 2);
|
||||
|
||||
@ -328,9 +333,11 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
/* Automatically switch on JSON_SEQ if we output multiple JSON objects */
|
||||
if (strv_length(interfaces) > 1)
|
||||
if (!list_methods && strv_length(interfaces) > 1)
|
||||
arg_json_format_flags |= SD_JSON_FORMAT_SEQ;
|
||||
|
||||
_cleanup_strv_free_ char **methods = NULL;
|
||||
|
||||
STRV_FOREACH(i, interfaces) {
|
||||
sd_json_variant *reply = NULL;
|
||||
r = varlink_callb_and_log(
|
||||
@ -341,9 +348,7 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) {
|
||||
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF) || list_methods) {
|
||||
static const struct sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "description", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, SD_JSON_MANDATORY },
|
||||
{}
|
||||
@ -356,22 +361,56 @@ static int verb_introspect(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (i > interfaces)
|
||||
if (!list_methods && i > interfaces)
|
||||
print_separator();
|
||||
|
||||
/* Try to parse the returned description, so that we can add syntax highlighting */
|
||||
r = varlink_idl_parse(ASSERT_PTR(description), &line, &column, &vi);
|
||||
if (r < 0) {
|
||||
if (list_methods)
|
||||
return log_error_errno(r, "Failed to parse returned interface description at %u:%u: %m", line, column);
|
||||
|
||||
log_warning_errno(r, "Failed to parse returned interface description at %u:%u, showing raw interface description: %m", line, column);
|
||||
|
||||
pager_open(arg_pager_flags);
|
||||
fputs_with_newline(description, stdout);
|
||||
} else if (list_methods) {
|
||||
for (const VarlinkSymbol *const *y = vi->symbols, *symbol; (symbol = *y); y++) {
|
||||
if (symbol->symbol_type != VARLINK_METHOD)
|
||||
continue;
|
||||
|
||||
r = strv_extendf(&methods, "%s.%s", vi->name, symbol->name);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
} else {
|
||||
pager_open(arg_pager_flags);
|
||||
r = varlink_idl_dump(stdout, /* use_colors= */ -1, vi);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to format parsed interface description: %m");
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
pager_open(arg_pager_flags);
|
||||
sd_json_variant_dump(reply, arg_json_format_flags, stdout, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (list_methods) {
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
strv_sort(strv_uniq(methods));
|
||||
|
||||
if (FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF))
|
||||
strv_print(methods);
|
||||
else {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL;
|
||||
|
||||
r = sd_json_build(&j, SD_JSON_BUILD_STRV(methods));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to build JSON array: %m");
|
||||
|
||||
sd_json_variant_dump(j, arg_json_format_flags, stdout, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -573,6 +612,7 @@ static int varlinkctl_main(int argc, char *argv[]) {
|
||||
{ "info", 2, 2, 0, verb_info },
|
||||
{ "list-interfaces", 2, 2, 0, verb_info },
|
||||
{ "introspect", 2, VERB_ANY, 0, verb_introspect },
|
||||
{ "list-methods", 2, VERB_ANY, 0, verb_introspect },
|
||||
{ "call", 3, 4, 0, verb_call },
|
||||
{ "validate-idl", 1, 2, 0, verb_validate_idl },
|
||||
{ "help", VERB_ANY, VERB_ANY, 0, verb_help },
|
||||
|
Loading…
Reference in New Issue
Block a user