UNPKG

10.5 kBtext/coffeescriptView Raw
1_ = require 'underscore'
2fs = require "fs-extra"
3os = require "os"
4url = require "url"
5path = require "path"
6http = require "http"
7https = require "https"
8shell = require "shelljs"
9helpers = require '../modules/common/helpers'
10request = require "request"
11querystring = require "querystring"
12readDirFiles = require 'read-dir-files'
13Processes = require '../lib/processes'
14KDKite = require '../lib/kdkite'
15Controller = require '../lib/controller'
16
17if process.env['HOME']
18 homedir = path.join process.env['HOME'], '.kd'
19else
20 homedir = '/root/.kd'
21
22kitemanifest = require "#{homedir}/kd-manifest.json"
23kitehelper = require "kite-amqp/lib/kite-amqp/kite.coffee"
24
25{ask, logger} = require "../lib/utils"
26{manifest, kite} = require "../lib/common"
27{exec, spawn} = require "child_process"
28{guard, findFile} = require '../modules/common/helpers'
29
30module.exports = class KiteController extends Controller
31
32 help_txt:"""
33 Kites are awesome simple processes that can do amazing things. (go check http://kd.io/kites)
34 """
35
36 @set
37 commands:
38 'create': ['create', 'Creates a kite']
39 'run': ['run', 'Runs the kite and all its dependencies']
40 'install': ['install', """
41 Installs kites dependencies
42
43 usage:
44
45 kd kite install
46
47 """]
48
49 'listdependencies': ['listDependencies',
50 '''
51 kd listdependencies
52 '''
53 ]
54
55 'removedependency': ['removeDependency',
56 '''
57 Removes kite dependency:
58
59 usage:
60 kd removedependency /projects/mykite
61 '''
62 ]
63
64 'zip': ['createZip', 'creates a zip file from kite']
65
66 'deploy': ['createZip', 'deploys the kite file']
67
68 'list': ['list', 'Lists running kites']
69
70 'cluster': ['cluster', 'Kite cluster related commands']
71
72 'adddependency': ['addDependency',
73 '''Adds a service dependency
74
75 That means when you run this kite, it will run the other kites that this kite depends on.
76
77 You can add another kite as a runtime dependency from a git repo, a zip url or from local filesystem.
78
79 usage:
80 kd adddependency git://
81
82 kd adddependency /projects/mykite/
83
84 kd adddependency http://example.com/mykite.zip
85
86 ''']
87
88 constructor: (@configuration)->
89 {@config} = @configuration
90 @config.KODING_ROOT or= "https://koding.com"
91 @cwd = process.cwd()
92
93 create: (type, name, kitePath=@cwd)->
94 console.log "type", type
95 guard (type not in ["worker", "server", "server-express"]), "You have to define a type for your kite: 'worker' or 'server'"
96 guard not name, "Please define a name for your kite."
97 guard name.match(/[^\w]/), "Please do not use special chars in kite name."
98
99 kiteDir = path.join kitePath, "#{name}.kite"
100 console.log "Creating #{name} kite in #{kiteDir}"
101
102 kite = new KDKite(kiteDir)
103 kite.name = name
104 kite.username = @config.username
105 kite.mail = @config.mail
106 kite.version = '1.0.1'
107 kite.cloneFrom "#{type}.kite", ->
108 kite.prepare (err)->
109 process.stdout.write os.EOL
110 console.log """
111
112 Kite created as #{type} successfully.
113 To run, do:
114
115 cd #{path.relative process.cwd(), kiteDir}
116 kd kite run
117 """
118 return kite
119
120 getKiteFromPath: (dir=@cwd)->
121 kite = new KDKite(dir)
122 kite.processes = @processes
123 return kite
124
125 applicationInstalled:(application)->
126 exec "which java", (error, stdout, stderr)->
127 if error
128 return false
129 return true
130
131 runMergen:(callback)->
132 mergen = spawn('mergen')
133 mergen.stdout.on 'data', (d)->
134 console.log ">>>>", d.toString()
135 search = "Mergen Server listening for commands on"
136 if d.toString().indexOf(search) > -1
137 callback /([0-9]+)/.exec(d.toString())[1]
138 mergen.stderr.on 'data', (d)->
139 console.log "" + d
140
141 prerun:(callback)->
142 if not @applicationInstalled("java")
143 console.warn "java is not installed, you wont be able to communicate with other kites, or use datastore"
144 console.warn "please install java by visiting http://java.com/download"
145 else
146 # find if we have mergen
147 @runMergen (port)->
148 console.log "here comes our port", port
149 return callback(port)
150
151 # if fs.existsSync("node_modules")
152 # return cb()
153 # cmd = "rm -rf node_modules; mkdir node_modules; npm i coffee-script hat redis underscore && " +
154 # "cd node_modules &&" +
155 # "wget http://local.koding.com/kite-amqp.tgz && tar zxvf kite-amqp.tgz && cd .. && npm i"
156
157 # exec cmd, (error, stdout, stderr)->
158 # console.log('stdout: ' + stdout)
159 # console.log('stderr: ' + stderr)
160 # if error
161 # console.log('exec error: ' + error)
162 # # npm gives an error because, kite-amqp is not in registry
163 # cb()
164
165 cluster:(cmd)->
166 if cmd is "create"
167 console.log __dirname
168 process.chdir path.join(__dirname, 'resources')
169 vagrant = spawn('vagrant', ['up'])
170 vagrant.stdout.on 'data', (d)-> console.log "" + d
171 vagrant.stderr.on 'data', (d)-> console.log "" + d
172
173 run:(dir=@cwd)->
174 console.log "preparing...."
175 process.chdir dir
176 @prerun (port)=>
177 console.log "here is our port", port
178 @run_(dir, port)
179
180 run_:(dir=@cwd, port=6380)->
181
182 @processes = new Processes()
183 kite = @getKiteFromPath(dir)
184 kite.prepare ->
185 console.log "prepare completed !!!!"
186 kite.run(messageBusPort:port)
187
188 net = require 'net'
189 server = net.createServer (socket) =>
190 cmds =
191 'hosts': (args, cb)=>
192 @mergenData.hkeys "kd-runner", (err, hosts)->
193 console.log hosts
194 cb hosts.join("\n")
195
196 'list': (args, cb)=>
197 ret = []
198 for i of @processes.list
199 ret.push "#{@processes.list[i].pid}\t#{i}\t#{ (Date.now() - @processes.list[i].startedAt)/1000 } seconds"
200 cb ret.join("\n")
201
202 'status': (name, cb)=>
203 if not @processes.list[name]
204 return 'no such process'
205 p = @processes.list[name]
206 cb "running for #{(Date.now() - p.startedAt) / 1000 } seconds \t with pid #{p.pid}"
207
208 'attach': (directory, cb)=>
209 kite = new KDKite(directory[0])
210 kite.processes = @processes
211 kite.prepare ->
212 console.log "prepared kite at ", directory
213 kite.run()
214 cb "attached"
215
216 'kill': (name, cb)->
217 cb 'TODO'
218
219 'restart': (name, cb)->
220 cb 'TODO'
221
222 'socketwrite': (args, cb)=>
223 console.log("socket write called", args)
224 socket.write args.join(' ') + "\n"
225 cb("") if cb
226
227 socket.on 'data', (data) ->
228 cmdline = data.toString().split("\n")
229 cmdline = cmdline[0].replace(/\r$/, '')
230 k = cmdline.split(' ')
231 try
232 cmds[k[0]] k[1...], (ret)->
233 socket.write ret + "\n"
234 catch Error
235 console.trace Error
236 ret = Error.toString()
237 socket.write ret + "\n"
238
239 # server.listen 9001, 'localhost'
240
241 listDependencies: ()->
242 kite = @getKiteFromPath(@cwd)
243 kite.listDependencies()
244
245 removeDependency: (dep)->
246 kite = @getKiteFromPath(@cwd)
247 kite.removeDependency dep, ->
248 # TODO: remove the dependency folder ???
249 console.log "Dependency removed"
250
251 addDependency: (dep)->
252 kite = @getKiteFromPath(@cwd)
253 kite.addDependency dep, ->
254 console.log "Dependency added"
255
256 createZip:()=>
257 sha1file = (file)->
258 crypto = require('crypto')
259 shasum = crypto.createHash('sha1')
260 s = fs.readFileSync(file)
261 return shasum.update(s).digest("hex")
262
263 kite = @getKiteFromPath(@cwd)
264 kite.prepare =>
265 console.log "Creating zip file"
266 zipfilename = "/tmp/#{kite.name}.zip"
267
268 process.chdir ".."
269 zip = spawn('zip', ['-r', zipfilename, "#{kite.name}.kite", '-x', '*/node_modules/*'])
270 zip.stdout.on 'data', (d)-> console.log "" + d
271 zip.stderr.on 'data', (d)-> console.log "" + d
272
273 zip.on 'exit', (code)=>
274 if code isnt 0
275 console.log('zip process exited with code ' + code);
276 else
277 console.log "done zip, now uploading"
278
279 client = require('needle')
280
281 url = "#{@config.KODING_ROOT}/-/kd/upload"
282
283 filekey = path.basename(zipfilename)
284 data =
285 username: @config.username
286 key: @config.publicKey
287 hash: sha1file(zipfilename)
288
289 data[filekey] = { file: zipfilename, content_type: 'application/zip' }
290 data["#{filekey}-size"] = fs.statSync(zipfilename).size
291
292 console.log "uploading to ", url
293 client.post url, data, multipart:true, (err, resp, body)->
294 console.log(err)
295 console.log("Got status code " + resp.statusCode)
296 console.log(body)
297 options = JSON.parse body
298 fs.unlink(zipfilename)
299 console.log "options", options
300 # now we can deploy...
301 mykite = kitehelper.worker kitemanifest,
302 list: ()->
303 options['kiteName'] = "#{kite.name}.kite"
304 @group "Deployer", "deploy", [options], (err, opts)->
305 console.log "here", err, opts.args[0].id
306 console.log "Deployed to", opts.args[0].id
307 #kites.push reply
308 process.exit 0
309 , true
310
311 mykite.start ()->
312 mykite.callFunction 'list', [], ()->
313 console.log "done"
314
315 install: ()->
316 kite = @getKiteFromPath(@cwd)
317 kite.prepare ->
318 console.log "Installation complete"
319
320 list: ()->
321 kites = []
322 listsent = false
323 setTimeout ()->
324 for i in kites
325 console.log ">>>>", i
326 process.exit 0
327 , 3000
328
329 mykite = kitehelper.worker kitemanifest,
330 list: ()->
331 @everyone "kite.who", [], (err, reply)->
332 kites.push reply.args[1]
333
334 mykite.start ()->
335 mykite.callFunction 'list', [], ()->
336 console.log "done"