353 Commits

Author SHA1 Message Date
fd919d0b91 another set of edits that reveal more regressions 2017-10-24 23:08:10 -04:00
3dcfbf4d77 patch for Worker.sync 2017-10-24 16:42:17 -04:00
db8914ed7f Updating Worker.sync and WorkerCollection.checkBalance
- adding maxAttempts and errorCallback to Worker.sync
- split checkBalance into two functions
- made checkZombies async so it can utilize Worker.sync
2017-10-24 14:45:03 -04:00
3db02e036e updating runner initialization to send user_data script to setup workers cronjob. 2017-10-24 12:03:29 -04:00
0a4162400b updating initialize function to include user_data 2017-10-23 15:53:49 -04:00
734eaeac2f adjusting cronjob 2017-10-21 11:05:04 -04:00
7bfda7be23 tweaking crontab creation. 2017-10-19 23:08:14 -04:00
e2371fe44e updating command for startRunners to create cron job. 2017-10-19 12:45:11 -04:00
02e7869846 patch 2017-10-18 01:10:32 -04:00
f8174428a1 patch 2017-10-18 01:04:16 -04:00
0ba6589aa7 fixed runner 2017-10-18 01:00:55 -04:00
36db6be4bc Adding some logging." 2017-10-18 00:59:47 -04:00
2fa3ae985b adding sync function 2017-10-18 00:49:42 -04:00
5cd95e2843 adding to bash script 2017-10-17 11:19:35 -04:00
32a338437e updated logic and names 2017-10-16 19:27:18 -04:00
178838366c moving more code out of api.js 2017-10-16 19:18:59 -04:00
b385c0cb7f patch 2017-10-16 19:12:44 -04:00
7bbf77c6ec fixed syntax error in allocate_runners.sh 2017-10-16 19:11:47 -04:00
337423d294 adding newStartRunners command 2017-10-16 17:33:10 -04:00
ce31c7f1d5 updating startRunners command. 2017-10-16 12:01:44 -04:00
cac789fed3 adding check before instantiating the runner 2017-10-13 00:46:44 -04:00
1231dbcebc Merge pull request #27 from wmantly/wmantly-patch-1
Update lxc.js
2017-10-13 00:44:38 -04:00
0ac93e70f6 Update lxc.js 2017-10-13 00:43:48 -04:00
a79e994331 debuging Worker.startRunners 2017-10-13 00:06:46 -04:00
4b6aacb769 moving runnerMap to Runner class 2017-10-12 21:50:49 -04:00
c5e75967d9 patching log bug 2017-10-12 01:26:32 -04:00
072d321b58 Merge pull request #25 from wmantly/rerefactor
compounding creating runners bug
2017-10-12 01:20:23 -04:00
4afb69cdf7 compounding creating runners bug 2017-10-12 01:15:33 -04:00
a1a85b2c69 patch 2017-10-12 00:58:13 -04:00
a358a5212a Simplifing balance 2017-10-11 23:25:17 -04:00
11e44c94e7 Removed odd use of null 2017-10-11 23:10:19 -04:00
41874764bd updated checkBalance 2017-10-11 22:59:23 -04:00
654628b44d adding changes 2017-10-11 02:06:21 -04:00
099bce3846 patches for zombie check 2017-10-11 00:29:50 -04:00
482fe08c07 patches for testing. 2017-10-10 23:31:02 -04:00
983b76afce Moving some code.
- grouped runnerMap code in workers object
- created isZombie function in Worker
2017-10-10 16:44:48 -04:00
6a11a0baa5 moved core of startRunners to Worker class. 2017-10-10 16:25:40 -04:00
43caeb73f0 adding iffy 2017-10-10 01:54:11 -04:00
87ee3a5fd1 updating file name 2017-10-10 01:51:28 -04:00
e94308f6ac updating workers.destroy 2017-10-10 01:48:55 -04:00
ca0b0ef153 adding afterFreed hook 2017-10-10 01:25:43 -04:00
6e0bf97142 removed '/updateID' route. 2017-10-10 00:48:03 -04:00
a3107de459 adding concept of Worker and Runner. Moved label2runner to Workers manager. 2017-10-09 23:12:48 -04:00
2c92d0f232 moved workers definition to seperate file. 2017-10-09 16:46:56 -04:00
81c14dbc80 Merge pull request #24 from wmantly/test
cleaned some files up
2017-10-09 14:23:22 -04:00
b81a5a9c2f cleaned some files up 2017-10-09 14:22:05 -04:00
0f0033a646 Merge pull request #23 from wmantly/test
Test
2017-10-09 02:18:50 -04:00
127a2caac1 fixes 2017-10-09 02:16:00 -04:00
47027fdf39 fixes 2017-10-09 02:06:37 -04:00
cfd6c373ad fixes 2017-10-09 01:51:34 -04:00
128320f80e fixes 2017-10-09 00:39:02 -04:00
5711070d92 simpler 2017-10-09 00:32:24 -04:00
8e89c986bb simpler 2017-10-09 00:28:29 -04:00
14a628a8ff simpler 2017-10-09 00:26:58 -04:00
b45f45153f fixed tag prepend hardcoded issue 2017-10-08 20:42:19 -04:00
8c64959482 fixes and tests 2017-10-08 19:34:01 -04:00
e74f24b2b9 cleaned up logging 2017-10-08 19:00:18 -04:00
5533187636 typo 2017-10-08 17:45:54 -04:00
4a0e16f5f6 typo 2017-10-08 17:42:47 -04:00
21ad051a4d docs and fixe 2017-10-08 17:38:51 -04:00
3b36642ff8 Update api.js 2017-10-08 16:15:50 -04:00
84a51ca0db Update api.js 2017-10-08 15:53:14 -04:00
8779c5c6ca Update api.js 2017-10-08 01:36:18 -04:00
3a948df9f1 Merge pull request #22 from wmantly/omg
updated workers.json
2017-09-10 11:59:42 -04:00
c2f7dc72aa updated workers.json 2017-09-10 11:58:11 -04:00
70091ddbdb Merge pull request #21 from wmantly/omg
Omg
2017-09-10 00:17:47 -04:00
ef2e953366 stuff 2017-03-22 21:10:03 -04:00
e01794edbc another commit 2016-07-23 01:41:53 -04:00
00f68ef649 works with settings file change 2016-07-23 01:40:14 -04:00
bfa3e689b3 upgrade works 2016-07-21 23:45:21 -04:00
ec565c2803 done 2016-07-20 15:36:07 -04:00
f525c4d98f omg... 2016-07-18 02:41:55 -04:00
7f04135505 fu 2016-07-15 17:25:33 -04:00
8e82a7f47a Merge pull request #20 from wmantly/dnsAPI
Dns api
2016-07-15 17:14:34 -04:00
40b6b6ffdc fu 2016-07-15 17:13:46 -04:00
3a5c110aec fu 2016-07-15 16:58:24 -04:00
e412dd3f1f added dns api 2016-07-15 16:53:25 -04:00
68e7c48bc7 added dns api 2016-07-15 16:38:07 -04:00
bbc1025c7d added dns api 2016-07-15 16:31:51 -04:00
08f3b1fce6 added dns api 2016-07-15 16:28:55 -04:00
432b056609 added dns api 2016-07-15 16:26:37 -04:00
7c49a0c623 stuff 2016-06-24 14:58:42 -04:00
841b7d1b35 stuff 2016-06-24 14:24:56 -04:00
1f4f9686bb stuff 2016-06-24 14:15:35 -04:00
bc1c56f37c stuff 2016-06-24 14:14:16 -04:00
992a891aee stuff 2016-06-24 14:12:49 -04:00
78658a5c9f stuff 2016-06-24 14:09:58 -04:00
ae8c58bfda stuff 2016-06-24 14:05:53 -04:00
cba7ba7dbe stuff 2016-06-24 13:58:56 -04:00
8723a7b97a stuff 2016-06-24 12:39:39 -04:00
8533950663 index 2016-06-24 12:16:32 -04:00
4dd67ea2f6 tisk tisk 2016-06-24 00:20:49 -04:00
640fb30c8a Merge branch 'master' of https://github.com/wmantly/lxc_manager_node 2016-06-24 00:19:15 -04:00
d4b45739f1 tisk tisk 2016-06-24 00:18:50 -04:00
ab317dc791 Merge pull request #19 from wmantly/eagerload
Eagerload
2016-06-22 00:27:12 -04:00
9bf4055923 Update api.js 2016-06-15 00:50:25 -04:00
f836ece931 bbbbb 2016-05-31 18:17:19 -04:00
2aa0257502 Merge pull request #18 from wmantly/eagerload
ja-ja-ja-jasmine
2016-05-31 17:47:05 -04:00
714ff75cb6 ja-ja-ja-jasmine 2016-05-31 17:45:09 -04:00
6b662f131d Merge pull request #17 from wmantly/eagerload
Eagerload
2016-05-31 01:13:55 -04:00
e27bb6deba mergable 2016-05-31 01:13:02 -04:00
de4ce8553e stuff 2016-05-31 00:28:31 -04:00
e9bd665cc1 stuff 2016-05-31 00:23:10 -04:00
d90e0aaa25 stuff 2016-05-31 00:07:48 -04:00
d204f29526 stuff 2016-05-31 00:06:18 -04:00
0c46420715 stuff 2016-05-30 23:59:13 -04:00
93bf4b2577 stuff 2016-05-30 23:58:32 -04:00
11c7b1907d stuff 2016-05-30 23:52:58 -04:00
b808d23965 stuff 2016-05-30 23:49:05 -04:00
2a21be1825 stuff 2016-05-30 23:47:32 -04:00
9c69033756 stuff 2016-05-30 23:41:12 -04:00
00bca4ff34 stuff 2016-05-30 23:21:28 -04:00
29ad409649 stuff 2016-05-30 23:14:28 -04:00
aee63de478 stuff 2016-05-30 23:06:45 -04:00
67b717ace1 stuff 2016-05-30 23:00:09 -04:00
4d78659654 stuff 2016-05-30 22:48:24 -04:00
5467209d25 stuff 2016-05-30 22:28:59 -04:00
a432df7879 stuff 2016-05-30 21:46:40 -04:00
ded9cff1dc stuff 2016-05-30 21:25:35 -04:00
9bb9809f51 stuff 2016-05-30 21:18:02 -04:00
9072167e65 stuff 2016-05-30 19:45:51 -04:00
7c97bed5b0 stuff 2016-05-30 18:54:36 -04:00
fd4405bca5 stuff 2016-05-30 18:46:29 -04:00
2237d3cac3 stuff 2016-05-30 18:37:08 -04:00
3e0d34a2f5 stuff 2016-05-30 18:35:00 -04:00
4b4ab75aaa stuff 2016-05-30 18:20:47 -04:00
cfc6d406a1 stuff 2016-05-30 18:11:52 -04:00
1624d9f7ff stuff 2016-05-30 18:11:00 -04:00
e8c26abd52 stuff 2016-05-30 18:03:59 -04:00
5a5c453ea3 stuff 2016-05-30 18:03:11 -04:00
71ab12c64e stuff 2016-05-30 17:56:52 -04:00
be7f518778 stuff 2016-05-30 17:50:21 -04:00
b8dfaff861 stuff 2016-05-30 17:27:21 -04:00
eec89027a4 stuff 2016-05-30 17:18:36 -04:00
421a8ec78b stuff 2016-05-30 17:10:32 -04:00
a77d00aab4 stuff 2016-05-30 17:06:03 -04:00
c971b609ee stuff 2016-05-30 17:03:21 -04:00
b8f72ef13c stuff 2016-05-30 16:55:48 -04:00
f9482b3483 stuff 2016-05-30 16:54:06 -04:00
136bf04825 stuff 2016-05-30 16:34:54 -04:00
6c2a8d48bf stuff 2016-05-30 16:31:46 -04:00
d22a79c81e stuff 2016-05-30 16:28:07 -04:00
4c2a4b7657 stuff 2016-05-30 16:21:22 -04:00
d1a87a033b stuff 2016-05-30 16:06:36 -04:00
18ff2ee3be stuff 2016-05-30 16:06:06 -04:00
651f3835e2 stuff 2016-05-30 15:43:49 -04:00
232e9b72bb stuff 2016-05-30 15:41:30 -04:00
f714a6e179 stuff 2016-05-30 15:12:24 -04:00
9b7936ee3a stuff 2016-05-30 15:09:17 -04:00
ce96c7cb87 stuff 2016-05-29 18:53:30 -04:00
23f7cf1f68 stuff 2016-05-29 18:41:11 -04:00
b1e3e23d91 stuff 2016-05-29 14:06:24 -04:00
f63b6c3acd stuff 2016-05-29 14:03:58 -04:00
05b6a477f4 stuff 2016-05-29 13:50:19 -04:00
848f439122 stuff 2016-05-29 13:47:36 -04:00
f0d6016a63 stuff 2016-05-29 13:44:34 -04:00
37fae2e413 stuff 2016-05-29 13:43:04 -04:00
42ea77720a stuff 2016-05-29 01:33:22 -04:00
4079ee8208 stuff 2016-05-29 01:09:01 -04:00
cd37c680f0 stuff 2016-05-29 01:05:54 -04:00
7d12414d74 stuff 2016-05-29 01:03:46 -04:00
a7e1478697 stuff 2016-05-29 00:52:26 -04:00
571e81ace5 stuff 2016-05-29 00:47:29 -04:00
02c0c85417 stuff 2016-05-29 00:37:43 -04:00
0b9b5c0627 stuff 2016-05-29 00:36:56 -04:00
e6dee5bde3 stuff 2016-05-28 01:55:21 -04:00
586c8cc32f stuff 2016-05-28 01:54:17 -04:00
2ba7fa58e2 stuff 2016-05-28 01:49:41 -04:00
b84c87d55d stuff 2016-05-28 01:48:40 -04:00
f86a74a589 stuff 2016-05-28 01:47:38 -04:00
a51f4c203c stuff 2016-05-28 01:40:35 -04:00
ccd128100a stuff 2016-05-28 01:40:01 -04:00
191851e2bb stuff 2016-05-28 01:08:17 -04:00
b5baacf668 stuff 2016-05-28 00:18:10 -04:00
3e592887d1 stuff 2016-05-28 00:13:24 -04:00
18897cd4e6 stuff 2016-05-27 20:37:14 -04:00
b5737a0470 stuff 2016-05-27 20:07:32 -04:00
732d15cc54 stuff 2016-05-27 20:02:27 -04:00
424b5c68c8 stuff 2016-05-27 19:54:47 -04:00
f6f5b81b49 stuff 2016-05-27 19:53:46 -04:00
eb9b8b2556 stuff 2016-05-27 19:48:04 -04:00
d5bd5d2c39 stuff 2016-05-27 19:47:34 -04:00
71bd4ffc4a stuff 2016-05-27 19:35:30 -04:00
101160e887 stuff 2016-05-27 15:54:07 -04:00
371a40a3d3 stuff 2016-05-27 15:45:19 -04:00
8a5001aee7 stuff 2016-05-27 15:39:41 -04:00
9991e7eb36 stuff 2016-05-27 15:28:28 -04:00
7fcbcecb6a stuff 2016-05-27 15:02:32 -04:00
6b72ddcdd4 stuff 2016-05-27 13:14:44 -04:00
a4f01f8062 stuff 2016-05-27 13:10:45 -04:00
5a0ab51c32 stuff 2016-05-27 13:07:44 -04:00
dd68a29208 stuff 2016-05-27 11:11:38 -04:00
bf21a8b966 stuff 2016-05-27 11:07:20 -04:00
99043948db stuff 2016-05-27 10:52:46 -04:00
ee3091ae3c stuff 2016-05-27 10:45:42 -04:00
ac524a1c76 stuff 2016-05-27 01:05:15 -04:00
d7b32996b3 stuff 2016-05-27 00:59:28 -04:00
7ba58ee8d6 stuff 2016-05-27 00:58:10 -04:00
9a58acdfa2 stuff 2016-05-27 00:56:37 -04:00
28596a0b4d stuff 2016-05-27 00:53:19 -04:00
1086baf65a stuff 2016-05-27 00:52:39 -04:00
8c32b2e246 stuff 2016-05-27 00:52:07 -04:00
c319487141 stuff 2016-05-27 00:50:04 -04:00
a301ad88e5 stuff 2016-05-27 00:45:38 -04:00
d4da910040 stuff 2016-05-27 00:43:07 -04:00
62fcae727a stuff 2016-05-27 00:40:59 -04:00
1ddda799d3 stuff 2016-05-27 00:38:52 -04:00
9a0ad761b9 stuff 2016-05-27 00:37:54 -04:00
26f06c0aa8 stuff 2016-05-27 00:35:57 -04:00
b8f23077da stuff 2016-05-27 00:34:52 -04:00
7d4965b21e stuff 2016-05-27 00:34:24 -04:00
1af8aed161 stuff 2016-05-27 00:32:03 -04:00
5fc47fbbcc stuff 2016-05-26 21:21:15 -04:00
129cd54812 stuff 2016-05-26 21:16:02 -04:00
c6e9ec62ba stuff 2016-05-26 20:58:17 -04:00
caf32c3809 stuff 2016-05-26 20:41:25 -04:00
19293fdaff stuff 2016-05-26 20:15:58 -04:00
f32d6f70a9 stuff 2016-05-26 20:14:01 -04:00
66f6c3b92a stuff 2016-05-26 19:54:24 -04:00
ed2b37d696 stuff 2016-05-26 19:52:16 -04:00
61dedb013d stuff 2016-05-26 19:47:13 -04:00
0e7ccf2637 stuff 2016-05-26 19:24:07 -04:00
b74a71efb4 stuff 2016-05-26 19:23:22 -04:00
4651a2f49c stuff 2016-05-26 19:22:06 -04:00
eff29a9922 stuff 2016-05-25 23:28:22 -04:00
baa8fe6730 workers 2016-05-25 16:08:36 -04:00
16f91f01a7 workers 2016-05-25 16:07:43 -04:00
b53c3e6808 workers 2016-05-25 16:07:01 -04:00
a1338c5792 workers 2016-05-25 16:06:16 -04:00
f875bf101a workers 2016-05-25 16:04:36 -04:00
f503f370b2 stuff 2016-05-25 15:38:58 -04:00
32e70d4be4 digital ocean API 2016-05-23 18:25:38 -04:00
15cac181c3 digital ocean API 2016-05-23 18:18:34 -04:00
63b7a3b481 do api started 2016-05-20 09:11:31 -04:00
360f2c591d info 2016-05-16 17:36:58 -04:00
d4214cbf1d info 2016-05-16 17:30:30 -04:00
d23f1b91d1 info 2016-05-16 17:26:56 -04:00
4ca49a9632 info 2016-05-16 17:24:17 -04:00
b8ce1fdcfc info 2016-05-16 17:23:02 -04:00
4257644d4e info 2016-05-16 17:18:04 -04:00
dd759efd8a info 2016-05-16 17:17:23 -04:00
ae2a4984e4 info 2016-05-16 17:07:02 -04:00
152b206f9c info 2016-05-16 17:02:36 -04:00
e6c45352c9 info 2016-05-16 17:01:52 -04:00
d00b325625 info 2016-05-16 16:52:18 -04:00
f5ea0966dc info 2016-05-16 16:50:55 -04:00
405569a0c9 info 2016-05-16 16:50:04 -04:00
3b356a48f8 info 2016-05-16 16:48:56 -04:00
30525c984c closer 2016-05-05 01:06:24 -04:00
998063268f closer 2016-05-05 01:03:44 -04:00
22905cf056 closer 2016-05-05 01:01:24 -04:00
923b6fdd78 closer 2016-05-05 00:57:32 -04:00
8f9a43c743 closer 2016-05-05 00:46:03 -04:00
8962181782 closer 2016-05-05 00:43:48 -04:00
82ce62a678 closer 2016-05-05 00:37:45 -04:00
8b0556b545 closer 2016-05-05 00:36:53 -04:00
2b8ef1d39e closer 2016-05-05 00:36:12 -04:00
f80988a929 closer 2016-05-05 00:26:14 -04:00
7834e892bf closer 2016-05-05 00:24:23 -04:00
1db5cbb600 closer 2016-05-05 00:22:44 -04:00
18cbb5536b closer 2016-05-05 00:20:05 -04:00
2e21a7d91b closer 2016-05-05 00:19:13 -04:00
3a1276db67 closer 2016-05-05 00:18:55 -04:00
fcb4612e1c closer 2016-05-05 00:18:10 -04:00
a158d05b9d maybe 2016-05-04 23:43:08 -04:00
7e5fae983b ssh 2016-05-02 00:40:50 -04:00
d10c699145 ssh 2016-04-30 23:36:19 -04:00
c97100c9a7 ssh 2016-04-30 23:33:02 -04:00
2a6cce6296 ssh 2016-04-30 23:31:17 -04:00
2fc8276634 ssh 2016-04-30 23:30:18 -04:00
651a4d82a5 ssh 2016-04-30 23:28:59 -04:00
19395652c4 ssh 2016-04-30 23:26:07 -04:00
7f0489cfa9 ssh 2016-04-30 23:25:41 -04:00
1db7bd8f3c ssh 2016-04-30 23:25:05 -04:00
a65c87017a ssh 2016-04-30 23:15:30 -04:00
70bd796bc6 ssh 2016-04-30 23:08:13 -04:00
a5afd8469c Merge pull request #16 from wmantly/eagerload
Eagerload
2016-04-25 17:51:27 -04:00
c742c8fb7a load stuff 2016-04-25 16:56:57 -04:00
c42cf797e7 load stuff 2016-04-25 16:51:27 -04:00
280a90a7eb load stuff 2016-04-25 16:50:20 -04:00
f82968fbbe load stuff 2016-04-25 16:46:32 -04:00
ceadfcb24f load stuff 2016-04-25 16:44:48 -04:00
f809e57ba5 load stuff 2016-04-25 16:37:29 -04:00
d93b43d37f load stuff 2016-04-25 16:36:48 -04:00
109db64634 load stuff 2016-04-25 16:24:30 -04:00
2f8cf5c120 load stuff 2016-04-25 15:46:05 -04:00
d452250126 load stuff 2016-04-25 15:42:07 -04:00
6acc3fba21 load stuff 2016-04-25 15:40:49 -04:00
5c94ea4c29 load stuff 2016-04-25 15:39:21 -04:00
0b1b1fd5c9 Merge pull request #13 from wmantly/timeout
Timeout
2016-04-25 13:40:14 -04:00
049972b278 crunner is a go! 2016-04-25 13:39:38 -04:00
5c91414521 crunner 2016-04-25 13:32:16 -04:00
299040be6f crunner 2016-04-25 12:52:00 -04:00
1dce0358cc crunner 2016-04-22 22:56:47 -04:00
7e2c575a06 crunner 2016-04-22 22:54:15 -04:00
96c931ba5c crunner 2016-04-22 22:50:19 -04:00
c9b66b1bd6 crunner 2016-04-22 14:39:35 -04:00
2ea36dc963 crunner 2016-04-22 13:08:46 -04:00
77d8f2b743 crunner 2016-04-22 13:07:45 -04:00
3a313a21d1 crunner 2016-04-22 13:03:04 -04:00
491f6c57e8 crunner 2016-04-22 13:00:47 -04:00
96b032f816 crunner 2016-04-22 12:59:52 -04:00
fbc9a308b9 crunner 2016-04-22 12:55:37 -04:00
56cebedf04 crunner 2016-04-22 12:36:21 -04:00
b7c8335a82 crunner 2016-04-22 12:32:42 -04:00
57cfc24e92 crunner 2016-04-22 12:21:03 -04:00
9c2fbaab99 Update README.md 2016-04-20 23:39:39 -04:00
d57058b59c Update README.md 2016-04-20 23:35:59 -04:00
147d7ab41f timeout 2016-02-14 11:24:48 -05:00
39b64a4ecd timeout 2016-02-14 11:02:08 -05:00
aa5dd97694 Merge pull request #12 from wmantly/new
New
2016-02-09 13:45:30 -05:00
e481f1c071 stuff 2016-02-08 17:22:51 -05:00
2dba8c9c4f stuff 2016-02-08 17:19:18 -05:00
81bda27acd stuff 2016-02-08 17:06:46 -05:00
3b89660ef1 stuff 2016-02-08 17:05:18 -05:00
a74d7130d7 stuff 2016-02-08 17:03:45 -05:00
1ee46f6d2c stuff 2016-02-08 16:56:54 -05:00
99dcc47e00 stuff 2016-02-08 16:48:45 -05:00
8ce30f1e60 stuff 2016-02-08 16:46:54 -05:00
1e3f9a7302 stuff 2016-02-08 16:42:08 -05:00
517690a454 stuff 2016-02-08 14:00:19 -05:00
469d4deb7e stuff 2016-02-08 13:57:37 -05:00
64af338a6c stuff 2016-02-08 13:55:43 -05:00
cf05db1c91 stuff 2016-02-08 13:53:25 -05:00
ee7ff554e7 stuff 2016-02-08 13:52:31 -05:00
c77ee3a007 stuff 2016-02-08 13:51:15 -05:00
46ad5ae25d stuff 2016-02-08 13:49:59 -05:00
8c0d3bd6da stuff 2016-02-08 13:28:45 -05:00
c8d32de96d runner 2016-02-08 10:39:55 -05:00
f19c673764 runner 2016-02-08 10:34:26 -05:00
238cfd94b3 runner 2016-02-08 10:32:43 -05:00
e7987d8035 runner 2016-02-08 10:30:01 -05:00
f8ff072690 runner 2016-02-08 10:25:48 -05:00
b0ab1a5313 runner 2016-02-08 10:18:12 -05:00
a1a0ec8d02 runner 2016-02-08 10:13:03 -05:00
d438cdd249 runner 2016-02-07 01:01:07 -05:00
708c5ea5d3 runner 2016-02-07 00:59:53 -05:00
7c37aa2e8b runner 2016-02-07 00:59:29 -05:00
025205e349 runner 2016-02-07 00:47:32 -05:00
85e0dcf729 runner 2016-02-07 00:47:07 -05:00
45bf9c67f6 runner 2016-02-07 00:46:02 -05:00
d34a482a60 runner 2016-02-07 00:45:48 -05:00
0c891f62ef runner 2016-02-07 00:42:45 -05:00
5df3ecd5af runner 2016-02-07 00:41:16 -05:00
55813dc422 runner 2016-02-07 00:39:34 -05:00
ee57ab01e1 runner 2016-02-07 00:38:55 -05:00
b27f0d6bd9 runner 2016-02-07 00:38:38 -05:00
303c80f601 runner 2016-02-07 00:37:46 -05:00
1cafd74cc4 runner 2016-02-07 00:37:28 -05:00
a8d53d5bc5 runner 2016-02-07 00:36:54 -05:00
c8a3d5c60d runner 2016-02-07 00:36:31 -05:00
cb68bc4eec runner 2016-02-07 00:36:04 -05:00
a4a1cf314a runner 2016-02-07 00:34:42 -05:00
16 changed files with 2001 additions and 135 deletions

