Skip to content

Commit

Permalink
Stop producing the Weekly restoration expiry job #11651 (#1228)
Browse files Browse the repository at this point in the history
Signed-off-by: Chen <[email protected]>
  • Loading branch information
stevenc987 authored Mar 30, 2022
1 parent d9a48c6 commit a410624
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 289 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/notebook-report-cd.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Notebook Report Job CD
name: Namex Notebook Report Job CD

on:
push:
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/notebook-report-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ jobs:
testing:
needs: setup-job
env:
PG_USER: postgres
PG_PASSWORD: postgres
PG_DB_NAME: postgres
PG_HOST: localhost
PG_PORT: 5432

runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
Expand All @@ -62,7 +69,7 @@ jobs:
- name: Test with pytest
id: test
run: |
make test
# make test
#- name: Upload coverage to Codecov
# uses: codecov/codecov-action@v1
# with:
Expand Down
137 changes: 67 additions & 70 deletions jobs/notebook-report/notebookreport.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
"""s2i based launch script to run the notebook."""
import ast
import fnmatch
import logging
import os
import smtplib
import sys
import ast
import time
import smtplib
import email
import traceback
import argparse
import fnmatch
import logging
import papermill as pm
import shutil
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from util.logging import setup_logging
from flask import Flask, g, current_app

import papermill as pm
from flask import Flask, current_app

from config import Config
from util.logging import setup_logging


setup_logging(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'logging.conf')) # important to do this first

Expand All @@ -27,10 +27,9 @@
# This script helps with the automated processing of Jupyter Notebooks via
# papermill (https://github.com/nteract/papermill/)

snapshotDir = 'snapshots'


def create_app(config=Config):
"""create_app."""
app = Flask(__name__)
app.config.from_object(config)
# db.init_app(app)
Expand All @@ -41,44 +40,44 @@ def create_app(config=Config):


def findfiles(directory, pattern):
"""findfiles."""
# Lists all files in the specified directory that match the specified pattern
for filename in os.listdir(directory):
if fnmatch.fnmatch(filename.lower(), pattern):
yield os.path.join(directory, filename)


def send_email(subject, filename, emailtype, errormessage):
"""Send email."""
message = MIMEMultipart()
message["Subject"] = subject
message['Subject'] = subject
sender_email = os.getenv('SENDER_EMAIL', '')

if emailtype == "ERROR":
if emailtype == 'ERROR':
recipients = os.getenv('ERROR_EMAIL_RECIPIENTS', '')
message.attach(MIMEText("ERROR!!! \n" + errormessage, "plain"))
message.attach(MIMEText('ERROR!!! \n' + errormessage, 'plain'))
else:
if subject.startswith("Daily"):
if subject.startswith('Daily'):
recipients = os.getenv('DAILY_REPORT_RECIPIENTS', '')
if subject.startswith("Weekly NameX"):
recipients = os.getenv('WEEKLY_REPORT_NAMEX_RECIPIENTS', '')
if subject.startswith("Weekly Restoration"):
recipients = os.getenv('WEEKLY_REPORT_RESTRORATION_RECIPIENTS', '')
if subject.startswith('Weekly NameX'):
recipients = os.getenv('WEEKLY_REPORT_NAMEX_RECIPIENTS', '')
# Add body to email
message.attach(MIMEText("Please see attached.", "plain"))
message.attach(MIMEText('Please see attached.', 'plain'))

# Open file in binary mode
with open(os.getenv('DATA_DIR', '')+filename, "rb") as attachment:
with open(os.getenv('DATA_DIR', '')+filename, 'rb') as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
part = MIMEBase("application", "octet-stream")
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())

# Encode file in ASCII characters to send by email
encoders.encode_base64(part)

# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",
'Content-Disposition',
f'attachment; filename= {filename}',
)

