-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.coffee
94 lines (83 loc) · 2.88 KB
/
index.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
'use strict'
env = process.env
async = require('async')
child_process = require('child_process')
fs = require('fs')
path = require('path')
etcdjs = require('etcdjs')
liveCollection = require('etcd-live-collection')
_ = require("lodash")
Hogan = require('hogan.js')
kvp = require('./kv-processor')
isFrontend = (key) ->
_.startsWith(key.split('/').pop(), "frontend:")
# Write file, but only if contents differs. Return true if changed, false if not
writeIfDifferent = (filepath, content, callback) ->
fs.readFile filepath, "utf-8", (err, data) ->
if data == content
callback(null, false)
else
console.log("Updating: "+filepath)
fs.writeFile filepath, content, (err) ->
if err
callback(err)
else
callback(null, true)
# Generate files, returning true if file was changed
generateFile = (outputDir, vhost, template, callback) ->
filename = vhost.domain_underscored + ".conf"
filepath = path.join(outputDir, filename)
rendered = template.render(vhost)
writeIfDifferent filepath, rendered, (err, changed) ->
if err
callback(err)
else
callback null,
file: filename
changed: changed
# Generate files, returning true if reload is required
generateFiles = (outputDir, vhosts, template, callback) ->
f = (vhost, cb) ->
generateFile(outputDir, vhost, template, cb)
async.mapLimit vhosts, 5, f, (err, results) ->
if (err)
callback(err)
else
callback null,
files: _.pluck(results, 'file')
changed: _.any(results, (r) -> r.changed)
removeOldFiles = (outputDir, filesToKeep, callback) ->
deleteFile = (filename, callback) ->
filepath = path.join(outputDir, filename)
console.log("Deleting: "+filepath)
fs.unlink filepath, callback
fs.readdir outputDir, (err, files) ->
filesToRemove = _.difference(files, filesToKeep)
async.eachSeries filesToRemove, deleteFile, callback
module.exports = (options) ->
template = Hogan.compile(options.template)
etcd = etcdjs(options.etcd.servers)
collection = liveCollection(etcd, options.etcd.path)
reloadConfig = (callback) ->
console.log("Reloading nginx: "+options.cmd)
child_process.exec options.cmd, (error, stdout, stderr) ->
callback()
updateConfig = () ->
generateFiles(
options.dir,
_.compact(kvp(k,v) for k, v of collection.values() when isFrontend(k)),
template,
(err, result) ->
if err
console.log(err)
else
removeOldFiles options.dir, result.files, (err) ->
if err
console.log(err)
else if result.changed
# Intentionally not reloading if all we did was delete files, as
# this could cause unpleasant consequences if the collection is
# falsely empty.
reloadConfig(() -> )
)
collection.on(event, updateConfig) for event in ['ready', 'action']