3
.gitignore vendored
View File

@ -29,3 +29,6 @@ node_modules
# Debug log from npm
npm-debug.log
.c9
# keys
secrets.js

View File

@ -53,10 +53,11 @@ Clone the repo and set it up:
git clone https://github.com/wmantly/lxc_manager_node.git
cd lxc_manager_node
npm install
```
Its safer at this point to reboot the system, `exit` back to the privlaged user and `reboot`
**SSH or log dercily into the `virt` user!!!** this will not if you use su!
**SSH or log dercily into the `virt` user!!!** this will not work if you use su to get into the user!
Now you can can create a test container:
```bash

33
allocate_runners.sh Normal file
View File

@ -0,0 +1,33 @@
# maxMemoryUsage must be defined
function usedMemoryPercent () {
memoryAvailable=$(head /proc/meminfo|grep MemAvail|grep -Po '\d+');
totalMemory=$(head /proc/meminfo|grep MemTotal|grep -Po '\d+');
difference=$(expr $totalMemory - $memoryAvailable);
difference=$(expr $difference \* 100);
memory=$(expr $difference / $totalMemory);
}
function buildRunners () {
baseName="crunner0";
namePrefix="crunner-batch-${RANDOM}";
runners="";
usedMemoryPercent;
# maxMemoryUsage must be defined
until [[ $memory -gt $maxMemoryUsage ]]; do
runnerName="${namePrefix}-id-${RANDOM}";
lxc-start-ephemeral -o $baseName -n $runnerName --union-type overlayfs -d;
if [[ $? -eq 0 ]]; then
runners="${runners};${runnerName}";
fi
usedMemoryPercent;
done
}
buildRunners;
# Add curl to manager here. Sending status report to manager
# curl -X POST "${PHONE_HOME}" -d'{"memory":${memory}, "runnersShort": "${runners}", "runnersLong": "'"$(lxc-ls --fancy)"'", "id": "${WORKER_UUID}"}'
exit 0;