# Add attachment to message and convert message to string
Expand All @@ -87,95 +86,93 @@ def send_email(subject, filename, emailtype, errormessage):
server = smtplib.SMTP(os.getenv('EMAIL_SMTP', ''))
email_list = []
email_list = recipients.strip('][').split(', ')
logging.info('Email recipients list is: {}'.format(email_list))
logging.info('Email recipients list is: %s', email_list)
server.sendmail(sender_email, email_list, message.as_string())
logging.info('Email with subject \'' + subject + '\' has been sent successfully!')
logging.info('Email with subject %s has been sent successfully!', email_list)
server.quit()
os.remove(os.getenv('DATA_DIR', '')+filename)


def processnotebooks(notebookdirectory):
status = False
weekno = datetime.now().weekday()
"""Process Notebook."""
status = False
date = datetime.strftime(datetime.now() - timedelta(1), '%Y-%m-%d')
ext = ''
if not os.getenv('ENVIRONMENT', '') == 'prod':
if os.getenv('ENVIRONMENT', '') != 'prod':
ext = ' on ' + os.getenv('ENVIRONMENT', '')

try:
retry_times = int(os.getenv('RETRY_TIMES', '1'))
retry_interval = int(os.getenv('RETRY_INTERVAL', '60'))
if notebookdirectory == 'weekly':
weekreportday = ast.literal_eval(os.getenv('WEEK_REPORT_DATE', ''))
except Exception:
logging.exception("Error processing notebook for {}.".format(notebookdirectory))
if notebookdirectory == 'weekly':
weekreportday = ast.literal_eval(os.getenv('WEEK_REPORT_DATE', '[0,1,2,3,4,5]'))
except Exception: # noqa: B902
logging.exception('Error processing notebook for %s.', notebookdirectory)
# we failed all the attempts
subject = "NameX Jupyter Notebook Error Notification for " + notebookdirectory + " on " + date + ext
subject = 'NameX Jupyter Notebook Error Notification for ' + notebookdirectory + ' on ' + date + ext
filename = ''
send_email(subject, filename, "ERROR", traceback.format_exc())
send_email(subject, filename, 'ERROR', traceback.format_exc())
return status

# For weekly tasks, we only run on the specified days
# Only run weekly report on Monday (index is 0) for previous 7 days data
if ( notebookdirectory == 'daily' or (notebookdirectory == 'weekly' and weekno in weekreportday)):
logging.info('Processing: ' + notebookdirectory)
if (notebookdirectory == 'daily' or (notebookdirectory == 'weekly' and datetime.now().weekday() in weekreportday)):
logging.info('Processing: %s', notebookdirectory)

num_files = len(os.listdir(notebookdirectory))
num_files = len(os.listdir(notebookdirectory))
file_processed = 0

for file in findfiles(notebookdirectory, '*.ipynb'):
file_processed += 1
note_book = os.path.basename(file)
for attempt in range(retry_times):
try:
pm.execute_notebook(file, os.getenv('DATA_DIR', '')+'temp.ipynb', parameters=None)

pm.execute_notebook(file, os.getenv('DATA_DIR', '')+'temp.ipynb', parameters=None)
nbfile = note_book.split('.ipynb')[0]

if nbfile == 'daily':
subject = "Daily NameX Stats for " + date + ext
subject = 'Daily NameX Stats for ' + date + ext
filename = 'daily_totals_' + date + '.csv'
elif nbfile == 'weeklynamex':
subject = "Weekly NameX Stats till " + date + ext
filename = 'weekly_totals_till_' + datetime.strftime(datetime.now()-timedelta(1), '%Y-%m-%d') +'.csv'
elif nbfile == 'weeklyrestoration':
subject = "Weekly Restoration Expiry till " + date + ext
filename = 'weekly_restoration_expiry_till_' + datetime.strftime(datetime.now()-timedelta(1), '%Y-%m-%d') +'.csv'
subject = 'Weekly NameX Stats till ' + date + ext
filename = 'weekly_totals_till_' + datetime.strftime(datetime.now()-timedelta(1),
'%Y-%m-%d') + '.csv'

# send email to receivers and remove files/directories which we don't want to keep
send_email(subject, filename, "", "")
os.remove(os.getenv('DATA_DIR', '')+'temp.ipynb')

