diff --git a/.env.example b/.env.example index 3bfd7e50..0c80d768 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,10 @@ API_URL=/api MONGO_URL=mongodb://localhost:27017/p5js-web-editor +MONGO_HOSTNAME=localhost +MONGO_PORT=27017 +MONGO_NAME=p5js-web-editor +MONGO_ROOT_USERNAME=processing_user +MONGO_ROOT_PASSWORD= PORT=8000 SESSION_SECRET=whatever_you_want_this_to_be_it_only_matters_for_production AWS_ACCESS_KEY= diff --git a/.travis.yml b/.travis.yml index c78422d0..721092f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,9 @@ sudo: required language: node_js node_js: - "8.11.1" +python: +- "3.4" +- "pypy-5.3.1" services: - docker @@ -18,7 +21,24 @@ script: - docker-compose exec -T app npm run test --verbose after_success: -# eventually wrap this in a if branch is master +# only run this if on the master branch eventually, not while testing tho +- sudo apt-get install -y python3.4 +- sudo apt-get install --upgrade -y python-pip +- sudo apt-get install jq +- sudo pip install --user virtualenv +# Create a virtual environment for AWS CLI +- virtualenv my_py3 --python=/usr/bin/python3.4 +- source my_py3/bin/activate +- pip install --upgrade awscli +- pip install --upgrade awsebcli +# Set AWS information +- aws configure set aws_access_key_id $AWS_ACCESS_KEY +- aws configure set aws_secret_access_key $AWS_SECRET_KEY +- aws configure set default.region $AWS_REGION +- aws configure set metadata_service_timeout 1200 +- aws configure set metadata_service_num_attempts 3 +- aws configure list +# build images - docker-compose stop - docker-compose build --no-cache - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" diff --git a/docker-compose.yml b/docker-compose.yml index fa865432..971789ec 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,33 +1,38 @@ version: '3.4' services: mongo: - image: mongo:3.4.7 + build: ./mongo volumes: - dbdata:/data/db expose: - "27017" - nginx: - build: ./nginx - ports: - - '80:80' - app: - build: - context: . - dockerfile: Dockerfile - target: production - # env_file: - # - .env - environment: - - MONGO_URL=mongodb://mongo:27017/p5js-web-editor - # - API_URL=https://localhost/api - # - PORT=80 - volumes: - - .:/opt/node/app - - /opt/node/app/node_modules - ports: - - '8000:8000' - # - '443:443' - depends_on: - - mongo + # restart: always + env_file: + - .env + # nginx: + # build: ./nginx + # ports: + # - '80:80' + # app: + # build: + # context: . + # dockerfile: Dockerfile + # target: production + # env_file: + # - .env + # environment: + # - MONGO_URL=mongodb://mongo:27017/p5js-web-editor + # - MONGO_HOSTNAME=mongo + # # - API_URL=https://localhost/api + # # - PORT=80 + # volumes: + # - .:/opt/node/app + # - /opt/node/app/node_modules + # ports: + # - '8000:8000' + # # - '443:443' + # # - '80:80' + # depends_on: + # - mongo volumes: dbdata: diff --git a/mongo/Dockerfile b/mongo/Dockerfile new file mode 100644 index 00000000..ca519793 --- /dev/null +++ b/mongo/Dockerfile @@ -0,0 +1,13 @@ +# Use an official mongo runtime as a parent image +FROM mongo:3.4 + +# Expose the mongo port +EXPOSE 27017 + +# Copy the mongod.conf file to env +# COPY mongod.conf /env/ + +# Copy the entrypoint file as well +COPY ./docker-entrypoint.sh . + +CMD ["/bin/bash", "docker-entrypoint.sh"] \ No newline at end of file diff --git a/mongo/docker-entrypoint.sh b/mongo/docker-entrypoint.sh new file mode 100644 index 00000000..179b5c2f --- /dev/null +++ b/mongo/docker-entrypoint.sh @@ -0,0 +1,42 @@ +#!/bin/bash +set -euo pipefail + +function waitForMongo { + port=$1 + n=0 + until [ $n -ge 20 ] + do + mongo admin --quiet --port $port --eval "db" && break + n=$[$n+1] + sleep 2 + done +} + +if ! [[ -a /data/db/mydb-initialized ]]; then + mongod & MONGO_PID=$! + waitForMongo 27017 + mongo admin --port 27017 --eval "db.system.version.insert({ '_id' : 'authSchema', 'currentVersion' : 3 })" + mongod --shutdown + + mongod & MONGO_PID=$! + waitForMongo 27017 + mongo admin --port 27017 --eval "db.createUser({ user: '${MONGO_INITDB_ROOT_USERNAME}', pwd: '${MONGO_INITDB_ROOT_PASSWORD}', roles: [ 'root' ]})" + mongo admin -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --port 27017 --eval "db.createUser({ user: '${MONGO_RW_USERNAME}', pwd: '${MONGO_RW_PASSWORD}', roles: [ {role: 'readWrite', db: 'isf-website'}, {role: 'readWrite', db: 'sessions'} ]})" + mongod --shutdown + + mongod -f /env/mongod.conf --auth & MONGO_PID=$! + waitForMongo 27017 + mongo admin -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --port 27017 --eval "db.runCommand({ replSetInitiate: '{}' })" + mongo admin -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --port 27017 --eval "db.setSlaveOk()" + mongod --shutdown + + touch /data/db/mydb-initialized +fi + +mongod -f /env/mongod.conf --auth & MONGO_PID=$! + +waitForMongo 27017 + +trap 'echo "KILLING"; kill $MONGO_PID; wait $MONGO_PID' SIGINT SIGTERM EXIT + +wait $MONGO_PID \ No newline at end of file diff --git a/server/Dockerrun.aws.json b/server/Dockerrun.aws.json new file mode 100644 index 00000000..261d66c5 --- /dev/null +++ b/server/Dockerrun.aws.json @@ -0,0 +1,73 @@ +{ + "AWSEBDockerrunVersion": 2, + "authentication": { + "bucket": "", + "key": ".dockercfg" + }, + "volumes": [ + { + "name": "storage", + "host": { + "sourcePath": "/var/data" + } + }, + { + "name": "app", + "host": { + "sourcePath": "/var/app/current/app" + } + } + ], + "containerDefinitions": [ + { + "name": "mongo", + "image": "mongo:3.4", + "essential": true, + "memory": 512, + "portMappings": [ + { + "hostPort": 27017, + "containerPort": 27017 + } + ], + "mountPoints": [ + { + "sourceVolume": "storage", + "containerPath": "/var/lib/mysql" + } + ], + "environment": [ + { + "name": "MYSQL_ROOT_PASSWORD", + "value": "password" + }, + { + "name": "MYSQL_DATABASE", + "value": "my_db" + } + ] + }, + { + "name": "app", + "image": ":", + "essential": true, + "memory": 256, + "portMappings": [ + { + "hostPort": 80, + "containerPort": 80 + } + ], + "links": [ + "db" + ], + "mountPoints": [ + { + "sourceVolume": "app", + "containerPath": "/var/www/html", + "readOnly": true + } + ] + } + ] +} \ No newline at end of file diff --git a/server/scripts/examples-gg-latest.js b/server/scripts/examples-gg-latest.js index a9a0a2cd..52f66b1b 100644 --- a/server/scripts/examples-gg-latest.js +++ b/server/scripts/examples-gg-latest.js @@ -3,6 +3,7 @@ import Q from 'q'; import mongoose from 'mongoose'; import objectID from 'bson-objectid'; import shortid from 'shortid'; +import { URL } from 'url'; import eachSeries from 'async/eachSeries'; import User from '../models/user'; @@ -65,7 +66,17 @@ canvas { const headers = { 'User-Agent': 'p5js-web-editor/0.0.1' }; -mongoose.connect(process.env.MONGO_URL); +let mongoConnectionString; +if (process.env.NODE_ENV === 'production') { + const { MONGO_RW_USERNAME, MONGO_RW_PASSWORD, MONGO_HOSTNAME, MONGO_PORT, MONGO_NAME } = process.env; + const muo = new URL(`mongodb://${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_NAME}`); + muo.username = MONGO_RW_USERNAME; + muo.password = MONGO_RW_PASSWORD; + mongoConnectionString = muo.href + "?authSource=admin"; +} else { + mongoConnectionString = process.env.MONGO_URL; +} +mongoose.connect(mongoConnectionString); mongoose.connection.on('error', () => { console.error('MongoDB Connection Error. Please make sure that MongoDB is running.'); process.exit(1); diff --git a/server/scripts/examples.js b/server/scripts/examples.js index c1cccc60..51841b2a 100644 --- a/server/scripts/examples.js +++ b/server/scripts/examples.js @@ -4,6 +4,7 @@ import mongoose from 'mongoose'; import objectID from 'bson-objectid'; import shortid from 'shortid'; import eachSeries from 'async/eachSeries'; +import { URL } from 'url'; import User from '../models/user'; import Project from '../models/project'; @@ -35,7 +36,18 @@ const clientSecret = process.env.GITHUB_SECRET; const headers = { 'User-Agent': 'p5js-web-editor/0.0.1' }; -mongoose.connect(process.env.MONGO_URL); +let mongoConnectionString; +if (process.env.NODE_ENV === 'production') { + const { MONGO_RW_USERNAME, MONGO_RW_PASSWORD, MONGO_HOSTNAME, MONGO_PORT, MONGO_NAME } = process.env; + const muo = new URL(`mongodb://${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_NAME}`); + muo.username = MONGO_RW_USERNAME; + muo.password = MONGO_RW_PASSWORD; + mongoConnectionString = muo.href + "?authSource=admin"; +} else { + mongoConnectionString = process.env.MONGO_URL; +} + +mongoose.connect(mongoConnectionString); mongoose.connection.on('error', () => { console.error('MongoDB Connection Error. Please make sure that MongoDB is running.'); process.exit(1); diff --git a/server/server.js b/server/server.js index efb915b7..4e471e29 100644 --- a/server/server.js +++ b/server/server.js @@ -7,6 +7,7 @@ import session from 'express-session'; import connectMongo from 'connect-mongo'; import passport from 'passport'; import path from 'path'; +import { URL } from 'url'; // Webpack Requirements import webpack from 'webpack'; @@ -44,6 +45,17 @@ if (process.env.NODE_ENV === 'development') { corsOriginsWhitelist.push(/localhost/); } +let mongoConnectionString; +if (process.env.NODE_ENV === 'production') { + const { MONGO_RW_USERNAME, MONGO_RW_PASSWORD, MONGO_HOSTNAME, MONGO_PORT, MONGO_NAME } = process.env; + const muo = new URL(`mongodb://${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_NAME}`); + muo.username = MONGO_RW_USERNAME; + muo.password = MONGO_RW_PASSWORD; + mongoConnectionString = muo.href + "?authSource=admin"; +} else { + mongoConnectionString = process.env.MONGO_URL; +} + // Enable Cross-Origin Resource Sharing (CORS) for all origins const corsMiddleware = cors({ credentials: true, @@ -72,7 +84,7 @@ app.use(session({ secure: false, }, store: new MongoStore({ - url: process.env.MONGO_URL, + url: mongoConnectionString, autoReconnect: true }) })); @@ -105,7 +117,7 @@ require('./config/passport'); // const passportConfig = require('./config/passport'); // Connect to MongoDB -mongoose.connect(process.env.MONGO_URL); +mongoose.connect(mongoConnectionString); mongoose.connection.on('error', () => { console.error('MongoDB Connection Error. Please make sure that MongoDB is running.'); process.exit(1);