6
app.js
View File

@ -18,6 +18,12 @@ app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use('/', require('./routes/index'));
app.use('/api', require('./routes/api'));

178
doapi.js Normal file
View File

@ -0,0 +1,178 @@
var request = require('request');
api = function(key){
key = key || require('./secrets.js').doAPI;
this.BASEURL = 'https://api.digitalocean.com/v2/';
this.headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+key
}
this.calls = 0;
this.account = function(callback){
var options = {
url: this.BASEURL+'account',
headers: this.headers
};
this.calls++;
return request.get(options, function(error, response, body){
return callback(body, response, error);
});
};
this.dropletsByTag = function(tag, callback){
var options = {
url: this.BASEURL+'droplets?tag_name='+tag,
headers: this.headers
};
this.calls++;
return request.get(options, function(error, response, body){
return callback(body, response, error);
});
};
this.dropletSetTag = function(tag, dropletID, callback) {
callback = callback || function(){};
var data = {
resources: [
{
resource_id: dropletID,
resource_type: 'droplet'
}
]
};
var options = {
url: this.BASEURL+'tags/'+tag+'/resources',
headers: this.headers,
body: JSON.stringify(data)
};
this.calls++;
return request.post(options, function(error, response, body){
return callback(body, response, error);
});
};
this.dropletCreate = function(args, callback){
callback = callback || function(){};
var data = {
name: args.name, // || return false,
region: args.region || 'nyc3',
size: args.size || '512mb',
image: args.image || 'ubuntu-14-04-x64',
ssh_keys: args.ssh_key || null,
backups: args.backup || false,
private_networking: args.private_networking || true,
user_data: args.user_data || null
};
var options = {
url: this.BASEURL+'droplets',
headers: this.headers,
body: JSON.stringify(data)
};
this.calls++;
return request.post(options, function(error, response, body){
return callback(body, response, error);
});
}
this.dropletToActive = function(args){
args.__doapi = this; // hold the DO api in the agrs scope
args.onCreated = args.onCreate || function(){};
this.dropletCreate(args, function(data){
data = JSON.parse(data);
args.onCreate(data, args);
// check if the server is ready, giving time to allow
// digital ocean to do its thing
setTimeout(function check(id, args){
time = args.time || 10000;
args.__doapi.dropletInfo(id, function (data){
var droplet = JSON.parse(data)['droplet'];
if(droplet.status == 'active'){
return args.onActive(droplet, args);
}else{
setTimeout(function(check, id){
check(id, args);
}, time, check, droplet.id);
}
});
}, 70000, data.droplet.id, args);
});
};
this.dropletDestroy = function(dropletID, callback){
callback = callback || function(){};
var options = {
url: this.BASEURL+'droplets/'+dropletID,
headers: this.headers
};
this.calls++;
return request.del(options, function(error, response, body){
callback(body, response, error);
});
};
this.dropletInfo = function(dropletID, callback){
var options = {
url: this.BASEURL+'droplets/'+dropletID,
headers: this.headers
};
this.calls++;
return request.get(options, function(error, response, body){
callback(body, response, error);
});
};
this.tagCreate = function(tag, callback){
callback = callback || function(){};
var options = {
url: this.BASEURL+'tags',
headers: this.headers,
body: JSON.stringify({name: tag})
};
this.calls++;
return request.post(options, function(error, response, body){
return callback(body, response, error);
});
};
this.tagsList = function(callback){
var options = {
url: this.BASEURL+'tags',
headers: this.headers
};
this.calls++;
return request.get(options, function(e,r,b){
callback(b,r,e);
});
};
this.domianAddRecord = function(args, callback){
callback = callback || function(){};
var options = {
url: this.BASEURL+'domains/'+ args.domain +'/records',
headers: this.headers,
body: JSON.stringify(args)
};
this.calls++;
return request.post(options, function(error, response, body){
return callback(body, response, error);
});
}
return this;
}
module.exports = api;

