balena-supervisor/src/utils.coffee

142 lines
4.3 KiB
CoffeeScript
Raw Normal View History

2013-12-23 04:22:54 +00:00
Promise = require 'bluebird'
2014-06-18 17:54:36 +01:00
_ = require 'lodash'
2013-12-23 04:22:54 +00:00
fs = Promise.promisifyAll require 'fs'
2014-06-18 17:54:36 +01:00
config = require './config'
knex = require './db'
2014-06-18 17:54:36 +01:00
mixpanel = require 'mixpanel'
networkCheck = require 'network-checker'
blink = require('blinking')(config.ledFile)
url = require 'url'
<<<<<<< HEAD
randomHexString = require './lib/random-hex-string'
=======
request = require 'request'
>>>>>>> Allow control of VPN + TCP check + Pub nub logs with Device Environment variables
2014-04-28 13:56:17 +03:00
utils = exports
# Parses package.json and returns resin-supervisor's version
exports.supervisorVersion = require('../package.json').version
mixpanelClient = mixpanel.init(config.mixpanelToken)
2014-06-18 17:54:36 +01:00
exports.mixpanelProperties = mixpanelProperties =
username: require('/boot/config.json').username
2014-09-15 12:31:14 +01:00
exports.mixpanelTrack = (event, properties = {}) ->
# Allow passing in an error directly and having it assigned to the error property.
if properties instanceof Error
properties = error: properties
# If the properties has an error argument that is an Error object then it treats it nicely,
# rather than letting it become `{}`
if properties.error instanceof Error
properties.error =
message: properties.error.message
stack: properties.error.stack
console.log('Event:', event, JSON.stringify(properties))
2014-06-18 17:54:36 +01:00
# Mutation is bad, and it should feel bad
properties = _.assign(_.cloneDeep(properties), mixpanelProperties)
mixpanelClient.track(event, properties)
networkPattern =
blinks: 4
pause: 1000
exports.blink = blink
pauseConnectivityCheck = false
disableConnectivityCheck = false
2015-08-27 03:27:14 +05:30
2015-08-26 19:10:22 +05:30
# options: An object of net.connect options, with the addition of:
# timeout: 10s
checkHost = (options) ->
2015-08-27 20:58:15 +05:30
if disableConnectivityCheck or pauseConnectivityCheck
2015-08-26 19:10:22 +05:30
return true
else
return networkCheck.checkHost(options)
2015-08-26 19:10:22 +05:30
2015-08-27 03:27:14 +05:30
# Custom monitor that uses checkHost function above.
2015-08-26 19:10:22 +05:30
customMonitor = (options, fn) ->
networkCheck.monitor(checkHost, options, fn)
# pause: A Boolean to pause the connectivity checks
exports.pauseCheck = (pause) ->
pauseConnectivityCheck = pause
# disable: A Boolean to disable the connectivity checks
2015-08-26 19:10:22 +05:30
exports.disableCheck = (disable) ->
disableConnectivityCheck = disable
2015-08-26 19:10:22 +05:30
2015-08-27 03:27:14 +05:30
# Call back for inotify triggered when the VPN status is changed.
2015-08-27 20:58:15 +05:30
vpnStatusInotifyCallback = ->
fs.lstatAsync(config.vpnStatusPath + '/active')
2015-08-27 19:50:10 +05:30
.then ->
2015-08-27 20:58:15 +05:30
pauseConnectivityCheck = true
2015-08-27 19:50:10 +05:30
.catch ->
2015-08-27 20:58:15 +05:30
pauseConnectivityCheck = false
2015-08-27 03:27:14 +05:30
2015-08-28 01:49:20 +05:30
# Use the following to catch EEXIST errors
EEXIST = (err) -> err.code is 'EEXIST'
exports.connectivityCheck = _.once ->
parsedUrl = url.parse(config.apiEndpoint)
2015-08-27 20:58:15 +05:30
fs.mkdirAsync(config.vpnStatusPath)
.catch EEXIST, (err) ->
console.log('VPN status path exists.')
2015-08-27 19:50:10 +05:30
.then ->
2015-08-27 20:58:15 +05:30
fs.watch(config.vpnStatusPath, vpnStatusInotifyCallback)
2015-08-28 01:49:20 +05:30
2015-08-27 03:27:14 +05:30
# Manually trigger the call back to detect cases when VPN was switched on before the supervisor starts.
vpnStatusInotifyCallback()
2015-08-26 19:10:22 +05:30
customMonitor
host: parsedUrl.hostname
port: parsedUrl.port ? (if parsedUrl.protocol is 'https:' then 443 else 80)
interval: 10 * 1000
(connected) ->
if connected
2014-12-11 13:29:59 +00:00
console.log('Internet Connectivity: OK')
blink.pattern.stop()
else
2014-12-11 13:29:59 +00:00
console.log('Waiting for connectivity...')
blink.pattern.start(networkPattern)
exports.getOrGenerateApiSecret = do ->
apiSecretPromise = null
return ->
apiSecretPromise ?= Promise.rejected()
apiSecretPromise = apiSecretPromise.catch ->
knex('config').select('value').where(key: 'apiSecret')
.then ([ apiSecret ]) ->
return apiSecret.value if apiSecret?
Promise.try ->
return config.forceApiSecret ? randomHexString.generate()
.then (newSecret) ->
knex('config').insert([{ key: 'apiSecret', value: newSecret }])
.return(newSecret)
exports.extendEnvVars = (env, uuid) ->
host = '127.0.0.1'
newEnv =
RESIN_DEVICE_UUID: uuid
RESIN_SUPERVISOR_ADDRESS: "http://#{host}:#{config.listenPort}"
RESIN_SUPERVISOR_HOST: host
RESIN_SUPERVISOR_PORT: config.listenPort
RESIN_SUPERVISOR_API_KEY: exports.getOrGenerateApiSecret()
RESIN: '1'
USER: 'root'
if env?
_.extend(newEnv, env)
return Promise.props(newEnv)
# VPN Control - Uses an enable Boolean
exports.VPNControl = (enable) ->
callback = (error, response, body ) ->
if !error && response.statusCode == 200
console.log('VPN Enabled: ' + enable)
else
console.log(error)
request.post(config.gosuperAddress + '/v1/vpncontrol', { json: true, body: Enable: enable }, callback)