315 Commits
1 ... master

Author SHA1 Message Date
6e034f26c3 Create guest_setup.sh 2017-10-26 11:55:19 -04:00
f01049df74 Create host_setup.sh 2017-10-26 11:54:40 -04:00
0a45462205 Update README.md 2017-10-25 17:21:49 -04:00
9dc7b76d11 Update README.md 2017-10-25 16:41:38 -04:00
10e5c885f6 Update README.md 2017-10-25 16:19:37 -04:00
ceb08124f0 Update README.md 2017-10-25 16:19:09 -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
14 changed files with 1820 additions and 132 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

@ -1,5 +1,5 @@
# lxc_manager_node
This has been tested on **clean** install of ubuntu 14.04 64bit.
This has been tested on **clean** install of ubuntu 16.04 64bit.
## install
Update you system to the newest packages and reboot. You may need to do this several times:
@ -18,9 +18,13 @@ Now you can install the packages we need:
sudo add-apt-repository ppa:ubuntu-lxc/stable
sudo add-apt-repository ppa:ubuntu-lxc/cgmanager-stable
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install git nodejs npm lxc redis-server btrfs-tools
sudo apt-get install git nodejs npm lxc btrfs-tools lxctl lxc-templates uidmap libpam-cgfs
```
### may need this
https://discuss.linuxcontainers.org/t/failed-creating-cgroups/272/10 looking more into it.
remap `nodejs` to `node`:
```bash
sudo ln -s /usr/bin/nodejs /usr/bin/node
@ -53,10 +57,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
@ -72,7 +77,52 @@ If everything worked you can stop and delete the container
lxc-stop -n test-ubuntu
lxc-destroy -n test-ubuntu
```
## Open resty config file
```lua
server {
listen 80;
location / {
resolver 10.0.3.1; # use LXC dns
set $target '';
access_by_lua '
function mysplit(inputstr, sep)
-- http://stackoverflow.com/a/7615129/3140931
if sep == nil then
sep = "%s"
end
local t={} ; i=0
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
t[i] = str
i = i + 1
end
return t,i
end
host, hostLen = mysplit(ngx.var.host, ".")
if hostLen == 1 then
ngx.var.target = host[0]..":15000"
elseif hostLen == 6 then
ngx.var.target = host[1]..":"..host[0]
elseif hostLen == 5 then
ngx.var.target = host[0]..":15000"
else
return ngx.exit(599)
end
';
proxy_pass http://$target;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
# auto start
## crontab

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;

18
guest_setup.sh Normal file
View File

@ -0,0 +1,18 @@
apt update;
apt upgrade -y;
wget https://github.com/wmantly/crunner/blob/master/crunner?raw=true -O /usr/local/bin/crunner;
chmod +x /usr/local/bin/crunner;
apt install git nano wget python3-dev python3-pip;
echo "
#!/bin/bash;
export NODE_PATH='/usr/local/lib/node_modules:$NODE_PATH';
export TERM=xterm-256color;
cd ~;
crunner &;
exit 0;
" > /opt/bytedev.sh

41
host_setup.sh Normal file
View File

@ -0,0 +1,41 @@
echo "Update the base system\n";
apt update;
apt upgrade -y;
echo "\n\n\nInstall stuff\n";
add-apt-repository -y ppa:ubuntu-lxc/stable;
apt update;
apt upgrade -y;
apt install -y git lxc btrfs-tools lxctl lxc-templates uidmap libpam-cgfs libpcre3-dev libssl-dev perl make build-essential curl;
echo "\n\n\ninstalling open resty\n";
# import our GPG key:
wget -qO - https://openresty.org/package/pubkey.gpg | sudo apt-key add -;
# for installing the add-apt-repository command
# (you can remove this package and its dependencies later):
apt-get -y install software-properties-common;
# add the our official APT repository:
add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main";
# to update the APT index:
apt-get update;
apt-get install -y openresty;
# TODO!
# Add the proxy config file
echo "\n\n\nSet up virt user\n";
adduser virt --gecos "" --disabled-password;
echo "virt:1lovebyte" | chpasswd;
echo "virt veth lxcbr0 1024" | tee -a /etc/lxc/lxc-usernet;
# TODO!
# added default base config for LXC runners.

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,51 +2,376 @@
var express = require('express');
var router = express.Router();
var extend = require('node.extend');
var redis = require("redis");
var client = redis.createClient();
var util = require('util');
var request = require('request');
var jsonfile = require('jsonfile');
var lxc = require('../lxc');
var doapi = require('../doapi')();
var settings = require('./workers.json');
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);
});
};
// mapping of current used runners for quick loop up based on runner label
var label2runner = {};
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(){});
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});
});
};
//
var tagPrefix = settings.tagPrefix || 'clwV';
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({});
var workers = (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;
workers.create = function(){
// manages the creation of a work from first call to all runners seeded
// dont create more workers then the settings file allows
if(workers.currentCreating > workers.settings.max ) return false;
workers.currentCreating++;
doapi.dropletToActive({
name: 'clw'+workers.settings.version+'-'+(Math.random()*100).toString().slice(-4),
image: workers.settings.image,
size: workers.settings.size,
onCreate: function(data){
doapi.dropletSetTag(tagPrefix+workers.settings.version, data.droplet.id);
},
onActive: function(worker, args){
workers.startRunners({
worker: workers.makeWorkerObj(worker),
onStart: function(runner, args){
workers.push(args.worker);
doapi.domianAddRecord({
domain: "codeland.us",
type: "A",
name: "*."+worker.name+".workers",
data: worker.publicIP
});
args.onStart = function(){};
},
onDone: function(args){
console.log("Seeded runners on", worker.name);
workers.currentCreating--;
}
});
}
});
};
workers.makeWorkerObj = function(worker){
// Create object for each worker.
worker.networks.v4.forEach(function(value){
worker[value.type+'IP'] = value.ip_address;
});
worker.availrunners = [];
worker.ip = worker.publicIP;
worker.usedrunners = 0;
worker.index = workers.length;
worker.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++;
runnerTimeout(runner);
return runner;
}
});
});
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);
return worker;
};
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){
// todo: If worker is passed, check for it in the workers array and
// remove it if found.
var worker = worker || workers.pop();
return doapi.dropletDestroy(worker.id, function(body) {
console.log('Deleted worker', worker.name);
});
};
workers.destroyByTag = function(tag){
// Delete works that with
tag = tag || 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}.`);
});
}
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.startRunners = function(args){
// console.log('starting runners on', args.worker.name, args.worker.ip)
// dont make runners on out dated workers
if(!args.worker || workers.settings.image > args.worker.image.id){
console.log(`Blocked outdated worker(${args.worker.image.id}), current image ${workers.settings.image}.`)
return ;
}
// percent of used RAM to stop runner creation
args.stopPercent = args.stopPercent || 80;
args.onStart = args.onStart || function(){};
args.onDone = args.onDone || function(){};
ramPercentUsed(args.worker.ip, function(usedMemPercent){
if(usedMemPercent > args.stopPercent ){
console.log('using', String(usedMemPercent).trim(),
'percent memory, stopping runner creation!', args.worker.availrunners.length,
'created on ', args.worker.name
);
args.onDone(args);
return ;
}
var name = 'crunner-'+(Math.random()*100).toString().slice(-4);
// console.log('Free ram check passed!')
lxc.startEphemeral(name, 'crunner0', args.worker.ip, function(data){
if(!data.ip) return setTimeout(workers.startRunners, 0, args);
// console.log('started runner on', args.worker.name)
var runner = {
ip: data.ip,
name: name,
worker: args.worker,
label: args.worker.name + ':' + name
};
args.onStart(runner, args);
args.worker.availrunners.push(runner);
setTimeout(workers.startRunners, 0, args);
});
});
};
workers.checkForZombies = function(){
// check to make sure all works are used or usable.
let zombies = 0;
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.
if(worker.availrunners.length === 0 && worker.usedrunners === 0){
workers.splice(workers.indexOf(worker), 1);
console.log(`Zombie! Worker ${worker.name}, destroying.`);
workers.destroy(worker);
zombies++;
}
}
return zombies;
};
workers.checkBalance = function(){
console.log(`Checking balance.`);
workers.checkForZombies();
// if there are workers being created, stop scale up and down check
if(workers.currentCreating+workers.length < workers.settings.min) null;
else if(workers.currentCreating)
return console.log(`Killing balance, workers are being created.`);
// hold amount of workers with no used runners
var lastMinAval = 0;
// check to make sure the `workers.settings.minAvail` have free runners
for(let worker of workers.slice(-workers.settings.minAvail)){
if(worker.usedrunners === 0){
lastMinAval++;
}else{
// no need to keep counting, workers need to be created
break;
}
}
if(lastMinAval > workers.settings.minAvail){
// Remove workers if there are more then the settings states
console.log(
`Last ${workers.settings.minAvail} workers not used, killing last worker`,
'lastMinAval:', lastMinAval,
'minAvail:', workers.settings.minAvail,
'workers:', workers.length
);
return workers.destroy();
} else if(lastMinAval < workers.settings.minAvail){
// creates workers if the settings file demands it
console.log(
'last 3 workers have no free runners, starting worker',
'lastMinAval:', lastMinAval,
'minAvail:', workers.settings.minAvail,
'workers:', workers.length
);
return workers.create();
}
};
workers.settingsSave = function(){
// save the live settings file to disk
jsonfile.writeFile('./workers.json', workers.settings, {spaces: 2}, function(err) {
console.error(err);
});
};
workers.add = function(newWorkers){
newWorkers.forEach(function(worker){
workers.push(worker);
});
};
// make sure Digital Ocean has a tag for the current worker version
doapi.tagCreate(tagPrefix+workers.settings.version);
return workers;
})();
var ramPercentUsed = function(ip, 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))\"",
ip,
callback
);
};
var runnerTimeout = function(runner, time){
time = time || 60000; // 1 minutes
if(runner.hasOwnProperty('timeout')){
clearTimeout(runner.timeout);
}
return runner.timeout = setTimeout(runnerFree, time, runner);
};
var runnerFree = function(runner){
lxc.stop(runner.name, runner.worker.ip);
runner.worker.usedrunners--;
if(runner.hasOwnProperty('timeout')){
clearTimeout(runner.timeout);
}
delete label2runner[runner.label];
console.log(`Runner freed ${runner.label}.`, runner.worker);
workers.startRunners({worker: runner.worker});
};
var getAvailrunner = function(runner){
for(let worker of workers){
if(worker.availrunners.length === 0) continue;
if(runner && runner.worker.index <= worker.index) break;
if(runner) runnerFree(runner);
return worker.getRunner();
}
if(runner) return runner;
};
var run = function(req, res, runner, count){
count = count || 0;
console.log(`Runner starting attempt ${count}.`);
if(!runner){
console.log(`No runner available!`);
res.status(503);
return res.json({error: 'No runners, try again soon.'});
}
if(count > 2){
console.log(`Runner attempt failed, to many requests!`);
return res.status(400).json({error: 'Runner restarted to many times'});
}
var httpOptions = {
url: 'http://' + runner.worker.ip,
headers: {
Host: runner.name
},
body: JSON.stringify({
code: req.body.code
})
};
return request.post(httpOptions, function(error, response, body){
// console.log('runner response:', arguments)
if(error || response.statusCode !== 200) return run(req, res, getAvailrunner(), ++count);
body = JSON.parse(body);
if(req.query.once){
res.json(body);
return runnerFree(runner, 0);
}
label2runner[runner.label] = runner;
body['ip'] = runner.label;
body['rname'] = runner.name;
body['wname'] = runner.worker.name;
res.json(body);
runnerTimeout(runner);
});
});
};
console.log('========STARTING===========')
setInterval(workers.checkBalance, 15000);
workers.destroyByTag();
router.get('/stop/:name', function(req, res, next){
return lxc.stop(req.params.name, function(data){
@ -58,66 +383,102 @@ 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});
}
});
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.post('/updateID', function(req, res, next){
var newWorkers = {
workers: [],
image: req.query.image,
target: req.query.target || workers.length,
size: req.query.size || workers.settings.size,
version: workers.settings.version+1,
min: req.query.min || workers.settings,
minAvail: req.query.minAvail || workers.settings
};
router.get('/info/:name', function(req, res, next){
return lxc.info(req.params.name, function(data){
return res.json(data);
});
});
doapi.tagCreate(tagPrefix+newWorkers.version);
workers.destroyByTag(tagPrefix+newWorkers.version);
router.get('/list', function(req, res, next) {
return lxc.list(function(data){
return res.json(data);
});
});
for(var i=0; i<newWorkers.target; i++){
router.post('/run/:ip?', function doRun(req, res, next){
// check if server is
doapi.dropletToActive({
name: 'clw'+newWorkers.version+'-'+(Math.random()*100).toString().slice(-4),
newWorkers: newWorkers,
image: newWorkers.image,
size: newWorkers.size,
onCreate: function(data, args){
doapi.dropletSetTag(tagPrefix+args.newWorkers.version, data.droplet.id);
},
onActive: function(droplet, args){
workers.startRunners({
worker: workers.makeWorkerObj(droplet),
newWorkers: args.newWorkers,
onStart: function(runner, args){
args.newWorkers.workers.push(args.worker);
console.log('onStart', args.worker.name);
args.onStart = function(){};
},
onDone: function(args){
console.log('new workers:', args.newWorkers.workers.length);
doapi.domianAddRecord({
domain: "codeland.us",
type: "A",
name: "*."+args.worker.name+".workers",
data: args.worker.publicIP
});
if(args.newWorkers.workers.length >= args.newWorkers.target){
console.log('upgrade complete!')
workers.settings.image = args.newWorkers.image;
workers.settings.size = args.newWorkers.size;
workers.settings.min = args.newWorkers.min;
workers.settings.minAvail = args.newWorkers.minAvail;
return lxc.list(function(data){
if(!req.params.ip) data = [];
var ip = '10.0.'+ req.params.ip;
var found = false;
workers.forEach(function(worker){
worker.availrunners.forEach(function(runner){
lxc.stop(runner.name, runner.worker.ip);
});
worker.availrunners = [];
});
for(var idx=data.length; idx--;){
if( data[idx]['ipv4'] === ip ){
found = true;
break;
workers.add(args.newWorkers.workers);
workers.settingsSave();
workers.checkBalance();
}
}
});
}
}
});
}
res.json({status: "maybe?"});
});
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);
});
}
});
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(label2runner)}</pre>
<h1>DO calls</h1>
${doapi.calls}
`);
});
router.get('/ping/:runner', function(req, res, next){
var runner = label2runner[req.params.runner];
runnerTimeout(runner);
res.json({res:''});
});
router.post('/run/:runner?', function (req, res, next){
console.log(`Request runner route!`);
var runner = getAvailrunner(label2runner[req.params.runner]);
return run(req, res, runner);
});
module.exports = router;

9
routes/workers.json Normal file
View File

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

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)
```

61
testAPI.js Normal file
View File

@ -0,0 +1,61 @@
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://codeland.bytedev.co: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++;
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(30)