diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/Dockerfile.db-create b/Dockerfile.db-create new file mode 100644 index 0000000..0239417 --- /dev/null +++ b/Dockerfile.db-create @@ -0,0 +1,10 @@ +FROM node:16 +WORKDIR /opt/app/ +COPY package.json ./ +RUN npm install +RUN npm prune +COPY . /opt/app +ARG NODE_ENV +ENV NODE_ENV $NODE_ENV + +CMD [ "npm", "run", "upgrade-db" ] \ No newline at end of file diff --git a/db/jambones-sql.sql b/db/jambones-sql.sql index 16fd530..b157f3a 100644 --- a/db/jambones-sql.sql +++ b/db/jambones-sql.sql @@ -28,6 +28,8 @@ DROP TABLE IF EXISTS account_offers; DROP TABLE IF EXISTS products; +DROP TABLE IF EXISTS schema_version; + DROP TABLE IF EXISTS api_keys; DROP TABLE IF EXISTS sbc_addresses; @@ -190,6 +192,11 @@ stripe_product_id VARCHAR(56) NOT NULL, PRIMARY KEY (account_offer_sid) ); +CREATE TABLE schema_version +( +version VARCHAR(16) +); + CREATE TABLE api_keys ( api_key_sid CHAR(36) NOT NULL UNIQUE , @@ -565,4 +572,4 @@ ALTER TABLE accounts ADD FOREIGN KEY queue_event_hook_sid_idxfk (queue_event_hoo ALTER TABLE accounts ADD FOREIGN KEY device_calling_application_sid_idxfk (device_calling_application_sid) REFERENCES applications (application_sid); -SET FOREIGN_KEY_CHECKS=1; +SET FOREIGN_KEY_CHECKS=0; diff --git a/db/jambones.sqs b/db/jambones.sqs index b8c40db..a6087ac 100644 --- a/db/jambones.sqs +++ b/db/jambones.sqs @@ -87,7 +87,7 @@ - + @@ -148,7 +148,7 @@ - + @@ -225,7 +225,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -426,7 +426,7 @@ - + @@ -492,7 +492,7 @@ - + @@ -670,7 +670,7 @@ - + @@ -752,7 +752,7 @@ - + @@ -880,10 +880,29 @@ - + + + + + + 2131.00 + 136.00 + + + 159.00 + 40.00 + + 28 + + + + + + + @@ -941,7 +960,7 @@ - + @@ -991,7 +1010,7 @@ - + @@ -1091,7 +1110,7 @@ - + @@ -1160,7 +1179,7 @@ - + @@ -1197,7 +1216,7 @@ - + @@ -1306,7 +1325,7 @@ - + @@ -1376,7 +1395,7 @@ - + @@ -1536,7 +1555,7 @@ - + @@ -1575,7 +1594,7 @@ - + @@ -1667,7 +1686,7 @@ - + @@ -1718,7 +1737,7 @@ - + @@ -1814,7 +1833,7 @@ - + @@ -1914,7 +1933,7 @@ - + @@ -2083,7 +2102,7 @@ - + @@ -2191,7 +2210,7 @@ - + @@ -2261,7 +2280,7 @@ - + @@ -2306,7 +2325,7 @@ - + @@ -2373,7 +2392,7 @@ - + @@ -2381,7 +2400,7 @@ - + @@ -2392,17 +2411,17 @@ - + - - - - - + + + + + diff --git a/db/upgrade-jambonz-db.js b/db/upgrade-jambonz-db.js new file mode 100644 index 0000000..17297cb --- /dev/null +++ b/db/upgrade-jambonz-db.js @@ -0,0 +1,71 @@ +#!/usr/bin/env node +const assert = require('assert'); +const mysql = require('mysql2/promise'); +const {readFile} = require('fs/promises'); +const {execSync} = require('child_process'); +const {version:desiredVersion} = require('../package.json'); +const logger = require('pino')(); + +logger.info(`upgrade-jambonz-db: desired version ${desiredVersion}`); + +assert.ok(process.env.JAMBONES_MYSQL_HOST, 'missing env JAMBONES_MYSQL_HOST'); +assert.ok(process.env.JAMBONES_MYSQL_DATABASE, 'missing env JAMBONES_MYSQL_DATABASE'); +assert.ok(process.env.JAMBONES_MYSQL_PASSWORD, 'missing env JAMBONES_MYSQL_PASSWORD'); +assert.ok(process.env.JAMBONES_MYSQL_USER, 'missing env JAMBONES_MYSQL_USER'); + +const doIt = async () => { + let connection; + try { + connection = await mysql.createConnection({ + host: process.env.JAMBONES_MYSQL_HOST, + user: process.env.JAMBONES_MYSQL_USER, + password: process.env.JAMBONES_MYSQL_PASSWORD, + database: process.env.JAMBONES_MYSQL_DATABASE, + port: process.env.JAMBONES_MYSQL_PORT || 3306, + multipleStatements: true + }); + } catch (err) { + logger.error({err}, 'Error connecting to database with provided env vars'); + return; + } + + try { + /* does the schema exist at all ? */ + const [r] = await connection.execute('SELECT version from schema_version'); + if (r.length) { + //TODO: check against desired version and perform upgrades + logger.info(`current version is ${r[0].version}, no upgrade will be performed`); + await connection.end(); + return; + } + } catch (err) { + } + try { + await createSchema(connection); + await seedDatabase(connection); + logger.info('reset admin password..'); + execSync(`${__dirname}/../db/reset_admin_password.js`); + await connection.query(`INSERT into schema_version (version) values('${desiredVersion}')`); + logger.info('database install/upgrade complete.'); + await connection.end(); + } catch (err) { + logger.error({err}, 'Error seeding database'); + process.exit(1); + } +}; + +const createSchema = async(connection) => { + logger.info('reading schema..'); + const sql = await readFile(`${__dirname}/../db/jambones-sql.sql`, {encoding: 'utf8'}); + logger.info('creating schema..'); + await connection.query(sql); +}; + +const seedDatabase = async(connection) => { + const sql = await readFile(`${__dirname}/../db/seed-production-database-open-source.sql`, {encoding: 'utf8'}); + logger.info('seeding data..'); + await connection.query(sql); +}; + +doIt(); + diff --git a/package.json b/package.json index 393ace4..f7c9af9 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "start": "node app.js", "test": "NODE_ENV=test APPLY_JAMBONZ_DB_LIMITS=1 JWT_SECRET=foobarbazzle JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_PORT=3360 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_TIME_SERIES_HOST=127.0.0.1 JAMBONES_LOGLEVEL=error JAMBONES_CREATE_CALL_URL=http://localhost/v1/createCall node test/ ", "integration-test": "NODE_ENV=test JAMBONES_TIME_SERIES_HOST=127.0.0.1 AWS_REGION='us-east-1' JAMBONES_CURRENCY=USD JWT_SECRET=foobarbazzle JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_PORT=3360 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=debug JAMBONES_CREATE_CALL_URL=http://localhost/v1/createCall node test/serve-integration.js", + "upgrade-db": "node ./db/upgrade-jambonz-db.js", "coverage": "./node_modules/.bin/nyc --reporter html --report-dir ./coverage npm run test", "jslint": "eslint app.js lib" },