Skip to content

Commit d229f2b

Browse files
committed
job-info: support job info CURRENT lookup flag
Problem: It is inconvenient that there is a job-info.lookup target and job-info.update-lookup target. Support the behavior of job-info.update-lookup in job-info.lookup via a new FLUX_JOB_LOOKUP_CURRENT flag.
1 parent 244febb commit d229f2b

File tree

2 files changed

+144
-19
lines changed

2 files changed

+144
-19
lines changed

src/common/libjob/job.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ enum job_lookup_flags {
3535
* - currently works for jobspec and R
3636
*/
3737
FLUX_JOB_LOOKUP_JSON_DECODE = 1,
38+
/* get current value of special fields by applying eventlog
39+
* updates for those fields
40+
* - currently works for R
41+
*/
42+
FLUX_JOB_LOOKUP_CURRENT = 2,
3843
};
3944

4045
enum job_urgency {

src/modules/job-info/lookup.c

Lines changed: 139 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include <assert.h>
1919

2020
#include "src/common/libczmqcontainers/czmq_containers.h"
21+
#include "src/common/libeventlog/eventlog.h"
22+
#include "src/common/libjob/idf58.h"
23+
#include "src/common/libutil/jpath.h"
2124
#include "ccan/str/str.h"
2225

2326
#include "job-info.h"
@@ -151,11 +154,105 @@ static int lookup_keys (struct lookup_ctx *l)
151154
return -1;
152155
}
153156

157+
static void apply_updates_R (struct lookup_ctx *l,
158+
const char *key,
159+
json_t *update_object,
160+
json_t *context)
161+
{
162+
const char *context_key;
163+
json_t *value;
164+
165+
json_object_foreach (context, context_key, value) {
166+
/* RFC 21 resource-update event only allows update
167+
* to:
168+
* - expiration
169+
*/
170+
if (streq (context_key, "expiration"))
171+
if (jpath_set (update_object,
172+
"execution.expiration",
173+
value) < 0)
174+
flux_log (l->ctx->h, LOG_INFO,
175+
"%s: failed to update job %s %s",
176+
__FUNCTION__, idf58 (l->id), key);
177+
}
178+
}
179+
180+
static int lookup_current (struct lookup_ctx *l,
181+
flux_future_t *fall,
182+
const char *key,
183+
const char *value,
184+
char **current_value)
185+
{
186+
flux_future_t *f_eventlog;
187+
const char *s_eventlog;
188+
json_t *value_object = NULL;
189+
json_t *eventlog = NULL;
190+
size_t index;
191+
json_t *entry;
192+
const char *update_event_name = NULL;
193+
char *value_object_str = NULL;
194+
int save_errno;
195+
196+
if (streq (key, "R"))
197+
update_event_name = "resource-update";
198+
199+
if (!(value_object = json_loads (value, 0, NULL))) {
200+
errno = EINVAL;
201+
goto error;
202+
}
203+
204+
if (!(f_eventlog = flux_future_get_child (fall, "eventlog"))) {
205+
flux_log_error (l->ctx->h, "%s: flux_future_get_child",
206+
__FUNCTION__);
207+
goto error;
208+
}
209+
210+
if (flux_kvs_lookup_get (f_eventlog, &s_eventlog) < 0) {
211+
if (errno != ENOENT)
212+
flux_log_error (l->ctx->h, "%s: flux_kvs_lookup_get",
213+
__FUNCTION__);
214+
goto error;
215+
}
216+
217+
if (!(eventlog = eventlog_decode (s_eventlog))) {
218+
errno = EINVAL;
219+
goto error;
220+
}
221+
222+
json_array_foreach (eventlog, index, entry) {
223+
const char *name;
224+
json_t *context = NULL;
225+
if (eventlog_entry_parse (entry, NULL, &name, &context) < 0)
226+
goto error;
227+
if (streq (name, update_event_name)) {
228+
if (streq (key, "R"))
229+
apply_updates_R (l, key, value_object, context);
230+
}
231+
}
232+
233+
if (!(value_object_str = json_dumps (value_object, 0)))
234+
goto error;
235+
236+
(*current_value) = value_object_str;
237+
json_decref (eventlog);
238+
json_decref (value_object);
239+
return 0;
240+
241+
error:
242+
save_errno = errno;
243+
json_decref (eventlog);
244+
json_decref (value_object);
245+
free (value_object_str);
246+
errno = save_errno;
247+
return -1;
248+
}
249+
154250
static void info_lookup_continuation (flux_future_t *fall, void *arg)
155251
{
156252
struct lookup_ctx *l = arg;
157253
struct info_ctx *ctx = l->ctx;
158254
const char *s;
255+
char *current_value = NULL;
159256
size_t index;
160257
json_t *key;
161258
json_t *o = NULL;
@@ -212,6 +309,15 @@ static void info_lookup_continuation (flux_future_t *fall, void *arg)
212309
goto error;
213310
}
214311

