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+
154250static 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