From cb6591029d9d23a9b73bc9bc879c4ca3c501cad8 Mon Sep 17 00:00:00 2001 From: Shea Silverman Date: Tue, 30 Mar 2021 17:12:00 -0400 Subject: [PATCH] Dockerized Faculty Tools --- .dockerignore | 22 +++++++++++++++ .env.template | 15 ++++++++++ .gitignore | 2 +- Dockerfile | 10 +++++++ README.md | 68 ++++++++++++++++++---------------------------- config.py | 18 ++++++++---- docker-compose.yml | 35 ++++++++++++++++++++++++ lti.py => main.py | 0 requirements.txt | 4 +-- settings.py | 55 +++++++++++++++++++++++++++++++++++++ 10 files changed, 180 insertions(+), 49 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.template create mode 100644 Dockerfile create mode 100644 docker-compose.yml rename lti.py => main.py (100%) create mode 100644 settings.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..20d7ebb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +.dockerignore +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +env +venv* +pip-log.txt +pip-delete-this-directory.txt +.tox +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +*.log +.git +*.template +.env* +fake-s3 diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..aef2480 --- /dev/null +++ b/.env.template @@ -0,0 +1,15 @@ +TOOL_TITLE=Faculty Tools +THEME_DIR= +API_URL=https://example.com/ +SECRET_KEY=CHANGEME +LTI_KEY=CHANGEME +LTI_SECRET=CHANGEME +OAUTH2_URI=https://127.0.0.1:9001/oauthlogin +OAUTH2_ID=CHANGEME +OAUTH2_KEY=CHANGEME +GOOGLE_ANALYTICS=GA-000000 +CONFIG=config.DevelopmentConfig +DATABASE_URI=mysql://root:secret@db/faculty_tools + +REQUIREMENTS=test_requirements.txt + diff --git a/.gitignore b/.gitignore index 0e980ad..86319a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # config/settings logs -settings.py whitelist.json +.env # local theming themes/* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..95af5ae --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM tiangolo/uwsgi-nginx-flask:python3.7 +ARG REQUIREMENTS +RUN apt-get update && apt-get -y install libffi-dev gcc python3-dev libffi-dev libssl-dev libxml2-dev libxmlsec1-dev libxmlsec1-openssl +RUN apt-get -y install ca-certificates +WORKDIR /app +COPY requirements.txt /app/ +COPY test_requirements.txt /app/ +RUN echo $REQUIREMENTS +RUN pip install -r $REQUIREMENTS +COPY ./ /app/ diff --git a/README.md b/README.md index 529383f..a946475 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,19 @@ # Documentation for Faculty Tools -## Settings +## Setting up Faculty Tools with Docker & Docker-Compose -Create a new `settings.py` file from the template +First clone and setup the repo. ```sh -cp settings.py.template settings.py +git clone git@github.com:ucfopen/faculty-tools.git +cp whitelist.json.template whitelist.json +cp .env.template .env +mkdir logs +touch logs/faculty-tools.log ``` -Edit `settings.py` to configure the application. All fields are required, +Edit `.env` to configure the application. All fields are required, unless specifically noted. ## Developer Key @@ -57,32 +61,13 @@ Add the tools you want instructors and faculty to see to `whitelist.json`. ] ``` -## Virtual Environment - -Create a new virtual environment. - -```sh -virtualenv env -``` - -Activate the environment. - -```sh -source env/bin/activate -``` - -Install everything: - -```sh -pip install -r requirements.txt -``` - ## Create DB -Change directory into the project folder. Create the database in python shell: +We need to generate the database and tables for faculty tools to run properly. The MySQL docker image automatically creates the user, password, and database name set in the `docker-compose.yml` file. ```sh -from lti import db +docker-compose run lti python +from main import db db.create_all() ``` @@ -90,34 +75,35 @@ If you want to look at your users table in the future, you can do so in the python shell: ```python -from lti import Users +docker-compose run lti python +from main import Users Users.query.all() ``` -## Environment Variables -Set the flask app to `lti.py` and debug to true. +## Run the App + +It's time to use docker-compose to bring up the application. ```sh -export FLASK_APP=lti.py -export FLASK_DEBUG=1 +docker-compose up -d ``` -Alternatively, you can run the setup script to simultaneously setup environment -variables and the virtual environment. +Go to the /xml page, [http://127.0.0.1:9001/xml](http://127.0.0.1:9001/xml) by default -```sh -source setup.sh -``` +Copy the xml, install it into a course. -## Run the App +## View the Logs -Run the lti script while your virtual environment is active. +To view the logs while the application is running use this docker command: ```sh -flask run +docker-compose logs -f ``` -Go to the /xml page, [http://0.0.0.0:5000/xml](http://0.0.0.0:5000/xml) by default +## Stopping the App -Copy the xml, install it into a course. +To shutdown Faculty Tools +```sh +docker-compose down +``` \ No newline at end of file diff --git a/config.py b/config.py index c360a34..41c8e96 100644 --- a/config.py +++ b/config.py @@ -1,10 +1,9 @@ import settings - +import os class Config(object): # make the warning shut up until Flask-SQLAlchemy v3 comes out SQLALCHEMY_TRACK_MODIFICATIONS = True - SQLALCHEMY_DATABASE_URI = settings.select_db("Config") PYLTI_CONFIG = settings.PYLTI_CONFIG @@ -14,6 +13,9 @@ class Config(object): SESSION_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "None" + SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URI") + + class BaseConfig(object): DEBUG = False @@ -21,7 +23,6 @@ class BaseConfig(object): # make the warning shut up until Flask-SQLAlchemy v3 comes out SQLALCHEMY_TRACK_MODIFICATIONS = True - SQLALCHEMY_DATABASE_URI = settings.select_db("BaseConfig") PYLTI_CONFIG = settings.PYLTI_CONFIG @@ -31,16 +32,23 @@ class BaseConfig(object): SESSION_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "None" + SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URI") + + class DevelopmentConfig(BaseConfig): DEBUG = True TESTING = True - SQLALCHEMY_DATABASE_URI = settings.select_db("DevelopmentConfig") + SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URI") + + class TestingConfig(BaseConfig): DEBUG = False TESTING = True - SQLALCHEMY_DATABASE_URI = settings.select_db("TestingConfig") + SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URI") + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..751f9ca --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,35 @@ +version: '3.1' + +services: + lti: + build: + context: . + args: + - "REQUIREMENTS=${REQUIREMENTS}" + ports: + - "9001:80" + env_file: + - .env + environment: + - MODULE_NAME=app + depends_on: + - db + + db: + image: mysql:5.7 + volumes: + - ft_dbdata:/var/lib/mysql + restart: always + environment: + MYSQL_ROOT_PASSWORD: secret + MYSQL_DATABASE: faculty_tools + MYSQL_USER: root + MYSQL_PASSWORD: secret + ports: + - "33061:3306" +volumes: + ft_dbdata: {} + + + + diff --git a/lti.py b/main.py similarity index 100% rename from lti.py rename to main.py diff --git a/requirements.txt b/requirements.txt index b4f768f..38b85d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ canvasapi==0.15.0 Flask==1.1.1 -Flask-SQLAlchemy==2.4.1 +Flask-SQLAlchemy==2.5.1 mysqlclient --e git+https://github.com/ucfcdl/pylti.git@roles#egg=PyLTI +git+https://github.com/ucfcdl/pylti.git@roles#egg=PyLTI requests==2.22.0 Werkzeug>=1.0.1 # Chrome 80 SameSite fix diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..a67aca3 --- /dev/null +++ b/settings.py @@ -0,0 +1,55 @@ +import os +# Title of the tool. Appears in the element, headers, and configuration XML +TOOL_TITLE = os.environ.get("TOOL_TITLE", "Faculty Tools") + +# Which theme directory to use. Leave blank for default. +THEME_DIR = os.environ.get("THEME_DIR", "") + +# Canvas instance URL. ex: https://example.instructure.com/ +BASE_URL = os.environ.get("API_URL") +API_URL = BASE_URL + "api/v1/" + +# Secret key to sign Flask sessions with. KEEP THIS SECRET! +secret_key = os.environ.get("SECRET_KEY") + +# LTI consumer key and shared secret +CONSUMER_KEY = os.environ.get("LTI_KEY") +SHARED_SECRET = os.environ.get("LTI_SECRET") + +# Configuration for pylti library. Uses the above key and secret +PYLTI_CONFIG = { + "consumers": { + CONSUMER_KEY: { + "secret": SHARED_SECRET + } + }, + # Custom configurable roles + "roles": { + "staff": [ + "urn:lti:instrole:ims/lis/Administrator", + "Instructor", + "ContentDeveloper", + "urn:lti:role:ims/lis/TeachingAssistant", + ] + }, +} + +# The "Oauth2 Redirect URI" that you provided to Instructure. +oauth2_uri = os.environ.get("OAUTH2_URI") # ex. 'https://localhost:5000/oauthlogin' +# The Client_ID Instructure gave you +oauth2_id = os.environ.get("OAUTH2_ID") +# The Secret Instructure gave you +oauth2_key = os.environ.get("OAUTH2_KEY") + +# Logging configuration +LOG_MAX_BYTES = 1024 * 1024 * 5 # 5 MB +LOG_BACKUP_COUNT = 2 +ERROR_LOG = "logs/faculty-tools.log" + +whitelist = "whitelist.json" + +# Google Analytics Tracking ID (optional) +GOOGLE_ANALYTICS = os.environ.get("GOOGLE_ANALYTICS", "GA-") + + +configClass = os.environ.get("CONFIG", "config.DevelopmentConfig") \ No newline at end of file