19
docs/lxc-world.md Normal file
View File

@ -0,0 +1,19 @@
##### LXC Commands
`lxc-top`:
Realtime Meta data about containers(not machine friendly). Monitor container statistics.
`lxc-ls --fancy`:
list of existing containers
`lxc-start-ephemeral`, `lxc-copy`:
start an ephemeral copy of an existing container
`lxc-attach`:
start a process inside a running container.(enter the droplet)

27
docs/memory-managment.md Normal file
View File

@ -0,0 +1,27 @@
##### Memory Managment
`free`, `free -h`:
display amount of free and used memory in the system.
* Disclamers:
- DO NOT USE IN SCRIPT
`/proc/`:
It is actually an kernel application. Looks like a file, but is actually generated on demand by the kernel. All "files" in proc are kernal commands. Interact with these commands as if they were files.
`/proc/meminfo`:
File containing realtime memory info.
`/proc/cpuinfo`:
cpu info
`/dev`:
DANGER This folder contains physical interfaces to hardware on or connected to the machine. Just don't. Read first. Except `/dev/null` it is a blackhole.

50
lxc.js
View File

@ -1,8 +1,12 @@
'use strict';
var exec = require('child_process').exec;
function sysExec(command, callback){
command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command;
function sysExec(command, ip, callback){
ip = ip || '104.236.77.157';
command = new Buffer(command).toString('base64')
command = 'ssh -i ~/.ssh/clw_rsa -o "StrictHostKeyChecking no" virt@'+ ip + ' "echo ' + command + '|base64 --decode|bash"';
// command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command;
return exec(command, (function(callback){
return function(err,data,stderr){
@ -13,30 +17,9 @@ function sysExec(command, callback){
})(callback));
};
var Container = function(config){
this.name = config.name;
this.state = config.state;
this.ip = config.ip || (config.ipv4 || '').replace('-', '') || null ;
}
Container.prototype.autoShutDown = function(time) {
time = time || 600000;
// this.__shutDownTimeout = setTimeout(function(){}, this.autoShutDown):
};
var lxcORM = function(){
var orm = {}
lxc.list(function(data){
for(var idx = data.length; idx--;){
orm[data[idx].name] = new Container(data[idx]);
}
});
return orm
};
var lxc = {
exec: sysExec,
create: function(name, template, config, callback){
return sysExec('lxc-create -n '+name+' -t '+template, callback);
},
@ -48,7 +31,7 @@ var lxc = {
destroy: function(name, callback){
return sysExec('lxc-destroy -n '+ name, function(data){
var info = data.match(/Destroyed container/);
console.log('destroy info:', info);
// console.log('destroy info:', info);
var args = [true].concat(Array.prototype.slice.call(arguments, 1));
return callback.apply(this, args);
});
@ -58,10 +41,10 @@ var lxc = {
return sysExec('lxc-start --name '+name+' --daemon', callback);
},
startEphemeral: function(name, base_name, callback){
startEphemeral: function(name, base_name, ip, callback){
var command = 'lxc-start-ephemeral -o '+base_name+ ' -n '+name +' --union-type overlayfs -d';
return sysExec(command, function(data){
console.log('startEphemeral', arguments);
return sysExec(command, ip, function(data){
// console.log('startEphemeral', arguments);
if(data.match("doesn't exist.")){
return callback({status: 500, error: "doesn't exist."});
}
@ -76,8 +59,8 @@ var lxc = {
});
},
stop: function(name, callback){
return sysExec('lxc-stop -n '+ name, callback);
stop: function(name, ip, callback){
return sysExec('lxc-stop -n '+ name, ip, callback);
},
freeze: function(name, callback){
@ -90,7 +73,7 @@ var lxc = {
info: function(name, callback){
return sysExec('lxc-info -n '+name, function(data){
console.log('info', arguments);
// console.log('info', arguments);
if(data.match("doesn't exist")){
return callback({state: 'NULL'});
}
@ -133,6 +116,3 @@ var lxc = {
};
module.exports = lxc;
var orm = lxcORM()
setTimeout(function(){console.log(orm)}, 5000)

974
package-lock.json generated Normal file
View File

@ -0,0 +1,974 @@
{
"name": "manager",
"version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"accepts": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz",
"integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=",
"requires": {
"mime-types": "2.1.17",
"negotiator": "0.5.3"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
},
"async": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
"integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==",
"requires": {
"lodash": "4.17.4"
}
},
"aws-sign2": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
},
"aws4": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
},
"basic-auth": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz",
"integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA="
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"bl": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz",
"integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=",
"requires": {
"readable-stream": "2.0.6"
}
},
"body-parser": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.13.3.tgz",
"integrity": "sha1-wIzzMMM1jhUQFqBXRvE/ApyX+pc=",
"requires": {
"bytes": "2.1.0",
"content-type": "1.0.4",
"debug": "2.2.0",
"depd": "1.0.1",
"http-errors": "1.3.1",
"iconv-lite": "0.4.11",
"on-finished": "2.3.0",
"qs": "4.0.0",
"raw-body": "2.1.7",
"type-is": "1.6.15"
}
},
"boom": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
"requires": {
"hoek": "2.16.3"
}
},
"bytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz",
"integrity": "sha1-rJPEEOL/ycx89LRks4KJBn9eR7Q="
},
"caseless": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
"integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c="
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "2.2.1",
"escape-string-regexp": "1.0.5",
"has-ansi": "2.0.0",
"strip-ansi": "3.0.1",
"supports-color": "2.0.0"
}
},
"combined-stream": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
"requires": {
"delayed-stream": "1.0.0"
}
},
"commander": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
},
"content-disposition": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz",
"integrity": "sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs="
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz",
"integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU="
},
"cookie-parser": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz",
"integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=",
"requires": {
"cookie": "0.1.3",
"cookie-signature": "1.0.6"
}
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cryptiles": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
"requires": {
"boom": "2.10.1"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}
}
},
"debug": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
"requires": {
"ms": "0.7.1"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"depd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz",
"integrity": "sha1-gK7GTJ1tl+ZcwqnKqTwKpqv3Oqo="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"double-ended-queue": {
"version": "2.1.0-0",
"resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
"integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw="
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"ejs": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.3.4.tgz",
"integrity": "sha1-PHbKoJZks1g7ADevncE2557Gi5g="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"etag": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz",
"integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg="
},
"express": {
"version": "4.13.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz",
"integrity": "sha1-PAt288d1kMg0VzkGHsC9O6Bn7CQ=",
"requires": {
"accepts": "1.2.13",
"array-flatten": "1.1.1",
"content-disposition": "0.5.1",
"content-type": "1.0.4",
"cookie": "0.1.5",
"cookie-signature": "1.0.6",
"debug": "2.2.0",
"depd": "1.1.1",
"escape-html": "1.0.3",
"etag": "1.7.0",
"finalhandler": "0.4.1",
"fresh": "0.3.0",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "1.0.10",
"qs": "4.0.0",
"range-parser": "1.0.3",
"send": "0.13.1",
"serve-static": "1.10.3",
"type-is": "1.6.15",
"utils-merge": "1.0.0",
"vary": "1.0.1"
},
"dependencies": {
"cookie": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz",
"integrity": "sha1-armUiksa4hlSzSWIUwpHItQETXw="
},
"depd": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
}
}
},
"extend": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"finalhandler": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz",
"integrity": "sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0=",
"requires": {
"debug": "2.2.0",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"unpipe": "1.0.0"
}
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz",
"integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=",
"requires": {
"async": "2.5.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.17"
}
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
"fresh": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz",
"integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8="
},
"generate-function": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
"integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ="
},
"generate-object-property": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
"requires": {
"is-property": "1.0.2"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}
}
},
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"optional": true
},
"har-validator": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
"integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
"requires": {
"chalk": "1.1.3",
"commander": "2.11.0",
"is-my-json-valid": "2.16.1",
"pinkie-promise": "2.0.1"
}
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"requires": {
"ansi-regex": "2.1.1"
}
},
"hawk": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
"requires": {
"boom": "2.10.1",
"cryptiles": "2.0.5",
"hoek": "2.16.3",
"sntp": "1.0.9"
}
},
"hoek": {
"version": "2.16.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
},
"http-errors": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
"integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=",
"requires": {
"inherits": "2.0.3",
"statuses": "1.3.1"
}
},
"http-signature": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
"requires": {
"assert-plus": "0.2.0",
"jsprim": "1.4.1",
"sshpk": "1.13.1"
}
},
"iconv-lite": {
"version": "0.4.11",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz",
"integrity": "sha1-LstC/SlHRJIiCaLnxATayHk9it4="
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ipaddr.js": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz",
"integrity": "sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c="
},
"is": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz",
"integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU="
},
"is-my-json-valid": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz",
"integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==",
"requires": {
"generate-function": "2.0.0",
"generate-object-property": "1.2.0",
"jsonpointer": "4.0.1",
"xtend": "4.0.1"
}
},
"is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"requires": {
"graceful-fs": "4.1.11"
}
},
"jsonpointer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}
}
},
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
"integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM="
},
"mime-db": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
},
"mime-types": {
"version": "2.1.17",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
"requires": {
"mime-db": "1.30.0"
}
},
"morgan": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz",
"integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=",
"requires": {
"basic-auth": "1.0.4",
"debug": "2.2.0",
"depd": "1.0.1",
"on-finished": "2.3.0",
"on-headers": "1.0.1"
}
},
"ms": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg="
},
"negotiator": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz",
"integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g="
},
"node-uuid": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
"integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
},
"node.extend": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz",
"integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=",
"requires": {
"is": "3.2.1"
}
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"on-headers": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
"integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c="
},
"parseurl": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"pinkie": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
},
"pinkie-promise": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
"requires": {
"pinkie": "2.0.4"
}
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"proxy-addr": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz",
"integrity": "sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU=",
"requires": {
"forwarded": "0.1.2",
"ipaddr.js": "1.0.5"
}
},
"qs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz",
"integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc="
},
"range-parser": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz",
"integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU="
},
"raw-body": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
"integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
"requires": {
"bytes": "2.4.0",
"iconv-lite": "0.4.13",
"unpipe": "1.0.0"
},
"dependencies": {
"bytes": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
},
"iconv-lite": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
"integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI="
}
}
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "0.10.31",
"util-deprecate": "1.0.2"
}
},
"redis": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redis/-/redis-2.4.2.tgz",
"integrity": "sha1-L5FgJVompsrSt5vwhH4GcoChRuo=",
"requires": {
"double-ended-queue": "2.1.0-0",
"redis-commands": "1.3.1"
}
},
"redis-commands": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz",
"integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs="
},
"request": {
"version": "2.69.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.69.0.tgz",
"integrity": "sha1-z5HS4AB1KxIXFVwAUkGRGZGiNGo=",
"requires": {
"aws-sign2": "0.6.0",
"aws4": "1.6.0",
"bl": "1.0.3",
"caseless": "0.11.0",
"combined-stream": "1.0.5",
"extend": "3.0.1",
"forever-agent": "0.6.1",
"form-data": "1.0.1",
"har-validator": "2.0.6",
"hawk": "3.1.3",
"http-signature": "1.1.1",
"is-typedarray": "1.0.0",
"isstream": "0.1.2",
"json-stringify-safe": "5.0.1",
"mime-types": "2.1.17",
"node-uuid": "1.4.8",
"oauth-sign": "0.8.2",
"qs": "6.0.4",
"stringstream": "0.0.5",
"tough-cookie": "2.2.2",
"tunnel-agent": "0.4.3"
},
"dependencies": {
"qs": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.0.4.tgz",
"integrity": "sha1-UQGdhHIMk5uCc36EVWp4Izjs6ns="
}
}
},
"send": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.13.1.tgz",
"integrity": "sha1-ow1fTILIqbrprQCh2bG9vm8Zntc=",
"requires": {
"debug": "2.2.0",
"depd": "1.1.1",
"destroy": "1.0.4",
"escape-html": "1.0.3",
"etag": "1.7.0",
"fresh": "0.3.0",
"http-errors": "1.3.1",
"mime": "1.3.4",
"ms": "0.7.1",
"on-finished": "2.3.0",
"range-parser": "1.0.3",
"statuses": "1.2.1"
},
"dependencies": {
"depd": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
},
"statuses": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz",
"integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg="
}
}
},
"serve-favicon": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz",
"integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=",
"requires": {
"etag": "1.7.0",
"fresh": "0.3.0",
"ms": "0.7.2",
"parseurl": "1.3.2"
},
"dependencies": {
"ms": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
"integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
}
}
},
"serve-static": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz",
"integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=",
"requires": {
"escape-html": "1.0.3",
"parseurl": "1.3.2",
"send": "0.13.2"
},
"dependencies": {
"depd": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
},
"send": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz",
"integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=",
"requires": {
"debug": "2.2.0",
"depd": "1.1.1",
"destroy": "1.0.4",
"escape-html": "1.0.3",
"etag": "1.7.0",
"fresh": "0.3.0",
"http-errors": "1.3.1",
"mime": "1.3.4",
"ms": "0.7.1",
"on-finished": "2.3.0",
"range-parser": "1.0.3",
"statuses": "1.2.1"
}
},
"statuses": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz",
"integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg="
}
}
},
"sntp": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
"requires": {
"hoek": "2.16.3"
}
},
"sshpk": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.1",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}
}
},
"statuses": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
"integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"stringstream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "2.1.1"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
"tough-cookie": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz",
"integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc="
},
"tunnel-agent": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
"integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
},
"type-is": {
"version": "1.6.15",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
"integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
"requires": {
"media-typer": "0.3.0",
"mime-types": "2.1.17"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
"integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg="
},
"vary": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz",
"integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "1.3.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}
}
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}
}
}

