######### Cloud Ops ######### ******** Overview ******** This repo controls all of the cloud operations for Titans Of Eden. This includes: #. Website HTML/CSS/JS #. Online Demo #. Blender Video-Rendering & Formatting #. Database Creation & Management #. Web-based API #. Email Listserv Management *********** Cloud Infra *********** The following infrastructure was setup for this project: #. `(Production) File Server / Static Website `_ #. `Dev File Server / Static Website `_ #. Batch Account (for parallel computing / video rendering) #. MySQL Server (as a general database) #. Container Registry #. `CDN (for public-facing website) `_ #. `Linux VM `_ (which provides all API functionality) All infrastructure resides on Azure. ******** Cloud VM ******** This project has a cloud VM. All development work should be carried out on this VM (e.g. by SSH'ing into it). The VM's IP is whitelisted, which allows it to access the database and other cloud services. Additionally, credentials are securely stored on this VM. If the cloud VM ever goes down and needs to be re-provisioned, once the VM is up again, you can re-provision by: #. Placing a MySQL connection string in :code:`~/secrets/titans-mysql` #. Whitelisting the VM's IP #. Running the command: .. code-block:: bash curl https://raw.githubusercontent.com/lakes-legendaries/titans/main/webserver/provision.sh | bash This will install all dependencies, establish credentials for a secure HTTPS connection, launch the API, and schedule regular updates and upgrades. ******* Website ******* All (most?) website code is contained in :code:`titans/website`. Please note that I am **not** a frontend developer: Cut me some slack if this doesn't look perfect! HTML ==== HTML code is contained in the subfolder `html`. I wrote my own compiler for HTML code: Comments that include the name of a file substitute in that file's contents on compilation. E.g. the comment :code:`` in :code:`html/constructed.html` substitutes in the contents of `html/partial/include.html` on compilation. Instructions on how to run the compiler are below. CSS === All CSS code is in the subfolder :code:`style`, including code for dynamic scaling to mobile / desktop screens. JS == All JS code is located in the subfolder :code:`script`. JQuery was used heavily. This code could definitely use some TLC by a real frontend developer (e.g. within the React framework). Compiling ========= To run the compiler, simpy run: .. code-block:: bash python titans/website/compile.py and all html files will be compiled and output to :code:`titans/website/site`. Assets ====== There are a handful of image files that are NOT managed by this repo, but are expected to be uploaded to the dev fileserver by other processes. This includes various card images, instructional images, and rules PDFs, among some other scattered files. The code to upload those files lives with each of the respective files. (Some other assets, like videos and online demo code, are discussed below.) Deploying ========= To Dev ------ Once all code has been compiled, you can deploy from local to dev by running: .. code-block:: bash python titans/website/deploy.py This will only deploy the HTML/JS/CSS files, and will NOT deploy other website files (e.g. online demo files, video files). To Production ------------- After reviewing the files on the dev fileserver, you can deploy from dev to production by running .. code-block:: bash python titans/website/deploy.py --prod Unlike the dev deployment code, this will copy over all files from dev to production, including demo files and video files. (The rationale is that, when you move from local to dev, with this script, you're testing out HTML code; and, when you move from dev to prod, you are testing out all files and code on the server.) *********** Online Demo *********** Code for the online demo lives in :code:`titans/demo`. To upload to the dev fileserver, simply run: .. code-block:: bash python titans/demo This code was written in Phaser 3. Potential future upgrades include upgrading the AI system; enabling P2P versus, and including additional cards. However, as the goal of this demo is to serve as a try-before-you-buy, this does NOT have a high priority. ****** Videos ****** Several blender videos have been created to demo this project. These use Blender to render, and have been setup to work using Azure Batch, which allows for massively-parallel rendering. (At one point, these were all running sequentially on my desktop, and would take several weeks to finish; now, they complete in mere hours.) A Dockerfile has been provided for use by Azure Batch, so that each pod doesn't have to install its own dependencies. To build the docker image and store it on a container registry, run: .. code-block:: bash python titans/videos/build_img.py --verbose Once this completes, you can launch various rendering tasks via the command: .. code-block:: bash python titans/videos The main commands that should be run, in order, are: .. code-block:: bash python titans/videos animate python titans/videos render python titans/videos convert Each command should only be run after all jobs on Azure complete. Several of these jobs string together multiple jobs that all depend on one another. (These could have all been strung together into a single job; however, I wanted to encourage users to look at the output of each job before moving onto the next.) The first command, animate, creates video frames as png files. The second, render, combines pngs to create videos. The third, convert, transforms videos into modern codec formats. Each of these commands has many command-line options for rerunning only certain subsets. Refer to the documentation of each for help. ********* Databases ********* This repo creates and manages a MySQL database with three tables: contacts, comments, and creds. Comments and creds are tables meant to store user input from the website. These were created via the python command: .. code-block:: bash python titans/sql/comments.py --create python titans/sql/contacts.py --create Some db management is available via flags on those arguments. Use with caution. Various credentials are also stored in this database. This is probably not best practice, but works, as all dev work happens on this project's cloud VM, which is the only IP able to access the database. This credentials table was made, and can be updated, via: .. code-block:: bash python titans/sql/creds.py Refer to the docstrings for additional information. *** API *** I setup a cloud VM to act as an API for this project. This API will one day be upgraded to handle the decisions made by the AI for the online demo (which will eventually be expanded into an online client). The API was setup with FastAPI, and it handles all database queries and insertions made from the website. This includes: #. Subscribing to the email list (which adds a user's name and email to the contacts table) #. Unsubscribing (removing name/email) #. Commenting (saving comment, and optionally email, to the comments table) Entries and scanned, sanitizied, and validating before insertions take place. Emails are additionally automatically sent by the API whenever a comment is left on the website, or whenever a new subscriber joins the email list. The API can be accessed `here `_. FastAPI docs for this API are located `here `_. Updates ======= If you want to test changes to the API before going live, you can update the code, and then run (on the webserver): .. code-block:: bash webserver/test-api.sh This will spin up a copy of the API on the webserver at the port 1024, which can be accessed `here `_. To update the real API, push your changes to GitHub, then run: .. code-block:: bash webserver/run-service.sh This command is automatically run every time the webserver restarts. ****** Emails ****** This package handles sending emails to all of our subscribers, all from the command line. This uses the MS 365 Graph API to execute sending. Emails are additionally automatically sent whenever a comment is left on the website, or whenever a new subscriber joins the email list. Authenticating ============== For first-time use, you must authenticate with Office365 by following these steps: In the Azure portal: #. Go to :code:`Azure Active Directory` -> :code:`App Registrations` #. Create a new app registration. Set the redirect URI to :code:`http://localhost`. #. Go to :code:`Certificates & secrets`, then create a new client secret. Copy the :code:`Value`, as you'll only be able to see this once. #. Go to :code:`API Permissions`, and from Microsoft Graph the Delegated Permission of Mail.Send. #. Create a :code:`~/secrets/titans-email-creds` file that looks like: .. code-block:: json { "tenant": "", "client_id": "", "client_secret": "", } In this repo: #. Make sure you have a :code:`SECRETS_DIR` environmental variable set, e.g. :code:`~/secrets`. #. Run :code:`titans/email/get-code.sh`. Follow the website it points you to, and authenticate with your office account. It'll redirect you to an error page. On that page, look at the url, and copy the :code:`code` parameter from the URL (i.e. the portion that reads :code:`&code=...&`). Paste that code into a :code:`$SECRETS_DIR/titans-email-code` file in this repo. #. Run `auth/get-token.sh`. This will create a :code:`$SECRETS_DIR/titans-email-token` file, containing your authentication token. #. Finally, update the :code:`creds` table in sql by running: .. code-block:: bash python titans/sql/creds.py Sending Emails ============== To send emails, run: .. code-block:: bash python titans/email yamlconfig where :code:`yamlconfig` is a configuration yaml file that is unpacked to initialize :code:`titans.email.sender.SendEmails`. An example configuration yaml file would look like: .. code-block:: yaml subject: We're Back! body: 2022-07/body.html attachments: [ 2022-07/box.png, 2022-07/divider.png, 2022-07/final_judgment.png, 2022-07/logo.png, ] where :code:`2022-07/body.html` is the name of an html file you want to send, and the attachments are names of attachments you want to attach. Please note that any attachments can be referenced and inserted in :code:`body` via their cid: .. code-block:: html and the string :code:`#|EMAIL|#` will be replaced with the receipient's email address. Dev: Testing ============ To send a test email, run: .. code-block:: bash python tests/titans/api/subscribe_test.py Please note that this test will fail unless it's run on the whitelisted VM! Polls ===== Periodically, we run polls out of the email service. To do so: #. Create a new table in the database: .. code-block:: bash python titans/sql/polls.py table_name This table will store the poll responses. #. Build the email that will contain this poll. This email needs to have links that the recipient can click on that query the API. These responses have to look like: .. code-block:: text https://titansapi.eastus.cloudapp.azure.com/poll/POLL_NAME?email=#|EMAIL|#&response=RESPONSE which includes the parameters: #. :code:`POLL_NAME``: The name of the poll, which is the name of the table created in the previous step. #. :code:`EMAIL`: The email of the responder, which will be auto-inserted by the email client. (The string :code:`#|EMAIL|#` is a special string that is processed by the email client.) #. :code:`RESPONSE`: The response to the poll, which should be hard-coded for each clickable link. #. Send the email, and check the results as they roll in!