312+
if ((l->flags & FLUX_JOB_LOOKUP_CURRENT)
313+
&& streq (keystr, "R")) {
314+
if (lookup_current (l, fall, keystr, s, &current_value) < 0)
315+
goto error;
316+
s = current_value;
317+
}
318+
319+
/* check for JSON_DECODE flag last, as changes above could affect
320+
* desired value */
215321
if ((l->flags & FLUX_JOB_LOOKUP_JSON_DECODE)
216322
&& (streq (keystr, "jobspec")
217323
|| streq (keystr, "R"))) {
@@ -229,6 +335,9 @@ static void info_lookup_continuation (flux_future_t *fall, void *arg)
229335
json_decref (val);
230336
goto enomem;
231337
}
338+
339+
free (current_value);
340+
current_value = NULL;
232341
}
233342

234343
/* must have been allowed earlier or above, otherwise should have
@@ -256,18 +365,23 @@ static void info_lookup_continuation (flux_future_t *fall, void *arg)
256365
* via zlist_remove() */
257366
json_decref (o);
258367
free (data);
368+
free (current_value);
259369
zlist_remove (ctx->lookups, l);
260370
}
261371

262-
/* If keys array doesn't contain eventlog, flag that we'll need to do
263-
* an eventlog check.
372+
/* Check if lookup allowed, either b/c message is from instance owner
373+
* or previous lookup verified it's ok.
264374
*/
265-
static int check_keys_for_eventlog (struct lookup_ctx *l)
375+
static int check_allow (struct lookup_ctx *l)
266376
{
267-
size_t index;
268-
json_t *key;
269377
int ret;
270378

379+
/* if rpc from owner, no need to do guest access check */
380+
if (flux_msg_authorize (l->msg, FLUX_USERID_UNKNOWN) == 0) {
381+
l->allow = true;
382+
return 0;
383+
}
384+
271385
if ((ret = eventlog_allow_lru (l->ctx,
272386
l->msg,
273387
l->id)) < 0)
@@ -278,12 +392,24 @@ static int check_keys_for_eventlog (struct lookup_ctx *l)
278392
return 0;
279393
}
280394

281-
json_array_foreach (l->keys, index, key) {
282-
if (streq (json_string_value (key), "eventlog"))
283-
return 0;
395+
return 0;
396+
}
397+
398+
/* If we need the eventlog for an allow check or for update-lookup
399+
* we need to add it to the key lookup list.
400+
*/
401+
static int check_to_lookup_eventlog (struct lookup_ctx *l)
402+
{
403+
if (!l->allow || (l->flags & FLUX_JOB_LOOKUP_CURRENT)) {
404+
size_t index;
405+
json_t *key;
406+
json_array_foreach (l->keys, index, key) {
407+
if (streq (json_string_value (key), "eventlog"))
408+
return 0;
409+
}
410+
l->lookup_eventlog = true;
284411
}
285412

286-
l->lookup_eventlog = true;
287413
return 0;
288414
}
289415

@@ -296,9 +422,8 @@ void lookup_cb (flux_t *h, flux_msg_handler_t *mh,
296422
json_t *key;
297423
json_t *keys;
298424
flux_jobid_t id;
299-
uint32_t rolemask;
300425
int flags;
301-
int valid_flags = FLUX_JOB_LOOKUP_JSON_DECODE;
426+
int valid_flags = FLUX_JOB_LOOKUP_JSON_DECODE | FLUX_JOB_LOOKUP_CURRENT;
302427
const char *errmsg = NULL;
303428

304429
if (flux_request_unpack (msg, NULL, "{s:I s:o s:i}",
@@ -331,16 +456,11 @@ void lookup_cb (flux_t *h, flux_msg_handler_t *mh,
331456
if (!(l = lookup_ctx_create (ctx, msg, id, keys, flags)))
332457
goto error;
333458

334-
if (flux_msg_get_rolemask (msg, &rolemask) < 0)
459+
if (check_allow (l) < 0)
335460
goto error;
336461

337-
/* if rpc from owner, no need to do guest access check */
338-
if ((rolemask & FLUX_ROLE_OWNER))
339-
l->allow = true;
340-
else {
341-
if (check_keys_for_eventlog (l) < 0)
342-
goto error;
343-
}
462+
if (check_to_lookup_eventlog (l) < 0)
463+
goto error;
344464

345465
if (lookup_keys (l) < 0)
346466
goto error;

0 commit comments

Comments
 (0)