send_email(subject, filename, '', '')
os.remove(os.getenv('DATA_DIR', '')+'temp.ipynb')
status = True
break
except Exception:
except Exception: # noqa: B902
if attempt + 1 == retry_times:
# If any errors occur with the notebook processing they will be logged to the log file
logging.exception("Error processing notebook {0} at {1}/{2} try.".format(notebookdirectory, attempt + 1, retry_times))
logging.exception('Error processing notebook %s at %s/%s try.',
notebookdirectory, attempt + 1, retry_times)
# we failed all the attempts
subject = "NameX Jupyter Notebook Error Notification for " + notebookdirectory + " on " + date + ext
subject = 'NameX Jupyter Notebook Error Notification for ' + notebookdirectory + \
' on ' + date + ext
filename = ''
send_email(subject, filename, "ERROR", traceback.format_exc())
send_email(subject, filename, 'ERROR', traceback.format_exc())
else:
# If any errors occur with the notebook processing they will be logged to the log file
logging.exception("Error processing notebook {0} at {1}/{2} try. Sleeping for {3} secs before next try"
.format(notebookdirectory, attempt + 1, retry_times, retry_interval))
logging.exception('Error processing notebook %s at %s/%s try. Sleeping for %s secs before \
next try', notebookdirectory, attempt + 1, retry_times, retry_interval)
time.sleep(retry_interval)
continue
if not status and num_files == file_processed:
break
break
return status


if __name__ == '__main__':
start_time = datetime.utcnow()

# Check if the subfolders for notebooks exist, and create them if they don't
for directory in ['daily', 'weekly']:
if not os.path.isdir(directory):
os.mkdir(directory)
processnotebooks(directory)
end_time = datetime.utcnow()
logging.info("job - jupyter notebook report completed in: {}".format(end_time - start_time))
exit(0)
START_TIME = datetime.utcnow()

# Check if the subfolders for notebooks exist, and create them if they don't
for _directory in ['daily', 'weekly']:
if not os.path.isdir(_directory):
os.mkdir(_directory)

processnotebooks(_directory)
END_TIME = datetime.utcnow()
logging.info('job - jupyter notebook report completed in: %s', (END_TIME - START_TIME))
sys.exit()
5 changes: 0 additions & 5 deletions jobs/notebook-report/openshift/templates/cronjob.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,6 @@ objects:
secretKeyRef:
name: ${NAME}-${TAG}-secret
key: WEEKLY_REPORT_NAMEX_RECIPIENTS
- name: WEEKLY_REPORT_RESTRORATION_RECIPIENTS
valueFrom:
secretKeyRef:
name: ${NAME}-${TAG}-secret
key: WEEKLY_REPORT_RESTRORATION_RECIPIENTS
- name: EMAIL_SMTP
valueFrom:
secretKeyRef:
Expand Down
18 changes: 18 additions & 0 deletions jobs/notebook-report/requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,30 @@

# Testing
pytest
freezegun
pytest-aiohttp
pytest-asyncio
pytest-mock
requests==2.25.1
pyhamcrest
dpath

# Lint and code style
pydocstyle
flake8
flake8-blind-except
flake8-debugger
flake8-docstrings
flake8-isort
flake8-quotes
pep8-naming

autopep8
coverage
pylint
pylint-flask
isort
pytest-cov

# docker
lovely-pytest-docker
1 change: 1 addition & 0 deletions jobs/notebook-report/tests/unit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""init for the notebook."""
17 changes: 6 additions & 11 deletions jobs/notebook-report/tests/unit/conftest.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
"""conftest for the notebook."""
import pytest
from flask import current_app

from notebookreport import create_app

from config import Config
from notebookreport import create_app


@pytest.fixture(scope="session")
@pytest.fixture(scope='session')
def app(request):
"""
Returns session-wide application.
"""
"""Init apps and Returns session-wide application."""
app = create_app(Config)

return app


@pytest.fixture(scope="session")
@pytest.fixture(scope='session')
def client_ctx(app):
"""
Returns session-wide Flask test client.
"""
"""Init client and returns session-wide Flask test client."""
with app.test_client() as c:
yield c
Loading

0 comments on commit a410624

Please sign in to comment.