]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolvectl: add JSON output support for "resolvectl query"
authorLennart Poettering <lennart@poettering.net>
Wed, 31 Jan 2024 10:28:12 +0000 (11:28 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 31 Jan 2024 15:13:16 +0000 (16:13 +0100)
It's easy to add. Let's do so.

This only covers record lookups, i.e. with the --type= switch.

The higher level lookups are not covered, I opted instead to print a
message there to use --type= instead.

I am a bit reluctant to defining a new JSON format for the high-level
lookups, hence I figured for now a helpful error is good enough, that
points people to the right use.

Fixes: #29755
man/resolvectl.xml
src/resolve/resolvectl.c
test/units/testsuite-75.sh

index 3babb8afc2124808b3225ebd311ab426534491bf..dada3f51d72100d2dca27be4a8f56e20c1b55fd3 100644 (file)
@@ -69,6 +69,9 @@
         <option>--type=</option>/<option>--class=</option> is used IDNA translation is turned off and domain
         names are processed as specified.</para>
 
+        <para>If combined with <option>--json=</option> (only supported in combination with
+        <option>--type=</option>) will output the resource record data in a JSON object.</para>
+
         <xi:include href="version-info.xml" xpointer="v239"/></listitem>
       </varlistentry>
 
       </varlistentry>
 
       <xi:include href="standard-options.xml" xpointer="json" />
-
-      <varlistentry>
-        <term><option>-j</option></term>
-
-        <listitem><para>Short for <option>--json=auto</option></para>
-
-        <xi:include href="version-info.xml" xpointer="v252"/></listitem>
-      </varlistentry>
-
+      <xi:include href="standard-options.xml" xpointer="j" />
       <xi:include href="standard-options.xml" xpointer="no-pager" />
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
index fcc8eb7bdc973d73a29afead55e51f9ac44a9779..56ba992c4f9116b7f309c1f59cfb094681853ffa 100644 (file)
@@ -184,6 +184,9 @@ static void print_source(uint64_t flags, usec_t rtt) {
         if (!arg_legend)
                 return;
 
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+                return;
+
         if (flags == 0)
                 return;
 
@@ -250,6 +253,9 @@ static int resolve_host(sd_bus *bus, const char *name) {
 
         assert(name);
 
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type=A or --type=AAAA to acquire address record information in JSON format.");
+
         log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname);
 
         r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveHostname");
@@ -348,6 +354,9 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         assert(IN_SET(family, AF_INET, AF_INET6));
         assert(address);
 
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
+
         if (ifindex <= 0)
                 ifindex = arg_ifindex;
 
@@ -433,11 +442,23 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) {
         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
         int r;
 
+        assert(d || l == 0);
+
         r = dns_resource_record_new_from_raw(&rr, d, l);
         if (r < 0)
                 return log_error_errno(r, "Failed to parse RR: %m");
 
-        if (arg_raw == RAW_PAYLOAD) {
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
+                _cleanup_(json_variant_unrefp) JsonVariant *j = NULL;
+                r = dns_resource_record_to_json(rr, &j);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to convert RR to JSON: %m");
+
+                r = json_variant_dump(j, arg_json_format_flags, NULL, NULL);
+                if (r < 0)
+                        return r;
+
+        } else if (arg_raw == RAW_PAYLOAD) {
                 void *data;
                 ssize_t k;
 
@@ -946,6 +967,9 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons
 static int verb_service(int argc, char **argv, void *userdata) {
         sd_bus *bus = userdata;
 
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
+
         if (argc == 2)
                 return resolve_service(bus, NULL, NULL, argv[1]);
         else if (argc == 3)
@@ -1005,6 +1029,9 @@ static int verb_openpgp(int argc, char **argv, void *userdata) {
         sd_bus *bus = userdata;
         int q, r = 0;
 
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
+
         STRV_FOREACH(p, argv + 1) {
                 q = resolve_openpgp(bus, *p);
                 if (q < 0)
@@ -1056,6 +1083,9 @@ static int verb_tlsa(int argc, char **argv, void *userdata) {
         const char *family = "tcp";
         int q, r = 0;
 
+        if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
+
         if (service_family_is_valid(argv[1])) {
                 family = argv[1];
                 args++;
index 92f6b8e030dd7cc0a891b4a38717948b27e5cc2f..818a23736d530969db5cc47a6a6f1dd279fafb13 100755 (executable)
@@ -821,6 +821,9 @@ run resolvectl reset-statistics --json=pretty
 
 run resolvectl reset-statistics --json=short
 
+test "$(resolvectl --json=short query -t AAAA localhost)" == '{"key":{"class":1,"type":28,"name":"localhost"},"address":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]}'
+test "$(resolvectl --json=short query -t A localhost)" == '{"key":{"class":1,"type":1,"name":"localhost"},"address":[127,0,0,1]}'
+
 # Check if resolved exits cleanly.
 restart_resolved