Compare commits
935 Commits
spike/comp
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
078513f603 | ||
|
a1ff036db1 | ||
|
fc81d666d0 | ||
|
deb1a8436f | ||
|
cad1431e79 | ||
|
2f9d135319 | ||
|
c268d88a4d | ||
|
6698a8eacb | ||
|
1e8e89b3c8 | ||
|
063e40859d | ||
|
fc84358dff | ||
|
6736caaf45 | ||
|
5cb02d709c | ||
|
b66f761a9e | ||
|
8422cdfe8c | ||
|
109988536b | ||
|
d75ae0f14f | ||
|
5c98a4cecb | ||
|
0189822a08 | ||
|
5d46689869 | ||
|
04cb9c32f8 | ||
|
8e6adb1ef4 | ||
|
a1154b2520 | ||
|
155a065281 | ||
|
f388e52549 | ||
|
882085a170 | ||
|
77fd895b6c | ||
|
bd332423be | ||
|
91e1fb192b | ||
|
88fe0ea92d | ||
|
8bb4c31aba | ||
|
867e9b35a0 | ||
|
574c3add4e | ||
|
c233b0d757 | ||
|
84b2d67d2c | ||
|
062ff0ba67 | ||
|
b00baa7028 | ||
|
588b833045 | ||
|
b3edb3aa02 | ||
|
542b491b52 | ||
|
7d8b478d20 | ||
|
7531e503f2 | ||
|
d1b2ba0002 | ||
|
98a8b2eb5b | ||
|
de356e1fbe | ||
|
f9c89cbccc | ||
|
1317894f27 | ||
|
f007889283 | ||
|
831be94521 | ||
|
e321c20906 | ||
|
429ad17262 | ||
|
d591d93547 | ||
|
33d3d4343d | ||
|
32d5cdc293 | ||
|
316773d9b7 | ||
|
0ae1290a5e | ||
|
3f75f812fa | ||
|
25223e7324 | ||
|
7651dff619 | ||
|
be18478f6c | ||
|
b929370124 | ||
|
e61399aa26 | ||
|
b429bc15ec | ||
|
1cd91b234f | ||
|
21317db964 | ||
|
95e420c419 | ||
|
c413677b0e | ||
|
f73a9f4eca | ||
|
682f9db749 | ||
|
5d274a419a | ||
|
0b9c464bb0 | ||
|
e2a3fb73df | ||
|
154b4cfeb6 | ||
|
cac551beaf | ||
|
495af5702d | ||
|
2accde1b4f | ||
|
39d4e0b853 | ||
|
281f9ef60e | ||
|
b51f135703 | ||
|
30b996fc48 | ||
|
023e8242b7 | ||
|
1298652193 | ||
|
86e60e6c5f | ||
|
76c6d18695 | ||
|
2937a37cdb | ||
|
35325cc573 | ||
|
7f0658e246 | ||
|
fab0bbfcc3 | ||
|
f5fbe0a169 | ||
|
9bdf02b1ba | ||
|
55d5d24475 | ||
|
95fc7092de | ||
|
63e7b31a4b | ||
|
5f63a54ba5 | ||
|
1c967f1b9b | ||
|
e95168bbf0 | ||
|
23ddc68ade | ||
|
90d6b31264 | ||
|
2787f051e0 | ||
|
d87c4e017b | ||
|
d1fa4c7950 | ||
|
da59d5e808 | ||
|
b64dbb289d | ||
|
4a7956782b | ||
|
9eabff8a60 | ||
|
4cf50a45c5 | ||
|
81c119a066 | ||
|
ec2f9fc141 | ||
|
b6e7af2422 | ||
|
50faa9d9ac | ||
|
3579c1d8f5 | ||
|
c673822cad | ||
|
11c41272d0 | ||
|
cb0b613034 | ||
|
ae866b401e | ||
|
110c80f65f | ||
|
7f136cc8bc | ||
|
31b46b216f | ||
|
3769e0b5ba | ||
|
bf0a1a0ba0 | ||
|
c6b245aebc | ||
|
d7f83c59fa | ||
|
cd242d7505 | ||
|
9d10a3fa92 | ||
|
abe7a58e3f | ||
|
577df6d187 | ||
|
ce232b7d6a | ||
|
e7cd8f7561 | ||
|
33d6b2ecab | ||
|
ac404ee33b | ||
|
584c8b2028 | ||
|
25c2735bf4 | ||
|
461d8697ca | ||
|
d8618eab30 | ||
|
255fd67f48 | ||
|
6848302022 | ||
|
943ef1daf6 | ||
|
84f6faf693 | ||
|
e405d47cea | ||
|
2b2e431830 | ||
|
e540425472 | ||
|
a6b32631c4 | ||
|
8b67cae8f3 | ||
|
21c0bc70a3 | ||
|
1a8a91e41e | ||
|
99374a8170 | ||
|
71c7743fef | ||
|
311dc6361b | ||
|
de5e7e9663 | ||
|
486fd8664f | ||
|
b72714fc94 | ||
|
5d333c57a6 | ||
|
8b36f40e9d | ||
|
5bd261ad6b | ||
|
f8675e4d8d | ||
|
318a510ee8 | ||
|
05550dd570 | ||
|
7d618d9992 | ||
|
9e67c3ab67 | ||
|
ef61bbce61 | ||
|
d13e23e15d | ||
|
4a8fa480c4 | ||
|
c7043f0b3a | ||
|
6f36e62f92 | ||
|
486d6f54f4 | ||
|
b5a29eb300 | ||
|
ffe9d2321c | ||
|
50c1b6e9b1 | ||
|
01e10c6962 | ||
|
9d7e4e22d5 | ||
|
3bfc7bd14b | ||
|
4593980883 | ||
|
929fcf0ab4 | ||
|
234a481c32 | ||
|
a9c63c20a7 | ||
|
17f58e4089 | ||
|
cb9ee4644e | ||
|
9966143337 | ||
|
d879202b4e | ||
|
bf9a85e4fd | ||
|
eae5345e62 | ||
|
a7ca59e4f2 | ||
|
a1423ea53f | ||
|
11b9f1978a | ||
|
a5ea102ab3 | ||
|
99ceda9033 | ||
|
a5eb142dcc | ||
|
bf5f0463e7 | ||
|
a7283454b8 | ||
|
e7a92656d6 | ||
|
4dc7b9179b | ||
|
29fc12d4dd | ||
|
ca1236fb80 | ||
|
1a53b0753c | ||
|
36756fe75b | ||
|
80af7af938 | ||
|
533e7d875e | ||
|
23e4554bf2 | ||
|
de5fba81e3 | ||
|
5eff7e0883 | ||
|
6ad179601e | ||
|
72d5c8b18f | ||
|
bae3e8145f | ||
|
fe5d468fdf | ||
|
49b831779c | ||
|
0a427940a7 | ||
|
47f2aa06c6 | ||
|
20b6525eda | ||
|
be7e9f6d03 | ||
|
2cc953daae | ||
|
1c1909324f | ||
|
38d162843d | ||
|
280842bd9f | ||
|
60128aef4a | ||
|
2e36b850ca | ||
|
89bddf5c3f | ||
|
18701442e1 | ||
|
684af7e18d | ||
|
b504d637ed | ||
|
0ce87d3edd | ||
|
26894e25d2 | ||
|
563a112d4f | ||
|
d625ed41b2 | ||
|
6f25747e09 | ||
|
e425de2c67 | ||
|
ad09744371 | ||
|
955b5e12e2 | ||
|
b8b64bfa17 | ||
|
055b58106a | ||
|
81b46b8c53 | ||
|
15213ba6ce | ||
|
2ebace64c0 | ||
|
c39536677b | ||
|
467edd24e2 | ||
|
598ab0d071 | ||
|
31d88baf44 | ||
|
52d651a598 | ||
|
396af2d2e6 | ||
|
f539c1eaca | ||
|
0681fb05fe | ||
|
7d02fb8777 | ||
|
0706548ed5 | ||
|
4760db95ff | ||
|
db420b1f5a | ||
|
a1ddd37546 | ||
|
2f87ec96ff | ||
|
b1a5290615 | ||
|
8d7455c07c | ||
|
bbfa427a92 | ||
|
a33b586e42 | ||
|
8c8dd1758d | ||
|
0d207f01e8 | ||
|
e650a070a4 | ||
|
67f36a464b | ||
|
57eecf0552 | ||
|
780814aef9 | ||
|
9fba1860b0 | ||
|
ccf704a1ee | ||
|
75767714ba | ||
|
0e342afd13 | ||
|
c5a8006636 | ||
|
380cded0bb | ||
|
da38cd444a | ||
|
c75bb9328d | ||
|
03766d7fd8 | ||
|
39d038fa73 | ||
|
35c50de56b | ||
|
74a4b82006 | ||
|
5266b5d485 | ||
|
2e3dfb3444 | ||
|
4bd89561c4 | ||
|
67c79c4629 | ||
|
9432bfd1a3 | ||
|
54d4b61250 | ||
|
069e56f921 | ||
|
5ff8d7165c | ||
|
ffb3215611 | ||
|
f489e34402 | ||
|
e12a0d4dd2 | ||
|
ed801eba0a | ||
|
ca7e34c8f5 | ||
|
2f92462be4 | ||
|
6bd073ff82 | ||
|
98166047fd | ||
|
5a8c8e8fb2 | ||
|
6fb2dc85e6 | ||
|
74d6968ce7 | ||
|
2c24ce536d | ||
|
16733251a1 | ||
|
17d3563a42 | ||
|
a6f9b74f6f | ||
|
96297b8728 | ||
|
28f44d943f | ||
|
a9ef5f91ba | ||
|
0bccbc1988 | ||
|
4678addd7a | ||
|
8f786ae278 | ||
|
3db639d2a9 | ||
|
8701aaebda | ||
|
3caaebb0e9 | ||
|
8eecebfe47 | ||
|
9d10faabe8 | ||
|
72c358aea7 | ||
|
9cc0150696 | ||
|
9c16a0c7ed | ||
|
02b9f88315 | ||
|
eec4821dee | ||
|
2d847da1d4 | ||
|
e9c833d1ea | ||
|
6fa74685f1 | ||
|
e297eb7669 | ||
|
a62b95072f | ||
|
8f7694f7f4 | ||
|
2538453d98 | ||
|
c184066f26 | ||
|
4b84756e47 | ||
|
0a409f0924 | ||
|
3bef7378e8 | ||
|
5d502df2d4 | ||
|
f6c2802b32 | ||
|
d0769903a3 | ||
|
882cb68ec2 | ||
|
1a2b278c32 | ||
|
890e093656 | ||
|
8c604df1d2 | ||
|
bba8c99ee6 | ||
|
6f226b5d7d | ||
|
cc5bb78dc4 | ||
|
9cf7a94e17 | ||
|
c087f0bd9f | ||
|
506048a64a | ||
|
195a24dc5e | ||
|
f0a64cf8af | ||
|
f863dc792b | ||
|
36de79324b | ||
|
48b9aef8cb | ||
|
0be8553e29 | ||
|
42b4c6230e | ||
|
c983f9f9ca | ||
|
897e56b772 | ||
|
3e650addcb | ||
|
607d2ae8cb | ||
|
c47333ed1b | ||
|
34db52d541 | ||
|
d8f0dec487 | ||
|
8a0a0a4457 | ||
|
28918fb464 | ||
|
8bb9c18b9c | ||
|
5d4b22070f | ||
|
e1ce2839b7 | ||
|
75e5454b92 | ||
|
d84f972fbe | ||
|
f7eb8a276c | ||
|
5ebce8fdea | ||
|
bff7fe704e | ||
|
2b7a7d9221 | ||
|
98b4a713a0 | ||
|
854afa0c0d | ||
|
ebcc19e8dd | ||
|
3c792c4150 | ||
|
6cf84c583c | ||
|
c1327083d3 | ||
|
86cd1430af | ||
|
c823d3f967 | ||
|
ee30f5e7bf | ||
|
af817cf059 | ||
|
1054d42660 | ||
|
fe3d5c1bb7 | ||
|
fd17bf995b | ||
|
772b097458 | ||
|
c15d7ae020 | ||
|
dccfd35525 | ||
|
70577ca442 | ||
|
f764b36479 | ||
|
18f2ace3e9 | ||
|
f055118c2a | ||
|
8cdf8070e8 | ||
|
55811372fb | ||
|
966d326f3f | ||
|
1a3593c9ca | ||
|
6f10428b0f | ||
|
7536cdfc85 | ||
|
e53a9360ee | ||
|
85afe3a228 | ||
|
549e08717a | ||
|
52fdc0f7dd | ||
|
8e26542b91 | ||
|
12ec0c33ea | ||
|
433d8db50a | ||
|
8d584459d0 | ||
|
a761b7da31 | ||
|
4baf6647d5 | ||
|
68834c31f4 | ||
|
a70e93aee9 | ||
|
e52ef9fbbb | ||
|
b4abe731c5 | ||
|
78ea172428 | ||
|
4a668e7c32 | ||
|
4562b7cc21 | ||
|
dd32058c9d | ||
|
3135f3b5a7 | ||
|
37c865687b | ||
|
e3dbb9086c | ||
|
8259bfd284 | ||
|
cf2fb5e645 | ||
|
8097d2f5ba | ||
|
525440c09b | ||
|
06ebc10ad2 | ||
|
6cd0b187e2 | ||
|
50a23cdb23 | ||
|
6a67a6f1b5 | ||
|
a3fc39c293 | ||
|
98cdf2a00b | ||
|
6c5a75fe89 | ||
|
77540223ab | ||
|
d3baebd25f | ||
|
3d99fda795 | ||
|
827f3d2ea0 | ||
|
6f721f28c7 | ||
|
d93ca077bd | ||
|
ed4ce42237 | ||
|
b64f345e13 | ||
|
09ef1cacde | ||
|
7a2a61a9db | ||
|
0c4f9e5080 | ||
|
0da6f30f38 | ||
|
2291666d81 | ||
|
4447a9c610 | ||
|
83b11b198b | ||
|
bdb364b63d | ||
|
3e0e7b2e5e | ||
|
be4190d8cb | ||
|
d9ea30bbfb | ||
|
718bab3c78 | ||
|
d315f7faa3 | ||
|
b76717d660 | ||
|
520205d1b9 | ||
|
0ac04c897d | ||
|
0a8b025c7e | ||
|
a6d69918fc | ||
|
097f57374a | ||
|
7749f1eb62 | ||
|
d36f869a64 | ||
|
93b199e957 | ||
|
beb8141869 | ||
|
3a425ee7e4 | ||
|
621f4c72f4 | ||
|
4c666bb438 | ||
|
5b1059882b | ||
|
c234b70bf7 | ||
|
e842f73b41 | ||
|
1fb157240c | ||
|
1e881f3148 | ||
|
884db125e0 | ||
|
3b427871cf | ||
|
e70d80425a | ||
|
1fe36f0e1b | ||
|
2ce08bbe30 | ||
|
9eda12e75d | ||
|
a58be6be37 | ||
|
87bd45b415 | ||
|
71ff59cb55 | ||
|
ff23179bfd | ||
|
ba6666433e | ||
|
d0e4bcd27e | ||
|
6aa2725cc8 | ||
|
08b97a430a | ||
|
5d7f7bcb00 | ||
|
e2e6069749 | ||
|
0083b29146 | ||
|
38e558e9f8 | ||
|
4cf174301a | ||
|
d8ac561552 | ||
|
1384d5b50a | ||
|
1ac0848ce2 | ||
|
c82a655375 | ||
|
19b1176435 | ||
|
9df5afc607 | ||
|
d1bc04c528 | ||
|
e1df4a14d3 | ||
|
3c3f6f1c65 | ||
|
f5d9085531 | ||
|
fa0a6b9ffc | ||
|
cceacbebab | ||
|
d4aff642e3 | ||
|
fcd0e2820a | ||
|
a6abc105a9 | ||
|
bf86427609 | ||
|
5ae0b20c86 | ||
|
5cbdb23e3f | ||
|
18c94f7f60 | ||
|
8ee09f8716 | ||
|
f67da0aeef | ||
|
a5a87a686e | ||
|
9be6a27012 | ||
|
81881e1019 | ||
|
27ab4fa81b | ||
|
e39e425db0 | ||
|
edcf2f3fa5 | ||
|
b2f0b4c205 | ||
|
2b46af7e2f | ||
|
9c4d69d586 | ||
|
8695a134d2 | ||
|
3bcd712e42 | ||
|
fd2916f90e | ||
|
94c664fecc | ||
|
d9ae6eb34a | ||
|
0d659c94e8 | ||
|
d08a8b00a9 | ||
|
3db2cfaea5 | ||
|
3ddeb0517e | ||
|
d30988f652 | ||
|
90975b30e3 | ||
|
468604058e | ||
|
441d4118d7 | ||
|
e986dcdc12 | ||
|
9b647a77eb | ||
|
666a9ad1e8 | ||
|
827379806b | ||
|
b918a5bb66 | ||
|
b89d1ad686 | ||
|
7f22dea0b8 | ||
|
17def8e304 | ||
|
c7938efd2f | ||
|
cac9453154 | ||
|
d1af5eec1a | ||
|
75ec47b234 | ||
|
1eac90c79a | ||
|
0d8a282248 | ||
|
983db9ede5 | ||
|
5fbb94f54d | ||
|
77acb731ac | ||
|
ce31f505a0 | ||
|
06fe7e1312 | ||
|
8d1a70e6e1 | ||
|
d8f727ef1a | ||
|
b5ea1580e5 | ||
|
ccf1fd6f9a | ||
|
f38a0c5907 | ||
|
3c0aa552f9 | ||
|
5f97704c78 | ||
|
7cce1e6f8e | ||
|
cc9dc08247 | ||
|
663bc9be9d | ||
|
291a771bd9 | ||
|
29e33ad174 | ||
|
7e0b4c8901 | ||
|
44fec7dfb1 | ||
|
c104251ac3 | ||
|
ad7d55544f | ||
|
e5187ff4c5 | ||
|
55f387e247 | ||
|
9f53c1fa17 | ||
|
454c37a3d6 | ||
|
7a1a890f1a | ||
|
bfd54d481a | ||
|
bc026b2341 | ||
|
24bee629e8 | ||
|
2fb4a77c96 | ||
|
2eb7f4197f | ||
|
0917d67b07 | ||
|
0330699c05 | ||
|
0cf61c628a | ||
|
2b552360e0 | ||
|
0ec4acce1e | ||
|
90b6031d96 | ||
|
dcb775a1fe | ||
|
b2803fcfed | ||
|
2f8ca24fa0 | ||
|
b1f76553ce | ||
|
e5bbdadd6a | ||
|
f896569f4c | ||
|
7daf22b5b6 | ||
|
9f3bdc6bf4 | ||
|
92b9f09c01 | ||
|
935e9bacca | ||
|
391267d609 | ||
|
820dcfd728 | ||
|
68685284ea | ||
|
08745d4b12 | ||
|
dab0beedc0 | ||
|
763bf9ecc8 | ||
|
d4877e8bb9 | ||
|
db58882a15 | ||
|
b865a1d118 | ||
|
e8600b2c0d | ||
|
de68427a0c | ||
|
1416f5821b | ||
|
b5605db095 | ||
|
5c1b76c92f | ||
|
f5cf049fe0 | ||
|
ae5eaba2c1 | ||
|
5a8eb965ff | ||
|
7f9c8b2847 | ||
|
4df7549799 | ||
|
2f4e9d4a57 | ||
|
dd1124a608 | ||
|
7f9eada428 | ||
|
173b6c9307 | ||
|
6882143a98 | ||
|
0a8fa05498 | ||
|
4d8f6a1d4f | ||
|
fdb24ebc13 | ||
|
cdd6d98af4 | ||
|
2ece20ead9 | ||
|
ce847046bb | ||
|
66c4bdc520 | ||
|
9296d51075 | ||
|
3ddc156c18 | ||
|
ee5a071bd9 | ||
|
db378a6f3a | ||
|
08e87475f6 | ||
|
8fd37d6cf7 | ||
|
68084a257d | ||
|
441d7398a8 | ||
|
6e5214fc07 | ||
|
f68c2ae78a | ||
|
0f74cb5453 | ||
|
09ae91af93 | ||
|
9802bba502 | ||
|
92181a2df0 | ||
|
46a352d0c8 | ||
|
5b169cc2a3 | ||
|
7b5cf714d2 | ||
|
7b8c4f1de9 | ||
|
fe760dcca6 | ||
|
1533bf5d6e | ||
|
b97e5679bf | ||
|
eddc8712b0 | ||
|
2a34632269 | ||
|
abdd9f9f6a | ||
|
be7bb5f871 | ||
|
47e9982d7f | ||
|
06ab07a966 | ||
|
5ccd873a54 | ||
|
9730b5733a | ||
|
012a44c00a | ||
|
1bf7913ac3 | ||
|
28699d0061 | ||
|
9c8ea8c489 | ||
|
05d0420813 | ||
|
6651208b2e | ||
|
86a1149acd | ||
|
f68ecddaa2 | ||
|
f94ba08c06 | ||
|
da40ee11e8 | ||
|
548c7f5f7e | ||
|
9f3782558f | ||
|
060e4186ce | ||
|
ef6c166c56 | ||
|
40f666adc2 | ||
|
48549e5d38 | ||
|
8e56cb0ada | ||
|
8717d19136 | ||
|
bb99662976 | ||
|
a2e0100f5e | ||
|
b3581a61d2 | ||
|
f94a0869a6 | ||
|
19635e7a0a | ||
|
15d689b0c2 | ||
|
20052a4a13 | ||
|
6aec0d3f68 | ||
|
0172d32bad | ||
|
4b7027295f | ||
|
5cade4e17d | ||
|
3aa88141d4 | ||
|
e8f05282fa | ||
|
cb908d33e5 | ||
|
d7a8a55d22 | ||
|
2bc7ef3973 | ||
|
ce2a13e501 | ||
|
041d6bf73f | ||
|
c438f07e56 | ||
|
4e241191bf | ||
|
3aa7ec54bb | ||
|
3f1625aa5a | ||
|
05bc971a58 | ||
|
12fa092c3b | ||
|
a150dabff2 | ||
|
190601a999 | ||
|
61bd88e437 | ||
|
aa853fe4c8 | ||
|
a14672355c | ||
|
8e90dbfa56 | ||
|
5dab93e59e | ||
|
f2ad0da7e2 | ||
|
fc160e6a17 | ||
|
8078471355 | ||
|
7f1d731dc6 | ||
|
59043760b6 | ||
|
20b8b23cbb | ||
|
b3926751ad | ||
|
892c5a4575 | ||
|
dfe3b66f53 | ||
|
a373e4efa2 | ||
|
2ea33c2a07 | ||
|
627761e98d | ||
|
885c6cfe5e | ||
|
53cd13b561 | ||
|
5fe14a7c5a | ||
|
b47ebebf9e | ||
|
d90c23cd38 | ||
|
be842aba31 | ||
|
bc679d6ac6 | ||
|
8530b24691 | ||
|
1fcd1b9eed | ||
|
aa8d9f7a25 | ||
|
c66164f37e | ||
|
920eaf0903 | ||
|
54a5c6a46e | ||
|
5a86686933 | ||
|
101f4fb423 | ||
|
7104e6e1a9 | ||
|
c30b688ee9 | ||
|
67aedbdc54 | ||
|
77bb76bf1a | ||
|
32b450c1b6 | ||
|
5e7bec0aa7 | ||
|
8a4a40f7f4 | ||
|
30d369f194 | ||
|
cb85b75a04 | ||
|
f78e170cb1 | ||
|
5307c1db1f | ||
|
f2bb72984d | ||
|
5275b2c7df | ||
|
914dbca77f | ||
|
76ee6b66ed | ||
|
d4bedc0515 | ||
|
7b02780472 | ||
|
aaef6e64e1 | ||
|
67cb34f658 | ||
|
6cd39b2d8c | ||
|
ffb66639d7 | ||
|
3fc72f667e | ||
|
edc5fcba87 | ||
|
eb37c7de49 | ||
|
e6b6f6a761 | ||
|
b8dfb73959 | ||
|
86662ae170 | ||
|
33bca3c2bd | ||
|
d9d5e6be4e | ||
|
443752dc75 | ||
|
29b42fd4fc | ||
|
7e359e5836 | ||
|
0623c06fc7 | ||
|
97a820688b | ||
|
dc5cd78f50 | ||
|
487e96e261 | ||
|
054306bb73 | ||
|
c65706c0ab | ||
|
eeb4fde251 | ||
|
ce3f63eaae | ||
|
b22121cb93 | ||
|
40c3ec24bd | ||
|
871893598f | ||
|
18be101068 | ||
|
bd2bf728c6 | ||
|
e0dc31610d | ||
|
9243ecdfab | ||
|
a5be52edc9 | ||
|
03e19d4a6a | ||
|
66c7e2d444 | ||
|
6cfeae136d | ||
|
4923f39463 | ||
|
376136f8dd | ||
|
5220139fdb | ||
|
1cc2330b22 | ||
|
b5a8a8e23d | ||
|
14ffdb9636 | ||
|
75eded4b06 | ||
|
def5b7e54d | ||
|
3c1763ceb4 | ||
|
1e157641b2 | ||
|
7e01748e8a | ||
|
b6f6f1b2a8 | ||
|
ebec51b965 | ||
|
6ab74d4216 | ||
|
4ca5fc4f3b | ||
|
f17fae6a74 | ||
|
56315d02c7 | ||
|
1510341307 | ||
|
ea27c18202 | ||
|
87b3d8e9f5 | ||
|
57bd1bc0fe | ||
|
3cd8e6b55a | ||
|
ad7aef77b7 | ||
|
527f046693 | ||
|
7b9a40a8f9 | ||
|
9674394709 | ||
|
86b52a96f5 | ||
|
123eafbb5c | ||
|
37bd108f40 | ||
|
372665f978 | ||
|
3c7800aba1 | ||
|
caf07a24d9 | ||
|
5c34c94935 | ||
|
6bc4d25521 | ||
|
7dcf112309 | ||
|
2ce47eb669 | ||
|
af899f353d | ||
|
340dd41645 | ||
|
caee178ad8 | ||
|
7445a9a3e5 | ||
|
c7faaffbfa | ||
|
96fae2b95d | ||
|
0503802282 | ||
|
46ff73d82a | ||
|
0fd6884e68 | ||
|
8cd863f394 | ||
|
53bec9df41 | ||
|
a2967210a3 | ||
|
539e1ea35e | ||
|
23871f351c | ||
|
cab7411454 | ||
|
c3b0dac605 | ||
|
a9fef4683d | ||
|
16199a4318 | ||
|
cecb1d58ce | ||
|
9ab1d7b37b | ||
|
246cee7a8c | ||
|
190230de2f | ||
|
5a3294b32c | ||
|
3ffc3b9d1d | ||
|
df5d8655f9 | ||
|
39b6ca3a0d | ||
|
932e5d13f2 | ||
|
1b672c5667 | ||
|
81b34c8efe | ||
|
e879b7be97 | ||
|
0b1c5830d9 | ||
|
a65f20ea45 | ||
|
e44471c1f1 | ||
|
61d1df94c1 | ||
|
0667ca8ad3 | ||
|
a0ea6d4a28 | ||
|
a44c12dcdd | ||
|
ead66d38e6 | ||
|
487f3dcc6d | ||
|
2687690407 | ||
|
b6c6139023 | ||
|
af86c0a4c4 | ||
|
52a5a4b932 | ||
|
e2245dd9c0 | ||
|
14df2c703c | ||
|
ef8241ef5a | ||
|
9081d50a0e | ||
|
31d34c412b | ||
|
20251ae0d0 | ||
|
1d463af70c | ||
|
6632d8c4e4 | ||
|
b7371b355a | ||
|
cf5f476898 | ||
|
cb1dfa20f8 | ||
|
6ad9c18683 | ||
|
96abc2a8bc | ||
|
fdbfeb2e37 | ||
|
c957d419ee | ||
|
cc16944dbe | ||
|
60f375cc4a | ||
|
82a667504a | ||
|
cd3b394c1b | ||
|
efd87268da | ||
|
0dbd8a6b84 | ||
|
b96e4321d4 | ||
|
ec482796a9 | ||
|
6f2eb3cbb1 | ||
|
33239dc2f6 | ||
|
b1c0701804 | ||
|
150a9e45ad | ||
|
c327f9f1ef | ||
|
ea478ca689 | ||
|
7892aab05c | ||
|
f252719aa1 | ||
|
c7567f3838 | ||
|
b665dec740 | ||
|
802dff3e42 | ||
|
8974a0546f | ||
|
06f17c828a | ||
|
65a104f7d4 | ||
|
9b3874ea56 | ||
|
8887fa3384 | ||
|
ca27ac2200 | ||
|
1efcc32748 | ||
|
fbaaca42f7 | ||
|
5706ae1f95 | ||
|
b9aa47a7f4 | ||
|
66ad5499fb | ||
|
7da2460b21 | ||
|
265b144cfa | ||
|
d93ab9eb74 | ||
|
5ffa07aeee | ||
|
e2c0845145 | ||
|
f3e531dbd8 | ||
|
91381bfe80 | ||
|
7bf95fd551 | ||
|
d2ac10ae28 | ||
|
11bb161bb2 | ||
|
73899b2784 | ||
|
c45fb3ce41 | ||
|
19f3678747 | ||
|
44a2f2ea43 | ||
|
185916e9bf | ||
|
b7343d9810 | ||
|
5fb69bec22 | ||
|
8295bd6882 | ||
|
597f1b628b | ||
|
845d9f4800 | ||
|
2e3a436594 | ||
|
ba5ccea851 | ||
|
ab93794724 | ||
|
80a417d33f | ||
|
d429f820e9 | ||
|
a8c34ee756 | ||
|
db4ac69452 | ||
|
7d39da51ed | ||
|
11751129b3 | ||
|
4b2e0f53ae | ||
|
aa8bdf5eb2 | ||
|
4574e8b007 | ||
|
b3463e7dab | ||
|
7cad8228ee | ||
|
7e2bfce707 | ||
|
131923ca59 | ||
|
99fb6f5057 | ||
|
cf737aa2e7 | ||
|
813fe9f814 | ||
|
08d71eb356 | ||
|
98f2329fa0 | ||
|
6ea3da5a9e | ||
|
06948c66d8 | ||
|
b039fdad8b | ||
|
559df105b6 | ||
|
3fd18589a9 | ||
|
fd19fff435 | ||
|
6365139253 |
9
.eslintignore
Normal file
9
.eslintignore
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
artifacts
|
||||||
|
reports
|
||||||
|
.nyc_output
|
||||||
|
coverage
|
||||||
|
dist
|
||||||
|
styleguide
|
||||||
|
build
|
||||||
|
consoles/*/lib/app
|
||||||
|
node_modules
|
10
.eslintrc
Normal file
10
.eslintrc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "joyent-portal",
|
||||||
|
"rules": {
|
||||||
|
"no-console": 1,
|
||||||
|
"new-cap": 0,
|
||||||
|
"jsx-a11y/href-no-hash": 0,
|
||||||
|
"no-negated-condition": 1,
|
||||||
|
"camelcase": 1
|
||||||
|
}
|
||||||
|
}
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +0,0 @@
|
|||||||
*.sketch filter=lfs diff=lfs merge=lfs -text
|
|
25
.github/COMMIT_GUIDELINES.md
vendored
Normal file
25
.github/COMMIT_GUIDELINES.md
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Commit Guidelines
|
||||||
|
|
||||||
|
```
|
||||||
|
<type><(scope)?>: <msg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Where type is one of:
|
||||||
|
|
||||||
|
```
|
||||||
|
build
|
||||||
|
chore
|
||||||
|
ci
|
||||||
|
docs
|
||||||
|
feat
|
||||||
|
fix
|
||||||
|
perf
|
||||||
|
refactor
|
||||||
|
revert
|
||||||
|
style
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
And where scope is one of ui-toolkit, my-joy-beta, cloudapi-gql, boilerplate, and create-instance.
|
||||||
|
|
||||||
|
_The recommended method to commit should be by running npm run commit._
|
17
.github/ISSUE_TEMPLATE.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
## I'm submitting a...
|
||||||
|
|
||||||
|
* [ ] bug report
|
||||||
|
* [ ] feature request
|
||||||
|
* [ ] design request
|
||||||
|
|
||||||
|
## What is the current behavior?
|
||||||
|
|
||||||
|
## If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem
|
||||||
|
|
||||||
|
## What is the expected behavior?
|
||||||
|
|
||||||
|
## What is the motivation / use case for changing the behavior?
|
||||||
|
|
||||||
|
## If the current behavior is a bug, please provide your browser
|
||||||
|
|
||||||
|
## Other information
|
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
**Please check if the PR fulfills these requirements**
|
||||||
|
|
||||||
|
* [ ] The commit message follows our [guidelines](https://github.com/yldio/joyent-portal/blob/master/.github/COMMIT_GUIDELINES.md)
|
||||||
|
* [ ] Tests for the changes have been added (for bug fixes / features)
|
||||||
|
|
||||||
|
**What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
|
||||||
|
|
||||||
|
**Does this PR close an issue?** (If not please create one)
|
||||||
|
|
||||||
|
**What is the new behavior (if this is a feature change)?**
|
||||||
|
|
||||||
|
**Does this PR introduce a breaking change?** (What changes might users need to make in their application due to this PR?)
|
||||||
|
|
||||||
|
**Other information**
|
19
.gitignore
vendored
19
.gitignore
vendored
@ -118,9 +118,6 @@ Session.vim
|
|||||||
# temporary
|
# temporary
|
||||||
.netrwhist
|
.netrwhist
|
||||||
*~
|
*~
|
||||||
# auto-generated tag files
|
|
||||||
tags
|
|
||||||
|
|
||||||
|
|
||||||
### Windows ###
|
### Windows ###
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
@ -154,3 +151,19 @@ $RECYCLE.BIN/
|
|||||||
tap-xunit
|
tap-xunit
|
||||||
/ui/dist
|
/ui/dist
|
||||||
|
|
||||||
|
_todo
|
||||||
|
packages/*/dist
|
||||||
|
prototypes/*/dist
|
||||||
|
packages/*/buid
|
||||||
|
prototypes/*/buid
|
||||||
|
packages/*/.next
|
||||||
|
prototypes/*/.next
|
||||||
|
packages/ui-toolkit/styleguide/
|
||||||
|
packages/ui-toolkit/.snapguidist/
|
||||||
|
packages/*/package-lock.json
|
||||||
|
prototypes/*/package-lock.json
|
||||||
|
|
||||||
|
_env*
|
||||||
|
keys*
|
||||||
|
/packages/*/public/index.html
|
||||||
|
/consoles/*/public/index.html
|
||||||
|
24
.licensesrc.json
Normal file
24
.licensesrc.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"ignoreDevDependencies": true,
|
||||||
|
"allowedPackages": [
|
||||||
|
{
|
||||||
|
"name": "colors",
|
||||||
|
"extraFieldsForDocumentation":
|
||||||
|
"Licence is MIT, but was not found by tool: https://github.com/Marak/colors.js/blob/v0.5.1/MIT-LICENSE.txt",
|
||||||
|
"date": "17 January 2017",
|
||||||
|
"reason": "MIT Licenced"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"allowedLicenses": [
|
||||||
|
"CC-BY-4.0",
|
||||||
|
"CC0-1.0",
|
||||||
|
"MIT",
|
||||||
|
"ISC",
|
||||||
|
"Apache",
|
||||||
|
"BSD",
|
||||||
|
"WTF",
|
||||||
|
"Public Domain",
|
||||||
|
"MPL",
|
||||||
|
"Unlicense"
|
||||||
|
]
|
||||||
|
}
|
29
.prettierignore
Normal file
29
.prettierignore
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
.git/*
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
license
|
||||||
|
yarn.lock
|
||||||
|
.travis.yml
|
||||||
|
|
||||||
|
.yarnclean
|
||||||
|
.eslintignore
|
||||||
|
.prettierignore
|
||||||
|
.npmignore
|
||||||
|
.gitignore
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
packages/*/lib/app
|
||||||
|
consoles/*/lib/app
|
||||||
|
|
||||||
|
*.ico
|
||||||
|
*.html
|
||||||
|
*.log
|
||||||
|
*.svg
|
||||||
|
*.map
|
||||||
|
*.png
|
||||||
|
*.snap
|
||||||
|
*.ttf
|
||||||
|
*.sh
|
||||||
|
*.txt
|
31
.prettierrc
Normal file
31
.prettierrc
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"jsxBracketSameLine": false,
|
||||||
|
"printWidth": 80,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"useTabs": false,
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
".prettierrc",
|
||||||
|
".eslintrc",
|
||||||
|
".babelrc",
|
||||||
|
".tern-project",
|
||||||
|
".stylelintrc",
|
||||||
|
".lighthouserc"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"parser": "json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["package.json"],
|
||||||
|
"options": {
|
||||||
|
"printWidth": 180
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
12
.tern-project
Normal file
12
.tern-project
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"libs": ["ecmascript", "browser"],
|
||||||
|
"plugins": {
|
||||||
|
"doc_comment": true,
|
||||||
|
"local-scope": true,
|
||||||
|
"jsx": true,
|
||||||
|
"node": true,
|
||||||
|
"webpack": {
|
||||||
|
"configPath": "./webpack/index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
.travis.yml
Normal file
5
.travis.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- '9'
|
||||||
|
script:
|
||||||
|
- yarn run test:ci
|
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Chrome against localhost",
|
||||||
|
"url": "http://localhost:3069/",
|
||||||
|
"webRoot": "${workspaceRoot}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1
.vscode/settings.json
vendored
Normal file
1
.vscode/settings.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
36
.yarnclean
Normal file
36
.yarnclean
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# test directories
|
||||||
|
__tests__
|
||||||
|
test
|
||||||
|
tests
|
||||||
|
powered-test
|
||||||
|
|
||||||
|
# asset directories
|
||||||
|
docs
|
||||||
|
doc
|
||||||
|
website
|
||||||
|
images
|
||||||
|
assets
|
||||||
|
|
||||||
|
# code coverage directories
|
||||||
|
coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# build scripts
|
||||||
|
Makefile
|
||||||
|
Gulpfile.js
|
||||||
|
Gruntfile.js
|
||||||
|
|
||||||
|
# configs
|
||||||
|
.tern-project
|
||||||
|
.gitattributes
|
||||||
|
.editorconfig
|
||||||
|
.*ignore
|
||||||
|
.eslintrc
|
||||||
|
.jshintrc
|
||||||
|
.flowconfig
|
||||||
|
.documentup.json
|
||||||
|
.yarn-metadata.json
|
||||||
|
|
||||||
|
# misc
|
||||||
|
*.gz
|
||||||
|
*.md
|
@ -1,33 +0,0 @@
|
|||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Small Feature Development
|
|
||||||
|
|
||||||
Contributors who have write access to the repository will practise continuous
|
|
||||||
delivery (CD as known from now on in this document).
|
|
||||||
|
|
||||||
We will define CD in this document as a method of developing a feature per commit
|
|
||||||
with an encapsulating test that proves that the functionality is working, the
|
|
||||||
contributor will test their code locally and if all is passing will push to *master*.
|
|
||||||
|
|
||||||
For contributors that do not have write access, follow the same conventions but
|
|
||||||
open a Pull Request instead.
|
|
||||||
|
|
||||||
### Large changesets
|
|
||||||
|
|
||||||
When larger changes need to be made, or the work that is carried out spans multiple
|
|
||||||
components / services of the application at the same time a single commit will
|
|
||||||
not suffice.
|
|
||||||
|
|
||||||
In this scenario, the contributor should open a pull request instead.
|
|
||||||
|
|
||||||
## Commit messages
|
|
||||||
|
|
||||||
Follow [Git blessed](http://chris.beams.io/posts/git-commit/)
|
|
||||||
|
|
||||||
1. Separate subject from body with a blank line
|
|
||||||
2. Limit the subject line to 50 characters
|
|
||||||
3. Capitalize the subject line
|
|
||||||
4. Do not end the subject line with a period
|
|
||||||
5. Use the imperative mood in the subject line
|
|
||||||
6. Wrap the body at 72 characters
|
|
||||||
7. Use the body to explain what and why vs. how
|
|
57
Makefile
57
Makefile
@ -1,57 +0,0 @@
|
|||||||
.PHONY: check
|
|
||||||
check:
|
|
||||||
@yarn install --prefer-offline
|
|
||||||
-@./bin/setup
|
|
||||||
|
|
||||||
.PHONE: licence
|
|
||||||
licence:
|
|
||||||
./node_modules/.bin/license-to-fail ./licence.js
|
|
||||||
make licence-check
|
|
||||||
|
|
||||||
SUBDIRS := $(dir $(wildcard */Makefile))
|
|
||||||
TARGETS := install clean test test-ci lint lint-ci licence-check# whatever else, but must not contain '/'
|
|
||||||
|
|
||||||
# foo/.all bar/.all foo/.clean bar/.clean
|
|
||||||
SUBDIRS_TARGETS := \
|
|
||||||
$(foreach t,$(TARGETS),$(addsuffix $t,$(SUBDIRS)))
|
|
||||||
|
|
||||||
.PHONY: $(TARGETS) $(SUBDIRS_TARGETS)
|
|
||||||
|
|
||||||
# static pattern rule, expands into:
|
|
||||||
# all clean: %: foo/.% bar/.%
|
|
||||||
$(TARGETS): %: $(addsuffix %,$(SUBDIRS))
|
|
||||||
@echo 'Done "$*" target'
|
|
||||||
|
|
||||||
# here, for foo/.all:
|
|
||||||
# $(@D) is foo
|
|
||||||
# $(@F) is .all, with leading period
|
|
||||||
# $(@F:.%=%) is just all
|
|
||||||
$(SUBDIRS_TARGETS):
|
|
||||||
$(MAKE) --no-print-directory -C $(@D) $(@F:.%=%)
|
|
||||||
|
|
||||||
DIFF := $(lastword $(subst /, ,${CIRCLE_COMPARE_URL}))
|
|
||||||
CHANGED_FILES := $(subst /, , $(dir $(shell git diff --name-only $(DIFF))))
|
|
||||||
CHANGES := $(patsubst %, %/, $(sort $(filter $(subst /, ,$(SUBDIRS)), $(CHANGED_FILES))))
|
|
||||||
.PHONY: diff
|
|
||||||
diff:
|
|
||||||
echo $(CHANGES)
|
|
||||||
|
|
||||||
BUILDS := build push
|
|
||||||
|
|
||||||
# foo/.all bar/.all foo/.clean bar/.clean
|
|
||||||
BUILDS_TARGETS := \
|
|
||||||
$(foreach t,$(BUILDS),$(addsuffix $t,$(CHANGES)))
|
|
||||||
|
|
||||||
.PHONY: $(BUILDS) $(BUILDS_TARGETS)
|
|
||||||
|
|
||||||
# static pattern rule, expands into:
|
|
||||||
# all clean: %: foo/.% bar/.%
|
|
||||||
$(BUILDS): %: $(addsuffix %,$(CHANGES))
|
|
||||||
@echo 'Done "$*" target'
|
|
||||||
|
|
||||||
# here, for foo/.all:
|
|
||||||
# $(@D) is foo
|
|
||||||
# $(@F) is .all, with leading period
|
|
||||||
# $(@F:.%=%) is just all
|
|
||||||
$(BUILDS_TARGETS):
|
|
||||||
$(MAKE) --no-print-directory -C $(@D) $(@F:.%=%)
|
|
120
README.md
120
README.md
@ -1,120 +0,0 @@
|
|||||||
[![CircleCI](https://circleci.com/gh/yldio/joyent-portal.svg?style=shield&circle-token=0bbeaaafc4868c707ca0ed0568f5193a04daddb4)](https://circleci.com/gh/yldio/joyent-portal)
|
|
||||||
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
|
|
||||||
|
|
||||||
# Prototype Triton Portal
|
|
||||||
|
|
||||||
This is a prototype project intended to explore some ideas that might contribute to new capabilities and a new user experience for managing applications on [Joyent's Triton](https://www.joyent.com/triton).
|
|
||||||
|
|
||||||
**This is not intended for general use and is completely unsupported.**
|
|
||||||
|
|
||||||
## Our Principles
|
|
||||||
We have designed this product with these principles in mind (to be completed).
|
|
||||||
|
|
||||||
## Our Design Library
|
|
||||||
We use inVision craft for our design components, you can downoad this library [here](https://drive.google.com/open?id=0Bw56g3tFwIuWOXNHUDZmRmQ3ZlE) and submit proposed changes to our Sketch wireframes [here](https://drive.google.com/open?id=0B1oWObk56wa5cE5iY2JWNmI2djg).
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
Our workshop meeting notes are kept in this [Google Drive folder](https://drive.google.com/open?id=0B1oWObk56wa5eklBNGFlWFRFOHM). Our meeting notes are kept in this [Google Drive folder](https://drive.google.com/open?id=0B1oWObk56wa5N1VzZjhZWWpDTTQ).
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
If you would like to contribute to the project, the recommended way to setup is to
|
|
||||||
insure that you have docker installed, and optionally have a triton account and profile
|
|
||||||
setup using the triton tool.
|
|
||||||
|
|
||||||
Currently requires [yarn](https://yarnpkg.com/en/docs/install) for installing dependencies,
|
|
||||||
as well as `docker` and `docker-compose` are installed correctly, this can be done by
|
|
||||||
running `make`, make continues without any errors, then you are good to go. [node-triton](https://github.com/joyent/node-triton)
|
|
||||||
is also needed if deployment to Triton is required.
|
|
||||||
|
|
||||||
```
|
|
||||||
make && make install
|
|
||||||
```
|
|
||||||
|
|
||||||
Then to run each individual component locally (subject to change).
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run services
|
|
||||||
|
|
||||||
To run the stack locally:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker-compose -f local-compose.yml up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
This will run the front-end at [http://127.0.0.1:8000](http://127.0.0.1:8000),
|
|
||||||
the UI framework at [http://127.0.0.1:8001](http://127.0.0.1:8001),
|
|
||||||
|
|
||||||
## Project Management
|
|
||||||
|
|
||||||
This project is using [Github Projects](https://www.youtube.com/watch?v=C6MGKHkNtxU) for organisation and development of the Joyent Dashboard.
|
|
||||||
|
|
||||||
## Repository Layout
|
|
||||||
|
|
||||||
Currently we are using this repository as a monolithic catch-all for all project communication, development and designs.
|
|
||||||
We will also include multiple PoC's of various bits of functionality from UI's prototypes to API development.
|
|
||||||
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── cloudapi-graphql
|
|
||||||
├── docs
|
|
||||||
├── frontend
|
|
||||||
├── nginx
|
|
||||||
├── ui
|
|
||||||
└── spikes
|
|
||||||
```
|
|
||||||
|
|
||||||
### cloudapi-graphql
|
|
||||||
|
|
||||||
An implementation of the [Joyent CloudAPI](https://apidocs.joyent.com/cloudapi/) in GraphQL.
|
|
||||||
|
|
||||||
### Docs
|
|
||||||
|
|
||||||
Documentation about the project, mainly focused on information for the technical runnings of this project.
|
|
||||||
Can be view online at the [documentation website](http://docs.svc.f4b20699-b323-4452-9091-977895896da6.eu-ams-1.triton.zone/)
|
|
||||||
|
|
||||||
### frontend
|
|
||||||
|
|
||||||
The client side code with a dev-server, this also includes the production server for the meantime, however we are looking at moving towards a deployment of the build artifacts to manta, and another server to host these assets.
|
|
||||||
|
|
||||||
### nginx
|
|
||||||
|
|
||||||
Nginx will be sitting in-front of the `ui` service, allowing the `ui` to scale out.
|
|
||||||
|
|
||||||
### ui
|
|
||||||
|
|
||||||
Code for the reusable UI framework.
|
|
||||||
|
|
||||||
### spikes
|
|
||||||
|
|
||||||
Implementation examples from spikes, this directory is experimental and is likely broken.
|
|
||||||
|
|
||||||
### Git LFS
|
|
||||||
- We are using Git LFS to track large files, such as design files in Sketch.
|
|
||||||
- Make sure you have this downloaded locally
|
|
||||||
`brew install git-lfs`
|
|
||||||
|
|
||||||
#### Helpful tips
|
|
||||||
- If there is an error cloning to a new machine, or there is an error cloning in the Circle CI process run `git lfs push origin master --all` from a machine that has it already checked out.
|
|
||||||
|
|
||||||
### Sketch Pre Commit
|
|
||||||
|
|
||||||
A pre-commit hook has been added to generate a PNG shot of each .sketch file "page".
|
|
||||||
|
|
||||||
To use, make sure the following are installed:
|
|
||||||
- [Sketch Toolbox](http://sketchtoolbox.com/)
|
|
||||||
- [Sketch Measure Plugin](https://github.com/utom/sketch-measure)
|
|
||||||
|
|
||||||
|
|
||||||
Then add following to your `.git/config`
|
|
||||||
|
|
||||||
```
|
|
||||||
[diff "sketchtool"]
|
|
||||||
textconv = "sketchtool dump"
|
|
||||||
cachetextconv = true
|
|
||||||
```
|
|
30
bin/deploy
30
bin/deploy
@ -1,30 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude - make bash behave sanely
|
|
||||||
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Beware of CDPATH gotchas causing cd not to work correctly when a user
|
|
||||||
# has set this in their environment
|
|
||||||
# https://bosker.wordpress.com/2012/02/12/bash-scripters-beware-of-the-cdpath/
|
|
||||||
unset CDPATH
|
|
||||||
|
|
||||||
readonly INCLUDE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
# shellcheck source=bin/setup-tools
|
|
||||||
. "${INCLUDE}"/setup-tools
|
|
||||||
|
|
||||||
echo ">> running triton deploy with docker-compose"
|
|
||||||
ensure_command triton
|
|
||||||
ensure_triton_cns_is_enabled
|
|
||||||
get_triton_details
|
|
||||||
write_env_file
|
|
||||||
|
|
||||||
export DOCKER_HOST=$_DOCKER_HOST
|
|
||||||
export DOCKER_CERT_PATH=$_DOCKER_CERT_PATH
|
|
||||||
# Do not TLS verify for now, incompatibilities between circleci and joyent
|
|
||||||
export DOCKER_TLS_VERIFY=
|
|
||||||
|
|
||||||
docker-compose pull
|
|
||||||
COMPOSE_PROJECT_NAME=${CIRCLE_BRANCH} docker-compose up -d
|
|
@ -1,10 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude - make bash behave sanely
|
|
||||||
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo ">> Logging into $_DOCKER_REGISTRY"
|
|
||||||
docker login -e="." -u="$_DOCKER_LOGIN_USERNAME" -p="$_DOCKER_LOGIN_PASSWORD" "$_DOCKER_REGISTRY"
|
|
@ -1,203 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude - make bash behave sanely
|
|
||||||
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
#
|
|
||||||
# Globals
|
|
||||||
#
|
|
||||||
remember_git_start_and_end() {
|
|
||||||
HEAD="$(git rev-parse HEAD)"
|
|
||||||
ROOT="$(git log --pretty=format:%H | tail -n 1)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Utilities
|
|
||||||
#
|
|
||||||
die() {
|
|
||||||
local msg="$@"
|
|
||||||
[[ -z "${msg}" ]] || {
|
|
||||||
tput setaf 1 # red
|
|
||||||
tput bold
|
|
||||||
echo "${msg}"
|
|
||||||
tput sgr0 # reset
|
|
||||||
}
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
error() {
|
|
||||||
local msg="$@"
|
|
||||||
echo -n '| '
|
|
||||||
tput setaf 1 # red
|
|
||||||
echo -n ' ✖'
|
|
||||||
tput sgr0 # reset
|
|
||||||
echo " ${msg}"
|
|
||||||
}
|
|
||||||
|
|
||||||
success() {
|
|
||||||
local msg="$@"
|
|
||||||
echo -n '| '
|
|
||||||
tput setaf 2 # green
|
|
||||||
echo -n ' ✓'
|
|
||||||
tput sgr0 # reset
|
|
||||||
echo " ${msg}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_commit() {
|
|
||||||
echo "○ $@"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check a command is present
|
|
||||||
ensure_command() {
|
|
||||||
local cmd="$1"
|
|
||||||
|
|
||||||
command -v "${cmd}" > /dev/null 2>&1 || {
|
|
||||||
die "Couldn't find required command: ${cmd}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Signal handling
|
|
||||||
#
|
|
||||||
cleanup() {
|
|
||||||
git reset --hard "${HEAD}" > /dev/null 2>&1
|
|
||||||
rm -f $$_commit_message
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup SIGHUP SIGINT SIGTERM
|
|
||||||
|
|
||||||
#
|
|
||||||
# Git helpers
|
|
||||||
#
|
|
||||||
|
|
||||||
# Go back one commit in history (first parent for merges)
|
|
||||||
step_back_one_commit() {
|
|
||||||
git reset --hard HEAD^ > /dev/null
|
|
||||||
log_commit "$(git rev-parse HEAD)"
|
|
||||||
}
|
|
||||||
|
|
||||||
current_commit_message() {
|
|
||||||
GIT_PAGER= git log --format=%B -n 1
|
|
||||||
}
|
|
||||||
|
|
||||||
current_commit_sha() {
|
|
||||||
git rev-parse HEAD
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_if_not_git_repo() {
|
|
||||||
local gitroot="$(git rev-parse --show-toplevel 2> /dev/null)"
|
|
||||||
|
|
||||||
[[ "${gitroot}" == "" ]] && die 'Current directory is not in a repository'
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Checks
|
|
||||||
#
|
|
||||||
check_commit_message() {
|
|
||||||
local lineno=0
|
|
||||||
local length=0
|
|
||||||
local succeded=1
|
|
||||||
|
|
||||||
while read -r line ; do
|
|
||||||
let succeded=1
|
|
||||||
let lineno+=1
|
|
||||||
length=${#line}
|
|
||||||
|
|
||||||
[[ "${lineno}" -eq "1" ]] && {
|
|
||||||
[[ "${length}" -gt 50 ]] && {
|
|
||||||
error "Commit message: Subject line longer than 50 characters";
|
|
||||||
succeded=0
|
|
||||||
};
|
|
||||||
|
|
||||||
[[ ! "${line}" =~ ^[A-Z].*$ ]] && {
|
|
||||||
error "Commit message: Subject line not capitalised";
|
|
||||||
succeded=0
|
|
||||||
};
|
|
||||||
|
|
||||||
[[ "${line}" == *. ]] && {
|
|
||||||
error "Commit message: Subject line ended with a full stop";
|
|
||||||
succeded=0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ "${lineno}" -eq "2" ]] && [[ -n "${line}" ]] && {
|
|
||||||
error "Commit message: Subject line not separated by a blank line";
|
|
||||||
succeded=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
[[ "${lineno}" -gt "1" ]] && [[ "${length}" -gt "72" ]] && {
|
|
||||||
error "Commit message: Body not wrapped at 72 characters";
|
|
||||||
succeded=0
|
|
||||||
};
|
|
||||||
done < $$_commit_message
|
|
||||||
|
|
||||||
[[ "${succeded}" -eq "1" ]] && success "Commit message"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
run_checks() {
|
|
||||||
current_commit_message > $$_commit_message
|
|
||||||
check_commit_message
|
|
||||||
rm -f $$_commit_message
|
|
||||||
set +e
|
|
||||||
npm run lint > /dev/null 2>&1
|
|
||||||
if [[ "$?" -eq 0 ]]; then
|
|
||||||
success 'Lint'
|
|
||||||
else
|
|
||||||
error 'Lint: script did not exit successfully'
|
|
||||||
fi
|
|
||||||
npm test > /dev/null 2>&1
|
|
||||||
if [[ "$?" -eq 0 ]]; then
|
|
||||||
success 'Test'
|
|
||||||
else
|
|
||||||
error 'Test: script did not exit successfully'
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
}
|
|
||||||
|
|
||||||
check_project() {
|
|
||||||
exit_if_not_git_repo
|
|
||||||
|
|
||||||
[[ -f './package.json' ]] || {
|
|
||||||
die 'This does not appear to be a node project'
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ -z "$(json -f package.json 'scripts.lint')" ]] && {
|
|
||||||
die 'There is no lint script in the package.json'
|
|
||||||
}
|
|
||||||
|
|
||||||
[[ -z "$(json -f package.json 'scripts.test')" ]] && {
|
|
||||||
die 'There is no test script in the package.json'
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
traverse_history() {
|
|
||||||
while [[ "${ROOT}" != "$(current_commit_sha)" ]] ; do
|
|
||||||
run_checks
|
|
||||||
step_back_one_commit
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Main
|
|
||||||
#
|
|
||||||
ensure_command git
|
|
||||||
ensure_command tail
|
|
||||||
ensure_command npm
|
|
||||||
ensure_command json
|
|
||||||
check_project
|
|
||||||
remember_git_start_and_end
|
|
||||||
log_commit "HEAD: $(current_commit_sha)"
|
|
||||||
traverse_history
|
|
||||||
run_checks
|
|
||||||
log_commit "ROOT: $(current_commit_sha)"
|
|
||||||
cleanup
|
|
||||||
|
|
||||||
# vim: syntax=sh et ts=2 sts=2 sw=2
|
|
@ -1,16 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
set -x
|
|
||||||
# Set internal field seperator to `/` to split up urls
|
|
||||||
IFS='/'
|
|
||||||
|
|
||||||
read -ra ADDR <<< "$CIRCLE_COMPARE_URL"
|
|
||||||
|
|
||||||
if [[ "$(git diff --name-only """${ADDR[-1]}""")" == *"ui/"* ]]
|
|
||||||
then
|
|
||||||
make -C ui publish | sed '/NPM_TOKEN/d'
|
|
||||||
fi
|
|
@ -1,60 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude - make bash behave sanely
|
|
||||||
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Make pushd & popd silent
|
|
||||||
pushd () {
|
|
||||||
command pushd "$@" > /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
popd () {
|
|
||||||
command popd "$@" > /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
export EXIT_CODE=0
|
|
||||||
|
|
||||||
|
|
||||||
function lint_changed() {
|
|
||||||
# Allow lint to be ran from outside of the root directory
|
|
||||||
local git_root
|
|
||||||
git_root=$(git rev-parse --show-cdup)
|
|
||||||
git_root=${git_root:-./}
|
|
||||||
|
|
||||||
local subdirs
|
|
||||||
subdirs=$(find "$git_root" -maxdepth 2 -mindepth 2 -name 'Makefile' -printf '%h\n')
|
|
||||||
|
|
||||||
|
|
||||||
for directory in $subdirs
|
|
||||||
do
|
|
||||||
pushd "$directory"
|
|
||||||
|
|
||||||
local npm_bin="node_modules/.bin"
|
|
||||||
local eslint="$npm_bin/eslint"
|
|
||||||
|
|
||||||
function lint() {
|
|
||||||
local to_lint
|
|
||||||
to_lint=$(git diff --staged --diff-filter=ACMTUXB --name-only -- '*.j'{s,sx})
|
|
||||||
echo $to_lint
|
|
||||||
echo $eslint
|
|
||||||
|
|
||||||
if [ "$to_lint" ]; then
|
|
||||||
$eslint "$to_lint" -c ".eslintrc" || EXIT_CODE=$?
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
lint
|
|
||||||
popd
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
lint_changed
|
|
||||||
if [[ "$EXIT_CODE" -gt "0" ]]; then
|
|
||||||
exit $EXIT_CODE
|
|
||||||
fi
|
|
||||||
make test
|
|
||||||
|
|
||||||
echo "⚡️ changed files pass eslint! ⚡️"
|
|
23
bin/setup
23
bin/setup
@ -1,23 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
# Beware of CDPATH gotchas causing cd not to work correctly when a user
|
|
||||||
# has set this in their environment
|
|
||||||
# https://bosker.wordpress.com/2012/02/12/bash-scripters-beware-of-the-cdpath/
|
|
||||||
unset CDPATH
|
|
||||||
|
|
||||||
readonly INCLUDE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
# shellcheck source=bin/setup-tools
|
|
||||||
. "${INCLUDE}"/setup-tools
|
|
||||||
|
|
||||||
#
|
|
||||||
# Main
|
|
||||||
#
|
|
||||||
ensure_prerequisites
|
|
||||||
get_triton_details
|
|
||||||
check_docker_config
|
|
||||||
write_env_file
|
|
105
bin/setup-tools
105
bin/setup-tools
@ -1,105 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
# setup.sh - Checks that all the required tools are present and that they are
|
|
||||||
# appropriately configured for deploying to Triton.
|
|
||||||
#
|
|
||||||
# Adapted from https://github.com/autopilotpattern/mysql/blob/master/setup.sh
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Prelude
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
#
|
|
||||||
# Utilities
|
|
||||||
#
|
|
||||||
die() {
|
|
||||||
local msg="$*"
|
|
||||||
[[ -z "${msg}" ]] || {
|
|
||||||
echo
|
|
||||||
tput setaf 1 # red
|
|
||||||
tput bold
|
|
||||||
echo "${msg}"
|
|
||||||
tput sgr0 # reset
|
|
||||||
}
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check functions
|
|
||||||
#
|
|
||||||
ensure_command() {
|
|
||||||
local cmd="$1"
|
|
||||||
|
|
||||||
command -v "${cmd}" > /dev/null 2>&1 || {
|
|
||||||
die "Couldn't find required command: ${cmd}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_triton_details() {
|
|
||||||
TRITON_USER=$(triton profile get | awk -F": " '/account:/{print $2}')
|
|
||||||
TRITON_DC=$(triton profile get | awk -F"/" '/url:/{print $3}' | awk -F'.' '{print $1}')
|
|
||||||
TRITON_URL=$(triton profile get | awk -F' ' '/url:/{print $2}')
|
|
||||||
TRITON_ACCOUNT=$(triton account get | awk -F": " '/id:/{print $2}')
|
|
||||||
TRITON_KEY=$(triton profile get | awk -F' ' '/keyId:/{print $2}')
|
|
||||||
}
|
|
||||||
|
|
||||||
check_docker_config() {
|
|
||||||
[[ "${DOCKER_HOST:=unset}" == "unset" ]] && {
|
|
||||||
echo "Run \"docker-compose -f local-compose.yml up\" to run locally"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_docker_config_matches_triton_config_and_capture_triton_details() {
|
|
||||||
local docker_user
|
|
||||||
docker_user=$(docker info 2>&1 | awk -F": " '/SDCAccount:/{print $2}')
|
|
||||||
local docker_dc
|
|
||||||
docker_dc="$(echo "${DOCKER_HOST}" | awk -F"/" '{print $3}' | awk -F'.' '{print $1}')"
|
|
||||||
get_triton_details
|
|
||||||
[[ ! "$docker_user" = "$TRITON_USER" ]] || [[ ! "$docker_dc" = "$TRITON_DC" ]] && {
|
|
||||||
echo "Docker user: ${docker_user}"
|
|
||||||
echo "Triton user: ${TRITON_USER}"
|
|
||||||
echo "Docker data center: ${docker_dc}"
|
|
||||||
echo "Triton data center: ${TRITON_DC}"
|
|
||||||
die "Your Triton config does not match your Docker configuration."
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_triton_cns_is_enabled() {
|
|
||||||
local triton_cns_enabled
|
|
||||||
triton_cns_enabled=$(triton account get | awk -F": " '/cns/{print $2}')
|
|
||||||
[[ "$triton_cns_enabled" == "true" ]] || {
|
|
||||||
die "Triton CNS is required and not enabled."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write_env_file() {
|
|
||||||
if [[ -f .env ]] ; then
|
|
||||||
echo "Env file already exists, not overwriting"
|
|
||||||
else
|
|
||||||
echo '# Consul discovery via Triton CNS' >> .env
|
|
||||||
[[ "${DOCKER_HOST:=unset}" == "*docker.joyent.com*" ]] || {
|
|
||||||
echo CONSUL="consul.svc.${TRITON_ACCOUNT}.${TRITON_DC}.cns.joyent.com" \
|
|
||||||
>> .env
|
|
||||||
}
|
|
||||||
echo SDC_KEY_ID=${TRITON_KEY} >> .env
|
|
||||||
echo SDC_ACCOUNT=${TRITON_ACCOUNT} >> .env
|
|
||||||
echo SDC_URL=${TRITON_URL} >> .env
|
|
||||||
echo >> .env
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_prerequisites() {
|
|
||||||
ensure_command docker
|
|
||||||
ensure_command docker-compose
|
|
||||||
ensure_command triton
|
|
||||||
}
|
|
||||||
|
|
||||||
# vim: syntax=sh et ts=2 sts=2 sw=2
|
|
@ -1,57 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
require 'fileutils'
|
|
||||||
|
|
||||||
PROGNAME = 'pre-commit (auto-generate sketch previews)'
|
|
||||||
|
|
||||||
def main
|
|
||||||
progress "Installing sketchtool"
|
|
||||||
system!(%W[/Applications/Sketch.app/Contents/Resources/sketchtool/install.sh])
|
|
||||||
|
|
||||||
progress "Looking for changed or added .sketch files"
|
|
||||||
diff_output = capture!(%W[git diff --name-only --cached --pretty=format:])
|
|
||||||
sketch_files = diff_output.split("\n").grep(/\.sketch\z/)
|
|
||||||
if sketch_files.empty?
|
|
||||||
progress "No sketch files to create preview images for in this commit!"
|
|
||||||
end
|
|
||||||
puts sketch_files
|
|
||||||
|
|
||||||
sketch_files.each do |f|
|
|
||||||
unless File.exist?(f)
|
|
||||||
progress "#{f} does not exist (anymore?)"
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
png_output_dir = f.sub(/\.sketch\z/, '') + '-sketch-previews'
|
|
||||||
progress "deleting old previews"
|
|
||||||
FileUtils.rm_rf(png_output_dir)
|
|
||||||
|
|
||||||
progress "exporting pages"
|
|
||||||
cmd = %W[sketchtool --overwriting=YES --output=#{png_output_dir} export pages #{f}]
|
|
||||||
system!(cmd)
|
|
||||||
|
|
||||||
progress "adding to git"
|
|
||||||
system!(%W[git add #{png_output_dir}])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def system!(cmd)
|
|
||||||
puts "running: #{cmd.join(' ')}"
|
|
||||||
abort failure_message(cmd) unless system(*cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
def capture!(cmd)
|
|
||||||
puts "capturing: #{cmd.join(' ')}"
|
|
||||||
result = IO.popen(cmd) { |io| io.read }
|
|
||||||
abort failure_message(cmd) unless $?.success?
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def failure_message(cmd)
|
|
||||||
"#{PROGNAME}: command failed: #{cmd.join(' ')}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def progress(msg)
|
|
||||||
puts "#{PROGNAME}: #{msg}"
|
|
||||||
end
|
|
||||||
|
|
||||||
main
|
|
8
bundle/.env.js
Normal file
8
bundle/.env.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { homedir } = require('os');
|
||||||
|
const { join } = require('path');
|
||||||
|
|
||||||
|
const { SDC_KEY_PATH } = process.env;
|
||||||
|
|
||||||
|
process.env.SDC_KEY_PATH = SDC_KEY_PATH || join(homedir(), './.ssh/id_rsa');
|
20
bundle/data/account.js
Normal file
20
bundle/data/account.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
name: 'Logout',
|
||||||
|
slug: 'logout',
|
||||||
|
description: 'Do the daggum logout',
|
||||||
|
url: '/logout'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Change Password',
|
||||||
|
slug: 'change-password',
|
||||||
|
description: 'Change yer own password',
|
||||||
|
url: '/password'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Account',
|
||||||
|
slug: 'account',
|
||||||
|
description: 'Your account information',
|
||||||
|
url: '/account'
|
||||||
|
}
|
||||||
|
];
|
89
bundle/data/categories.js
Normal file
89
bundle/data/categories.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
name: 'Compute',
|
||||||
|
services: [
|
||||||
|
{
|
||||||
|
name: 'VMs & Containers',
|
||||||
|
slug: 'instances',
|
||||||
|
description: 'Run VMs and bare metal containers'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Network',
|
||||||
|
services: [
|
||||||
|
{
|
||||||
|
name: 'VLANs',
|
||||||
|
slug: 'vlans',
|
||||||
|
description: 'Wire your application your way'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Subnets',
|
||||||
|
slug: 'subnets',
|
||||||
|
description: 'A network for everything'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Firewall Rules',
|
||||||
|
slug: 'firewall',
|
||||||
|
description: 'Control the bits coming and going'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Storage',
|
||||||
|
services: [
|
||||||
|
{
|
||||||
|
name: 'Triton Object Storage',
|
||||||
|
slug: 'object-storage',
|
||||||
|
description: 'Modern cloud object storage',
|
||||||
|
tags: ["'note'='was Manta'"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'S3 Compatibility Bridge',
|
||||||
|
slug: 's3-bridge',
|
||||||
|
description: 'Modern storage, legacy compability'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Triton Volumes',
|
||||||
|
slug: 'volumes',
|
||||||
|
description: 'Network filesystems for your apps',
|
||||||
|
tags: ["'is-new'='true'"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Access',
|
||||||
|
services: [
|
||||||
|
{
|
||||||
|
name: 'Role Based Access Control',
|
||||||
|
slug: 'rbac',
|
||||||
|
description: 'Manage users within your account'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Help & Support',
|
||||||
|
services: [
|
||||||
|
{
|
||||||
|
name: 'Service Status',
|
||||||
|
slug: 'status',
|
||||||
|
description: 'Find out about the status of our services'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Contact Support',
|
||||||
|
slug: 'contact-support',
|
||||||
|
description: 'Chat to us via phone or email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Support Plans',
|
||||||
|
slug: 'support-plans',
|
||||||
|
description: 'Write here about Support Plans'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Getting Started',
|
||||||
|
slug: 'getting-started',
|
||||||
|
description: 'Write here about Getting Started'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
86
bundle/data/regions.js
Normal file
86
bundle/data/regions.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
name: 'Ashburn, Virginia, USA',
|
||||||
|
continent: 'NORTH_AMERICA',
|
||||||
|
datacenters: [
|
||||||
|
{
|
||||||
|
name: 'us-east-1',
|
||||||
|
url: 'http://localhost'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'us-east-2',
|
||||||
|
url: 'http://localhost'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'us-east-3',
|
||||||
|
url: 'http://localhost'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Las Vegas, Nevada, USA',
|
||||||
|
continent: 'NORTH_AMERICA',
|
||||||
|
datacenters: [
|
||||||
|
{
|
||||||
|
name: 'us-sw-1',
|
||||||
|
url: 'http://localhost'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Emeryville, California, USA',
|
||||||
|
continent: 'NORTH_AMERICA',
|
||||||
|
datacenters: [
|
||||||
|
{
|
||||||
|
name: 'us-west-1',
|
||||||
|
url: 'http://localhost'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Amsterdam, Netherlands',
|
||||||
|
continent: 'EUROPE',
|
||||||
|
datacenters: [
|
||||||
|
{
|
||||||
|
name: 'us-ams-1',
|
||||||
|
url: 'http://localhost'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Singapore',
|
||||||
|
continent: 'ASIA',
|
||||||
|
datacenters: [
|
||||||
|
{
|
||||||
|
name: 'ap-sg-1',
|
||||||
|
url: 'http://localhost'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ap-sg-2',
|
||||||
|
url: 'http://localhost'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ap-sg-3',
|
||||||
|
url: 'http://localhost'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Seoul, South Korea',
|
||||||
|
continent: 'ASIA',
|
||||||
|
datacenters: [
|
||||||
|
{
|
||||||
|
name: 'ap-kr-1',
|
||||||
|
url: 'http://localhost'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ap-kr-2',
|
||||||
|
url: 'http://localhost'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ap-kr-3',
|
||||||
|
url: 'http://localhost'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
72
bundle/index.js
Normal file
72
bundle/index.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Requires .env.js file with the following exports:
|
||||||
|
// SDC_URL, SDC_KEY_ID, SDC_KEY_PATH
|
||||||
|
require('./.env.js');
|
||||||
|
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const Hapi = require('hapi');
|
||||||
|
const H2O2 = require('h2o2');
|
||||||
|
const Execa = require('execa');
|
||||||
|
const Path = require('path');
|
||||||
|
const Fs = require('fs');
|
||||||
|
|
||||||
|
const { PORT = 4000 } = process.env;
|
||||||
|
const ROOT = Path.join(__dirname, 'src');
|
||||||
|
|
||||||
|
const calcPort = i => Number(PORT) + Number(i) + 1;
|
||||||
|
|
||||||
|
const namespaces = Fs.readdirSync(ROOT)
|
||||||
|
.filter(filename => /.js$/.test(filename))
|
||||||
|
.map(filename => filename.replace(/.js$/, ''))
|
||||||
|
.filter(filename => !['index', 'server'].includes(filename));
|
||||||
|
|
||||||
|
const routes = namespaces.map((namespace, i) => ({
|
||||||
|
method: '*',
|
||||||
|
path: `/${namespace}/{params*}`,
|
||||||
|
handler: {
|
||||||
|
proxy: {
|
||||||
|
uri: `{protocol}://0.0.0.0:${calcPort(i)}/${namespace}/{params}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
namespaces.forEach((namespace, i) => {
|
||||||
|
const child = Execa('node', [namespace], {
|
||||||
|
cwd: ROOT,
|
||||||
|
cleanup: true,
|
||||||
|
env: Object.assign({}, process.env, {
|
||||||
|
PORT: calcPort(i),
|
||||||
|
PREFIX: namespace
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stdout.pipe(process.stdout);
|
||||||
|
child.stderr.pipe(process.stderr);
|
||||||
|
});
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
const server = Hapi.server({
|
||||||
|
port: PORT,
|
||||||
|
routes: {
|
||||||
|
cors: {
|
||||||
|
origin: ['*'],
|
||||||
|
credentials: true,
|
||||||
|
additionalHeaders: ['Cookie', 'X-CSRF-Token']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
debug: {
|
||||||
|
log: ['error'],
|
||||||
|
request: ['error']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register({
|
||||||
|
plugin: H2O2
|
||||||
|
});
|
||||||
|
|
||||||
|
routes.map(route => server.route(route));
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(`server started at http://0.0.0.0:${server.info.port}`);
|
||||||
|
});
|
31
bundle/package.json
Normal file
31
bundle/package.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "joyent-portal-bundle",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "NODE_ENV=development PORT=4000 node index.js",
|
||||||
|
"build:test": "echo 0",
|
||||||
|
"build:lib": "echo 0",
|
||||||
|
"build:bundle": "echo 0",
|
||||||
|
"prepublish": "echo 0",
|
||||||
|
"test": "echo 0",
|
||||||
|
"test:ci": "echo 0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"apr-main": "^4.0.3",
|
||||||
|
"cloudapi-gql": "^8.0.0",
|
||||||
|
"execa": "^0.10.0",
|
||||||
|
"graphi": "^5.7.0",
|
||||||
|
"h2o2": "^8.1.2",
|
||||||
|
"hapi": "^17.5.0",
|
||||||
|
"hapi-triton-auth": "^3.0.0",
|
||||||
|
"hapi-webconsole-nav": "^2.1.0",
|
||||||
|
"my-joy-images": "*",
|
||||||
|
"my-joy-instances": "*",
|
||||||
|
"my-joy-navigation": "*",
|
||||||
|
"my-joy-service-groups": "*",
|
||||||
|
"my-joy-templates": "*",
|
||||||
|
"tsg-graphql": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
64
bundle/src/images.js
Normal file
64
bundle/src/images.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
require('../.env.js');
|
||||||
|
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const CloudApiGql = require('cloudapi-gql');
|
||||||
|
const Graphi = require('graphi');
|
||||||
|
const Url = require('url');
|
||||||
|
|
||||||
|
const Server = require('./server');
|
||||||
|
const Ui = require('my-joy-images');
|
||||||
|
|
||||||
|
const {
|
||||||
|
PORT = 4003,
|
||||||
|
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||||
|
PREFIX = 'images',
|
||||||
|
DC_NAME,
|
||||||
|
SDC_URL,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||||
|
const keyPath = SDC_KEY_PATH;
|
||||||
|
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||||
|
const apiBaseUrl = SDC_URL;
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
const server = await Server({
|
||||||
|
PORT,
|
||||||
|
BASE_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register([
|
||||||
|
{
|
||||||
|
plugin: Graphi,
|
||||||
|
options: {
|
||||||
|
graphqlPath: '/graphql',
|
||||||
|
graphiqlPath: '/graphiql',
|
||||||
|
authStrategy: 'sso'
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: CloudApiGql,
|
||||||
|
options: {
|
||||||
|
authStrategy: 'sso',
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl,
|
||||||
|
dcName
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Ui
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
});
|
64
bundle/src/instances.js
Normal file
64
bundle/src/instances.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
require('../.env.js');
|
||||||
|
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const CloudApiGql = require('cloudapi-gql');
|
||||||
|
const Graphi = require('graphi');
|
||||||
|
const Url = require('url');
|
||||||
|
|
||||||
|
const Server = require('./server');
|
||||||
|
const Ui = require('my-joy-instances');
|
||||||
|
|
||||||
|
const {
|
||||||
|
PORT = 4002,
|
||||||
|
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||||
|
PREFIX = 'instances',
|
||||||
|
DC_NAME,
|
||||||
|
SDC_URL,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||||
|
const keyPath = SDC_KEY_PATH;
|
||||||
|
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||||
|
const apiBaseUrl = SDC_URL;
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
const server = await Server({
|
||||||
|
PORT,
|
||||||
|
BASE_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register([
|
||||||
|
{
|
||||||
|
plugin: Graphi,
|
||||||
|
options: {
|
||||||
|
graphqlPath: '/graphql',
|
||||||
|
graphiqlPath: '/graphiql',
|
||||||
|
authStrategy: 'sso'
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: CloudApiGql,
|
||||||
|
options: {
|
||||||
|
authStrategy: 'sso',
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl,
|
||||||
|
dcName
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Ui
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
});
|
72
bundle/src/navigation.js
Normal file
72
bundle/src/navigation.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
require('../.env.js');
|
||||||
|
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const Nav = require('hapi-webconsole-nav');
|
||||||
|
const Graphi = require('graphi');
|
||||||
|
const Url = require('url');
|
||||||
|
|
||||||
|
const Server = require('./server');
|
||||||
|
const Ui = require('my-joy-navigation');
|
||||||
|
|
||||||
|
const Regions = require('../data/regions');
|
||||||
|
const Categories = require('../data/categories');
|
||||||
|
const Account = require('../data/account');
|
||||||
|
|
||||||
|
const {
|
||||||
|
PORT = 4001,
|
||||||
|
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||||
|
PREFIX = 'navigation',
|
||||||
|
DC_NAME,
|
||||||
|
SDC_URL,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||||
|
const keyPath = SDC_KEY_PATH;
|
||||||
|
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||||
|
const apiBaseUrl = SDC_URL;
|
||||||
|
const baseUrl = BASE_URL;
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
const server = await Server({
|
||||||
|
PORT,
|
||||||
|
BASE_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register([
|
||||||
|
{
|
||||||
|
plugin: Graphi,
|
||||||
|
options: {
|
||||||
|
graphqlPath: '/graphql',
|
||||||
|
graphiqlPath: '/graphiql',
|
||||||
|
authStrategy: 'sso'
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Nav,
|
||||||
|
options: {
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl,
|
||||||
|
dcName,
|
||||||
|
baseUrl,
|
||||||
|
regions: Regions,
|
||||||
|
accountServices: Account,
|
||||||
|
categories: Categories
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Ui
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
});
|
84
bundle/src/server.js
Normal file
84
bundle/src/server.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
require('../.env.js');
|
||||||
|
|
||||||
|
const Hapi = require('hapi');
|
||||||
|
const Sso = require('hapi-triton-auth');
|
||||||
|
|
||||||
|
const {
|
||||||
|
COOKIE_PASSWORD,
|
||||||
|
COOKIE_DOMAIN,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID,
|
||||||
|
SDC_URL
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
module.exports = async ({ PORT, BASE_URL }) => {
|
||||||
|
const keyPath = SDC_KEY_PATH;
|
||||||
|
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||||
|
const apiBaseUrl = SDC_URL;
|
||||||
|
const ssoUrl = 'https://sso.joyent.com/login';
|
||||||
|
const baseUrl = BASE_URL;
|
||||||
|
const isDev = true;
|
||||||
|
|
||||||
|
const permissions = {
|
||||||
|
cloudapi: ['/my/*']
|
||||||
|
};
|
||||||
|
|
||||||
|
const cookie = {
|
||||||
|
password: COOKIE_PASSWORD,
|
||||||
|
domain: COOKIE_DOMAIN,
|
||||||
|
isSecure: false,
|
||||||
|
isHttpOnly: true,
|
||||||
|
ttl: 1000 * 60 * 60 // 1 hour
|
||||||
|
};
|
||||||
|
|
||||||
|
const server = Hapi.server({
|
||||||
|
port: PORT,
|
||||||
|
routes: {
|
||||||
|
cors: {
|
||||||
|
origin: ['*'],
|
||||||
|
credentials: true,
|
||||||
|
additionalHeaders: ['Cookie', 'X-CSRF-Token']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
debug: {
|
||||||
|
log: ['error'],
|
||||||
|
request: ['error']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.events.on('log', (event, tags) => {
|
||||||
|
if (tags.error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.events.on('request', (request, event) => {
|
||||||
|
const { tags } = event;
|
||||||
|
if (tags.includes('error') && event.data && event.data.errors) {
|
||||||
|
event.data.errors.forEach(error => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register({
|
||||||
|
plugin: Sso,
|
||||||
|
options: {
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl,
|
||||||
|
ssoUrl,
|
||||||
|
permissions,
|
||||||
|
baseUrl,
|
||||||
|
isDev,
|
||||||
|
cookie
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.auth.default('sso');
|
||||||
|
|
||||||
|
return server;
|
||||||
|
};
|
78
bundle/src/service-groups.js
Normal file
78
bundle/src/service-groups.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
require('../.env.js');
|
||||||
|
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const CloudApiGql = require('cloudapi-gql');
|
||||||
|
const Tsg = require('tsg-graphql');
|
||||||
|
const Graphi = require('graphi');
|
||||||
|
const Url = require('url');
|
||||||
|
|
||||||
|
const Server = require('./server');
|
||||||
|
const Ui = require('my-joy-service-groups');
|
||||||
|
|
||||||
|
const {
|
||||||
|
PORT = 4004,
|
||||||
|
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||||
|
PREFIX = 'service-groups',
|
||||||
|
DC_NAME,
|
||||||
|
TSG_URL = 'http://0.0.0.0:3000',
|
||||||
|
SDC_URL,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||||
|
const keyPath = SDC_KEY_PATH;
|
||||||
|
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
const server = await Server({
|
||||||
|
PORT,
|
||||||
|
BASE_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register([
|
||||||
|
{
|
||||||
|
plugin: Graphi,
|
||||||
|
options: {
|
||||||
|
graphqlPath: '/graphql',
|
||||||
|
graphiqlPath: '/graphiql',
|
||||||
|
authStrategy: 'sso'
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Tsg,
|
||||||
|
options: {
|
||||||
|
authStrategy: 'sso',
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl: TSG_URL,
|
||||||
|
dcName
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: CloudApiGql,
|
||||||
|
options: {
|
||||||
|
authStrategy: 'sso',
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl: SDC_URL,
|
||||||
|
dcName
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Ui
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
});
|
78
bundle/src/templates.js
Normal file
78
bundle/src/templates.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
require('../.env.js');
|
||||||
|
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const CloudApiGql = require('cloudapi-gql');
|
||||||
|
const Tsg = require('tsg-graphql');
|
||||||
|
const Graphi = require('graphi');
|
||||||
|
const Url = require('url');
|
||||||
|
|
||||||
|
const Server = require('./server');
|
||||||
|
const Ui = require('my-joy-templates');
|
||||||
|
|
||||||
|
const {
|
||||||
|
PORT = 4005,
|
||||||
|
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||||
|
PREFIX = 'templates',
|
||||||
|
DC_NAME,
|
||||||
|
TSG_URL = 'http://0.0.0.0:3000',
|
||||||
|
SDC_URL,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||||
|
const keyPath = SDC_KEY_PATH;
|
||||||
|
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
const server = await Server({
|
||||||
|
PORT,
|
||||||
|
BASE_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register([
|
||||||
|
{
|
||||||
|
plugin: Graphi,
|
||||||
|
options: {
|
||||||
|
graphqlPath: '/graphql',
|
||||||
|
graphiqlPath: '/graphiql',
|
||||||
|
authStrategy: 'sso'
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Tsg,
|
||||||
|
options: {
|
||||||
|
authStrategy: 'sso',
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl: TSG_URL,
|
||||||
|
dcName
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: CloudApiGql,
|
||||||
|
options: {
|
||||||
|
authStrategy: 'sso',
|
||||||
|
keyPath,
|
||||||
|
keyId,
|
||||||
|
apiBaseUrl: SDC_URL,
|
||||||
|
dcName
|
||||||
|
},
|
||||||
|
routes: {
|
||||||
|
prefix: `/${PREFIX}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Ui
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
});
|
51
circle.yml
51
circle.yml
@ -1,51 +0,0 @@
|
|||||||
## Customize the test machine
|
|
||||||
machine:
|
|
||||||
pre:
|
|
||||||
- git config --global user.email "circleci@joyent.zone"
|
|
||||||
- git config --global user.name "circlebot"
|
|
||||||
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
|
|
||||||
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
node:
|
|
||||||
version: 7.7.3
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
pre:
|
|
||||||
- sudo curl -L https://github.com/docker/compose/releases/download/1.8.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
|
|
||||||
- sudo chmod +x /usr/local/bin/docker-compose
|
|
||||||
- yarn global add triton@4.15.0 || cat /home/ubuntu/.yarn-config/global/yarn-error.log
|
|
||||||
- echo '{"url":"https://eu-ams-1.api.joyent.com","account":"'$SDC_ACCOUNT'","keyId":"c3:30:35:9b:85:48:73:44:31:cc:4b:2e:6a:00:16:e2","name":"eu-ams-1","curr":true}' | triton profile create -f -
|
|
||||||
- triton env --docker eu-ams-1
|
|
||||||
- mkdir -p ${CIRCLE_TEST_REPORTS}/tap-xunit/
|
|
||||||
- echo -e "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
|
||||||
override:
|
|
||||||
- make && make install
|
|
||||||
# Install git-lfs - TODO: Move to make task
|
|
||||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
|
|
||||||
- sudo apt-get install git-lfs
|
|
||||||
- ssh git@github.com git-lfs-authenticate yldio/joyent-portal.git download
|
|
||||||
- git config credential.helper manager
|
|
||||||
- git lfs pull
|
|
||||||
|
|
||||||
test:
|
|
||||||
override:
|
|
||||||
- make -j2 lint-ci test-ci
|
|
||||||
|
|
||||||
deployment:
|
|
||||||
development:
|
|
||||||
branch: master
|
|
||||||
commands:
|
|
||||||
- ./bin/docker-login
|
|
||||||
- ./bin/on-changes-publish-ui
|
|
||||||
- make -j2 build
|
|
||||||
- make -j2 push
|
|
||||||
- ./bin/deploy
|
|
||||||
staging:
|
|
||||||
tag: /release.*/
|
|
||||||
commands:
|
|
||||||
- CIRCLE_BRANCH=staging ./bin/docker-login
|
|
||||||
- CIRCLE_BRANCH=staging ./bin/on-changes-publish-ui
|
|
||||||
- CIRCLE_BRANCH=staging make -j2 build
|
|
||||||
- CIRCLE_BRANCH=staging make -j2 push
|
|
||||||
- CIRCLE_BRANCH=staging ./bin/deploy
|
|
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended",
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"no-console": 0,
|
|
||||||
"prettier/prettier": ["error", {
|
|
||||||
"useTabs": false,
|
|
||||||
"printWidth": 80,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "none",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"jsxBracketSameLine": false,
|
|
||||||
"parser": "flow",
|
|
||||||
"semi": true
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
}
|
|
||||||
}
|
|
50
cloudapi-graphql/.gitignore
vendored
50
cloudapi-graphql/.gitignore
vendored
@ -1,50 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules
|
|
||||||
jspm_packages
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Vim files:
|
|
||||||
*.sw*
|
|
||||||
|
|
||||||
# Mac OS dirty files
|
|
||||||
.DS_Store
|
|
@ -1 +0,0 @@
|
|||||||
FROM quay.io/yldio/alpine-node-containerpilot:6.9.4-3
|
|
@ -1,54 +0,0 @@
|
|||||||
NAME := $(lastword $(subst /, ,$(CURDIR)))
|
|
||||||
|
|
||||||
bindir := $(shell yarn bin)
|
|
||||||
AVA := $(bindir)/ava
|
|
||||||
NYC := $(bindir)/nyc
|
|
||||||
|
|
||||||
.PHONY: install
|
|
||||||
install:
|
|
||||||
yarn install --prefer-offline
|
|
||||||
|
|
||||||
.PHONY: install-production
|
|
||||||
install-production:
|
|
||||||
yarn install --production --pure-lockfile --prefer-offline
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
@rm -rf node_modules
|
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
test:
|
|
||||||
$(AVA) $(TEST_ARGS)
|
|
||||||
|
|
||||||
XUNIT_DIR := ${CIRCLE_TEST_REPORTS}/tap-xunit
|
|
||||||
XUNIT := $(bindir)/tap-xunit
|
|
||||||
XUNIT_OUTPUT := >> ${CIRCLE_TEST_REPORTS}/tap-xunit/xunit-$(NAME)
|
|
||||||
.PHONY: test-ci
|
|
||||||
test-ci:
|
|
||||||
mkdir -p $(XUNIT_DIR)
|
|
||||||
$(NYC) $(AVA) -t | $(XUNIT) $(XUNIT_OUTPUT).xml
|
|
||||||
|
|
||||||
.PHONY: start
|
|
||||||
start:
|
|
||||||
yarn run start
|
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build:
|
|
||||||
docker build -t quay.io/yldio/joyent-dashboard-$(NAME):$(CIRCLE_BRANCH) .
|
|
||||||
|
|
||||||
.PHONY: push
|
|
||||||
push:
|
|
||||||
docker push quay.io/yldio/joyent-dashboard-$(NAME)
|
|
||||||
|
|
||||||
.PHONY: lint
|
|
||||||
lint:
|
|
||||||
$(bindir)/eslint .
|
|
||||||
|
|
||||||
.PHONY: lint-ci
|
|
||||||
lint-ci:
|
|
||||||
mkdir -p $(XUNIT_DIR)
|
|
||||||
-$(bindir)/eslint . --format tap | $(XUNIT) $(XUNIT_OUTPUT)-lint.xml
|
|
||||||
|
|
||||||
.PHONY: licence-check
|
|
||||||
licence-check:
|
|
||||||
../node_modules/.bin/license-to-fail ../licence.js
|
|
@ -1,166 +0,0 @@
|
|||||||
[![Docker Repository on Quay](https://quay.io/repository/yldio/joyent-dashboard-cloudapi-graphql/status?token=bddd694a-a913-4b66-b7bc-fb71992672c4 "Docker Repository on Quay")](https://quay.io/repository/yldio/joyent-dashboard-cloudapi-graphql)
|
|
||||||
# cloudapi-graphql
|
|
||||||
|
|
||||||
Proof-of-Concept of the [Joyent Cloud API](https://apidocs.joyent.com/cloudapi/) running on GraphQL.
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
### Setup Credentials
|
|
||||||
|
|
||||||
Create `credentials.json`:
|
|
||||||
|
|
||||||
```json5
|
|
||||||
{
|
|
||||||
"url": "https://us-sw-1.api.joyentcloud.com",
|
|
||||||
"keyId": "", //public key fingerprint ex: 35:jh:42:56...
|
|
||||||
"account": "", // account ex: raoulmillais
|
|
||||||
"user": "" // sub-account ex: ramitos
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively you can just use ENV variables:
|
|
||||||
|
|
||||||
```
|
|
||||||
SDC_URL
|
|
||||||
SDC_ACCOUNT
|
|
||||||
SDC_USER
|
|
||||||
SDC_KEY_ID
|
|
||||||
```
|
|
||||||
|
|
||||||
As a third option you can use a `.env` file.
|
|
||||||
|
|
||||||
### Install Dependencies and run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn install
|
|
||||||
yarn start
|
|
||||||
```
|
|
||||||
|
|
||||||
### Visit GraphiQL
|
|
||||||
|
|
||||||
Go-to http://0.0.0.0:4000/graphql to use the REPL with interactive documentation.
|
|
||||||
|
|
||||||
![GraphiQL](https://cloud.githubusercontent.com/assets/524382/19242455/1e371978-8f0b-11e6-9563-d6f5b93fa63c.png)
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
- [x] Account
|
|
||||||
- [x] GetAccount
|
|
||||||
- [x] UpdateAccount
|
|
||||||
- [x] Keys
|
|
||||||
- [x] ListKeys
|
|
||||||
- [x] GetKey
|
|
||||||
- [x] CreateKey
|
|
||||||
- [x] DeleteKey
|
|
||||||
- [x] Users
|
|
||||||
- [x] ListUsers
|
|
||||||
- [x] GetUser
|
|
||||||
- [x] CreateUser
|
|
||||||
- [x] UpdateUser
|
|
||||||
- [ ] ChangeUserPassword
|
|
||||||
- [x] DeleteUser
|
|
||||||
- [x] Roles
|
|
||||||
- [x] ListRoles
|
|
||||||
- [x] GetRole
|
|
||||||
- [x] CreateRole
|
|
||||||
- [x] UpdateRole
|
|
||||||
- [x] DeleteRole
|
|
||||||
- [x] Role Tags
|
|
||||||
- [x] SetRoleTags
|
|
||||||
- [x] Policies
|
|
||||||
- [x] ListPolicies
|
|
||||||
- [x] GetPolicy
|
|
||||||
- [x] CreatePolicy
|
|
||||||
- [x] UpdatePolicy
|
|
||||||
- [x] DeletePolicy
|
|
||||||
- [x] User SSH Keys
|
|
||||||
- [x] ListUserKeys
|
|
||||||
- [x] GetUserKey
|
|
||||||
- [x] CreateUserKey
|
|
||||||
- [x] DeleteUserKey
|
|
||||||
- [ ] Config
|
|
||||||
- [ ] GetConfig
|
|
||||||
- [ ] UpdateConfig
|
|
||||||
- [x] Datacenters
|
|
||||||
- [x] ListDatacenters
|
|
||||||
- [x] GetDatacenter
|
|
||||||
- [x] Services
|
|
||||||
- [x] ListServices
|
|
||||||
- [x] Images
|
|
||||||
- [x] ListImages
|
|
||||||
- [x] GetImage
|
|
||||||
- [x] DeleteImage
|
|
||||||
- [x] ExportImage
|
|
||||||
- [x] CreateImageFromMachine
|
|
||||||
- [ ] UpdateImage
|
|
||||||
- [x] Packages
|
|
||||||
- [x] ListPackages
|
|
||||||
- [x] GetPackage
|
|
||||||
- [x] Instances
|
|
||||||
- [x] ListMachines
|
|
||||||
- [x] GetMachine
|
|
||||||
- [x] CreateMachine
|
|
||||||
- [x] StopMachine
|
|
||||||
- [x] StartMachine
|
|
||||||
- [x] RebootMachine
|
|
||||||
- [ ] ResizeMachine
|
|
||||||
- [ ] RenameMachine
|
|
||||||
- [x] EnableMachineFirewall
|
|
||||||
- [x] DisableMachineFirewall
|
|
||||||
- [x] CreateMachineSnapshot
|
|
||||||
- [x] StartMachineFromSnapshot
|
|
||||||
- [x] ListMachineSnapshots
|
|
||||||
- [x] GetMachineSnapshot
|
|
||||||
- [x] DeleteMachineSnapshot
|
|
||||||
- [ ] UpdateMachineMetadata
|
|
||||||
- [ ] ListMachineMetadata
|
|
||||||
- [ ] GetMachineMetadata
|
|
||||||
- [ ] DeleteMachineMetadata
|
|
||||||
- [ ] DeleteAllMachineMetadata
|
|
||||||
- [x] AddMachineTags
|
|
||||||
- [x] ReplaceMachineTags
|
|
||||||
- [ ] ListMachineTags
|
|
||||||
- [x] GetMachineTag
|
|
||||||
- [x] DeleteMachineTag
|
|
||||||
- [x] DeleteMachineTags
|
|
||||||
- [x] DeleteMachine
|
|
||||||
- [x] MachineAudit
|
|
||||||
- [ ] Analytics
|
|
||||||
- [ ] DescribeAnalytics
|
|
||||||
- [ ] ListInstrumentations
|
|
||||||
- [ ] GetInstrumentation
|
|
||||||
- [ ] GetInstrumentationValue
|
|
||||||
- [ ] GetInstrumentationHeatmap
|
|
||||||
- [ ] GetInstrumentationHeatmapDetails
|
|
||||||
- [ ] CreateInstrumentation
|
|
||||||
- [ ] DeleteInstrumentation
|
|
||||||
- [x] FirewallRules
|
|
||||||
- [x] Firewall Rule Syntax
|
|
||||||
- [x] ListFirewallRules
|
|
||||||
- [x] GetFirewallRule
|
|
||||||
- [x] CreateFirewallRule
|
|
||||||
- [x] UpdateFirewallRule
|
|
||||||
- [x] EnableFirewallRule
|
|
||||||
- [x] DisableFirewallRule
|
|
||||||
- [x] DeleteFirewallRule
|
|
||||||
- [x] ListMachineFirewallRules
|
|
||||||
- [x] ListFirewallRuleMachines
|
|
||||||
- [ ] Fabrics
|
|
||||||
- [ ] ListFabricVLANs
|
|
||||||
- [ ] CreateFabricVLAN
|
|
||||||
- [ ] GetFabricVLAN
|
|
||||||
- [ ] UpdateFabricVLAN
|
|
||||||
- [ ] DeleteFabricVLAN
|
|
||||||
- [ ] ListFabricNetworks
|
|
||||||
- [ ] CreateFabricNetwork
|
|
||||||
- [ ] GetFabricNetwork
|
|
||||||
- [ ] DeleteFabricNetwork
|
|
||||||
- [x] Networks
|
|
||||||
- [x] ListNetworks
|
|
||||||
- [x] GetNetwork
|
|
||||||
- [ ] Nics
|
|
||||||
- [ ] ListNics
|
|
||||||
- [ ] GetNic
|
|
||||||
- [ ] AddNic
|
|
||||||
- [ ] RemoveNic
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
"consul": "{{ .CONSUL }}:8500",
|
|
||||||
"services": [{
|
|
||||||
"name": "joyent-portal-cloudapi-graphql",
|
|
||||||
"port": 4000,
|
|
||||||
"health": "/usr/bin/curl -o /dev/null --fail -s http://localhost:4000/graphql",
|
|
||||||
"poll": 3,
|
|
||||||
"ttl": 10
|
|
||||||
}],
|
|
||||||
"telemetry": {
|
|
||||||
"port": 9090,
|
|
||||||
"sensors": [{
|
|
||||||
"name": "graphql_memory_percent",
|
|
||||||
"help": "percentage of memory used",
|
|
||||||
"type": "gauge",
|
|
||||||
"poll": 5,
|
|
||||||
"check": ["/bin/sensors", "memory"]
|
|
||||||
}, {
|
|
||||||
"name": "graphql_cpu_load",
|
|
||||||
"help": "cpu load",
|
|
||||||
"type": "gauge",
|
|
||||||
"poll": 5,
|
|
||||||
"check": ["/bin/sensors", "cpu"]
|
|
||||||
}, {
|
|
||||||
"name": "graphql_disk_capacity",
|
|
||||||
"help": "disk capacity",
|
|
||||||
"type": "gauge",
|
|
||||||
"poll": 60,
|
|
||||||
"check": ["/bin/sensors", "diskcapacity"]
|
|
||||||
}, {
|
|
||||||
"name": "graphql_disk_usage",
|
|
||||||
"help": "disk usage",
|
|
||||||
"type": "gauge",
|
|
||||||
"poll": 60,
|
|
||||||
"check": ["/bin/sensors", "diskusage"]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "cloudapi-graphql",
|
|
||||||
"private": true,
|
|
||||||
"license": "MPL-2.0",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "src/index.js",
|
|
||||||
"scripts": {
|
|
||||||
"lint": "eslint src --fix",
|
|
||||||
"start": "node src/index.js",
|
|
||||||
"test": "make test"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"bunyan": "^1.8.10",
|
|
||||||
"dotenv": "^4.0.0",
|
|
||||||
"express": "^4.15.2",
|
|
||||||
"express-graphql": "^0.6.4",
|
|
||||||
"got": "^6.7.1",
|
|
||||||
"graphql": "^0.9.3",
|
|
||||||
"smartdc-auth": "^2.5.2",
|
|
||||||
"triton": "^5.2.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"ava": "^0.19.1",
|
|
||||||
"eslint": "^3.19.0",
|
|
||||||
"eslint-config-prettier": "^1.7.0",
|
|
||||||
"eslint-plugin-prettier": "^2.0.1",
|
|
||||||
"nyc": "^10.2.0",
|
|
||||||
"prettier": "^1.2.2",
|
|
||||||
"tap-xunit": "^1.7.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.get = () => {
|
|
||||||
return request('getAccount');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.update = ctx => {
|
|
||||||
return request('updateAccount', ctx);
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
// const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.get = () => {
|
|
||||||
// return request('', ctx);
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
return request('listDatacenters');
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listFirewallRules', {});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getFirewallRule', ctx);
|
|
||||||
};
|
|
@ -1,37 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listFirewallRules', {});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.listByMachine = ctx => {
|
|
||||||
return request('listMachineFirewallRules', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.listMachines = ctx => {
|
|
||||||
return request('listFirewallRuleMachines', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getFirewallRule', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.create = ctx => {
|
|
||||||
return request('createFirewallRule', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.update = ctx => {
|
|
||||||
return request('updateFirewallRule', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.enable = ctx => {
|
|
||||||
return request('enableFirewallRule', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.disable = ctx => {
|
|
||||||
return request('disableFirewallRule', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.destroy = ctx => {
|
|
||||||
return request('deleteFirewallRule', ctx);
|
|
||||||
};
|
|
@ -1,25 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = ctx => {
|
|
||||||
return request('listImages', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getImage', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.create = ctx => {
|
|
||||||
return request('createImageFromMachine', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
// module.exports.update = (ctx) => {
|
|
||||||
// return request('UpdateImage', ctx);
|
|
||||||
// };
|
|
||||||
|
|
||||||
module.exports.destroy = uuid => {
|
|
||||||
return request('deleteImage', uuid);
|
|
||||||
};
|
|
||||||
|
|
||||||
// module.exports.xport = (uuid) => {
|
|
||||||
// return request('deleteImage', uuid);
|
|
||||||
// };
|
|
@ -1,16 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
account: require('./account'),
|
|
||||||
users: require('./users'),
|
|
||||||
policies: require('./policies'),
|
|
||||||
roles: require('./roles'),
|
|
||||||
keys: require('./keys'),
|
|
||||||
datacenters: require('./datacenters'),
|
|
||||||
services: require('./services'),
|
|
||||||
images: require('./images'),
|
|
||||||
packages: require('./packages'),
|
|
||||||
machines: require('./machines'),
|
|
||||||
firewallRules: require('./firewall-rules'),
|
|
||||||
// fabrics: require('./fabrics'),
|
|
||||||
networks: require('./networks'),
|
|
||||||
nics: require('./nics')
|
|
||||||
};
|
|
@ -1,35 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
user: {
|
|
||||||
list: ctx => {
|
|
||||||
return request('listUserKeys', ctx);
|
|
||||||
},
|
|
||||||
get: ctx => {
|
|
||||||
return request('getUserKey', ctx);
|
|
||||||
},
|
|
||||||
create: ctx => {
|
|
||||||
return request('createUserKey', ctx);
|
|
||||||
},
|
|
||||||
destroy: ctx => {
|
|
||||||
return request('deleteUserKey', ctx);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
account: {
|
|
||||||
list: () => {
|
|
||||||
return request('listKeys', {});
|
|
||||||
},
|
|
||||||
|
|
||||||
get: ctx => {
|
|
||||||
return request('getKey', ctx);
|
|
||||||
},
|
|
||||||
|
|
||||||
create: ctx => {
|
|
||||||
return request('createKey', ctx);
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: ctx => {
|
|
||||||
return request('deleteKey', ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,108 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
const snapshots = {
|
|
||||||
list: ctx => {
|
|
||||||
return request('listMachineSnapshots', ctx);
|
|
||||||
},
|
|
||||||
get: ctx => {
|
|
||||||
return request('getMachineSnapshot', ctx);
|
|
||||||
},
|
|
||||||
create: ctx => {
|
|
||||||
return request('createMachineSnapshot', ctx);
|
|
||||||
},
|
|
||||||
destroy: ctx => {
|
|
||||||
return request('deleteMachineSnapshot', ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const metadata = {
|
|
||||||
list: ctx => {
|
|
||||||
return request('', ctx);
|
|
||||||
},
|
|
||||||
get: ctx => {
|
|
||||||
return request('', ctx);
|
|
||||||
},
|
|
||||||
update: ctx => {
|
|
||||||
return request('', ctx);
|
|
||||||
},
|
|
||||||
destroy: ctx => {
|
|
||||||
return request('', ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const firewall = {
|
|
||||||
enable: ctx => {
|
|
||||||
return request('enableMachineFirewall', ctx);
|
|
||||||
},
|
|
||||||
disable: ctx => {
|
|
||||||
return request('disableMachineFirewall', ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const tags = {
|
|
||||||
list: ctx => {
|
|
||||||
return request('listMachineTags', ctx);
|
|
||||||
},
|
|
||||||
get: ctx => {
|
|
||||||
return request('getMachineTag', ctx);
|
|
||||||
},
|
|
||||||
add: ctx => {
|
|
||||||
return request('addMachineTags', ctx);
|
|
||||||
},
|
|
||||||
replace: ctx => {
|
|
||||||
return request('replaceMachineTags', ctx);
|
|
||||||
},
|
|
||||||
destroy: ctx => {
|
|
||||||
const method = ctx.tag ? 'deleteMachineTag' : 'deleteMachineTags';
|
|
||||||
return request(method, ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.list = ctx => {
|
|
||||||
return request('listMachines', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getMachine', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.create = ctx => {
|
|
||||||
return request('createMachine', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.stop = ctx => {
|
|
||||||
return request('stopMachine', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.start = uuid => {
|
|
||||||
return request('startMachine', uuid);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.startFromSnapshot = ctx => {
|
|
||||||
return request('startMachineFromSnapshot', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.reboot = ctx => {
|
|
||||||
return request('rebootMachine', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.resize = ctx => {
|
|
||||||
return request('', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.rename = ctx => {
|
|
||||||
return request('', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.destroy = ctx => {
|
|
||||||
return request('deleteMachine', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.audit = ctx => {
|
|
||||||
return request('machineAudit', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.snapshots = snapshots;
|
|
||||||
module.exports.metadata = metadata;
|
|
||||||
module.exports.firewall = firewall;
|
|
||||||
module.exports.tags = tags;
|
|
@ -1,9 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listNetworks');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getNetwork', ctx);
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listNics');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getNic', ctx);
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = ctx => {
|
|
||||||
return request('listPackages', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getPackage', ctx);
|
|
||||||
};
|
|
@ -1,21 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listPolicies');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getPolicy', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.create = ctx => {
|
|
||||||
return request('createPolicy', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.update = ctx => {
|
|
||||||
return request('updatePolicy', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.destroy = ctx => {
|
|
||||||
return request('deletePolicy', ctx);
|
|
||||||
};
|
|
@ -1,40 +0,0 @@
|
|||||||
const credentials = require('../credentials');
|
|
||||||
const auth = require('smartdc-auth');
|
|
||||||
const cloudapi = require('triton/lib/cloudapi2');
|
|
||||||
const bunyan = require('bunyan');
|
|
||||||
const pkg = require('../../package.json');
|
|
||||||
|
|
||||||
var log = bunyan.createLogger({
|
|
||||||
name: pkg.name
|
|
||||||
});
|
|
||||||
|
|
||||||
var client = cloudapi.createClient({
|
|
||||||
log: log,
|
|
||||||
url: credentials.url,
|
|
||||||
account: credentials.account,
|
|
||||||
user: credentials.user,
|
|
||||||
sign: auth.cliSigner({
|
|
||||||
log: log,
|
|
||||||
keyId: credentials.keyId,
|
|
||||||
user: credentials.account,
|
|
||||||
subuser: credentials.user
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = (method, args) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const fn = client[method].bind(client);
|
|
||||||
|
|
||||||
const cb = (err, res) => {
|
|
||||||
if (err) {
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(res);
|
|
||||||
};
|
|
||||||
|
|
||||||
return args ? fn(args, cb) : fn(cb);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.client = client;
|
|
@ -1,31 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listRoles');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getRole', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.create = ctx => {
|
|
||||||
return request('createRole', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.set = ctx => {
|
|
||||||
const id = ctx.id ? `/${ctx.id}` : '';
|
|
||||||
const resource = `/${request.client.account}/${ctx.resource}${id}`;
|
|
||||||
|
|
||||||
return request('setRoleTags', {
|
|
||||||
roleTags: ctx.role,
|
|
||||||
resource
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.update = ctx => {
|
|
||||||
return request('updateRole', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.destroy = ctx => {
|
|
||||||
return request('deleteRole', ctx);
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
return request('listServices');
|
|
||||||
};
|
|
@ -1,21 +0,0 @@
|
|||||||
const request = require('./request');
|
|
||||||
|
|
||||||
module.exports.list = () => {
|
|
||||||
return request('listUsers');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.get = ctx => {
|
|
||||||
return request('getUser', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.create = ctx => {
|
|
||||||
return request('createUser', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.destroy = ctx => {
|
|
||||||
return request('deleteUser', ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.update = ctx => {
|
|
||||||
return request('updateUser', ctx);
|
|
||||||
};
|
|
@ -1,27 +0,0 @@
|
|||||||
const json = (() => {
|
|
||||||
try {
|
|
||||||
const res = require('dotenv').config({
|
|
||||||
path: '../.env',
|
|
||||||
silent: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.error) {
|
|
||||||
throw res.error;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
try {
|
|
||||||
return require('../credentials.json');
|
|
||||||
} catch (err) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
})();
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
url: process.env.SDC_URL || json.SDC_URL || json.url || '',
|
|
||||||
account: process.env.SDC_ACCOUNT || json.SDC_ACCOUNT || json.account || '',
|
|
||||||
user: process.env.SDC_USER || json.SDC_USER || json.user || '',
|
|
||||||
keyId: process.env.SDC_KEY_ID || json.SDC_KEY_ID || json.keyId || ''
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
const graphqlHTTP = require('express-graphql');
|
|
||||||
const schema = require('./schema');
|
|
||||||
|
|
||||||
module.exports = graphqlHTTP(() => ({
|
|
||||||
schema: schema,
|
|
||||||
graphiql: true,
|
|
||||||
pretty: true
|
|
||||||
}));
|
|
@ -1,14 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.use('/graphql', require('./endpoint'));
|
|
||||||
|
|
||||||
const server = app.listen(4000, err => {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Listening at http://0.0.0.0:${server.address().port}/graphql`);
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
const graphql = require('graphql');
|
|
||||||
const mutation = require('./mutations');
|
|
||||||
const query = require('./queries');
|
|
||||||
|
|
||||||
const { GraphQLSchema } = graphql;
|
|
||||||
|
|
||||||
module.exports = new GraphQLSchema({
|
|
||||||
query,
|
|
||||||
mutation
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
const AccountType = require('../types/login');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLBoolean, GraphQLString } = require('graphql');
|
|
||||||
|
|
||||||
module.exports.updateAccount = {
|
|
||||||
type: AccountType,
|
|
||||||
description: 'Update your account details',
|
|
||||||
args: {
|
|
||||||
email: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
company_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
first_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
last_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
postal_code: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
city: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
country: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
phone: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
cns_enabled: {
|
|
||||||
type: GraphQLBoolean
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.account.get().then(account => {
|
|
||||||
return api.account.update(
|
|
||||||
Object.assign(account, args, {
|
|
||||||
firstName: args.first_name || account.firstName,
|
|
||||||
lastName: args.first_name || account.lastName,
|
|
||||||
companyName: args.company_name || account.companyName,
|
|
||||||
postalCode: args.postal_code || account.postalCode
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,98 +0,0 @@
|
|||||||
const FirewallRuleType = require('../types/firewall-rule');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLID, GraphQLBoolean, GraphQLString } = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createFirewallRule = {
|
|
||||||
type: FirewallRuleType,
|
|
||||||
description: "Adds a new firewall rule for the specified account. This rule will be added to all the account's instances where it may be necessary",
|
|
||||||
args: {
|
|
||||||
enabled: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Indicates if the rule is enabled (optional, false by default)'
|
|
||||||
},
|
|
||||||
rule: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Firewall rule text'
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Human-readable description for the rule (optional)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.firewallRules.create({
|
|
||||||
rule: args.rule,
|
|
||||||
description: args.description,
|
|
||||||
enabled: !!args.enabled
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.updateFirewallRule = {
|
|
||||||
type: FirewallRuleType,
|
|
||||||
description: 'Updates the given rule record and -- depending on rule contents -- adds/removes/updates the rule on all the required instances',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Firewall rule id'
|
|
||||||
},
|
|
||||||
enabled: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Indicates if the rule is enabled (optional, false by default)'
|
|
||||||
},
|
|
||||||
rule: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Firewall rule text'
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Human-readable description for the rule (optional)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.firewallRules.update(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.enableFirewallRule = {
|
|
||||||
type: FirewallRuleType,
|
|
||||||
description: 'Enables the given firewall rule if it is disabled',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Firewall rule id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.firewallRules.enable(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.disableFirewallRule = {
|
|
||||||
type: FirewallRuleType,
|
|
||||||
description: 'Disables the given firewall rule if it is enabled',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Firewall rule id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.firewallRules.disable(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteFirewallRule = {
|
|
||||||
type: FirewallRuleType,
|
|
||||||
description: 'Removes the given firewall rule from all the required instances',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Firewall rule id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.firewallRules.destroy(args);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,54 +0,0 @@
|
|||||||
const AccountType = require('../types/login');
|
|
||||||
const DynamicObjectType = require('../types/dynamic-object');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLList,
|
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLID
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createImage = {
|
|
||||||
type: AccountType,
|
|
||||||
description: 'Create a new custom image from an instance',
|
|
||||||
args: {
|
|
||||||
machine: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The prepared and stopped instance UUID from which the image is to be created'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'The name of the custom image, e.g. "my-image". Maximum 512 characters. However, typical names should be much shorter, e.g. 5-20 characters'
|
|
||||||
},
|
|
||||||
version: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'The version of the custom image, e.g. "1.0.0". Maximum 128 characters'
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'A short prose description of this image. Maximum 512 characters'
|
|
||||||
},
|
|
||||||
homepage: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Homepage URL where users can find more information about the image. Maximum 128 characters'
|
|
||||||
},
|
|
||||||
eula: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'URL of the End User License Agreement (EULA) for the image. Maximum 128 characters'
|
|
||||||
},
|
|
||||||
acl: {
|
|
||||||
type: new GraphQLList(GraphQLID),
|
|
||||||
description: 'An array of user/account UUIDs to which to give read access to a private image. I.e. this is only relevant for images with public === false'
|
|
||||||
},
|
|
||||||
tags: {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'An object of key/value pairs that allows clients to categorize images by any given criteria'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { create } = api.images;
|
|
||||||
|
|
||||||
return create(args);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,16 +0,0 @@
|
|||||||
const { GraphQLObjectType } = require('graphql');
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'RootMutationType',
|
|
||||||
fields: Object.assign(
|
|
||||||
require('./account'),
|
|
||||||
require('./keys'),
|
|
||||||
require('./users'),
|
|
||||||
require('./roles'),
|
|
||||||
require('./policies'),
|
|
||||||
require('./machines'),
|
|
||||||
require('./images'),
|
|
||||||
require('./firewall-rules'),
|
|
||||||
require('./snapshots')
|
|
||||||
)
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
const KeyType = require('../types/key');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLNonNull, GraphQLString, GraphQLID } = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createKey = {
|
|
||||||
type: KeyType,
|
|
||||||
description: 'Uploads a new OpenSSH key to Triton for use in HTTP signing and SSH',
|
|
||||||
args: {
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
key: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
userId: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'UserId to add this key to. Leaving this in blank will add the key to the account'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const _api = args.userId ? api.keys.user : api.keys.account;
|
|
||||||
return _api.create(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteKey = {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Deletes a single SSH key, by name or fingerprint',
|
|
||||||
args: {
|
|
||||||
name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
fingerprint: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
userId: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'UserId who this key belongs to. Leaving this in blank will delete an account key'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const _api = args.userId ? api.keys.user : api.keys.account;
|
|
||||||
|
|
||||||
return _api.destroy(args).then(() => {
|
|
||||||
return args.name || args.fingerprint;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,320 +0,0 @@
|
|||||||
const MachineType = require('../types/machine');
|
|
||||||
const DynamicObjectType = require('../types/dynamic-object');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLBoolean,
|
|
||||||
GraphQLID,
|
|
||||||
GraphQLList
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createMachine = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to provision an instance',
|
|
||||||
args: {
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Friendly name for this instance; default is the first 8 characters of the machine id'
|
|
||||||
},
|
|
||||||
package: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'Id of the package to use on provisioning, obtained from ListPackages'
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'The image UUID (from images { id })'
|
|
||||||
},
|
|
||||||
networks: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: 'Desired networks ids (from networks { id })'
|
|
||||||
},
|
|
||||||
locality: {
|
|
||||||
type: MachineType.locality,
|
|
||||||
description: 'Optionally specify which instances the new instance should be near or far from'
|
|
||||||
},
|
|
||||||
metadata: {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'An arbitrary set of metadata key/value pairs can be set at provision time'
|
|
||||||
},
|
|
||||||
tags: {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'An arbitrary set of tags can be set at provision time'
|
|
||||||
},
|
|
||||||
firewall_enabled: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Completely enable or disable firewall for this instance. Default is false'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const resolveNames = (obj = {}, namespace) => {
|
|
||||||
return Object.keys(obj).reduce((all, name) => {
|
|
||||||
return Object.assign(all, {
|
|
||||||
[`${namespace}.${name}`]: obj[name]
|
|
||||||
});
|
|
||||||
}, {});
|
|
||||||
};
|
|
||||||
|
|
||||||
const tags = resolveNames(args.tags, 'tag');
|
|
||||||
const metadata = resolveNames(args.tags, 'metadata');
|
|
||||||
|
|
||||||
const machine = Object.assign(
|
|
||||||
{
|
|
||||||
name: args.name,
|
|
||||||
package: args['package'],
|
|
||||||
image: args.image,
|
|
||||||
networks: args.networks,
|
|
||||||
locality: args.locality,
|
|
||||||
firewall_enabled: args.firewall_enabled
|
|
||||||
},
|
|
||||||
tags,
|
|
||||||
metadata
|
|
||||||
);
|
|
||||||
|
|
||||||
return api.machines.create(machine);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.startMachine = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to boot up an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.machines.start(args.id).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.startMachineFromSnapshot = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'If an instance is in the "stopped" state, you can choose to start the instance from the referenced snapshot',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The snapshot id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.machines.startFromSnapshot(args).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.stopMachine = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to shut down an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.machines.stop(args.id).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.rebootMachine = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to reboot an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.machines.reboot(args.id).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteMachine = {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'Allows you to completely destroy an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.machines.destroy(args.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.auditMachine = {
|
|
||||||
type: new GraphQLList(DynamicObjectType),
|
|
||||||
description: "Provides a list of an instance's accomplished actions. Results are sorted from newest to oldest action",
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.machines.destroy(args.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.setMachineFirewall = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to set the firewall state for an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
enabled: {
|
|
||||||
type: new GraphQLNonNull(GraphQLBoolean)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { firewall } = api.machines;
|
|
||||||
|
|
||||||
const fn = args.enabled ? firewall.enable : firewall.disable;
|
|
||||||
|
|
||||||
return fn(args.id).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.enableMachineFirewall = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to enable the firewall for an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { firewall } = api.machines;
|
|
||||||
|
|
||||||
return firewall.enable(args.id).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.disableMachineFirewall = {
|
|
||||||
type: MachineType,
|
|
||||||
description: 'Allows you to completely disable the firewall of an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { firewall } = api.machines;
|
|
||||||
|
|
||||||
return firewall.disable(args.id).then(machine => {
|
|
||||||
if (machine) {
|
|
||||||
return machine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api.machines.get(args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.addMachineTags = {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'Set tags on the given instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
tags: {
|
|
||||||
type: new GraphQLNonNull(DynamicObjectType),
|
|
||||||
description: 'Tag name/value pairs'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { tags } = api.machines;
|
|
||||||
|
|
||||||
return tags.add(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.replaceMachineTags = {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'Fully replace all tags on an instance with the given tags',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
tags: {
|
|
||||||
type: new GraphQLNonNull(DynamicObjectType),
|
|
||||||
description: 'Tag name/value pairs'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { tags } = api.machines;
|
|
||||||
|
|
||||||
return tags.replace(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteMachineTags = {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'Deletes tags from an instance',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
tag: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Tag name to remove. If value is not supplied, all machine tags are removed'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { tags } = api.machines;
|
|
||||||
|
|
||||||
return tags.destroy(args);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,71 +0,0 @@
|
|||||||
const PolicyType = require('../types/policy');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLID,
|
|
||||||
GraphQLList
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createPolicy = {
|
|
||||||
type: PolicyType,
|
|
||||||
description: 'Creates a new account policy',
|
|
||||||
args: {
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'The policy name'
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
|
|
||||||
description: 'One or more Aperture sentences to be added to the current policy'
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'A description for this policy (Optional)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.policies.create(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.updatePolicy = {
|
|
||||||
type: PolicyType,
|
|
||||||
description: 'Upgrades an existing account policy. Everything but id can be modified',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID)
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'The policy name'
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
|
|
||||||
description: 'One or more Aperture sentences to be added to the current policy'
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'A description for this policy (Optional)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.policies.update(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deletePolicy = {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Delete an RBAC policy',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.policies.destroy(args).then(() => {
|
|
||||||
return args.id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,103 +0,0 @@
|
|||||||
const RoleType = require('../types/role');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLID,
|
|
||||||
GraphQLList
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createRole = {
|
|
||||||
type: RoleType,
|
|
||||||
description: 'Create a new role for your account',
|
|
||||||
args: {
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: "The role's name"
|
|
||||||
},
|
|
||||||
policies: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: "This account's policies to be given to this role (Optional)"
|
|
||||||
},
|
|
||||||
members: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: "This account's user logins to be added to this role (Optional)"
|
|
||||||
},
|
|
||||||
default_members: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: "This account's user logins to be added to this role and have it enabled by default (Optional)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.roles.create(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.updateRole = {
|
|
||||||
type: RoleType,
|
|
||||||
description: 'Modifies an account role. Anything but id can be modified',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID)
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: "The role's name"
|
|
||||||
},
|
|
||||||
policies: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: "This account's policies to be given to this role (Optional)"
|
|
||||||
},
|
|
||||||
members: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: "This account's user logins to be added to this role (Optional)"
|
|
||||||
},
|
|
||||||
default_members: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: "This account's user logins to be added to this role and have it enabled by default (Optional)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.roles.update(args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteRole = {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Remove a role',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.roles.destroy(args).then(() => {
|
|
||||||
return args.id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.setRoleTags = {
|
|
||||||
type: RoleType.tag,
|
|
||||||
description: "Sets the given role tags to the provided resource path. resource_path can be the path to any of the CloudAPI resources described in this document: account, keys, users, roles, policies, user's ssh keys, datacenters, images, packages, instances, analytics, instrumentations, firewall rules and networks.",
|
|
||||||
args: {
|
|
||||||
resource: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString),
|
|
||||||
description: 'The resource type e.g. `machines`, `policies`...'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'The resource id'
|
|
||||||
},
|
|
||||||
role: {
|
|
||||||
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
|
|
||||||
description: 'The list role-tags to be added to this resource'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { set } = api.roles;
|
|
||||||
|
|
||||||
return set(args);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,60 +0,0 @@
|
|||||||
const SnapshotType = require('../types/snapshot');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLNonNull, GraphQLString, GraphQLID } = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createSnapshot = {
|
|
||||||
type: SnapshotType,
|
|
||||||
description: 'Allows you to take a snapshot of a machine instance',
|
|
||||||
args: {
|
|
||||||
machine: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The name to assign to the new snapshot'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { snapshot: { create, get } } = api.machines;
|
|
||||||
|
|
||||||
const newArgs = {
|
|
||||||
id: args.machine,
|
|
||||||
name: args.name
|
|
||||||
};
|
|
||||||
|
|
||||||
return create(newArgs).then(snapshot => {
|
|
||||||
if (snapshot) {
|
|
||||||
return snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
return get(newArgs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteSnapshot = {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Deletes the specified snapshot of an instance',
|
|
||||||
args: {
|
|
||||||
machine: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID),
|
|
||||||
description: 'The machine id'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The name to assign to the new snapshot'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
const { snapshot: { destroy } } = api.machines;
|
|
||||||
|
|
||||||
const newArgs = {
|
|
||||||
id: args.machine,
|
|
||||||
name: args.name
|
|
||||||
};
|
|
||||||
|
|
||||||
return destroy(newArgs).then(() => args.name);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,144 +0,0 @@
|
|||||||
const UserType = require('../types/login');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLNonNull, GraphQLString, GraphQLID } = require('graphql');
|
|
||||||
|
|
||||||
module.exports.createUser = {
|
|
||||||
type: UserType,
|
|
||||||
description: 'Creates a new user under an account',
|
|
||||||
args: {
|
|
||||||
login: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
company_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
first_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
last_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
postal_code: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
city: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
country: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
phone: {
|
|
||||||
type: GraphQLString
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.users.create(
|
|
||||||
Object.assign(args, {
|
|
||||||
firstName: args.first_name,
|
|
||||||
lastName: args.first_name,
|
|
||||||
companyName: args.company_name,
|
|
||||||
postalCode: args.postal_code
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.deleteUser = {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Remove a user',
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.users.destroy(args).then(() => {
|
|
||||||
return args.id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.updateUser = {
|
|
||||||
type: UserType,
|
|
||||||
description: "Update a user's modifiable properties",
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: new GraphQLNonNull(GraphQLID)
|
|
||||||
},
|
|
||||||
login: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
company_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
first_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
last_name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
postal_code: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
city: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
country: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
phone: {
|
|
||||||
type: GraphQLString
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: (root, args) => {
|
|
||||||
return api.users.update(
|
|
||||||
Object.assign(args, {
|
|
||||||
firstName: args.first_name,
|
|
||||||
lastName: args.first_name,
|
|
||||||
companyName: args.company_name,
|
|
||||||
postalCode: args.postal_code
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// module.exports.changeUserPassword = {
|
|
||||||
// type: UserType,
|
|
||||||
// description: 'This is a separate rule for password changes, so different policies can be used for an user trying to modify other data, or only their own password',
|
|
||||||
// args: {
|
|
||||||
// id: {
|
|
||||||
// type: new GraphQLNonNull(GraphQLID)
|
|
||||||
// },
|
|
||||||
// password: {
|
|
||||||
// type: GraphQLString
|
|
||||||
// },
|
|
||||||
// password_confirmation: {
|
|
||||||
// type: GraphQLString
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// resolve: (root, args) => {
|
|
||||||
// return api.users.updatePassword(args);
|
|
||||||
// }
|
|
||||||
// };
|
|
@ -1,13 +0,0 @@
|
|||||||
const AccountType = require('../types/login');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: AccountType,
|
|
||||||
resolve() {
|
|
||||||
return api.account.get().then(account => {
|
|
||||||
return Object.assign(account, {
|
|
||||||
isUser: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
const DatacenterType = require('../types/datacenter');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(DatacenterType),
|
|
||||||
resolve() {
|
|
||||||
return api.datacenters().then(datacenters => {
|
|
||||||
return Object.keys(datacenters).map(name => {
|
|
||||||
return {
|
|
||||||
url: datacenters[name],
|
|
||||||
name
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,12 +0,0 @@
|
|||||||
const FabricType = require('../types/fabrics');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(FabricType),
|
|
||||||
resolve() {
|
|
||||||
return api.fabrics.list();
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
const FirewallRuleType = require('../types/firewall-rule');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(FirewallRuleType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Filter on id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.firewallRules;
|
|
||||||
|
|
||||||
return !args.id ? list() : get(args.id).then(rule => [rule]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
const ImageType = require('../types/image');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLBoolean, GraphQLString, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(ImageType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Filter on id'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on "friendly" name'
|
|
||||||
},
|
|
||||||
os: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the underlying operating system'
|
|
||||||
},
|
|
||||||
version: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the version'
|
|
||||||
},
|
|
||||||
public: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Filter public/private images'
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on image state. By default only active images are shown. Use "all" to list all images'
|
|
||||||
},
|
|
||||||
owner: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on owner UUID'
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on image type'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.images;
|
|
||||||
|
|
||||||
return args.id
|
|
||||||
? get({
|
|
||||||
id: args.id
|
|
||||||
}).then(img => [img])
|
|
||||||
: list(args);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
const { GraphQLObjectType } = require('graphql');
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'RootQueryType',
|
|
||||||
fields: {
|
|
||||||
account: require('./account'),
|
|
||||||
users: require('./users'),
|
|
||||||
policies: require('./policies'),
|
|
||||||
roles: require('./roles'),
|
|
||||||
datacenters: require('./datacenters'),
|
|
||||||
services: require('./services'),
|
|
||||||
images: require('./images'),
|
|
||||||
packages: require('./packages'),
|
|
||||||
machines: require('./machines'),
|
|
||||||
firewallRules: require('./firewall-rules'),
|
|
||||||
// fabrics: require('./fabrics')
|
|
||||||
networks: require('./networks')
|
|
||||||
// nics: require('./nics')
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,74 +0,0 @@
|
|||||||
const MachineType = require('../types/machine');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLInt, GraphQLList, GraphQLString, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(MachineType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID
|
|
||||||
},
|
|
||||||
brand: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the type of instance (e.g. lx)'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Machine name to find (will make your list size 1, or 0 if nothing found)'
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Image id; returns instances provisioned with that image'
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the current state (e.g. running)'
|
|
||||||
},
|
|
||||||
memory: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on the current size of the RAM deployed (in MiB)'
|
|
||||||
},
|
|
||||||
tombstone: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on instances destroyed in the last N minutes'
|
|
||||||
},
|
|
||||||
first: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Return a max of N instances; default is 1000 (which is also the maximum allowable result set size)'
|
|
||||||
},
|
|
||||||
after: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Get a `first` number of instances starting at this offset'
|
|
||||||
},
|
|
||||||
tags: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: 'Filter on existing tags'
|
|
||||||
},
|
|
||||||
docker: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Whether to only list Docker instances, or only non-Docker instances, if present. Defaults to showing all instances.'
|
|
||||||
},
|
|
||||||
credentials: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Whether to include the generated credentials for instances, if present. Defaults to false'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.machines;
|
|
||||||
|
|
||||||
const { after, first } = args;
|
|
||||||
|
|
||||||
const newArgs = Object.assign(args, {
|
|
||||||
limit: first,
|
|
||||||
offset: after
|
|
||||||
});
|
|
||||||
|
|
||||||
return args.id
|
|
||||||
? get({
|
|
||||||
id: args.id
|
|
||||||
}).then(machine => [machine])
|
|
||||||
: list(newArgs);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
const NetworkType = require('../types/network');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(NetworkType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.networks;
|
|
||||||
|
|
||||||
return !args.id ? list() : get(args).then(network => [network]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
const NicType = require('../types/nic');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLString } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(NicType),
|
|
||||||
args: {
|
|
||||||
mac: {
|
|
||||||
type: GraphQLString
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.nics;
|
|
||||||
|
|
||||||
return !args.id ? list() : get(args).then(nic => [nic]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,56 +0,0 @@
|
|||||||
const PackageType = require('../types/package');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLInt, GraphQLList, GraphQLString, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(PackageType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Filter on package id'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the "friendly" name'
|
|
||||||
},
|
|
||||||
memory: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on how much memory will by available (in MiB)'
|
|
||||||
},
|
|
||||||
disk: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on how much disk space will be available (in MiB)'
|
|
||||||
},
|
|
||||||
swap: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on how much swap space will be available (in MiB)'
|
|
||||||
},
|
|
||||||
lwps: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on maximum number of light-weight processes (threads) allowed'
|
|
||||||
},
|
|
||||||
vcpus: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'Filter on number of vCPUs'
|
|
||||||
},
|
|
||||||
version: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the version'
|
|
||||||
},
|
|
||||||
group: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on the group belonging to'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.packages;
|
|
||||||
|
|
||||||
return args.id
|
|
||||||
? get({
|
|
||||||
id: args.id
|
|
||||||
}).then(pkg => [pkg])
|
|
||||||
: list(args);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
const PolicyType = require('../types/policy');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(PolicyType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: '`id` of the `PolicyType` to filter'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.policies;
|
|
||||||
|
|
||||||
return !args.id ? list() : get(args).then(policy => [policy]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
const RoleType = require('../types/role');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(RoleType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: '`id` or `name` of the `RoleType` to filter'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.roles;
|
|
||||||
|
|
||||||
return !args.id ? list() : get(args).then(role => [role]);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
const ServiceType = require('../types/service');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(ServiceType),
|
|
||||||
resolve() {
|
|
||||||
return api.services().then(services => {
|
|
||||||
return Object.keys(services).map(name => {
|
|
||||||
return {
|
|
||||||
url: services[name],
|
|
||||||
name
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,26 +0,0 @@
|
|||||||
const UserType = require('../types/login');
|
|
||||||
const graphql = require('graphql');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const { GraphQLList, GraphQLID } = graphql;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
type: new GraphQLList(UserType),
|
|
||||||
args: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: '`id` or `login` of the `UserType` to filter'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const { list, get } = api.users;
|
|
||||||
|
|
||||||
return !args.id
|
|
||||||
? list()
|
|
||||||
: get(args).then(user => [user]).then(user => {
|
|
||||||
return Object.assign(user, {
|
|
||||||
isUser: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,54 +0,0 @@
|
|||||||
const DynamicObjectType = require('./dynamic-object');
|
|
||||||
|
|
||||||
const { GraphQLString, GraphQLObjectType, GraphQLBoolean } = require('graphql');
|
|
||||||
|
|
||||||
const CallerType = new GraphQLObjectType({
|
|
||||||
name: 'CallerType',
|
|
||||||
fields: {
|
|
||||||
type: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Authentication type for the action request. One of "basic", "operator", "signature" or "token"'
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'When the authentication type is "basic", this member will be present and include user login'
|
|
||||||
},
|
|
||||||
ip: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The IP addresses this from which the action was requested. Not present if type is "operator"'
|
|
||||||
},
|
|
||||||
keyId: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'When authentication type is either "signature" or "token", SSH key identifier'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'AuditType',
|
|
||||||
fields: {
|
|
||||||
action: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The name of the action'
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'The original set of parameters sent when the action was requested'
|
|
||||||
},
|
|
||||||
success: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: "`true` or `false`, depending on the action's success",
|
|
||||||
resolve: root => {
|
|
||||||
return root.success === 'yes';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
caller: {
|
|
||||||
type: CallerType,
|
|
||||||
description: 'Account requesting the action'
|
|
||||||
},
|
|
||||||
time: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'When the action finished'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,14 +0,0 @@
|
|||||||
const { GraphQLString, GraphQLObjectType } = require('graphql');
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'DatacenterType',
|
|
||||||
fields: {
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'location of the datacenter'
|
|
||||||
},
|
|
||||||
url: {
|
|
||||||
type: GraphQLString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,41 +0,0 @@
|
|||||||
const { GraphQLScalarType, Kind } = require('graphql');
|
|
||||||
|
|
||||||
const kinds = {
|
|
||||||
[Kind.STRING]: ast => {
|
|
||||||
return ast.value;
|
|
||||||
},
|
|
||||||
[Kind.BOOLEAN]: ast => {
|
|
||||||
return kinds[Kind.STRING](ast);
|
|
||||||
},
|
|
||||||
[Kind.INT]: ast => {
|
|
||||||
return Number(ast.value);
|
|
||||||
},
|
|
||||||
[Kind.FLOAT]: ast => {
|
|
||||||
return kinds[Kind.INT](ast);
|
|
||||||
},
|
|
||||||
[Kind.OBJECT]: ast => {
|
|
||||||
const value = Object.create(null);
|
|
||||||
ast.fields.forEach(field => {
|
|
||||||
value[field.name.value] = parseLiteral(field.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
[Kind.LIST]: ast => {
|
|
||||||
return ast.values.map(parseLiteral);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://github.com/taion/graphql-type-json/blob/master/src/index.js
|
|
||||||
const parseLiteral = ast => {
|
|
||||||
const kind = kinds[ast.kind];
|
|
||||||
return kind ? kinds[ast.kind](ast) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// from http://stackoverflow.com/a/34229603
|
|
||||||
module.exports = new GraphQLScalarType({
|
|
||||||
name: 'DynamicObjectType',
|
|
||||||
serialize: v => v,
|
|
||||||
parseValue: v => v,
|
|
||||||
parseLiteral: parseLiteral
|
|
||||||
});
|
|
@ -1,19 +0,0 @@
|
|||||||
const { GraphQLString, GraphQLObjectType, GraphQLInt } = require('graphql');
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'FabricsType',
|
|
||||||
fields: {
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'A unique name to identify the VLAN'
|
|
||||||
},
|
|
||||||
vlan_id: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: "A number from 0-4095 that indicates the VLAN's id"
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'An optional description of the VLAN'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,90 +0,0 @@
|
|||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLBoolean,
|
|
||||||
GraphQLObjectType,
|
|
||||||
GraphQLList,
|
|
||||||
GraphQLID,
|
|
||||||
GraphQLInt
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
const FirewallRuleSyntaxType = new GraphQLObjectType({
|
|
||||||
name: 'FirewallRuleSyntaxType',
|
|
||||||
fields: {
|
|
||||||
text: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
from: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
action: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
protocol: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
type: GraphQLInt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'FirewallRuleType',
|
|
||||||
// function to allow circular dependencies
|
|
||||||
fields: () => ({
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Unique identifier for this rule'
|
|
||||||
},
|
|
||||||
enabled: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Indicates if the rule is enabled',
|
|
||||||
resolve: root => {
|
|
||||||
return !!root.enabled;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rule: {
|
|
||||||
type: FirewallRuleSyntaxType,
|
|
||||||
description: 'Firewall rule',
|
|
||||||
resolve: ({ rule }) => {
|
|
||||||
const regex = /from (.*?) to (.*?) (allow|deny) (.*?) port (\d*)/i;
|
|
||||||
const tokens = rule.match(regex);
|
|
||||||
|
|
||||||
return {
|
|
||||||
from: tokens[1],
|
|
||||||
to: tokens[2],
|
|
||||||
action: tokens[3],
|
|
||||||
protocol: tokens[4],
|
|
||||||
port: tokens[5],
|
|
||||||
text: rule
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Indicates if the rule is global',
|
|
||||||
resolve: root => {
|
|
||||||
return !!root.global;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Human-readable description for the rule'
|
|
||||||
},
|
|
||||||
machines: {
|
|
||||||
// circular dependency
|
|
||||||
type: new GraphQLList(require('./machine')),
|
|
||||||
description: 'Lists all instances a firewall rule is applied to',
|
|
||||||
resolve: root => {
|
|
||||||
return api.firewallRules.listMachines({
|
|
||||||
id: root.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
@ -1,116 +0,0 @@
|
|||||||
const DynamicObjectType = require('./dynamic-object');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLBoolean,
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLObjectType,
|
|
||||||
GraphQLInt,
|
|
||||||
GraphQLList,
|
|
||||||
GraphQLID
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
const ErrorType = new GraphQLObjectType({
|
|
||||||
name: 'ErrorType',
|
|
||||||
fields: {
|
|
||||||
code: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'A CamelCase string code for this error, e.g. "PrepareImageDidNotRun". See GetImage docs for a table of error.code values'
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'A short description of the image creation failure'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ImageFileType = new GraphQLObjectType({
|
|
||||||
name: 'ImageFileType',
|
|
||||||
fields: {
|
|
||||||
compression: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The type of file compression used for the image file. One of "bzip2", "gzip", "none"'
|
|
||||||
},
|
|
||||||
sha1: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'SHA-1 hex digest of the file content. Used for corruption checking'
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: 'File size in bytes'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'ImageType',
|
|
||||||
description: 'An image contains the software packages that will be available on newly-provisioned instance. In the case of hardware virtual machines, the image also includes the operating system',
|
|
||||||
fields: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Unique id for this image'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The "friendly" name for this image'
|
|
||||||
},
|
|
||||||
os: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The underlying operating system for this image'
|
|
||||||
},
|
|
||||||
version: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The version for this image'
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'What kind of image this is. The values differ after v8.0.0+'
|
|
||||||
},
|
|
||||||
requirements: {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'Contains a grouping of various minimum requirements for provisioning an instance with this image. For example "password" indicates that a password must be provided'
|
|
||||||
},
|
|
||||||
homepage: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The URL for a web page with more detailed information for this image'
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
type: new GraphQLList(ImageFileType),
|
|
||||||
description: 'An array of image files that make up each image. Currently only a single file per image is supported'
|
|
||||||
},
|
|
||||||
published_at: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The time this image has been made publicly available'
|
|
||||||
},
|
|
||||||
owner: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The UUID of the user who owns this image'
|
|
||||||
},
|
|
||||||
public: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'Indicates if this image is publicly available',
|
|
||||||
resolve: root => {
|
|
||||||
return !!root['public'];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'The current state of the image. One of "active", "unactivated", "disabled", "creating", "failed"'
|
|
||||||
},
|
|
||||||
tags: {
|
|
||||||
type: DynamicObjectType,
|
|
||||||
description: 'An object of key/value pairs that allows clients to categorize images by any given criteria'
|
|
||||||
},
|
|
||||||
eula: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'URL of the End User License Agreement (EULA) for the image'
|
|
||||||
},
|
|
||||||
acl: {
|
|
||||||
type: new GraphQLList(GraphQLString),
|
|
||||||
description: 'Access Control List. An array of account UUIDs given access to a private image. The field is only relevant to private images'
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
type: ErrorType,
|
|
||||||
description: 'If state=="failed", resulting from CreateImageFromMachine failure, then there may be an error object of the form {"code": "<string error code>", "message": "<string desc>"}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,16 +0,0 @@
|
|||||||
const { GraphQLString, GraphQLObjectType } = require('graphql');
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'KeyType',
|
|
||||||
fields: {
|
|
||||||
name: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
fingerprint: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
key: {
|
|
||||||
type: GraphQLString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,108 +0,0 @@
|
|||||||
const KeyType = require('./key');
|
|
||||||
const api = require('../../api');
|
|
||||||
|
|
||||||
const {
|
|
||||||
GraphQLBoolean,
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLList,
|
|
||||||
GraphQLObjectType,
|
|
||||||
GraphQLID
|
|
||||||
} = require('graphql');
|
|
||||||
|
|
||||||
module.exports = new GraphQLObjectType({
|
|
||||||
name: 'LoginType',
|
|
||||||
fields: {
|
|
||||||
id: {
|
|
||||||
type: GraphQLID,
|
|
||||||
description: 'Unique id for this user/account'
|
|
||||||
},
|
|
||||||
login: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Account/Sub-user login name'
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Email address'
|
|
||||||
},
|
|
||||||
company_name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
resolve: root => {
|
|
||||||
return !!root.company_name || root.companyName;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
first_name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
resolve: root => {
|
|
||||||
return !!root.first_name || root.firstName;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
last_name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
resolve: root => {
|
|
||||||
return !!root.last_name || root.lastName;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
postal_code: {
|
|
||||||
type: GraphQLString,
|
|
||||||
resolve: root => {
|
|
||||||
return !!root.postal_code || root.postalCode;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
city: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
country: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
phone: {
|
|
||||||
type: GraphQLString
|
|
||||||
},
|
|
||||||
cns_enabled: {
|
|
||||||
type: GraphQLBoolean,
|
|
||||||
description: 'true if Triton CNS is enabled for account',
|
|
||||||
resolve: root => {
|
|
||||||
return root.isUser ? null : !!root.triton_cns_enabled;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
keys: {
|
|
||||||
type: new GraphQLList(KeyType),
|
|
||||||
description: 'Get keys for user/account',
|
|
||||||
args: {
|
|
||||||
name: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on key name'
|
|
||||||
},
|
|
||||||
fingerprint: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'Filter on key fingerprint'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve(root, args) {
|
|
||||||
const _api = root.isUser ? api.keys.user : api.keys.account;
|
|
||||||
|
|
||||||
const { list, get } = _api;
|
|
||||||
|
|
||||||
const newArgs = Object.assign(args, {
|
|
||||||
userId: root.id
|
|
||||||
});
|
|
||||||
|
|
||||||
const filtered = args.name || args.fingerprint;
|
|
||||||
return !filtered ? list(newArgs) : get(newArgs).then(key => [key]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updated: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: "When this user/account's details was last updated"
|
|
||||||
},
|
|
||||||
created: {
|
|
||||||
type: GraphQLString,
|
|
||||||
description: 'When this user/account was created'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user