]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared: extend Job varlink type with Unit and ActivationDetails fields
authorIvan Kruglov <mail@ikruglov.com>
Fri, 15 May 2026 14:00:07 +0000 (07:00 -0700)
committerIvan Kruglov <mail@ikruglov.com>
Tue, 19 May 2026 09:05:55 +0000 (11:05 +0200)
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
src/core/meson.build
src/core/varlink-job.c [new file with mode: 0644]
src/core/varlink-job.h [new file with mode: 0644]
src/core/varlink-unit.c
src/shared/varlink-io.systemd.Job.c

index 98cf02aef8879a10837638b8740400a26876869e..a0ff0baf8dcd4abcae471a2572c97e691da8b192 100644 (file)
@@ -70,6 +70,7 @@ libcore_sources = files(
         'varlink-common.c',
         'varlink-dynamic-user.c',
         'varlink-execute.c',
+        'varlink-job.c',
         'varlink-kill.c',
         'varlink-manager.c',
         'varlink-metrics.c',
diff --git a/src/core/varlink-job.c b/src/core/varlink-job.c
new file mode 100644 (file)
index 0000000..46b9a4c
--- /dev/null
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-varlink.h"
+
+#include "job.h"
+#include "json-util.h"
+#include "strv.h"
+#include "unit.h"
+#include "varlink-job.h"
+
+static int activation_details_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+        _cleanup_strv_free_ char **pairs = NULL;
+        Job *j = ASSERT_PTR(userdata);
+        int r;
+
+        assert(ret);
+
+        r = activation_details_append_pair(j->activation_details, &pairs);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to get activation details: %m");
+        if (r == 0) {
+                *ret = NULL;
+                return 0;
+        }
+
+        STRV_FOREACH_PAIR(key, value, pairs) {
+                r = sd_json_variant_set_field_string(&v, *key, *value);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = TAKE_PTR(v);
+        return 0;
+}
+
+int job_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+        Job *j = ASSERT_PTR(userdata);
+
+        /* "Unit" is omitted in StartTransient streaming notifications where the caller already knows the unit. */
+        return sd_json_buildo(
+                        ASSERT_PTR(ret),
+                        SD_JSON_BUILD_PAIR_INTEGER("Id", j->id),
+                        JSON_BUILD_PAIR_STRING_NON_EMPTY("Unit", j->unit ? j->unit->id : NULL),
+                        JSON_BUILD_PAIR_ENUM("JobType", job_type_to_string(j->type)),
+                        JSON_BUILD_PAIR_ENUM("State", job_state_to_string(j->state)),
+                        JSON_BUILD_PAIR_ENUM_NON_EMPTY("Result", job_result_to_string(j->result)),
+                        JSON_BUILD_PAIR_CALLBACK_NON_NULL("ActivationDetails", activation_details_build_json, j));
+}
diff --git a/src/core/varlink-job.h b/src/core/varlink-job.h
new file mode 100644 (file)
index 0000000..cd661da
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "core-forward.h"
+
+int job_build_json(sd_json_variant **ret, const char *name, void *userdata);
index 31f7898a8cf04cd168bf0f6bea8ef157821d0dc7..4bf8136fa91645fc74337a73b6cfe5c4b3ce6f29 100644 (file)
@@ -27,6 +27,7 @@
 #include "varlink-cgroup.h"
 #include "varlink-common.h"
 #include "varlink-execute.h"
+#include "varlink-job.h"
 #include "varlink-kill.h"
 #include "varlink-mount.h"
 #include "varlink-path.h"
@@ -617,18 +618,6 @@ void varlink_unit_send_change_signal(Unit *u) {
                         SD_JSON_BUILD_PAIR_CALLBACK("runtime", unit_runtime_build_json, u));
 }
 
-static int job_build_json(sd_json_variant **ret, const char *name, void *userdata) {
-        Job *j = ASSERT_PTR(userdata);
-
-        /* Note that "Result" is suppressed until the job reaches JOB_FINISHED. */
-        return sd_json_buildo(
-                        ASSERT_PTR(ret),
-                        SD_JSON_BUILD_PAIR_INTEGER("Id", j->id),
-                        JSON_BUILD_PAIR_ENUM("JobType", job_type_to_string(j->type)),
-                        JSON_BUILD_PAIR_ENUM("State", job_state_to_string(j->state)),
-                        JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY("Result", job_result_to_string(j->result)));
-}
-
 void varlink_job_send_change_signal(Job *j) {
         assert(j);
 
index 8dfc403c7be8189c37ec16e19488dc03727c8037..17b06a7de5865281e118d2a823fcf690a5612f65 100644 (file)
@@ -39,17 +39,24 @@ SD_VARLINK_DEFINE_ENUM_TYPE(
                 SD_VARLINK_DEFINE_ENUM_VALUE(frozen),
                 SD_VARLINK_DEFINE_ENUM_VALUE(concurrency));
 
-/* Field names match the D-Bus Job properties (Id, JobType, State) */
+/* Field names match the D-Bus Job properties (Id, Unit, JobType, State) */
+#define VARLINK_DEFINE_JOB_FIELDS(direction)                                                                                         \
+        SD_VARLINK_FIELD_COMMENT("The numeric job ID"),                                                                              \
+        SD_VARLINK_DEFINE_##direction(Id, SD_VARLINK_INT, 0),                                                                        \
+        SD_VARLINK_FIELD_COMMENT("The unit name this job operates on"),                                                              \
+        SD_VARLINK_DEFINE_##direction(Unit, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),                                                 \
+        SD_VARLINK_FIELD_COMMENT("The job type"),                                                                                    \
+        SD_VARLINK_DEFINE_##direction##_BY_TYPE(JobType, JobType, 0),                                                                \
+        SD_VARLINK_FIELD_COMMENT("Current job state. 'finished' indicates the job has completed; in that case Result is also set."), \
+        SD_VARLINK_DEFINE_##direction##_BY_TYPE(State, JobState, SD_VARLINK_NULLABLE),                                               \
+        SD_VARLINK_FIELD_COMMENT("Job result. Only set once the job has reached the 'finished' state."),                             \
+        SD_VARLINK_DEFINE_##direction##_BY_TYPE(Result, JobResult, SD_VARLINK_NULLABLE),                                             \
+        SD_VARLINK_FIELD_COMMENT("Activation details describing what triggered this job, as key-value pairs"),                       \
+        SD_VARLINK_DEFINE_##direction(ActivationDetails, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_MAP)
+
 SD_VARLINK_DEFINE_STRUCT_TYPE(
                 Job,
-                SD_VARLINK_FIELD_COMMENT("The numeric job ID"),
-                SD_VARLINK_DEFINE_FIELD(Id, SD_VARLINK_INT, 0),
-                SD_VARLINK_FIELD_COMMENT("The job type"),
-                SD_VARLINK_DEFINE_FIELD_BY_TYPE(JobType, JobType, 0),
-                SD_VARLINK_FIELD_COMMENT("Current job state. 'finished' indicates the job has completed; in that case Result is also set."),
-                SD_VARLINK_DEFINE_FIELD_BY_TYPE(State, JobState, SD_VARLINK_NULLABLE),
-                SD_VARLINK_FIELD_COMMENT("Job result. Only set once the job has reached the 'finished' state."),
-                SD_VARLINK_DEFINE_FIELD_BY_TYPE(Result, JobResult, SD_VARLINK_NULLABLE));
+                VARLINK_DEFINE_JOB_FIELDS(FIELD));
 
 SD_VARLINK_DEFINE_INTERFACE(
                 io_systemd_Job,