nanocyte-deployer
Version:
Deploy flows to nanocyte
221 lines (178 loc) • 7.72 kB
text/coffeescript
_ = require 'lodash'
async = require 'async'
debug = require('debug')('nanocyte-deployer:flow-deployer')
FLOW_START_NODE = 'engine-start'
FLOW_STOP_NODE = 'engine-stop'
MeshbluConfig = require 'meshblu-config'
debug = require('debug')('nanocyte-deployer:flow-deployer')
FlowStatusMessenger = require './flow-status-messenger'
SimpleBenchmark = require 'simple-benchmark'
class FlowDeployer
constructor: (options, dependencies={}) ->
{, , , , , , , } = options
{} = options
{, , MeshbluHttp, } = dependencies
= new SimpleBenchmark label: "nanocyte-deployer-#{@flowUuid}-#{@deploymentUuid}"
MeshbluHttp ?= require 'meshblu-http'
?= require 'request'
meshbluConfig = new MeshbluConfig
meshbluJSON = _.assign meshbluConfig.toJSON(), uuid: , token:
= new MeshbluHttp meshbluJSON
= new FlowStatusMessenger ,
userUuid:
flowUuid:
workflow: 'flow-start'
deploymentUuid:
flowLoggerUuid:
deploy: (callback=->) =>
.message 'begin'
(error, results) =>
debug 'getFlowAndUserData', .toString()
.message 'error', error.message if error?
return callback error if error?
results.flowToken =
results.deploymentUuid =
.configure results, (error, config, stopConfig) =>
debug 'configurationGenerator.configure', .toString()
.message 'error', error.message if error?
return callback error if error?
config: config, stopConfig: stopConfig, (error) =>
debug 'clearAndSaveConfig', .toString()
.message 'error', error.message if error?
return callback error if error?
results.flowData, config, (error) =>
debug 'setupDevice', .toString()
.message 'error', error.message if error?
.message 'end' unless error?
callback error
destroy: (callback=->) =>
.stop flowId: , (error) =>
debug 'configurationSaver.stop', .toString()
callback error
clearAndSaveConfig: (options, callback) =>
{config, stopConfig} = options
saveOptions =
flowId:
instanceId:
flowData: config
saveStopOptions =
flowId: "#{@flowUuid}-stop"
instanceId:
flowData: stopConfig
async.series [
async.apply .stop, flowId:
async.apply .save, saveOptions
async.apply .save, saveStopOptions
], callback
getFlowAndUserData: (callback) =>
async.parallel
userData: async.apply , "#{@octobluUrl}/api/user"
flowData: async.apply , "#{@octobluUrl}/api/flows/#{@flowUuid}"
, callback
_get: (url, callback)=>
options =
json: true
auth:
user:
pass:
.get url, options, (error, response, body) =>
callback error, body
setupDevice: (flow, flowConfig, callback=->) =>
async.series [
async.apply
async.apply , flowConfig
async.apply
async.apply , flow.nodes
async.apply , flow
], callback
addFlowToDevice:(flow, callback) =>
.updateDangerously , $set: flow: flow, callback
setupDeviceForwarding: (callback=->) =>
messageHook =
url:
method: 'POST'
signRequest: true
name: 'nanocyte-flow-deploy'
type: 'webhook'
.whoami (error, device) =>
return callback error if error?
pullMessageHooks =
$pull:
'meshblu.forwarders.received': {name: messageHook.name}
'meshblu.messageHooks': {name: messageHook.name}
'meshblu.forwarders.broadcast.received': {name: messageHook.name}
'meshblu.forwarders.message.received': {name: messageHook.name}
addNewMessageHooks =
$addToSet:
'meshblu.forwarders.broadcast.received': messageHook
'meshblu.forwarders.message.received': messageHook
tasks = [
async.apply .updateDangerously, , pullMessageHooks
async.apply .updateDangerously, , addNewMessageHooks
]
if _.isArray device?.meshblu?.forwarders?.broadcast
removeOldMessageHooks =
$unset:
'meshblu.forwarders.broadcast': ''
tasks.unshift async.apply .updateDangerously, , removeOldMessageHooks
async.series tasks, callback
setupMessageSchema: (nodes, callback=->) =>
triggers = _.filter nodes, class: 'trigger'
messageSchema =
type: 'object'
properties:
from:
type: 'string'
title: 'Trigger'
required: true
enum: _.pluck(triggers, 'id')
messageFormSchema = [
key: 'from'
titleMap: triggers
]
setMessageSchema =
$set : { 'messageSchema': messageSchema, 'messageFormSchema': messageFormSchema }
.updateDangerously , setMessageSchema, callback
buildFormTitleMap: (triggers) =>
_.transform triggers, (result, trigger) ->
triggerId = _.first trigger.id.split /-/
result[trigger.id] = "#{trigger.name} (#{triggerId})"
, {}
createSelfSubscriptions: (callback) =>
subscriptions =
'broadcast.received': []
'message.received': []
async.forEachOf subscriptions, , callback
createSubscriptions: (flowConfig, callback) =>
async.forEachOf flowConfig['subscribe-devices'].config, , callback
createSubscriptionsForType: (uuids, type, callback) =>
debug 'createSubscriptions', {uuids, type}
async.each uuids, ((uuid, cb) => uuid, type, cb), callback
createSubscriptionForType: (emitterUuid, type, callback) =>
subscriberUuid =
debug '@meshbluHttp.createSubscription', {subscriberUuid, emitterUuid, type}
.createSubscription {subscriberUuid, emitterUuid, type}, callback
startFlow: (callback=->) =>
onStartMessage =
devices: []
payload:
from: FLOW_START_NODE
subscribePulseMessage =
devices: []
topic: 'subscribe:pulse'
_.defer .message, 'begin', undefined, application: 'flow-runner'
async.series [
async.apply .updateDangerously, , $set: {online: true, deploying: false, stopping: false}
async.apply .message, subscribePulseMessage
async.apply .message, onStartMessage
], callback
stopFlow: (callback=->) =>
message =
devices: []
payload:
from: FLOW_STOP_NODE
async.series [
async.apply .updateDangerously, , $set: {online: false, deploying: false, stopping: false}
async.apply .message, message
], callback
module.exports = FlowDeployer