From 5241fac7de8286984ddc9f653916a5f924b78955 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Fri, 4 Jan 2019 13:32:04 +0100 Subject: [PATCH] #814 Docker & test --- .env | 3 + Dockerfile | 10 +- back/methods/account/login.js | 92 ++++++++++++ back/methods/account/logout.js | 25 ++++ back/models/account.js | 3 + back/models/account.json | 17 ++- services_tests.js => back/tests.js | 10 +- docker-compose.yml | 2 +- smokes_tests.js => e2e/smokes-tests.js | 3 +- e2e_tests.js => e2e/tests.js | 0 front/{test_index.js => test-index.js} | 0 gulpfile.js | 35 ++--- karma.conf.js | 4 +- package.json | 8 +- services/db/Dockerfile | 31 ++-- services/db/docker-entrypoint.sh | 189 +++++++++++++++++++++++++ services/db/install/boot.sh | 44 +++--- db_tests.js => services/db/tests.js | 4 +- services/nginx/Dockerfile | 6 +- 19 files changed, 403 insertions(+), 83 deletions(-) create mode 100644 .env create mode 100644 back/methods/account/login.js create mode 100644 back/methods/account/logout.js rename services_tests.js => back/tests.js (77%) rename smokes_tests.js => e2e/smokes-tests.js (95%) rename e2e_tests.js => e2e/tests.js (100%) rename front/{test_index.js => test-index.js} (100%) create mode 100644 services/db/docker-entrypoint.sh mode change 100644 => 100755 services/db/install/boot.sh rename db_tests.js => services/db/tests.js (89%) diff --git a/.env b/.env new file mode 100644 index 000000000..f12ad79d3 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +BRANCH_NAME=latest +PORT=5000 +NODE_ENV=test \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 94db6085e..7efe70614 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ RUN apt-get update \ && npm -g install pm2 WORKDIR /salix -COPY package.json . +COPY package.json package-lock.json ./ COPY loopback/package.json loopback/ RUN npm install --only=prod @@ -22,9 +22,9 @@ COPY back back COPY modules modules COPY dist/webpack-assets.json dist/ COPY \ - modules.yml \ - LICENSE \ - README.md \ + modules.yml \ + LICENSE \ + README.md \ ./ -CMD pm2-docker ./loopback/server/server.js +CMD ["pm2-docker", "./loopback/server/server.js"] diff --git a/back/methods/account/login.js b/back/methods/account/login.js new file mode 100644 index 000000000..59ce78690 --- /dev/null +++ b/back/methods/account/login.js @@ -0,0 +1,92 @@ +const url = require('url'); +const md5 = require('md5'); + +module.exports = Self => { + Self.remoteMethod('login', { + description: 'Login a user with username/email and password', + accepts: [ + { + arg: 'user', + type: 'String', + description: 'The user name or email', + required: true + }, { + arg: 'password', + type: 'String', + description: 'The user name or email', + required: true + }, { + arg: 'location', + type: 'String', + description: 'Location to redirect after login' + } + ], + returns: { + type: 'object', + root: true + }, + http: { + path: `/login`, + verb: 'POST' + } + }); + + Self.login = async function(user, password, location) { + let token; + let usesEmail = user.indexOf('@') !== -1; + let User = Self.app.models.User; + + let loginInfo = {password}; + + if (usesEmail) + loginInfo.email = user; + else + loginInfo.username = user; + + try { + token = await User.login(loginInfo, 'user'); + } catch (err) { + if (err.code != 'LOGIN_FAILED' || usesEmail) + throw err; + + let filter = {where: {name: user}}; + let instance = await Self.findOne(filter); + + if (!instance || instance.password !== md5(password)) + throw err; + + let where = {id: instance.id}; + let userData = { + id: instance.id, + username: user, + password: password, + email: instance.email, + created: instance.created, + updated: instance.updated + }; + await User.upsertWithWhere(where, userData); + token = await User.login(loginInfo, 'user'); + } + + let apiKey; + let continueUrl; + + try { + let query = url.parse(location, true).query; + apiKey = query.apiKey; + continueUrl = query.continue; + } catch (e) { + continueUrl = null; + } + + let applications = Self.app.get('applications'); + if (!apiKey) apiKey = 'default'; + let loginUrl = applications[apiKey] || '/login'; + + return { + token: token.id, + continue: continueUrl, + loginUrl: loginUrl + }; + }; +}; diff --git a/back/methods/account/logout.js b/back/methods/account/logout.js new file mode 100644 index 000000000..515855267 --- /dev/null +++ b/back/methods/account/logout.js @@ -0,0 +1,25 @@ +module.exports = Self => { + Self.remoteMethod('logout', { + description: 'Logout a user with access token', + accepts: [ + { + arg: 'ctx', + type: 'Object', + http: {source: 'context'} + } + ], + returns: { + type: 'Boolean', + root: true + }, + http: { + path: `/logout`, + verb: 'POST' + } + }); + + Self.logout = async function(ctx) { + await Self.app.models.User.logout(ctx.req.accessToken.id); + return true; + }; +}; diff --git a/back/models/account.js b/back/models/account.js index 6426bc3a7..dbf3cdabe 100644 --- a/back/models/account.js +++ b/back/models/account.js @@ -1,6 +1,9 @@ const md5 = require('md5'); module.exports = Self => { + require('../methods/account/login')(Self); + require('../methods/account/logout')(Self); + // Validations Self.validatesUniquenessOf('name', { diff --git a/back/models/account.json b/back/models/account.json index e087208d6..00d031f9e 100644 --- a/back/models/account.json +++ b/back/models/account.json @@ -31,5 +31,20 @@ "updated": { "type": "date" } - } + }, + "acls": [ + { + "property": "login", + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }, { + "property": "logout", + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$authenticated", + "permission": "ALLOW" + } + ] } diff --git a/services_tests.js b/back/tests.js similarity index 77% rename from services_tests.js rename to back/tests.js index d64b02447..7bf462998 100644 --- a/services_tests.js +++ b/back/tests.js @@ -11,20 +11,20 @@ let verbose = false; if (process.argv[2] === '--v') verbose = true; -serviceRoot = `${__dirname}/loopback`; +serviceRoot = `${__dirname}/../loopback`; let Jasmine = require('jasmine'); let jasmine = new Jasmine(); let SpecReporter = require('jasmine-spec-reporter').SpecReporter; let serviceSpecs = [ - 'loopback/**/*[sS]pec.js', - 'back/**/*[sS]pec.js' + './loopback/**/*[sS]pec.js', + './back/**/*[sS]pec.js' ]; -let services = require(`./modules.yml`); +let services = require(`../modules.yml`); for (let service of services) - serviceSpecs.push(`modules/${service}/back/**/*[sS]pec.js`); + serviceSpecs.push(`./modules/${service}/back/**/*[sS]pec.js`); jasmine.loadConfig({ spec_dir: '.', diff --git a/docker-compose.yml b/docker-compose.yml index 50c1a9451..645cc2366 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,7 +13,7 @@ services: api: build: . environment: - NODE_ENV: ${NODE_ENV} + - NODE_ENV restart: unless-stopped image: salix-api:${BRANCH_NAME} volumes: diff --git a/smokes_tests.js b/e2e/smokes-tests.js similarity index 95% rename from smokes_tests.js rename to e2e/smokes-tests.js index a9c26446c..942479d35 100644 --- a/smokes_tests.js +++ b/e2e/smokes-tests.js @@ -8,10 +8,9 @@ process.on('warning', warning => { let verbose = false; -if (process.argv[2] === '--v') +if (process.argv[2] === '--v') verbose = true; - let Jasmine = require('jasmine'); let jasmine = new Jasmine(); let SpecReporter = require('jasmine-spec-reporter').SpecReporter; diff --git a/e2e_tests.js b/e2e/tests.js similarity index 100% rename from e2e_tests.js rename to e2e/tests.js diff --git a/front/test_index.js b/front/test-index.js similarity index 100% rename from front/test_index.js rename to front/test-index.js diff --git a/gulpfile.js b/gulpfile.js index 08db729ac..dcdf51ef2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -395,31 +395,16 @@ gulp.task('watch', function() { */ gulp.task('docker', async() => { try { - await execP('docker rm -fv dblocal'); - } catch (e) {} - - await runSequenceP('docker-run'); -}); - -/** - * Rebuilds the docker image, if already exists, destroys and - * rebuild it. calls upon docker task afterwards. - */ -gulp.task('docker-build', async() => { - try { - await execP('docker rm -fv dblocal'); - } catch (e) {} - try { - await execP('docker rmi dblocal:latest'); + await execP('docker rm -fv salix-db'); } catch (e) {} try { await execP('docker volume rm data'); } catch (e) {} log('Building image...'); - await execP('docker build -t dblocal:latest ./services/db'); + await execP('docker build -t salix-db:latest ./services/db'); - await runSequenceP('docker'); + await runSequenceP('docker-run'); }); /** @@ -431,7 +416,7 @@ gulp.task('docker-build', async() => { gulp.task('docker-start', async() => { let state; try { - let result = await execP('docker container inspect -f "{{json .State}}" dblocal'); + let result = await execP('docker container inspect -f "{{json .State}}" salix-db'); state = JSON.parse(result.stdout); } catch (err) { return await runSequenceP('docker-run'); @@ -441,7 +426,9 @@ gulp.task('docker-start', async() => { case 'running': return; case 'exited': - return await execP('docker start dblocal'); + await execP('docker start salix-db'); + await runSequenceP('docker-wait'); + return; default: throw new Error(`Unknown docker status: ${status}`); } @@ -452,11 +439,11 @@ gulp.task('docker-start', async() => { */ gulp.task('docker-run', async() => { try { - await execP('docker image inspect -f "{{json .Id}}" dblocal'); - await execP('docker run -d --name dblocal --volume data:/data -p 3306:3306 dblocal'); + await execP('docker image inspect -f "{{json .Id}}" salix-db'); + await execP('docker run -d --name salix-db --volume ./dist/salix-db:/data -p 3306:3306 salix-db'); await runSequenceP('docker-wait'); } catch (err) { - await runSequenceP('docker-build'); + await runSequenceP('docker'); } }); @@ -478,7 +465,7 @@ gulp.task('docker-wait', callback => { let state; try { - let result = await execP('docker container inspect -f "{{json .State}}" dblocal'); + let result = await execP('docker container inspect -f "{{json .State}}" salix-db'); state = JSON.parse(result.stdout); } catch (err) { return callback(new Error(err.message)); diff --git a/karma.conf.js b/karma.conf.js index 948e5a7c1..addf1dc55 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -22,7 +22,7 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - {pattern: 'front/test_index.js', watched: false} + {pattern: 'front/test-index.js', watched: false} ], // list of files to exclude @@ -41,7 +41,7 @@ module.exports = function(config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - './front/test_index.js': ['webpack', 'sourcemap'] + './front/test-index.js': ['webpack', 'sourcemap'] }, // test results reporter to use diff --git a/package.json b/package.json index 92aa2c14e..c6b700e92 100644 --- a/package.json +++ b/package.json @@ -87,9 +87,9 @@ "url": "https://git.verdnatura.es/salix" }, "scripts": { - "test": "nodemon -q services_tests.js -w services", - "dbtest": "nodemon -q db_tests.js -w services/db/tests", - "lint": "eslint ./ --cache --ignore-pattern .gitignore", - "services": "nodemon --inspect -w services ./node_modules/gulp/bin/gulp.js services" + "test": "nodemon -q back/tests.js -w modules", + "dbtest": "nodemon -q services/db/tests.js -w services/db/tests", + "services": "nodemon --inspect -w modules ./node_modules/gulp/bin/gulp.js services", + "lint": "eslint ./ --cache --ignore-pattern .gitignore" } } diff --git a/services/db/Dockerfile b/services/db/Dockerfile index 6acbcdac4..71febebb0 100644 --- a/services/db/Dockerfile +++ b/services/db/Dockerfile @@ -1,12 +1,27 @@ -FROM verdnatura/vn-mysql:latest +FROM mysql:5.6 + ENV MYSQL_ROOT_PASSWORD root -ENV TZ=Europe/Madrid +ENV TZ Europe/Madrid + +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl ca-certificates \ + && curl -L https://apt.verdnatura.es/conf/verdnatura.gpg | apt-key add - \ + && echo "deb http://apt.verdnatura.es/ jessie main" > /etc/apt/sources.list.d/vn.list \ + && apt-get update \ + && apt-get install -y vn-mysql + +RUN cp /usr/local/bin/docker-entrypoint.sh /usr/local/bin/my-docker-entrypoint.sh \ + && sed -i '$ d' /usr/local/bin/my-docker-entrypoint.sh + WORKDIR /docker-entrypoint-initdb.d -COPY install ./ -RUN chmod -R 777 . -RUN mkdir /data -RUN chmod 777 /data -CMD ["mysqld"] +COPY install /docker-entrypoint-initdb.d +RUN mkdir /mysql-data \ + && chmod 770 /mysql-data + +RUN /usr/local/bin/my-docker-entrypoint.sh mysqld --datadir /mysql-data + +CMD ["mysqld", "--datadir", "/mysql-data"] + #HEALTHCHECK --interval=5s --timeout=10s --retries=200 \ # CMD mysqladmin ping -h 127.0.0.1 -u root || exit 1 -EXPOSE 3306 \ No newline at end of file diff --git a/services/db/docker-entrypoint.sh b/services/db/docker-entrypoint.sh new file mode 100644 index 000000000..f1ec177e5 --- /dev/null +++ b/services/db/docker-entrypoint.sh @@ -0,0 +1,189 @@ +#!/bin/bash +set -eo pipefail +shopt -s nullglob + +# if command starts with an option, prepend mysqld +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# skip setup if they want an option that stops mysqld +wantHelp= +for arg; do + case "$arg" in + -'?'|--help|--print-defaults|-V|--version) + wantHelp=1 + break + ;; + esac +done + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +_check_config() { + toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) + if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then + cat >&2 <<-EOM + ERROR: mysqld failed while attempting to check config + command was: "${toRun[*]}" + $errors + EOM + exit 1 + fi +} + +# Fetch value from server config +# We use mysqld --verbose --help instead of my_print_defaults because the +# latter only show values present in config files, and not server defaults +_get_config() { + local conf="$1"; shift + "$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \ + | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }' + # match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)" +} + +# allow the container to be started with `--user` +if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then + _check_config "$@" + DATADIR="$(_get_config 'datadir' "$@")" + mkdir -p "$DATADIR" + find "$DATADIR" \! -user mysql -exec chown mysql '{}' + + exec gosu mysql "$BASH_SOURCE" "$@" +fi + +if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then + # still need to check config, container may have started with --user + _check_config "$@" + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + file_env 'MYSQL_ROOT_PASSWORD' + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 'error: database is uninitialized and password option is not specified ' + echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD' + exit 1 + fi + + mkdir -p "$DATADIR" + + echo 'Initializing database' + # "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here) + mysql_install_db --datadir="$DATADIR" --rpm "${@:2}" + echo 'Database initialized' + + SOCKET="$(_get_config 'socket' "$@")" + "$@" --skip-networking --socket="${SOCKET}" & + pid="$!" + + mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" ) + + for i in {30..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi + echo 'MySQL init process in progress...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then + # sed is for https://bugs.mysql.com/bug.php?id=20545 + mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql + fi + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)" + echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + + rootCreate= + # default root to listen for connections from anywhere + file_env 'MYSQL_ROOT_HOST' '%' + if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then + # no, we don't care if read finds a terminating character in this heredoc + # https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151 + read -r -d '' rootCreate <<-EOSQL || true + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; + EOSQL + fi + + "${mysql[@]}" <<-EOSQL + -- What's done in this file shouldn't be replicated + -- or products like mysql-fabric won't work + SET @@SESSION.SQL_LOG_BIN=0; + DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ; + SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ; + GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ; + ${rootCreate} + DROP DATABASE IF EXISTS test ; + FLUSH PRIVILEGES ; + EOSQL + + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) + fi + + file_env 'MYSQL_DATABASE' + if [ "$MYSQL_DATABASE" ]; then + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" + mysql+=( "$MYSQL_DATABASE" ) + fi + + file_env 'MYSQL_USER' + file_env 'MYSQL_PASSWORD' + if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then + echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}" + + if [ "$MYSQL_DATABASE" ]; then + echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}" + fi + fi + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + echo + echo 'MySQL init process done. Ready for start up.' + echo + fi +fi + +exec "$@" \ No newline at end of file diff --git a/services/db/install/boot.sh b/services/db/install/boot.sh old mode 100644 new mode 100755 index e63215174..70704c48e --- a/services/db/install/boot.sh +++ b/services/db/install/boot.sh @@ -1,32 +1,24 @@ #!/bin/bash export MYSQL_PWD=root -if [ -d /data/mysql ]; then - cp -R /data/mysql /var/lib - echo "[INFO] -> Restored database to default state" -else - # Dump structure - echo "[INFO] -> Imported ./dump/truncateAll.sql" - mysql -u root -f < ./dump/truncateAll.sql - echo "[INFO] -> Imported ./dump/structure.sql" - mysql -u root -f < ./dump/structure.sql - echo "[INFO] -> Imported ./dump/mysqlPlugins.sql" - mysql -u root -f < ./dump/mysqlPlugins.sql +# Dump structure +echo "[INFO] -> Imported ./dump/truncateAll.sql" + mysql -u root -f < ./dump/truncateAll.sql +echo "[INFO] -> Imported ./dump/structure.sql" + mysql -u root -f < ./dump/structure.sql +echo "[INFO] -> Imported ./dump/mysqlPlugins.sql" + mysql -u root -f < ./dump/mysqlPlugins.sql - # Import changes - for file in changes/*/*.sql; do - echo "[INFO] -> Imported ./$file" - mysql -u root -fc < $file - done +# Import changes +for file in changes/*/*.sql; do + echo "[INFO] -> Imported ./$file" + mysql -u root -fc < $file +done - # Import fixtures - echo "[INFO] -> Imported ./dump/dumpedFixtures.sql" - mysql -u root -f < ./dump/dumpedFixtures.sql - echo "[INFO] -> Imported ./dump/fixtures.sql" - mysql -u root -f < ./dump/fixtures.sql +# Import fixtures +echo "[INFO] -> Imported ./dump/dumpedFixtures.sql" +mysql -u root -f < ./dump/dumpedFixtures.sql +echo "[INFO] -> Imported ./dump/fixtures.sql" +mysql -u root -f < ./dump/fixtures.sql - # Copy dumpted data to volume - cp -R /var/lib/mysql /data - - echo "[INFO] -> Dumped database" -fi \ No newline at end of file +echo "[INFO] -> Dumped database" diff --git a/db_tests.js b/services/db/tests.js similarity index 89% rename from db_tests.js rename to services/db/tests.js index a20d26bb6..88bac1488 100644 --- a/db_tests.js +++ b/services/db/tests.js @@ -9,14 +9,14 @@ let verbose = false; if (process.argv[2] === '--v') verbose = true; -loopbackApp = `${__dirname}/loopback/server/server`; +serviceRoot = __dirname; let Jasmine = require('jasmine'); let jasmine = new Jasmine(); let SpecReporter = require('jasmine-spec-reporter').SpecReporter; let serviceSpecs = [ - 'db/tests/**/*[sS]pec.js' + './db/tests/**/*[sS]pec.js' ]; jasmine.loadConfig({ diff --git a/services/nginx/Dockerfile b/services/nginx/Dockerfile index dce275b08..08f65d9fe 100644 --- a/services/nginx/Dockerfile +++ b/services/nginx/Dockerfile @@ -7,13 +7,13 @@ RUN apt-get update \ && apt-get install -y apt-utils \ && apt-get install -y --no-install-recommends nginx +RUN ln -sf /dev/stdout /var/log/nginx/access.log \ + && ln -sf /dev/stderr /var/log/nginx/error.log + WORKDIR /etc/nginx COPY services/nginx/temp/nginx.conf sites-available/salix RUN rm sites-enabled/default && ln -s ../sites-available/salix sites-enabled/salix -RUN ln -sf /dev/stdout /var/log/nginx/access.log \ - && ln -sf /dev/stderr /var/log/nginx/error.log - COPY dist /salix/dist CMD ["nginx", "-g", "daemon off;"]