class DCMReportRunner(ReportRunner): report_type = Type.CM def __init__(self, cm_id: str=None, profile: str=None, email: str=None, project: str=None): self.email = email self.cm_id = cm_id self.cm_profile = profile self.project = project self.firestore = Firestore(email=email, project=project) def run(self, unattended: bool=True) -> None: dcm = DCM(email=self.email, project=self.project, profile=self.cm_profile) if unattended: self._unattended_run(dcm) else: self._attended_run(dcm) def _attended_run(self, dcm: DCM) -> None: successful = [] response = dcm.run_report(report_id=self.cm_id, synchronous=True) if response: buffer = StringIO() pprint.pprint(response, stream=buffer) logging.info(buffer.getvalue()) while response['status'] == 'PROCESSING': time.sleep(60 * 0.5) response = dcm.report_state(report_id=self.cm_id, file_id=response['id']) buffer = StringIO() pprint.pprint(response, stream=buffer) logging.info(buffer.getvalue()) report2bq = Report2BQ( cm=True, cm_id=self.cm_id, email=self.email, project=self.project, profile=self.cm_profile ) report2bq.handle_report_fetcher(fetcher=dcm, report_id=self.cm_id) def _unattended_run(self, dcm: DCM) -> None: response = dcm.run_report(report_id=self.cm_id, synchronous=False) if response: buffer = StringIO() pprint.pprint(response, stream=buffer) logging.info(buffer.getvalue()) runner = { 'type': Type.CM.value, 'project': self.project, 'report_id': self.cm_id, 'email': self.email, 'profile': self.cm_profile, 'file_id': response['id'] } self.firestore.store_report_runner(runner)
class DBMReportRunner(ReportRunner): report_type = Type.DV360 def __init__(self, dbm_id: str = None, email: str = None, project: str = None): self.email = email self.dbm_id = dbm_id self.project = project self.firestore = Firestore(email=email, project=project) def run(self, unattended: bool = True): dbm = DBM(email=self.email, project=self.project) if unattended: self._unattended_run(dbm) else: self._attended_run(dbm) def _attended_run(self, dbm: DBM) -> None: response = dbm.run_report(self.dbm_id) if response: buffer = StringIO() pprint.pprint(response, stream=buffer) logging.info(buffer.getvalue()) while True: status = dbm.report_state(self.dbm_id) logging.info(f'Report {self.dbm_id} status: {status}') if status == 'RUNNING': time.sleep(10) elif status == 'DONE': report2bq = Report2BQ(dv360=True, dv360_id=self.dbm_id, email=self.email, project=self.project) report2bq.handle_report_fetcher(fetcher=dbm, report_id=self.dbm_id) break else: logging.error( f'DV360 Report {self.dbm_id} failed to run: {status}') break def _unattended_run(self, dbm: DBM) -> None: response = dbm.run_report(self.dbm_id) if response: runner = { 'type': Type.DV360.value, 'project': self.project, 'report_id': self.dbm_id, 'email': self.email, } self.firestore.store_report_runner(runner)
class SA360ReportRunner(ReportRunner): report_type = Type.SA360_RPT def __init__(self, report_id: str, email: str, project: str=None, timezone: str=None): self.email = email self.report_id = report_id self.project = project self.timezone = timezone self.firestore = Firestore() def run(self, unattended: bool = True) -> Dict[str, Any]: # TODO: Make SA360 object here sa360 = SA360(self.email, self.project) if unattended: return self._unattended_run(sa360=sa360) else: return self._attended_run(sa360=sa360) def _unattended_run(self, sa360: SA360) -> Dict[str, Any]: runner = None report_config = None try: report_config = self.firestore.get_document(type=Type.SA360_RPT, id=self.report_id) if not report_config: raise NotImplementedError(f'No such runner: {self.report_id}') _tz = pytz.timezone(report_config.get('timezone') or self.timezone or 'America/Toronto') _today = datetime.now(_tz) report_config['StartDate'] = (_today - timedelta(days=(report_config.get('offset') or 0))).strftime('%Y-%m-%d') report_config['EndDate'] = (_today - timedelta(days=(report_config.get('lookback') or 0))).strftime('%Y-%m-%d') template = self.firestore.get_document(Type.SA360_RPT, '_reports').get(report_config['report']) request_body = SA360ReportTemplate().prepare(template=template, values=report_config) sa360_service = DiscoverService.get_service(Service.SA360, sa360.creds) request = sa360_service.reports().request(body=request_body) response = request.execute() logging.info(response) runner = { 'type': Type.SA360_RPT.value, 'project': self.project, 'report_id': self.report_id, 'email': self.email, 'file_id': response['id'] } self.firestore.store_report_runner(runner) except Exception as e: self._email_error(email=self.email, error=e, report_config=report_config, message=f'Error in SA360 Report Runner for report {self.report_id}') finally: return runner def _email_error(self, message: str, email: str=None, error: Exception=None, report_config: Dict[str, Any]=None) -> None: _to = [email] if email else [] _administrator = os.environ.get('ADMINISTRATOR_EMAIL') or self.FIRESTORE.get_document(Type._ADMIN, 'admin').get('email') _cc = [_administrator] if _administrator else [] if _to or _cc: message = GMailMessage( to=_to, cc=_cc, subject=message, body=f''' {message} Config: {report_config if report_config else 'Config unknown.'} Error: {error if error else 'No exception.'} ''', project=os.environ.get('GCP_PROJECT')) GMail().send_message( message=message, credentials=Credentials(email=email, project=os.environ.get('GCP_PROJECT')) ) def _attended_run(self, sa360: SA360) -> None: raise NotImplementedError()