View File

@ -11,10 +11,11 @@
"debug": "~2.2.0",
"ejs": "~2.3.3",
"express": "~4.13.1",
"jsonfile": "^2.3.1",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"node.extend": "~1.1.5",
"redis": "~2.4.2",
"request": "~2.69.0"
"request": "~2.69.0",
"serve-favicon": "~2.3.0"
}
}

View File

@ -2,52 +2,18 @@
var express = require('express');
var router = express.Router();
var extend = require('node.extend');
var redis = require("redis");
var client = redis.createClient();
var request = require('request');
// what is util for??
var util = require('util');
var lxc = require('../lxc');
var doapi = require('../doapi')();
var runner = function(req, res, ip){
return request.post({url:'http://'+ip, form: req.body}, function(error, response, body){
body = JSON.parse(body);
body['ip'] = ip.replace('10.0.', '');
return res.json(body);
});
};
var workers = require('./worker_collection.js');
var addToRedis = function(){
lxc.info(req.params.name, null, function(data){
var domain = req.query.domain || 'vm42.us';
domain = req.params.name+'.'+domain;
client.SADD("hosts", domain, function(){});
console.log('========STARTING===========');
var ip = data.ip + ':5000';
client.HSET(domain, "ip", ip, redis.print);
client.HSET(domain, "updated", (new Date).getTime(), redis.print);
client.hset(domain, "include", "proxy.include");
return res.json({status: 200, info: data});
});
};
router.get('/start/:name', function(req, res, next){
return lxc.start(req.params.name, function(data){
console.log('start', arguments);
if(!data){
return res.json({status: 500, name: req.params.name, message: data});
}else{
res.json({});
}
});
});
router.get('/live/:template/:name', function(req, res, next){
return lxc.startEphemeral(req.params.name, req.params.template, function (data) {
console.log('live', arguments);
return res.json(data);
});
});
workers.start();
// Why is this a GET?
router.get('/stop/:name', function(req, res, next){
return lxc.stop(req.params.name, function(data){
console.log('stop', arguments);
@ -59,65 +25,49 @@ router.get('/stop/:name', function(req, res, next){
});
});
router.get('/clone/:template/:name', function(req, res, next){
return lxc.clone(req.params.name, req.params.template, function(data){
console.log('clone', arguments);
if( data.match(/Created container/) ){
return res.json({status: 200});
}else{
return res.json({status: 500, message: data});
}
});
// Why is this a GET?
router.get('/destroyByTag', function(req, res, next) {
workers.destroyByTag();
res.send('?');
});
router.get('/destroy/:name', function(req, res, next){
return lxc.destroy(req.params.name, function(data){
console.log('destroy', arguments);
if(data){
return res.json({status: 500, message: data});
}else{
return res.json({status: 200});
}
});
router.get('/liststuff', function(req, res, next){
var obj = util.inspect(workers, {depth: 4});
res.send(`
<h1>Workers</h1>
<pre>${obj}</pre>
<h1>label2runner</h1>
<pre>${util.inspect(workers.runnerMap)}</pre>
<h1>DO calls</h1>
${doapi.calls}
`);
});
router.get('/info/:name', function(req, res, next){
return lxc.info(req.params.name, function(data){
return res.json(data);
});
router.get('/ping/:runner', function(req, res, next){
var runner = workers.getRunner(req.params.runner);
// runnerTimeout(runner);
runner.setTimeout();
res.json({res:''});
});
router.get('/list', function(req, res, next) {
return lxc.list(function(data){
return res.json(data);
});
});
router.post('/run/:runner?', function (req, res, next){
console.log(`Request runner route!`);
router.post('/run/:ip?', function doRun(req, res, next){
// check if server is
return lxc.list(function(data){
if(!req.params.ip) data = [];
var ip = '10.0.'+ req.params.ip;
var found = false;
for(var idx=data.length; idx--;){
if( data[idx]['ipv4'] === ip ){
found = true;
break;
return workers.attemptRun(
req.body.code, req.query.once, req.params.runner,
(body) => {
res.json(body);
},
(error, statusCode) => {
if (statusCode === 503){
res.status(503);
return res.json({error: 'No runners, try again soon.'});
} else if (statusCode === 400){
return res.status(400).json({error: 'Runner restarted too many times'});
}
}
if(found){
return runner(req, res, ip)
}else{
var name = 'u1-'+(Math.random()*100).toString().replace('.','');
return lxc.startEphemeral(name, 'u1', function(data){
return runner(req, res, data.ip);
});
}
});
);
});
module.exports = router;

607
routes/worker_collection.js Normal file
View File

@ -0,0 +1,607 @@
'use strict';
var jsonfile = require('jsonfile');
var request = require('request');
var lxc = require('../lxc');
var doapi = require('../doapi')();
var settings = require('./workers.json');
var fs = require('fs');
settings.tagPrefix = settings.tagPrefix || 'clwV';
var utils = (function(){
return {
"uuid": function(){
return (Math.random()*100).toString().slice(-4);
}
};
})();
var Runner = (function(){
var proto = {};
var __empty = function(){};
proto.runnerMap = {};
proto.cleanUp = function(label){
delete proto.runnerMap[label];
};
proto.set = function(runner){
proto.runnerMap[runner.label] = runner;
proto.runnerMap[runner.label] = runner;
};
proto.get = function(label){
return proto.runnerMap[label];
};
proto.create = function(config){
var runner = Object.create(proto);
Object.assign(runner, config);
return runner;
};
proto.free = function(){
// track how often this happens in a minute
var runner = this;
lxc.stop(runner.name, runner.worker.ip);
// this should be done by the worker
runner.worker.usedrunners--;
if(runner.hasOwnProperty('timeout')){
clearTimeout(runner.timeout);
}
if(runner.hasOwnProperty('cleanUp')){
runner.cleanUp();
}
// worker has more space now
// worker should track this
setTimeout(()=>{
runner.worker.populate();
}, 0);
};
proto.setTimeout = function(time){
time = time || 60000; // 1 minutes
var runner = this;
if(runner.hasOwnProperty('timeout')){
clearTimeout(runner.timeout);
}
return runner.timeout = setTimeout(function(){
runner.free();
}, time);
};
return proto;
})();
var Worker = (function(){
var proto = {};
var __empty = function(){};
// settings should probably be retrieved via a function
proto.settings = settings;
var maxSyncAttempts = 6;
proto.create = function(config){
var worker = Object.create(proto);
Object.assign(worker, config);
worker.networks.v4.forEach(function(value){
worker[ value.type + 'IP' ] = value.ip_address;
});
worker.availrunners = [];
worker.ip = worker.publicIP;
worker.usedrunners = 0;
worker.age = +(new Date());
worker.canSchedule = true;
worker.isBuildingRunners = false;
worker.isSyncing = false;
worker.syncAttempts = 0;
return worker;
};
proto.populate = function(callback){
callback = callback || __empty;
return lxc.startEphemeral(
"crunner-batch-$RANDOM-id-$RANDOM", "crunner0", this.ip, callback
);
};
proto.getRunner = function(){
if(this.availrunners.length === 0) return false;
// console.log('getting runner from ', worker.name, ' avail length ', this.availrunners.length);
var runner = this.availrunners.pop();
this.usedrunners++;
runner.setTimeout();
return runner;
};
proto.ramPercentUsed = function(callback){
// checks the percent of ram used on a worker.
return lxc.exec(
"python3 -c \"a=`head /proc/meminfo|grep MemAvail|grep -Po '\\d+'`;t=`head /proc/meminfo|grep MemTotal|grep -Po '\\d+'`;print(round(((t-a)/t)*100, 2))\"",
this.ip,
callback
);
};
proto.destroy = function(){
var worker = this;
worker.canSchedule = false;
return doapi.dropletDestroy(this.id, function(body) {
console.log('Deleted worker', worker.name);
});
};
proto.isZombie = function(){
return this.availrunners.length === 0 && this.usedrunners === 0 && !this.isBuildingRunners;
};
proto.register = function(){
var worker = this;
doapi.domianAddRecord({
domain: "codeland.us",
type: "A",
name: "*." + this.name + ".workers",
data: this.publicIP
});
};
// When should this be called
proto.sync = function(callback, errorCallback, maxAttempts){
var worker = this;
maxAttempts = maxAttempts || maxSyncAttempts;
worker.isSyncing = true;
callback = callback || __empty;
errorCallback = errorCallback || __empty;
// this will call the droplet or the droplet will send the data using a cron job
// mainly to update the active runners on the worker
// potentially collect stats about the droplet as well
// - check memory and check runners
lxc.exec('lxc-ls --fancy', worker.ip, function(data, error, stderr){
if (error){
console.log("Sync Error: \n", error);
if (worker.syncAttempts > maxAttempts){
setTimeout(function(){
errorCallback(error, worker);
}, 0);
} else {
console.log("Waiting 15 seconds")
worker.syncAttempts++;
setTimeout(function(){
worker.sync(maxAttempts, callback, errorCallback);
}, 15000);
}
} else {
var output = data.split("\n");
var keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1);
var runners = [];
keys = keys.map(function(v){return v.toLowerCase()});
output = output.slice(0).slice(0,-1);
for(var i in output){
if(output[i].match(/^-/)) continue; // compatibility with 1.x and 2.x output
var aIn = output[i].split(/\s+/).slice(0,-1);
var mapOut = {};
aIn.map(function(value,idx){
mapOut[keys[idx]] = value;
});
runners.push(mapOut);
}
console.log(`RUNNERS FOUND[=> ${worker.ip}`);
console.log(`RUNNERS FOUND[=>`, runners);
worker.availrunners = [];
for (let idx = 0, stop = runners.length; idx < stop; idx++){
if(runners[idx].state === "STOPPED" || Runner.get(worker.name + ':' + runners[idx].name)){
continue;
} else {
var runner = Runner.create({
"name": runners[idx].name,
"ipv4": runners[idx].ipv4,
"worker": worker,
"label": worker.name + ':' + runners[idx].name
});
worker.availrunners.push(runner);
}
}
console.log(`RUNNERS AVAILABLE[=>`, worker.availrunners);
// TODO: Determine if this flag is needed anymore
worker.isBuildingRunners = false;
worker.isSyncing = false;
worker.syncAttempts = 0;
callback(null, worker);
}
});
};
proto.initialize = function(params, config){
// Create droplet
// Once active the droplet begins to create runners
var maxMemoryUsage = params.maxMemoryUsage || config.maxMemoryUsage || 80;
var worker_uuid = utils.uuid();
var phone_home = config.home || "/worker/ping";
var callback = params.callback || __empty;
var errorCallback = params.errorCallback || empty;
fs.readFile(__dirname + "/../allocate_runners.sh", function(error, file){
doapi.dropletToActive({
name: config.tagPrefix + (config.version + "") + '-' + utils.uuid(),
image: config.image,
size: config.size,
user_data: proto.__buildCommand(file, maxMemoryUsage, worker_uuid, phone_home),
onCreate: function(data){
doapi.dropletSetTag(
config.tagPrefix + config.version,
data.droplet.id
);
},
onActive: function(data, args){
data.worker_uuid = worker_uuid;
var worker = Worker.create(data);
// wait for boot before syncing runners
setTimeout(function(){
worker.sync(callback, errorCallback);
}, 75000);
}
});
});
};
proto.__buildCommand = function(file, maxMemoryUsage, worker_uuid, phone_home){
var scriptSetup, script, createScript, makeScriptExecutable, setupCrontab;
var interval = 1;
// worker_uuid and phone_home are only usable with localhost tunnels setup in dev
// cronjobSetup = `export PATH=\${PATH};export WORKER_UUID="${worker_uuid}";export PHONE_HOME=${phone_home};export maxMemoryUsage=${maxMemoryUsage};`;
scriptSetup = `export PATH=\${PATH};export WORKER_UUID="${worker_uuid}";export maxMemoryUsage=${maxMemoryUsage};`;
script = scriptSetup + `echo '${file.toString("base64")}'|base64 --decode|bash`;
createScript = `echo "${script}" | cat > /home/virt/allocate_runners.sh`;
makeScriptExecutable = `chmod o+x /home/virt/allocate_runners.sh`;
setupCrontab = `echo "*/${interval} * * * * /home/virt/allocate_runners.sh > /home/virt/allocate_runners.log 2>&1" | crontab -u virt -`;
return `#!/bin/bash\n\n${createScript} && ${makeScriptExecutable} && ${setupCrontab};`;
};
return proto;
})();
var WorkerCollection = (function(){
// works array constructor. This will hold the works(order by creation) and all
// the methods interacting with the workers.
// base array that will be the workers objects.
var workers = [];
// persistent settings object
// .image is the currently used Digital Ocean snap shot ID
// .lastSnapShotId is the previous ID used Digital Ocean snap shot
// .version is the current worker version
// .size is the base Droplet size for worker creation
// .min is the minimum amount of workers that should exist
// .max is the maximum amount of works that ca exist
// .minAvail is the amount of empty workers there should be
workers.settings = settings;
// How many droplets are currently in the process of being created. It takes
// about 3 minutes to create a worker.
workers.currentCreating = 0;
// REMOVE THIS
workers.runnerMap = Runner.runnerMap;
workers.setRunner = function(runner){
Runner.set(runner);
};
workers.getRunner = function(label){
return Runner.get(label);
};
//**************************************************
//**************************************************
workers.getAvailableRunner = function(runner){
for(let worker of workers){
if(worker.availrunners.length === 0) continue;
if(runner && runner.worker.age <= worker.age) break;
if(runner) runner.free();
return worker.getRunner();
}
if(runner) return runner;
};
workers.create = function(config){
// manages the creation of a work from first call to all runners seeded
// dont create more workers then the settings file allows
if(workers.length + workers.currentCreating >= workers.settings.max ) return false;
workers.currentCreating++;
var count = 0;
config = config || workers.settings;
Worker.initialize({
"callback": function(error, worker){
console.log("Seeded runners on", worker.name);
workers.push(worker);
worker.register();
workers.currentCreating--;
},
"errorCallback": function(error, worker){
// destroy worker
workers.currentCreating--;
}
}, config);
};
workers.__workersId = function(argument){
// create array of all current worker Digital Ocean ID
return workers.map(function(item){
return item.id;
});
};
workers.destroy = function(worker){
// removes last one
// X TODO: If worker is passed, check for it in the workers array and
// remove it if found.
if ( worker ){
var worker_idx = workers.indexOf(worker);
if (~worker_idx){
workers.splice(worker_idx, 1);
return worker.destroy();
}
} else {
worker = workers.pop();
return worker.destroy();
}
};
workers.destroyByTag = function(tag){
// Delete works that with
tag = tag || workers.settings.tagPrefix + workers.settings.version;
let currentIDs = workers.__workersId();
let deleteDroplets = function(droplets){
if(droplets.length === 0) return true;
let droplet = droplets.pop();
if(~currentIDs.indexOf(droplet.id)) return deleteDroplets(droplets);
doapi.dropletDestroy(droplet.id, function(body){
setTimeout(deleteDroplets, 1000, droplets);
if(!droplets.length) console.log(`Finished deleting workers tagged ${tag}.`);
});
}
// TODO: move to seperate method
doapi.dropletsByTag(tag, function(data){
data = JSON.parse(data);
console.log(`Deleting ${data['droplets'].length} workers tagged ${tag}. Workers`,
data['droplets'].map(function(item){
return item.name+' | '+item.id;
})
);
deleteDroplets(data['droplets']);
});
};
workers.checkForZombies = function(callback){
// check to make sure all works are used or usable.
if (workers.length === 0) callback();
let
zombies = 0,
syncedCount = workers.length,
workerCleanUp = function(error, worker){
console.log(`Zombie! Worker ${worker.name}, destroying.`);
workers.destroy(worker);
zombies++;
if(!--count) callback();
};
for(let worker of workers){
console.log(`Checking if ${worker.name} is a zombie worker.`);
// if a runner has no available runners and no used runners, its a
// zombie. This should happen when a newer image ID has been added
// and old workers slowly lose there usefulness.
worker.sync(function(error, worker){
if(worker.isZombie()) workerCleanUp(error, worker);
}, workerCleanUp);
}
};
workers.checkBalance = function(){
console.log(`${(new Date())} Checking balance.`);
workers.checkForZombies(function(){
// if there are workers being created, stop scale up and down check
var skipBalance = workers.currentCreating + workers.length >= workers.settings.min;
if(workers.currentCreating && skipBalance){
return console.log(`Killing balance, workers are being created.`);
}
workers.balance();
});
};
workers.balance = function(){
console.log(`BALANCING: ${(new Date())}`);
// count workers and locate oldest worker
var oldestWorker, isNotOlder, workerCount = 0;
for(let worker of workers){
console.log(`
Checking worker
worker.name: ${worker.name}
worker.usedrunners: ${worker.usedrunners}
worker.availrunners: ${worker.availrunners.length}
workerCount: ${workerCount}
compare: ${worker.usedrunners !== 0}
`);
if(worker.usedrunners === 0){
workerCount++;
isNotOlder = oldestWorker && oldestWorker.age < worker.age
oldestWorker = (isNotOlder ? oldestWorker:worker);
}
}
if(workerCount > workers.settings.minAvail){
// Remove oldest worker if there are more than the settings file state
console.log(`
Destroying Worker
Last ${workers.settings.minAvail} workers not used, killing last worker
workerCount: ${workerCount}
minAvail: ${workers.settings.minAvail}
workers: ${workers.length}
`);
return workers.destroy(oldestWorker);
} else if( workerCount < workers.settings.minAvail){
// Creates worker if there are less than the settings state
console.log(`
Creating Worker
last 3 workers have no free runners, starting worker,
workerCount: ${workerCount}
minAvail: ${workers.settings.minAvail}
workers: ${workers.length}
`);
return workers.create();
} else {
console.log(`
Blanced
LMA: ${workerCount}
Settings MA: ${workers.settings.minAvail}
Workers: ${workers.length}
`);
}
};
workers.start = function(interval){
setInterval(workers.checkBalance, interval || 15000);
workers.destroyByTag();
};
workers.settingsSave = function(){
// save the live settings file to disk
jsonfile.writeFile('./workers.json', workers.settings, {spaces: 2}, function(err) {
console.error(err);
});
};
workers.attemptRun = function(code, once, runnerLabel, callback, errorCallback, count){
// PARAMS: code, once, runnerLabel, callback, errorCallback, count;
var runner = workers.getAvailableRunner(
workers.getRunner(runnerLabel)
);
if(!runner){
console.log(`No runner available!`);
return errorCallback(null, 503);
}
count = count || 0;
console.log(`Runner starting attempt ${count}.`);
if(count > 2){
console.log(`Runner attempt failed, to many requests!`);
return errorCallback(null, 400);
}
var httpOptions = {
url: 'http://' + runner.worker.ip,
headers: {
Host: runner.name
},
body: JSON.stringify({
code: code
})
};
// Move the http stuff to the runner
return request.post(httpOptions, function(error, response, body){
// console.log('runner response:', arguments)
if(error || response.statusCode !== 200) {
return workers.attemptRun(code, once, void 0, callback, errorCallback, ++count);
}
body = JSON.parse(body);
if(once){
runner.free();
} else {
runner.setTimeout();
body['ip'] = runner.label;
body['rname'] = runner.name;
body['wname'] = runner.worker.name;
workers.setRunner(runner);
}
return callback(body);
});
};
workers.add = function(newWorkers){
newWorkers.forEach(function(worker){
workers.push(worker);
});
};
// does this have to be last?
// make sure Digital Ocean has a tag for the current worker version
doapi.tagCreate(workers.settings.tagPrefix + workers.settings.version);
return workers;
})();
module.exports = WorkerCollection;

10
routes/workers.json Normal file
View File

@ -0,0 +1,10 @@
{
"image":"25092187",
"version":10,
"lastSnapShotId":"23505298",
"size":"512mb",
"max":100,
"min":3,
"minAvail":3,
"tagPrefix": "dev--CLW"
}

3
rx.sh
View File

@ -1,3 +0,0 @@
sudo cgm create all virt
sudo cgm chown all virt $(id -u virt) $(id -g virt)

View File

@ -1,5 +1,14 @@
# Random things not to lose
## Auto start
`@reboot /usr/local/bin/forever start -o /var/log/forver.out.log -e /var/log/sorver.err.log -c "/usr/local/bin/codebox run -p 5000" /workspace/`
http://stackoverflow.com/a/13388741/3140931
```crontab
@reboot /usr/local/bin/forever start -o /var/log/forver.out.log -e /var/log/sorver.err.log -c "/usr/local/bin/codebox run -p 5000" /workspace/`
```
## LXC permission issue
```bash
sudo cgm create all virt
sudo cgm chown all virt $(id -u virt) $(id -g virt)
```

71
testAPI.js Normal file
View File

@ -0,0 +1,71 @@
const request = require('request');
var callRunner = (function(){
let started = 0;
let completed = 0;
let errors = 0;
let noRunner = 0;
let func = function(code, callback) {
// code | `string` block of code to send runner or
// `number` sleep timeout in seconds
let sleepTime = 0;
let id = started++;
callback = callback || function(){};
if(/^\+?(0|[1-9]\d*)$/.test(code)){
sleepTime = code;
code = null;
}
console.log(id, ': Running...');
let httpOptions = {
url: 'http://localhost:2000/api/run?once=true',
form: {
code: code || `python3 -c "
from time import sleep
sleep(${sleepTime})
"`,
}
};
return request.post(httpOptions, function(error, response, body){
completed++;
let res = ``;
if(response.statusCode == 503){
noRunner++;
}else if(error || response.statusCode !== 200){
errors++;
console.log(`
ID: ${id}
Error: ${error}
`);
} else {
body = JSON.parse(body);
res = (Buffer.from(body.res, 'base64').toString('ascii'));
}
console.log(`
${id} with results ${res}.
Errors ${errors}.
No runner ${noRunner}.
Completed ${completed}
`);
callback()
});
};
return func;
})();
let __do = function(till){
if(!till) return ;
callRunner(String(Math.random())[3]);
setTimeout(__do, 1500, --till);
};
__do(1000);