22import time , warnings
33from dataikuapi .utils import DataikuException
44from .discussion import DSSObjectDiscussions
5+ from .utils import DSSTaggableObjectListItem
56
67class DSSScenario (object ):
78 """
@@ -87,6 +88,14 @@ def get_run(self, run_id):
8788 "GET" , "/projects/%s/scenarios/%s/%s/" % (self .project_key , self .id , run_id ))
8889 return DSSScenarioRun (self .client , run_details ["scenarioRun" ])
8990
91+ def get_status (self ):
92+ """
93+ Returns the status of this scenario
94+ :rtype :class:`DSSScenarioStatus`
95+ """
96+ data = self .client ._perform_json ("GET" , "/projects/%s/scenarios/%s/light" % (self .project_key , self .id ))
97+ return DSSScenarioStatus (self , data )
98+
9099 def get_settings (self ):
91100 """
92101 Returns the settings of this scenario
@@ -198,6 +207,34 @@ def set_payload(self, script, with_status=True):
198207 return self .client ._perform_json (
199208 "PUT" , "/projects/%s/scenarios/%s/payload" % (self .project_key , self .id ), body = {'script' : script })
200209
210+ class DSSScenarioStatus (object ):
211+ """Status of a scenario. Do not instantiate this class, use :meth:`DSSScenario.get_status`"""
212+
213+ def __init__ (self , scenario , data ):
214+ self .scenario = scenario
215+ self .data = data
216+
217+ def get_raw (self ):
218+ return self .data
219+
220+ @property
221+ def running (self ):
222+ return self .data ["running" ]
223+
224+ @property
225+ def next_run (self ):
226+ """
227+ Time at which the scenario is expected to next run based on its triggers.
228+
229+ May be None if there are no temporal triggers
230+
231+ This is an approximate indication as scenario run may be delayed, especially in the case of
232+ multiple triggers or high load
233+ """
234+ if not "nextRun" in self .data or self .data ["nextRun" ] == 0 :
235+ return None
236+ return datetime .fromtimestamp (self .data ["nextRun" ] / 1000 )
237+
201238
202239class DSSScenarioSettings (object ):
203240 """Settings of a scenario. Do not instantiate this class, use :meth:`DSSScenario.get_settings`"""
@@ -209,9 +246,46 @@ def __init__(self, client, scenario, data):
209246 def get_raw (self ):
210247 return self .data
211248
212- def set_active (self , active ):
249+ @property
250+ def active (self ):
251+ """
252+ Whether this scenario is currently active, i.e. its auto-triggers are executing
253+ """
254+ return self .data ["active" ]
255+ @active .setter
256+ def active (self , active ):
213257 self .data ["active" ] = active
214258
259+ @property
260+ def run_as (self ):
261+ """
262+ The configured 'run as' of the scenario. None means that the scenario runs as its last modifier.
263+ Only administrators may set a non-None value
264+ """
265+ return self .data .get ("runAsUser" , None )
266+ @run_as .setter
267+ def run_as (self , run_as ):
268+ self .data ["runAsUser" ] = run_as
269+
270+ @property
271+ def effective_run_as (self ):
272+ """
273+ The effective 'run as' of the scenario. If a run_as has been configured by an administrator,
274+ this will be used. Else, this will be the last modifier of the scenario.
275+
276+ If this method returns None, it means that it was not possible to identify who this
277+ scenario runs as. This scenario is probably not currently functioning.
278+ """
279+ # Note: this logic must match the one in ScenarioBaseService
280+ if "runAsUser" in self .data :
281+ return self .data ["runAsUser" ]
282+ elif "versionTag" in self .data :
283+ return self .data ["versionTag" ]["lastModifiedBy" ]["login" ]
284+ elif "creationTag" in self .data :
285+ return self .data ["creationTag" ]["lastModifiedBy" ]["login" ]
286+ else :
287+ return Non
288+
215289 @property
216290 def raw_triggers (self ):
217291 return self .data ["triggers" ]
@@ -343,9 +417,17 @@ def get_details(self):
343417
344418 :rtype dict
345419 """
346- return self .client ._perform_json (
420+ raw_data = self .client ._perform_json (
347421 "GET" , "/projects/%s/scenarios/%s/%s/" % (self .run ['scenario' ]['projectKey' ], self .run ['scenario' ]['id' ], self .run ['runId' ]))
348422
423+ details = DSSScenarioRunDetails (raw_data )
424+ if "stepRuns" in details :
425+ structured_steps = []
426+ for step in details ["stepRuns" ]:
427+ structured_steps .append (DSSStepRunDetails (step ))
428+ details ["stepRuns" ] = structured_steps
429+ return details
430+
349431 def get_start_time (self ):
350432 """
351433 Get the start time of the scenario run
@@ -376,6 +458,31 @@ def get_duration(self):
376458 return duration
377459 duration = property (get_duration )
378460
461+ class DSSScenarioRunDetails (dict ):
462+ def __init__ (self , data ):
463+ super (DSSScenarioRunDetails , self ).__init__ (data )
464+
465+ @property
466+ def steps (self ):
467+ return self ["stepRuns" ]
468+
469+ @property
470+ def last_step (self ):
471+ return self ["stepRuns" ][len (self ["stepRuns" ]) - 1 ]
472+
473+ class DSSStepRunDetails (dict ):
474+ def __init__ (self , data ):
475+ super (DSSStepRunDetails , self ).__init__ (data )
476+
477+ @property
478+ def outcome (self ):
479+ return self ["result" ]["outcome" ]
480+
481+ @property
482+ def job_ids (self ):
483+ """The list of DSS job ids that were ran as part of this step"""
484+ return [ri ["jobId" ] for ri in self ["additionalReportItems" ] if ri ["type" ] == "JOB_EXECUTED" ]
485+
379486class DSSScenarioRunWaiter (object ):
380487 """
381488 Helper to wait for a scenario to run to complete
@@ -459,3 +566,17 @@ def is_cancelled(self, refresh=False):
459566 })
460567 return self .trigger_fire ["cancelled" ]
461568
569+
570+ class DSSScenarioListItem (DSSTaggableObjectListItem ):
571+ """An item in a list of scenarios. Do not instantiate this class, use :meth:`dataikuapi.dss.project.DSSProject.list_scenarios"""
572+ def __init__ (self , client , data ):
573+ super (DSSScenarioListItem , self ).__init__ (data )
574+ self .client = client
575+
576+ def to_scenario (self ):
577+ """Gets the :class:`DSSScenario` corresponding to this scenario"""
578+ return DSSScenario (self .client , self ._data ["projectKey" ], self ._data ["name" ])
579+
580+ @property
581+ def id (self ):
582+ return self ._data ["name" ]
0 commit comments