diff --git a/src/app.coffee b/src/app.coffee index dc00f02e..5bd8410e 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -42,17 +42,7 @@ knex.init.then -> ) console.log('Starting Apps..') - knex('app').select() - .then (apps) -> - Promise.all(apps.map(application.unlockAndStart)) - .catch (error) -> - console.error('Error starting apps:', error) - .then -> - utils.mixpanelTrack('Start application update poll', {interval: config.appUpdatePollInterval}) - setInterval(-> - application.update() - , config.appUpdatePollInterval) - application.update() + application.initialize() updateIpAddr = -> callback = (error, response, body ) -> diff --git a/src/application.coffee b/src/application.coffee index d6980aae..cfcd7e83 100644 --- a/src/application.coffee +++ b/src/application.coffee @@ -297,6 +297,19 @@ specialActionEnvVars = executedSpecialActionEnvVars = {} +executeSpecialActionsAndBootConfig = (env) -> + _.map specialActionEnvVars, (specialActionCallback, key) -> + if env[key]? && specialActionCallback? + # This makes the Special Action Envs only trigger their functions once. + if !_.has(executedSpecialActionEnvVars, key) or executedSpecialActionEnvVars[key] != env[key] + specialActionCallback(env[key]) + executedSpecialActionEnvVars[key] = env[key] + bootConfigVars = _.pick env, (val, key) -> + configRegex = new RegExp('^/' + device.bootConfigEnvVarPrefix + '*/') + return configRegex.exec(key)? + if !_.isEmpty(bootConfigVars) + device.setBootConfig(bootConfigVars) + UPDATE_IDLE = 0 UPDATE_UPDATING = 1 UPDATE_REQUIRED = 2 @@ -368,20 +381,13 @@ application.update = update = (force) -> remoteAppIds = _.keys(remoteApps) # Run special functions against variables if remoteAppEnvs has the corresponding variable function mapping. - _.map specialActionEnvVars, (specialActionCallback, key) -> - _.map remoteAppIds, (appId) -> - if remoteAppEnvs[appId][key]? && specialActionCallback? - # This makes the Special Action Envs only trigger their functions once. - if _.has(executedSpecialActionEnvVars, key) - if executedSpecialActionEnvVars[key] != remoteAppEnvs[appId][key] - specialActionCallback(remoteAppEnvs[appId][key]) - else - specialActionCallback(remoteAppEnvs[appId][key]) - executedSpecialActionEnvVars[key] = remoteAppEnvs[appId][key] + _.map remoteAppIds, (appId) -> + executeSpecialActionsAndBootConfig(remoteAppEnvs[appId]) apps = _.indexBy(apps, 'appId') localApps = _.mapValues apps, (app) -> - _.pick(app, [ 'appId', 'commit', 'imageId', 'env' ]) + app = _.pick(app, [ 'appId', 'commit', 'imageId', 'env' ]) + app.env = JSON.stringify(_.omit(JSON.parse(app.env), _.keys(specialActionEnvVars))) localAppIds = _.keys(localApps) toBeRemoved = _.difference(localAppIds, remoteAppIds) @@ -417,10 +423,14 @@ application.update = update = (force) -> throw err else if _.includes(toBeInstalled, appId) app = remoteApps[appId] + # Restore the complete environment so that it's persisted in the DB + app.env = JSON.stringify(remoteAppEnvs[appId]) start(app) else if _.includes(toBeUpdated, appId) localApp = apps[appId] app = remoteApps[appId] + # Restore the complete environment so that it's persisted in the DB + app.env = JSON.stringify(remoteAppEnvs[appId]) logSystemEvent(logTypes.updateApp, app) if localApp.imageId == app.imageId forceThisApp = remoteAppEnvs[appId]['RESIN_OVERRIDE_LOCK'] == '1' Promise.using lockUpdates(localApp, force || forceThisApp), -> @@ -461,6 +471,21 @@ application.update = update = (force) -> # Set the updating as finished in its own block, so it never has to worry about other code stopping this. updateStatus.state = UPDATE_IDLE +application.initialize = -> + knex('app').select() + .then (apps) -> + Promise.map apps, (app) -> + executeSpecialActionsAndBootConfig(JSON.parse(app.env)) + unlockAndStart(app) + .catch (error) -> + console.error('Error starting apps:', error) + .then -> + utils.mixpanelTrack('Start application update poll', {interval: config.appUpdatePollInterval}) + setInterval(-> + application.update() + , config.appUpdatePollInterval) + application.update() + module.exports = (uuid) -> logger.init( dockerSocket: config.dockerSocket diff --git a/src/device.coffee b/src/device.coffee index b6ede22a..b7476a08 100644 --- a/src/device.coffee +++ b/src/device.coffee @@ -4,7 +4,9 @@ knex = require './db' utils = require './utils' { resinApi } = require './request' device = exports +config = require './config' configPath = '/boot/config.json' +request = require 'request' exports.getID = do -> deviceIdPromise = null @@ -32,6 +34,24 @@ exports.getID = do -> throw new Error('Could not find this device?!') return devices[0].id +rebootDevice = -> + request.post(config.gosuperAddress + '/v1/reboot', -> console.log('Rebooting.')) + +exports.bootConfigEnvVarPrefix = 'RESIN_HOST_CONFIG_' +bootConfigPath = '/mnt/root/boot/config.txt' +exports.setBootConfig = (env) -> + configChanged = false + # TODO: + # Translate env to config.txt-compatible statements + # Read and parse config.txt + # Detect if variables are present + # If not there or different: + # mark configChanged as true + # Replace those and create new ones as necessary + # Create config.txt.new + # Move config.txt.new to config.txt + # rebootDevice() + exports.getDeviceType = do -> deviceTypePromise = null return ->