From 81966446d97b3989e65be22b7d2dec379d3bcb32 Mon Sep 17 00:00:00 2001 From: Pagan Gazzard Date: Mon, 23 Mar 2020 18:42:27 +0000 Subject: [PATCH] Update to balena-lint and enable javascript linting Change-type: patch --- .lintstagedrc | 2 +- package-lock.json | 129 +++--- package.json | 8 +- src/migrations/20171129013519_legacy.js | 258 +++++------ .../20171129064057_multicontainer.js | 401 +++++++++--------- .../20171214172530_image_docker_id.js | 14 +- .../20180516164000-endpoint-specific-apps.js | 38 +- ...907164000-endpoint-specific-logschannel.js | 39 +- .../20190619152500-engine-snapshot.js | 7 +- src/migrations/M00000.js | 13 +- src/migrations/M00001.js | 45 +- src/migrations/M00002.js | 16 +- tools/dind/balenaos-in-container | 2 +- tslint.json | 2 +- webpack.config.js | 3 +- 15 files changed, 531 insertions(+), 446 deletions(-) diff --git a/.lintstagedrc b/.lintstagedrc index 9bf58ae7..e877f3f7 100644 --- a/.lintstagedrc +++ b/.lintstagedrc @@ -2,7 +2,7 @@ "*.coffee": [ "resin-lint" ], - "*.ts": [ + "*.ts$|!(*webpack.config).js$": [ "resin-lint --typescript --fix", ], "test/**/*.coffee": [ diff --git a/package-lock.json b/package-lock.json index 81aee9f8..39b5a63b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -82,6 +82,71 @@ } } }, + "@balena/lint": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@balena/lint/-/lint-4.1.0.tgz", + "integrity": "sha512-5db6EhVYblBh70J8k9LZYww1ntd3xwL/4hkysyB70itS/wBQLIMqGIVaiqfpayN61mYdbs24Fm5ijgDkhT4OLQ==", + "dev": true, + "requires": { + "@types/depcheck": "^0.6.0", + "@types/glob": "^7.1.1", + "@types/lodash": "^4.14.149", + "@types/node": "^8.10.59", + "@types/optimist": "0.0.29", + "@types/prettier": "^1.18.3", + "coffee-script": "^1.10.0", + "coffeelint": "^1.15.0", + "coffeescope2": "^0.4.5", + "depcheck": "^0.6.7", + "glob": "^7.1.6", + "lodash": "^4.17.15", + "optimist": "^0.6.1", + "prettier": "^1.19.1", + "tslint": "^5.20.1", + "tslint-config-prettier": "^1.18.0", + "tslint-no-unused-expression-chai": "^0.1.4", + "typescript": "^3.7.5" + }, + "dependencies": { + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/node": { + "version": "8.10.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz", + "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==", + "dev": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "@resin.io/types-hidepath": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@resin.io/types-hidepath/-/types-hidepath-1.0.1.tgz", @@ -398,9 +463,9 @@ "dev": true }, "@types/prettier": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.0.tgz", - "integrity": "sha512-gDE8JJEygpay7IjA/u3JiIURvwZW08f0cZSZLAzFoX/ZmeqvS0Sqv+97aKuHpNsalAMMhwPe+iAS6fQbfmbt7A==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==", "dev": true }, "@types/range-parser": { @@ -6363,7 +6428,7 @@ "dependencies": { "ansi-escapes": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, @@ -7059,7 +7124,7 @@ }, "chalk": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { @@ -9673,60 +9738,6 @@ "lodash": "^4.0.0" } }, - "resin-lint": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/resin-lint/-/resin-lint-3.2.4.tgz", - "integrity": "sha512-VtsEAG8fgSkZMnZ2CPLtukEqJMjFBSya8T//AjUHGEqFr/M8aUfdSZvIXq8vVFholaCMW84XBmVu9zWK8H0arg==", - "dev": true, - "requires": { - "@types/depcheck": "^0.6.0", - "@types/glob": "^5.0.35", - "@types/lodash": "^4.14.149", - "@types/node": "^8.10.59", - "@types/optimist": "0.0.29", - "@types/prettier": "^1.18.3", - "coffee-script": "^1.10.0", - "coffeelint": "^1.15.0", - "coffeescope2": "^0.4.5", - "depcheck": "^0.6.7", - "glob": "^7.1.6", - "lodash": "^4.17.15", - "optimist": "^0.6.1", - "prettier": "^1.19.1", - "tslint": "^5.20.1", - "tslint-config-prettier": "^1.18.0", - "tslint-no-unused-expression-chai": "^0.1.4", - "typescript": "^3.7.5" - }, - "dependencies": { - "@types/node": { - "version": "8.10.59", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz", - "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==", - "dev": true - }, - "coffee-script": { - "version": "1.12.7", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", - "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "resin-register-device": { "version": "3.0.0", "resolved": "http://registry.npmjs.org/resin-register-device/-/resin-register-device-3.0.0.tgz", diff --git a/package.json b/package.json index 93ca4947..a97a334d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "coverage": "istanbul report text && istanbul report html", "test:fast": "TEST=1 mocha --opts test/fast-mocha.opts", "test:debug": "npm run test:build && TEST=1 mocha --inspect-brk", - "prettify": "resin-lint --typescript --fix src/ test/ typings/", + "prettify": "balena-lint -e ts -e js --typescript --fix src/ test/ typings/ webpack.config.js", "typescript:test-build": "tsc --project tsconfig.json", "typescript:release": "tsc --project tsconfig.release.json && cp -r build/src/* build && rm -rf build/src", "coffeescript:test": "coffee -m -c -o build .", @@ -26,8 +26,8 @@ "migrations:copy-test": "cp -r src/migrations build/src", "packagejson:copy": "cp package.json build/", "testitems:copy": "cp -r test/data build/test/", - "lint:coffee": "resin-lint src/ test/", - "lint:typescript": "resin-lint --typescript src/ test/ typings/ && tsc --noEmit" + "lint:coffee": "balena-lint src/ test/", + "lint:typescript": "balena-lint -e ts -e js --typescript src/ test/ typings/ && tsc --noEmit" }, "private": true, "dependencies": { @@ -38,6 +38,7 @@ }, "devDependencies": { "@balena/contrato": "^0.2.1", + "@balena/lint": "^4.1.0", "@types/bluebird": "^3.5.30", "@types/chai": "^4.2.10", "@types/chai-as-promised": "^7.1.2", @@ -104,7 +105,6 @@ "pinejs-client-request": "^5.2.0", "pretty-ms": "^5.1.0", "request": "^2.88.2", - "resin-lint": "^3.2.4", "resin-register-device": "^3.0.0", "resumable-request": "^2.0.0", "rimraf": "^2.6.2", diff --git a/src/migrations/20171129013519_legacy.js b/src/migrations/20171129013519_legacy.js index ab96718f..7f9f63ed 100644 --- a/src/migrations/20171129013519_legacy.js +++ b/src/migrations/20171129013519_legacy.js @@ -7,130 +7,150 @@ // a few dropColumn and dropTable calls to delete things that were removed throughout the supervisor's // history without actually adding drop statements (mostly just becoming unused, but still there). -exports.up = function (knex, Promise) { - const addColumn = function (table, column, type) { - return knex.schema.hasColumn(table, column) - .then((exists) => { - if (!exists) { - return knex.schema.table(table, (t) => { return t[type](column) }) - } - }) - } - const dropColumn = function (table, column) { - return knex.schema.hasColumn(table, column) - .then((exists) => { - if (exists) { - return knex.schema.table(table, (t) => { return t.dropColumn(column) }) - } - }) - } - const createTableOrRun = function (tableName, tableCreator, runIfTableExists) { - return knex.schema.hasTable(tableName) - .then((exists) => { - if (!exists) { - return knex.schema.createTable(tableName, tableCreator) - } else if (runIfTableExists != null) { - return runIfTableExists() - } - }) - } - const dropTable = function (tableName) { - return knex.schema.hasTable(tableName) - .then((exists) => { - if (exists) { - return knex.schema.dropTable(tableName) - } - }) - } +exports.up = function(knex, Promise) { + const addColumn = function(table, column, type) { + return knex.schema.hasColumn(table, column).then(exists => { + if (!exists) { + return knex.schema.table(table, t => { + return t[type](column); + }); + } + }); + }; + const dropColumn = function(table, column) { + return knex.schema.hasColumn(table, column).then(exists => { + if (exists) { + return knex.schema.table(table, t => { + return t.dropColumn(column); + }); + } + }); + }; + const createTableOrRun = function(tableName, tableCreator, runIfTableExists) { + return knex.schema.hasTable(tableName).then(exists => { + if (!exists) { + return knex.schema.createTable(tableName, tableCreator); + } else if (runIfTableExists != null) { + return runIfTableExists(); + } + }); + }; + const dropTable = function(tableName) { + return knex.schema.hasTable(tableName).then(exists => { + if (exists) { + return knex.schema.dropTable(tableName); + } + }); + }; return Promise.all([ - createTableOrRun('config', (t) => { - t.string('key').primary() - t.string('value') + createTableOrRun('config', t => { + t.string('key').primary(); + t.string('value'); }), - createTableOrRun('deviceConfig', (t) => { - t.json('values') - t.json('targetValues') + createTableOrRun('deviceConfig', t => { + t.json('values'); + t.json('targetValues'); }).then(() => { - return knex('deviceConfig').select() - .then((deviceConfigs) => { - if (deviceConfigs.length == 0) { - return knex('deviceConfig').insert({ values: '{}', targetValues: '{}' }) + return knex('deviceConfig') + .select() + .then(deviceConfigs => { + if (deviceConfigs.length === 0) { + return knex('deviceConfig').insert({ + values: '{}', + targetValues: '{}', + }); } - }) - }), - createTableOrRun('app', (t) => { - t.increments('id').primary() - t.string('name') - t.string('containerName') - t.string('commit') - t.string('imageId') - t.string('appId') - t.boolean('privileged') - t.json('env') - t.json('config') - t.boolean('markedForDeletion') - }, () => { - return Promise.all([ - addColumn('app', 'commit', 'string'), - addColumn('app', 'appId', 'string'), - addColumn('app', 'containerName', 'string'), - addColumn('app', 'config', 'json'), - addColumn('app', 'markedForDeletion', 'boolean'), - dropColumn('app', 'containerId') - ]).then(() => { - //When updating from older supervisors, config can be null - return knex('app').update({ config: '{}' }).whereNull('config') - .then(() => { - knex('app').update({ markedForDeletion: false }).whereNull('markedForDeletion') - }) - }) - }), - createTableOrRun('dependentApp', (t) => { - t.increments('id').primary() - t.string('appId') - t.string('parentAppId') - t.string('name') - t.string('commit') - t.string('imageId') - t.json('config') - t.json('environment') - }, () => { - return addColumn('dependentApp', 'environment', 'json') - }), - createTableOrRun('dependentDevice', (t) => { - t.increments('id').primary() - t.string('uuid') - t.string('appId') - t.string('localId') - t.string('device_type') - t.string('logs_channel') - t.string('deviceId') - t.boolean('is_online') - t.string('name') - t.string('status') - t.string('download_progress') - t.string('is_managed_by') - t.dateTime('lock_expiry_date') - t.string('commit') - t.string('targetCommit') - t.json('environment') - t.json('targetEnvironment') - t.json('config') - t.json('targetConfig') - t.boolean('markedForDeletion') - }, () => { - return Promise.all([ - addColumn('dependentDevice', 'markedForDeletion', 'boolean'), - addColumn('dependentDevice', 'localId', 'string'), - addColumn('dependentDevice', 'is_managed_by', 'string'), - addColumn('dependentDevice', 'lock_expiry_date', 'dateTime') - ]) + }); }), + createTableOrRun( + 'app', + t => { + t.increments('id').primary(); + t.string('name'); + t.string('containerName'); + t.string('commit'); + t.string('imageId'); + t.string('appId'); + t.boolean('privileged'); + t.json('env'); + t.json('config'); + t.boolean('markedForDeletion'); + }, + () => { + return Promise.all([ + addColumn('app', 'commit', 'string'), + addColumn('app', 'appId', 'string'), + addColumn('app', 'containerName', 'string'), + addColumn('app', 'config', 'json'), + addColumn('app', 'markedForDeletion', 'boolean'), + dropColumn('app', 'containerId'), + ]).then(() => { + //When updating from older supervisors, config can be null + return knex('app') + .update({ config: '{}' }) + .whereNull('config') + .then(() => { + knex('app') + .update({ markedForDeletion: false }) + .whereNull('markedForDeletion'); + }); + }); + }, + ), + createTableOrRun( + 'dependentApp', + t => { + t.increments('id').primary(); + t.string('appId'); + t.string('parentAppId'); + t.string('name'); + t.string('commit'); + t.string('imageId'); + t.json('config'); + t.json('environment'); + }, + () => { + return addColumn('dependentApp', 'environment', 'json'); + }, + ), + createTableOrRun( + 'dependentDevice', + t => { + t.increments('id').primary(); + t.string('uuid'); + t.string('appId'); + t.string('localId'); + t.string('device_type'); + t.string('logs_channel'); + t.string('deviceId'); + t.boolean('is_online'); + t.string('name'); + t.string('status'); + t.string('download_progress'); + t.string('is_managed_by'); + t.dateTime('lock_expiry_date'); + t.string('commit'); + t.string('targetCommit'); + t.json('environment'); + t.json('targetEnvironment'); + t.json('config'); + t.json('targetConfig'); + t.boolean('markedForDeletion'); + }, + () => { + return Promise.all([ + addColumn('dependentDevice', 'markedForDeletion', 'boolean'), + addColumn('dependentDevice', 'localId', 'string'), + addColumn('dependentDevice', 'is_managed_by', 'string'), + addColumn('dependentDevice', 'lock_expiry_date', 'dateTime'), + ]); + }, + ), dropTable('image'), - dropTable('container') - ]) -} + dropTable('container'), + ]); +}; exports.down = function(knex, Promise) { - return Promise.reject(new Error('Not implemented')) -} + return Promise.reject(new Error('Not implemented')); +}; diff --git a/src/migrations/20171129064057_multicontainer.js b/src/migrations/20171129064057_multicontainer.js index a7750750..b18f4d49 100644 --- a/src/migrations/20171129064057_multicontainer.js +++ b/src/migrations/20171129064057_multicontainer.js @@ -1,24 +1,23 @@ -const _ = require('lodash') +const _ = require('lodash'); -var tryParse = function (obj) { +var tryParse = function(obj) { try { - return JSON.parse(obj) + return JSON.parse(obj); + } catch (e) { + return {}; } - catch(e) { - return {} - } -} +}; -var singleToMulticontainerApp = function (app) { +var singleToMulticontainerApp = function(app) { // From *very* old supervisors, env or config may be null // so we ignore errors parsing them - const conf = tryParse(app.config) - const env = tryParse(app.env) - const environment = {} - const appId = parseInt(app.appId) + const conf = tryParse(app.config); + const env = tryParse(app.env); + const environment = {}; + const appId = parseInt(app.appId, 10); for (let key in env) { if (!/^RESIN_/.test(key)) { - environment[key] = env[key] + environment[key] = env[key]; } } const newApp = { @@ -27,13 +26,17 @@ var singleToMulticontainerApp = function (app) { name: app.name, releaseId: 1, networks: {}, - volumes: {} - } - const defaultVolume = 'resin-data' - newApp.volumes[defaultVolume] = {} - const updateStrategy = _.get(conf, 'RESIN_SUPERVISOR_UPDATE_STRATEGY', 'download-then-kill') - const handoverTimeout = _.get(conf, 'RESIN_SUPERVISOR_HANDOVER_TIMEOUT', '') - const restartPolicy = _.get(conf, 'RESIN_APP_RESTART_POLICY', 'always') + volumes: {}, + }; + const defaultVolume = 'resin-data'; + newApp.volumes[defaultVolume] = {}; + const updateStrategy = _.get( + conf, + 'RESIN_SUPERVISOR_UPDATE_STRATEGY', + 'download-then-kill', + ); + const handoverTimeout = _.get(conf, 'RESIN_SUPERVISOR_HANDOVER_TIMEOUT', ''); + const restartPolicy = _.get(conf, 'RESIN_APP_RESTART_POLICY', 'always'); newApp.services = [ { serviceId: 1, @@ -45,9 +48,7 @@ var singleToMulticontainerApp = function (app) { image: app.imageId, privileged: true, networkMode: 'host', - volumes: [ - `${defaultVolume}:/data` - ], + volumes: [`${defaultVolume}:/data`], labels: { 'io.resin.features.kernel-modules': '1', 'io.resin.features.firmware': '1', @@ -56,26 +57,26 @@ var singleToMulticontainerApp = function (app) { 'io.resin.features.resin-api': '1', 'io.resin.update.strategy': updateStrategy, 'io.resin.update.handover-timeout': handoverTimeout, - 'io.resin.legacy-container': '1' + 'io.resin.legacy-container': '1', }, environment: environment, restart: restartPolicy, - running: true - } - ] - return newApp -} + running: true, + }, + ]; + return newApp; +}; -var jsonifyAppFields = function (app) { - const newApp = _.clone(app) - newApp.services = JSON.stringify(app.services) - newApp.networks = JSON.stringify(app.networks) - newApp.volumes = JSON.stringify(app.volumes) - return newApp -} +var jsonifyAppFields = function(app) { + const newApp = _.clone(app); + newApp.services = JSON.stringify(app.services); + newApp.networks = JSON.stringify(app.networks); + newApp.volumes = JSON.stringify(app.volumes); + return newApp; +}; -var imageForApp = function (app) { - const service = app.services[0] +var imageForApp = function(app) { + const service = app.services[0]; return { name: service.image, appId: service.appId, @@ -83,11 +84,11 @@ var imageForApp = function (app) { serviceName: service.serviceName, imageId: service.imageId, releaseId: service.releaseId, - dependent: 0 - } -} + dependent: 0, + }; +}; -var imageForDependentApp = function (app) { +var imageForDependentApp = function(app) { return { name: app.image, appId: app.appId, @@ -95,203 +96,225 @@ var imageForDependentApp = function (app) { serviceName: null, imageId: app.imageId, releaseId: null, - dependent: 1 - } -} + dependent: 1, + }; +}; // TODO: this whole thing is WIP -exports.up = function (knex, Promise) { - return knex.schema.createTable('image', (t) => { - t.increments('id').primary() - t.string('name') - t.integer('appId') - t.integer('serviceId') - t.string('serviceName') - t.integer('imageId') - t.integer('releaseId') - t.boolean('dependent') +exports.up = function(knex, Promise) { + return knex.schema + .createTable('image', t => { + t.increments('id').primary(); + t.string('name'); + t.integer('appId'); + t.integer('serviceId'); + t.string('serviceName'); + t.integer('imageId'); + t.integer('releaseId'); + t.boolean('dependent'); }) - .then(() => knex('app').select().whereNot({ markedForDeletion: true }).orWhereNull('markedForDeletion')) - .tap((apps) => { + .then(() => + knex('app') + .select() + .whereNot({ markedForDeletion: true }) + .orWhereNull('markedForDeletion'), + ) + .tap(apps => { if (apps.length > 0) { - return knex('config').insert({ key: 'legacyAppsPresent', value: 'true' }) + return knex('config').insert({ + key: 'legacyAppsPresent', + value: 'true', + }); } }) .tap(() => { // We're in a transaction, and it's easier to drop and recreate // than to migrate each field... - return knex.schema.dropTable('app') - .then(() => { - return knex.schema.createTable('app', (t) => { - t.increments('id').primary() - t.string('name') - t.integer('releaseId') - t.string('commit') - t.integer('appId') - t.json('services') - t.json('networks') - t.json('volumes') - }) - }) + return knex.schema.dropTable('app').then(() => { + return knex.schema.createTable('app', t => { + t.increments('id').primary(); + t.string('name'); + t.integer('releaseId'); + t.string('commit'); + t.integer('appId'); + t.json('services'); + t.json('networks'); + t.json('volumes'); + }); + }); }) - .map((app) => { - const migratedApp = singleToMulticontainerApp(app) - return knex('app').insert(jsonifyAppFields(migratedApp)) - .then(() => knex('image').insert(imageForApp(migratedApp))) + .map(app => { + const migratedApp = singleToMulticontainerApp(app); + return knex('app') + .insert(jsonifyAppFields(migratedApp)) + .then(() => knex('image').insert(imageForApp(migratedApp))); }) .then(() => { // For some reason dropping a column in this table doesn't work. Anyways, we don't want to store old targetValues. // Instead, on first run the supervisor will store current device config values as targets - so we want to // make the old values that refer to supervisor config be the *current* values, and we do that by inserting // to the config table. - return knex('deviceConfig').select() - .then((deviceConf) => { - return knex.schema.dropTable('deviceConfig') - .then(() => { - const values = JSON.parse(deviceConf[0].values) - const configKeys = { - 'RESIN_SUPERVISOR_POLL_INTERVAL': 'appUpdatePollInterval', - 'RESIN_SUPERVISOR_LOCAL_MODE': 'localMode', - 'RESIN_SUPERVISOR_CONNECTIVITY_CHECK': 'connectivityCheckEnabled', - 'RESIN_SUPERVISOR_LOG_CONTROL': 'loggingEnabled', - 'RESIN_SUPERVISOR_DELTA': 'delta', - 'RESIN_SUPERVISOR_DELTA_REQUEST_TIMEOUT': 'deltaRequestTimeout', - 'RESIN_SUPERVISOR_DELTA_APPLY_TIMEOUT': 'deltaApplyTimeout', - 'RESIN_SUPERVISOR_DELTA_RETRY_COUNT': 'deltaRetryCount', - 'RESIN_SUPERVISOR_DELTA_RETRY_INTERVAL': 'deltaRequestTimeout', - 'RESIN_SUPERVISOR_OVERRIDE_LOCK': 'lockOverride' + return knex('deviceConfig') + .select() + .then(deviceConf => { + return knex.schema.dropTable('deviceConfig').then(() => { + const values = JSON.parse(deviceConf[0].values); + const configKeys = { + RESIN_SUPERVISOR_POLL_INTERVAL: 'appUpdatePollInterval', + RESIN_SUPERVISOR_LOCAL_MODE: 'localMode', + RESIN_SUPERVISOR_CONNECTIVITY_CHECK: 'connectivityCheckEnabled', + RESIN_SUPERVISOR_LOG_CONTROL: 'loggingEnabled', + RESIN_SUPERVISOR_DELTA: 'delta', + RESIN_SUPERVISOR_DELTA_REQUEST_TIMEOUT: 'deltaRequestTimeout', + RESIN_SUPERVISOR_DELTA_APPLY_TIMEOUT: 'deltaApplyTimeout', + RESIN_SUPERVISOR_DELTA_RETRY_COUNT: 'deltaRetryCount', + RESIN_SUPERVISOR_DELTA_RETRY_INTERVAL: 'deltaRequestTimeout', + RESIN_SUPERVISOR_OVERRIDE_LOCK: 'lockOverride', + }; + return Promise.map(Object.keys(values), envVarName => { + if (configKeys[envVarName] != null) { + return knex('config').insert({ + key: configKeys[envVarName], + value: values[envVarName], + }); } - return Promise.map(Object.keys(values), (envVarName) => { - if (configKeys[envVarName] != null) { - return knex('config').insert({ key: configKeys[envVarName], value: values[envVarName]}) - } - }) - }) + }); + }); }) .then(() => { - return knex.schema.createTable('deviceConfig', (t) => { - t.json('targetValues') - }) + return knex.schema.createTable('deviceConfig', t => { + t.json('targetValues'); + }); }) - .then(() => knex('deviceConfig').insert({ targetValues: '{}' })) + .then(() => knex('deviceConfig').insert({ targetValues: '{}' })); }) .then(() => knex('dependentApp').select()) - .then((dependentApps) => { - return knex.schema.dropTable('dependentApp') + .then(dependentApps => { + return knex.schema + .dropTable('dependentApp') .then(() => { - return knex.schema.createTable('dependentApp', (t) => { - t.increments('id').primary() - t.integer('appId') - t.integer('parentApp') - t.string('name') - t.string('commit') - t.integer('releaseId') - t.integer('imageId') - t.string('image') - t.json('environment') - t.json('config') - }) + return knex.schema.createTable('dependentApp', t => { + t.increments('id').primary(); + t.integer('appId'); + t.integer('parentApp'); + t.string('name'); + t.string('commit'); + t.integer('releaseId'); + t.integer('imageId'); + t.string('image'); + t.json('environment'); + t.json('config'); + }); }) .then(() => { - return knex.schema.createTable('dependentAppTarget', (t) => { - t.increments('id').primary() - t.integer('appId') - t.integer('parentApp') - t.string('name') - t.string('commit') - t.integer('releaseId') - t.integer('imageId') - t.string('image') - t.json('environment') - t.json('config') - }) + return knex.schema.createTable('dependentAppTarget', t => { + t.increments('id').primary(); + t.integer('appId'); + t.integer('parentApp'); + t.string('name'); + t.string('commit'); + t.integer('releaseId'); + t.integer('imageId'); + t.string('image'); + t.json('environment'); + t.json('config'); + }); }) .then(() => { - return Promise.map(dependentApps, (app) => { + return Promise.map(dependentApps, app => { const newApp = { - appId: parseInt(app.appId), - parentApp: parseInt(app.parentAppId), + appId: parseInt(app.appId, 10), + parentApp: parseInt(app.parentAppId, 10), image: app.imageId, releaseId: null, commit: app.commit, name: app.name, config: JSON.stringify(tryParse(app.config)), - environment: JSON.stringify(tryParse(app.environment)) - } - const image = imageForDependentApp(newApp) - return knex('image').insert(image) + environment: JSON.stringify(tryParse(app.environment)), + }; + const image = imageForDependentApp(newApp); + return knex('image') + .insert(image) .then(() => knex('dependentApp').insert(newApp)) - .then(() => knex('dependentAppTarget').insert(newApp)) - }) - }) + .then(() => knex('dependentAppTarget').insert(newApp)); + }); + }); }) .then(() => knex('dependentDevice').select()) - .then((dependentDevices) => { - return knex.schema.dropTable('dependentDevice') + .then(dependentDevices => { + return knex.schema + .dropTable('dependentDevice') .then(() => { - return knex.schema.createTable('dependentDevice', (t) => { - t.increments('id').primary() - t.string('uuid') - t.integer('appId') - t.string('localId') - t.string('device_type') - t.string('logs_channel') - t.integer('deviceId') - t.boolean('is_online') - t.string('name') - t.string('status') - t.string('download_progress') - t.integer('is_managed_by') - t.dateTime('lock_expiry_date') - t.string('commit') - t.string('targetCommit') - t.json('environment') - t.json('targetEnvironment') - t.json('config') - t.json('targetConfig') - t.boolean('markedForDeletion') - }) + return knex.schema.createTable('dependentDevice', t => { + t.increments('id').primary(); + t.string('uuid'); + t.integer('appId'); + t.string('localId'); + t.string('device_type'); + t.string('logs_channel'); + t.integer('deviceId'); + t.boolean('is_online'); + t.string('name'); + t.string('status'); + t.string('download_progress'); + t.integer('is_managed_by'); + t.dateTime('lock_expiry_date'); + t.string('commit'); + t.string('targetCommit'); + t.json('environment'); + t.json('targetEnvironment'); + t.json('config'); + t.json('targetConfig'); + t.boolean('markedForDeletion'); + }); }) .then(() => { - return knex.schema.createTable('dependentDeviceTarget', (t) => { - t.increments('id').primary() - t.string('uuid') - t.string('name') - t.json('apps') - }) + return knex.schema.createTable('dependentDeviceTarget', t => { + t.increments('id').primary(); + t.string('uuid'); + t.string('name'); + t.json('apps'); + }); }) .then(() => { - return Promise.map(dependentDevices, (device) => { - const newDevice = _.clone(device) - newDevice.appId = parseInt(device.appId) - newDevice.deviceId = parseInt(device.deviceId) + return Promise.map(dependentDevices, device => { + const newDevice = _.clone(device); + newDevice.appId = parseInt(device.appId, 10); + newDevice.deviceId = parseInt(device.deviceId, 10); if (device.is_managed_by != null) { - newDevice.is_managed_by = parseInt(device.is_managed_by) + newDevice.is_managed_by = parseInt(device.is_managed_by, 10); } - newDevice.config = JSON.stringify(tryParse(device.config)) - newDevice.environment = JSON.stringify(tryParse(device.environment)) - newDevice.targetConfig = JSON.stringify(tryParse(device.targetConfig)) - newDevice.targetEnvironment = JSON.stringify(tryParse(device.targetEnvironment)) + newDevice.config = JSON.stringify(tryParse(device.config)); + newDevice.environment = JSON.stringify( + tryParse(device.environment), + ); + newDevice.targetConfig = JSON.stringify( + tryParse(device.targetConfig), + ); + newDevice.targetEnvironment = JSON.stringify( + tryParse(device.targetEnvironment), + ); if (newDevice.markedForDeletion == null) { - newDevice.markedForDeletion = false + newDevice.markedForDeletion = false; } const deviceTarget = { uuid: device.uuid, name: device.name, - apps: {} - } + apps: {}, + }; deviceTarget.apps[device.appId] = { commit: newDevice.targetCommit, config: newDevice.targetConfig, - environment: newDevice.targetEnvironment - } - return knex('dependentDevice').insert(newDevice) - .then(() => knex('dependentDeviceTarget').insert(deviceTarget)) - }) - }) - }) -} + environment: newDevice.targetEnvironment, + }; + return knex('dependentDevice') + .insert(newDevice) + .then(() => knex('dependentDeviceTarget').insert(deviceTarget)); + }); + }); + }); +}; exports.down = function(knex, Promise) { - return Promise.reject(new Error('Not implemented')) -} + return Promise.reject(new Error('Not implemented')); +}; diff --git a/src/migrations/20171214172530_image_docker_id.js b/src/migrations/20171214172530_image_docker_id.js index e76d9e48..2a6ea284 100644 --- a/src/migrations/20171214172530_image_docker_id.js +++ b/src/migrations/20171214172530_image_docker_id.js @@ -1,10 +1,10 @@ // Adds a dockerImageId column to the image table to identify images downloaded with deltas -exports.up = function (knex, Promise) { - return knex.schema.table('image', (t) => { - t.string('dockerImageId') - }) -} +exports.up = function(knex, Promise) { + return knex.schema.table('image', t => { + t.string('dockerImageId'); + }); +}; exports.down = function(knex, Promise) { - return Promise.reject(new Error('Not implemented')) -} + return Promise.reject(new Error('Not implemented')); +}; diff --git a/src/migrations/20180516164000-endpoint-specific-apps.js b/src/migrations/20180516164000-endpoint-specific-apps.js index 8677229f..75e20c7c 100644 --- a/src/migrations/20180516164000-endpoint-specific-apps.js +++ b/src/migrations/20180516164000-endpoint-specific-apps.js @@ -1,39 +1,45 @@ const fs = require('fs'); const configJsonPath = process.env.CONFIG_MOUNT_POINT; -exports.up = function (knex, Promise) { +exports.up = function(knex, Promise) { return new Promise((resolve, reject) => { if (!configJsonPath) { - console.log('Unable to locate config.json! Things may fail unexpectedly!'); + console.log( + 'Unable to locate config.json! Things may fail unexpectedly!', + ); resolve({}); } fs.readFile(configJsonPath, (err, data) => { if (err) { - console.log('Failed to read config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to read config.json! Things may fail unexpectedly!', + ); resolve({}); return; } try { const parsed = JSON.parse(data.toString()); resolve(parsed); - } catch(e) { - console.log('Failed to parse config.json! Things may fail unexpectedly!'); + } catch (e) { + console.log( + 'Failed to parse config.json! Things may fail unexpectedly!', + ); resolve({}); } }); - }) - .then((config) => { - return knex.schema.table('app', (t) => { + }).then(config => { + return knex.schema + .table('app', t => { // Create a new column on the table and add the apiEndpoint config json // field if it exists t.string('source'); }) - .then(() => { - return knex('app').update({ source: (config.apiEndpoint || '') }); - }); - }); -} + .then(() => { + return knex('app').update({ source: config.apiEndpoint || '' }); + }); + }); +}; -exports.down = function (knex, Promise) { - return Promise.reject(new Error('Not Implemented')) -} +exports.down = function(knex, Promise) { + return Promise.reject(new Error('Not Implemented')); +}; diff --git a/src/migrations/20181907164000-endpoint-specific-logschannel.js b/src/migrations/20181907164000-endpoint-specific-logschannel.js index 627043fc..9169e4da 100644 --- a/src/migrations/20181907164000-endpoint-specific-logschannel.js +++ b/src/migrations/20181907164000-endpoint-specific-logschannel.js @@ -1,16 +1,20 @@ const fs = require('fs'); const configJsonPath = process.env.CONFIG_MOUNT_POINT; -exports.up = function (knex, Promise) { +exports.up = function(knex, Promise) { return new Promise((resolve, reject) => { if (!configJsonPath) { - console.log('Unable to locate config.json! Things may fail unexpectedly!'); + console.log( + 'Unable to locate config.json! Things may fail unexpectedly!', + ); resolve({}); return; } fs.readFile(configJsonPath, (err, data) => { if (err) { - console.log('Failed to read config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to read config.json! Things may fail unexpectedly!', + ); resolve({}); return; } @@ -18,7 +22,9 @@ exports.up = function (knex, Promise) { const parsed = JSON.parse(data.toString()); resolve(parsed); } catch (e) { - console.log('Failed to parse config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to parse config.json! Things may fail unexpectedly!', + ); resolve({}); } }); @@ -26,18 +32,20 @@ exports.up = function (knex, Promise) { .tap(() => { // take the logsChannelSecret, and the apiEndpoint config field, // and store them in a new table - return knex.schema.hasTable('logsChannelSecret').then((exists) => { + return knex.schema.hasTable('logsChannelSecret').then(exists => { if (!exists) { - return knex.schema.createTable('logsChannelSecret', (t) => { + return knex.schema.createTable('logsChannelSecret', t => { t.string('backend'); t.string('secret'); }); } }); }) - .then((config) => { - return knex('config').where({ key: 'logsChannelSecret' }).select('value') - .then((results) => { + .then(config => { + return knex('config') + .where({ key: 'logsChannelSecret' }) + .select('value') + .then(results => { if (results.length === 0) { return { config, secret: null }; } @@ -47,15 +55,16 @@ exports.up = function (knex, Promise) { .then(({ config, secret }) => { return knex('logsChannelSecret').insert({ backend: config.apiEndpoint || '', - secret + secret, }); }) .then(() => { - return knex('config').where('key', 'logsChannelSecret').del(); + return knex('config') + .where('key', 'logsChannelSecret') + .del(); }); +}; -} - -exports.down = function (knex, Promise) { +exports.down = function(knex, Promise) { return Promise.reject(new Error('Not Implemented')); -} +}; diff --git a/src/migrations/20190619152500-engine-snapshot.js b/src/migrations/20190619152500-engine-snapshot.js index 5b049f25..c135303a 100644 --- a/src/migrations/20190619152500-engine-snapshot.js +++ b/src/migrations/20190619152500-engine-snapshot.js @@ -1,11 +1,10 @@ - exports.up = (knex, Promise) => { - return knex.schema.createTable('engineSnapshot', (t) => { + return knex.schema.createTable('engineSnapshot', t => { t.string('snapshot'); // Engine snapshot encoded as JSON. t.string('timestamp'); // When the snapshot was created. }); -} +}; exports.down = (knex, Promise) => { return Promise.reject(new Error('Not Implemented')); -} +}; diff --git a/src/migrations/M00000.js b/src/migrations/M00000.js index 45ac2b31..41de30b8 100644 --- a/src/migrations/M00000.js +++ b/src/migrations/M00000.js @@ -3,18 +3,21 @@ const _ = require('lodash'); // We take legacy deviceConfig targets and store them without the RESIN_ prefix // (we also strip the BALENA_ prefix for completeness, even though no supervisors // using this prefix made it to production) -exports.up = function (knex, Promise) { - return knex('deviceConfig').select('targetValues') - .then((devConfigs) => { +exports.up = function(knex, Promise) { + return knex('deviceConfig') + .select('targetValues') + .then(devConfigs => { const devConfig = devConfigs[0]; const targetValues = JSON.parse(devConfig.targetValues); const filteredTargetValues = _.mapKeys(targetValues, (_v, k) => { return k.replace(/^(?:RESIN|BALENA)_(.*)/, '$1'); }); - return knex('deviceConfig').update({ targetValues: JSON.stringify(filteredTargetValues) }); + return knex('deviceConfig').update({ + targetValues: JSON.stringify(filteredTargetValues), + }); }); }; -exports.down = function (knex, Promise) { +exports.down = function(knex, Promise) { return Promise.reject(new Error('Not Implemented')); }; diff --git a/src/migrations/M00001.js b/src/migrations/M00001.js index 585c98bf..3b917cee 100644 --- a/src/migrations/M00001.js +++ b/src/migrations/M00001.js @@ -3,9 +3,11 @@ const configJsonPath = process.env.CONFIG_MOUNT_POINT; const { checkTruthy } = require('../lib/validation'); -exports.up = function (knex, Promise) { - return knex('config').where({ key: 'localMode' }).select('value') - .then((results) => { +exports.up = function(knex, Promise) { + return knex('config') + .where({ key: 'localMode' }) + .select('value') + .then(results => { if (results.length === 0) { // We don't need to do anything return; @@ -14,15 +16,19 @@ exports.up = function (knex, Promise) { let value = checkTruthy(results[0].value); value = value != null ? value : false; - return new Promise((resolve) => { + return new Promise(resolve => { if (!configJsonPath) { - console.log('Unable to locate config.json! Things may fail unexpectedly!'); + console.log( + 'Unable to locate config.json! Things may fail unexpectedly!', + ); resolve(); return; } fs.readFile(configJsonPath, (err, data) => { if (err) { - console.log('Failed to read config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to read config.json! Things may fail unexpectedly!', + ); resolve(); return; } @@ -31,27 +37,30 @@ exports.up = function (knex, Promise) { // Assign the local mode value parsed.localMode = value; - fs.writeFile(configJsonPath, JSON.stringify(parsed), (err) => { - if (err) { - console.log('Failed to write config.json! Things may fail unexpectedly!'); + fs.writeFile(configJsonPath, JSON.stringify(parsed), err2 => { + if (err2) { + console.log( + 'Failed to write config.json! Things may fail unexpectedly!', + ); return; } resolve(); }); - } catch (e) { - console.log('Failed to parse config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to parse config.json! Things may fail unexpectedly!', + ); resolve(); } }); - }) - .then(() => { - return knex('config').where('key', 'localMode').del(); - }); + }).then(() => { + return knex('config') + .where('key', 'localMode') + .del(); + }); }); }; -exports.down = function (knex, Promise) { +exports.down = function(knex, Promise) { return Promise.reject(new Error('Not Implemented')); -} - +}; diff --git a/src/migrations/M00002.js b/src/migrations/M00002.js index 06b2396a..3c90c998 100644 --- a/src/migrations/M00002.js +++ b/src/migrations/M00002.js @@ -3,16 +3,20 @@ const configJsonPath = process.env.CONFIG_MOUNT_POINT; const { checkTruthy } = require('../lib/validation'); -exports.up = function (knex, Promise) { +exports.up = function(knex, Promise) { return new Promise(resolve => { if (!configJsonPath) { - console.log('Unable to locate config.json! Things may fail unexpectedly!'); + console.log( + 'Unable to locate config.json! Things may fail unexpectedly!', + ); return resolve(false); } fs.readFile(configJsonPath, (err, data) => { if (err) { - console.log('Failed to read config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to read config.json! Things may fail unexpectedly!', + ); return resolve(); } try { @@ -22,7 +26,9 @@ exports.up = function (knex, Promise) { } return resolve(false); } catch (e) { - console.log('Failed to parse config.json! Things may fail unexpectedly!'); + console.log( + 'Failed to parse config.json! Things may fail unexpectedly!', + ); return resolve(false); } }); @@ -36,6 +42,6 @@ exports.up = function (knex, Promise) { }); }; -exports.down = function (knex, Promise) { +exports.down = function(knex, Promise) { return Promise.reject(new Error('Not Implemented')); }; diff --git a/tools/dind/balenaos-in-container b/tools/dind/balenaos-in-container index 5b145900..e413fced 160000 --- a/tools/dind/balenaos-in-container +++ b/tools/dind/balenaos-in-container @@ -1 +1 @@ -Subproject commit 5b1459007cea18b5891d6bdf4b0694241487cc8b +Subproject commit e413fcedb9e3a5365da91c01a45e633d620947af diff --git a/tslint.json b/tslint.json index 34478831..8c46b572 100644 --- a/tslint.json +++ b/tslint.json @@ -1,3 +1,3 @@ { - "extends": ["resin-lint/config/tslint-prettier.json"] + "extends": ["@balena/lint/config/tslint-prettier.json"] } diff --git a/webpack.config.js b/webpack.config.js index d0c23203..8e972af5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,7 +2,6 @@ var webpack = require('webpack'); var path = require('path'); var fs = require('fs'); var _ = require('lodash'); -var path = require('path'); const CopyWebpackPlugin = require('copy-webpack-plugin'); var ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); @@ -122,7 +121,7 @@ module.exports = function(env) { (m instanceof RegExp && m.test(request)) ) { return callback(null, 'commonjs ' + request); - } else if (typeof m != 'string' && !(m instanceof RegExp)) { + } else if (typeof m !== 'string' && !(m instanceof RegExp)) { throw new Error('Invalid entry in external modules: ' + m); } }